This addresses [Issue #151](http://code.google.com/p/phantomjs/issues/detail?id=151).
Summary of the new API:
- page.pages[]
- page.pagesWindowName[]
- page.getPage(windowName)
- page.windowName
- page.onPageCreated = function(newPage) { ... }
The page object created by the user holds responsibility of the "child" pages it creates.
If a page closes (i.e. window.close()) or a call to "page.pages[i].release()" is done,
the array "page.pages[]" will automatically update to contain only the pages still open.
This is still needed so that injectJs() methods work with CoffeeScript
and so that the main script file can be in CoffeeScript.
It causes duplication of code and some consideration is needed as to
how we could refactor the old inject code so that it uses modules
underneath. Lots of the module functionality written in JS could replace
the old C++ code (CSConverter, most functions in Utils).
http://code.google.com/p/phantomjs/issues/detail?id=47
Instead of using a C++ wrapper, I used a Node version of CoffeeScript
with a small JS wrapper (src/modules/_coffee-script.js). This way, since
the module system is similar enough to the Node.js module system, I only
need to require CoffeeScript in bootstrap.js and all the support for
.coffee is added by CoffeeScript itself.
To include a newer version of CoffeeScript in the source tree, see
tools/import-coffee-script.sh.
http://code.google.com/p/phantomjs/issues/detail?id=47
nativeRequire() has been refactored so that native modules are also
wrapped in Module objects. Additionally, native modules are also
cached and included in stack traces if an error occures inside them.
Phantom::loadModuleSource() has been renamed to
Phantom::readNativeModule() so that it's clear that it's used only to
load native modules.
Finally, all the require() code has been move after setting error
handlers in bootstrap.js so that if an error occurs in the require()
code, the stack trace is printed.
http://code.google.com/p/phantomjs/issues/detail?id=47
Instead of trying to use sourceId to determine what module threw an
error, we now load module's source code using modified
QWebFrame::evaluateJavaScript and leverage PhantomJS's stack traces.
http://code.google.com/p/phantomjs/issues/detail?id=47
Most of the tests passed after merging almost unchanged phantomjs-nodify
code, some needed small changes. The one that is still failing is for
CoffeeScript modules.
http://code.google.com/p/phantomjs/issues/detail?id=47
For some reason, it seems that checking CONFIG(static) inside
src/phantomjs.pro is not reliable. That caused the STATIC_BUILD define
not to be set, and hence Q_INIT_RESOURCE would never get called in
main.cpp.
Instead of using Q_INIT_RESOURCE, let's just compile the resources
directly into the phantomjs binary. This means we don't need to detect
whether Qt is linked statically or dynamically.
https://code.google.com/p/phantomjs/issues/detail?id=430
Debug mode turns off all optimisations. This make PhantomJS considerably
slower.
Instead, we build in 'release' mode, but generate debugging symbols at
the same time.
This may present some problems analysing crashes, if the optimisations
make that difficult. However, in my testing I was able to get useful
debug output even with optimisations enabled. So we should see how we go
- if it becomes a problem we can produce seperate debug binaries with no
optimisations.
https://code.google.com/p/phantomjs/issues/detail?id=599
This provides support for compiling the breakpad client into PhantomJS,
and generifies that Linux packaging scripts so that they also apply to
OS X and automate the symbol generation.
Building the Breakpad tool programs seems to be less than
straightforward on OS X, and documentation is poor. We have managed to
produce tools/dump-syms-mac.pro which allows building the dump_syms
program for dumping the debugging symbols. This needed a couple of
modifications to breakpad in order to compile successfully.
We have run out of time to work on making the minidump_stackwalk program
build. However, this is solely a developer tool and so it can wait until
after the 1.6 release before we complete this work.
Testing is welcome!
https://code.google.com/p/phantomjs/issues/detail?id=576
When console.error was called, there was a segfault because it was
treated as an uncaught exception, but did not have the correct stack
trace information (I am not sure why, but still...)
Now that we are generating the stackTrace in WebCore::reportException,
the MessageType gets set correctly, so we can use this to differentiate
between uncaught exceptions and other messages.
https://code.google.com/p/phantomjs/issues/detail?id=47
On reflection, this approach seems like a bad idea and a source of bugs.
I think passing object references between pages seems inherently
problematic, and we are better off just passing data to the onError
handler. If users need the actual object reference, they are able to use
try ... catch within the page.
This change also means that we are no longer breaking backwards
compatibility with the page.onError function signature.
WebCore already has a bunch of plumbing to pass around stacks. This
exists for the inspector/console. However, we need to actually retrieve
the error stack in WebCore::reportException.
To achieve this, I am attaching a stackArray property to the error
object. This is not as clean as I'd like, but seems ok for now. (We
should not document stackArray though.)
https://code.google.com/p/phantomjs/issues/detail?id=166
1. Passing JavaScript eval and other related actions to the CurrentFrame, not the MainFrame.
2. Added different methods to navigate between frames
3. With a call to "window.frames[0].focus()", the "currentFrame" changes: commands after that are sent to the new frame under focus.
4. The navigation between frames allows to walk over the "tree of frames" contained in the page.
This commit also adds examples (both in JS and CoffeeScript) and Unit Test.
http://code.google.com/p/phantomjs/issues/detail?id=573
The callback is harmless: if the user registers a "page.onCallback = [Function]",
that will receive any JS type passed via "phantomCallback()".
Also, if the handler for ".onCallback" returns a value, that is passed back as a
return value of "phantomCallback()".
Also, added "page.onConfirm" and "page.onPrompt".
This solves [Issue #133](http://code.google.com/p/phantomjs/issues/detail?id=133).
This is useful in case:
* we don't care about the result of the evaluate
* we don't need to have the result of the evaluate on the spot
* we need the stack of execution to begin WITHIN the page
Also, linting code: everyone should use a linter when writing Javascript. Everyone.
http://code.google.com/p/phantomjs/issues/detail?id=593
This removes the need to build breakpad as a separate step.
PhantomJS developers will still need to cd src/breakpad && ./configure
&& make in order to analyse crash dumps, but it is not longer necessary
in order to build PhantomJS itself.
https://code.google.com/p/phantomjs/issues/detail?id=576
This adds a new WebPage::zoomFactor property, which can be used to
zoom the page, i.e.:
page.zoomFactor = 1.5; // zoom by 50% in
page.zoomFactor = 0.5; // zoom by 50% out
The rasterize.js example is adapted to take an optional fourth argument
to set the zoom factor. Furthermore, the webpage-spec is extended with
a simple test case for the new property.
ISSUE: 579 (http://code.google.com/p/phantomjs/issues/detail?id=579)
Note that for errors that occur within subpages, this object is not the
real error object, but a copy. This is because the real object exists
within the subpage, but the page.onError handler runs within the main
context, so we have to pass it through as data.
https://code.google.com/p/phantomjs/issues/detail?id=166
Info.plist is needed to surpress the dock icon. Up to now, we need to have
the file available at run-time. With this change, the contents of
Info.plist are embedded in the executable at the linking stage, thus
there is no need to deploy the Info.plist file anymore.
Credit to Smokey Ardisson for the tip.
http://code.google.com/p/phantomjs/issues/detail?id=528
ISSUE: 460 (http://code.google.com/p/phantomjs/issues/detail?id=460)
this is a backport from qtbase:
commit 89cfe9eb01ad75c14121dbd6038b7c791226acf1
Author: Jiang Jiang <jiang.jiang@nokia.com>
Date: Thu Nov 10 18:01:56 2011 +0100
We need to reregister fonts in initializeDb because basic font db
doesn't have an internal record like fontconfig does, so just
repopulating the font database won't work. db->reregisterAppFonts
is now used properly as intended (reregister application fonts
after the system font database has been cleared).
Also, static variable 'initialized' in initializeDb() is removed
since we check privateDb()->count to see if it needs to be populated
again.
Task-number: QTBUG-22063
Change-Id: Ifc66392b56b72acbe08b99256c61421c204be5d7
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Usage:
page.paperSize = {
margin: "1cm",
header: {
height: "1cm",
contents: phantom.callback(function(pageNum, numPages) {
return "<h1>" + pageNum + " / " + numPages + "</h1>";
})
},
footer: {
height: "0.5cm",
contents: phantom.callback(function(pageNum, numPages) {
return "<h2>" + pageNum + " / " + numPages + "</h1>";
})
}
};
Note: The contents can return arbitrary HTML but since we cannot
re-layout the whole website for every page, the header/footers
must have the static height defined in the height property.
Note: The new example printheaderfooter.js shows the usage. It
also shows how one could delegate the above to a JavaScript
function on the loaded website, which allows one to print pages
and let the actually printed page decide how the header/footer
should look like.
Note: The page-counter can be reset by adding the class "phantomjs_reset_pagination"
to HTML block-elements that should reset the counter.
ISSUE: 410 (http://code.google.com/p/phantomjs/issues/detail?id=410)
commit c373ac4d17814588f4e3344f634ec469e56c0303
Author: Danny Wang <wangyang0123@gmail.com>
Date: Tue Apr 10 12:38:13 2012 +0800
moved i and l delarations to the top of page.evaluate()
commit bf24d4d1ecdb9e06c7bf461e87c222b10b74bc9d
Author: Danny Wang <wangyang0123@gmail.com>
Date: Tue Apr 10 08:54:55 2012 +0800
fixed defects in evaluate() pointed out by detro
commit 0bb8cff7803b70fe60fd761b1b748b5510705ee0
Author: Danny Wang <wangyang0123@gmail.com>
Date: Fri Apr 6 19:21:47 2012 +0800
added passing variables to function for page.evaluate
http://code.google.com/p/phantomjs/issues/detail?id=132
[Issue 439](http://code.google.com/p/phantomjs/issues/detail?id=439).
This works for all kind of "Content Body" but with raw bytes: the issue is that QtWebKit doesn't know how to convert a "QByteArray" to a "QVariant" (to inject it in the JavaScript space), resulting in a malformed conversion (somehow it decides to create a map where byte position is the 'key' and the byte at that position is the 'value').
This fix covers most scenarios (hopefully) but we are blocked on solving it completely.
Stop passing around lineNumber and sourceID as they are unused and don't
contain useful information.
Also declare Q_UNUSED on them to fix compiler warnings.
The hasHandler flag passed to JSC::Debugger::exception only applies to
the current stack frame. It does not indicate if there are exception
handlers in earlier stack frames.
Therefore, we are saving the frame when an exception occurs, but only
reporting the exception if it is still present once the stack has been
fully unwound.
http://code.google.com/p/phantomjs/issues/detail?id=166
add a default error handler on all pages. people can override if they
need.
ensure error handler can be removed without errors.
Hack ScriptSourceCode so we can pass in a raw string and not have it
validated as a URL
change source location hint for webpage.evaluate().
http://code.google.com/p/phantomjs/issues/detail?id=166
Please enter the commit message for your changes. Lines starting
In non-static build, JPEG is built as plugin. We force to have JPEG
support built-in by explicitly change a variable in the configure
script (unfortunately this can't be done via command-line options).
http://code.google.com/p/phantomjs/issues/detail?id=163
These classes are from the official Qt 4.8.0 platform plugins with some
tweaks:
* By default, use Fontconfig font database.
* No need to save the captured screen on every flush.
* Enlarge the screen to make it more like a typical desktop size.
http://code.google.com/p/phantomjs/issues/detail?id=163
This addresses [Issue #409](http://code.google.com/p/phantomjs/issues/detail?id=409).
The script:
* Get the latest code. Since LineNoise is pretty small, grabbing the tarball straight from the repo should be just fine.
* Extract and place the files in the right directory (src/linenoise).
* Remove unnecessary stuff (project files etc).
* Update the src/linenoise/README.md to refer to the revision being imported.
The recent patch that brought asynchronous webserver response handling
made it impossible to have proper keep-alive support in the server.
We want the server to support keep-alive though, which is especially
useful when writing a PhantomJS script that allows one to "remote control"
PhantomJS, using the WebServer API, without flooding the TCP connections.
Also the performance might be improved.
Note: This patch reverts commit bbce8920d0,
and resets the Mongoose code to the vanilla 3.0 version. Instead we now
support the async handling of HTTP requests using some QWaitCondition
magic.
Note: keep-alive support is optional, and disabled by default. To enable
it, use something like:
server.listen(port, {"keep-alive": true}, function(request, response) {...});
Like before, calling response.close() is crucial. Furthermore though, a
server that has keep-alive enabled *must* set a proper "Content-Length: ..."
header in it's response, otherwise clients will not be able to know when
the response has finished.
fix memory leaks in webserver
ISSUE: 416 (http://code.google.com/p/phantomjs/issues/detail?id=416)
Compositing depends on Graphics View and/or GL-based texture mapper.
Since we don't plan to support either of them, at least for the near
future, we might as well disable compositing.
http://code.google.com/p/phantomjs/issues/detail?id=414
In the current state of our imported minimalistic Qt, some header files
are missing. Since the module include like <QtGui> just includes
everything, this leads to a preprocessor error.
The solution is to include only needed headers from particular class.
http://code.google.com/p/phantomjs/issues/detail?id=226
This covers [Issue 252](http://code.google.com/p/phantomjs/issues/detail?id=252)
The commit is composed of 12 squashed commits:
commit efdc6ba4f143c30a690fd97d92d80fa412e79999
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Mon Feb 27 00:19:36 2012 +0000
Pretty-pringing and Completion Caching done!
* This completes pretty-printing for the result of evaluated
* expressions in the REPL.
* Also, now we cache the "possible completions", to speed things up
* a bit (nothing fancy though).
* Minor tweaks to the internal doc and the way we "mock"
* pretty-printing for QObjects/REPLCompletanle
* All tests passing :)
commit 1f9ef690e112a535b431fca409b77bb9c09d1c70
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Sun Feb 26 22:35:00 2012 +0000
Moving most of REPL shim JavaScritp code in a separate file. Way
easier to work on.
commit 02d460a16fee14e7096ae7d899c03902c5b8a9c6
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Sat Feb 25 20:25:18 2012 +0000
Initialisation of the Completions is now done in a pure virtual.
This means that every REPLCompletable object will ACTUALLY register
completion strings, ONLY if we are running a REPL
and that object is ACTUALLY created.
Otherwise, why bother?
Adding completions for all exposed REPLCompletable objects
Also, fixed an issue with _getCompletions()
commit 412c3778fb04aa1c7379f8e760afce702b0428dd
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Tue Feb 21 00:49:17 2012 +0000
Few more tweaks to the REPL:
- Now 'phantom' is the first QObject with proper completion
- No repetition in QObject completions
- LVAL of any user expression is now correctly prettified and
printed
Major things left to do:
- Cache completions (using QCache?)
- Add completions for the other QObject
- When the LVAL of a user expression is a QObject, print what's
expected, not the QObject "real" structure
commit 46f04713c8165d898055e15478bb31403f8c93f1
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Tue Feb 7 10:13:23 2012 -0800
Pretty-print expressions result
Still not done though: there are issues with the NON-Native JS
objects.
commit 98b2fe67651dc750b62c6fa9cf1d80317fd9ae06
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Fri Feb 3 00:22:52 2012 -0800
Introducing REPLCompletable.
This class should be inherited by any JavaScript-exposed QObject, to
ensure correct Auto-Completion.
Correct auto-completion for QObjects.
- Now even QObjects can correctly provide auto-completion, and avoid
showing "not for users" methods
- The strings used for the auto-completion are stored in a single
Index: minimum memory footprint
- Still, there is optimization that should be done (when "searching"
for the right completion by prefix)
- Completion for the objects not set up yet, but now it's just a
trivial sequence of "addCompletion('bla')" in their constructors
commit 9bd48618154b1530a37b41f4060440184e23253d
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Thu Feb 2 00:20:25 2012 -0800
Changing the way we import Linenoise.
Will just import a specific commit, and update manually when needed.
commit cfc9bae9fbdab13b01019b34b7cbd565e3153780
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Sun Jan 29 23:22:26 2012 -0800
Made the REPL into a Singleton. With Auto-completion!.
Reasons:
1) Needed a pointer to function (i.e. a static method) to be used
with Linenoise to provide auto-completions
2) It makes more sense, as it's not like we are going to have 2 REPL
running at the same time, are we?
There are problems to address:
- the enumeration in JS seems to return only the native interface of
our objects
- the function completions contain argument types of those functions
- "private" methods are exposed
commit c78bd32e17f8e0e4cc4a0066858de8cc81d33b97
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Sun Jan 29 22:10:20 2012 -0800
Migrating from the original, now [unmantained
Linenoise](https://github.com/antirez/linenoise) to the fairly active
[tadmarshall fork](https://github.com/tadmarshall/linenoise).
Also now the project is imported as a Git Submodule.
Having migrated to the latest Linenoise (see prev. commit), now this
_SHOULD_ work on Windows too.
But, of course, this needs testing. :)
commit 43713c5723d7c5ed446ba41ae8d6f8c9feba7f9b
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Tue Jan 24 23:17:06 2012 -0800
Now that the basics work, I'm adding support for REPL history.
This is something almost everyone today is accustomed to.
Also, now REPL history works!
And I found some useful resources to solve pending TODOs.
commit 31e5f88b044a5b4a823c67527ef8c245d2ac7863
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Sun Jan 22 20:56:36 2012 -0800
Adding Linenoise Project (https://github.com/antirez/linenoise).
For now is included as a drop-in set of files.
Later on, if the Linenoise project has frequent
updates, we might prefer to do it as a
git-submodule.
commit 4be9c15c65db4767e482fba0be13f8aab286d5f3
Author: Ivan De Marino <ivan.de.marino@gmail.com>
Date: Thu Jan 5 15:31:13 2012 +0000
First simple REPL implementation.
- Not complete
- Still doesn't handle arrow keys (needed for history)
This is done via the tools/import-qt.sh script. Note that the script
also removes some unnecesary stuff. In practice, src/qt is not as
big as the plain vanilla Qt source tree.
http://code.google.com/p/phantomjs/issues/detail?id=226
CommonJS proposal: http://wiki.commonjs.org/wiki/Filesystem/A.
It's called "raw".
http://code.google.com/p/phantomjs/issues/detail?id=400
Squashed commit of the following:
commit dd5fab4778bb7b67f1eca26a07d430aadd458c6e
Author: Milian Wolff <milian.wolff@kdab.com>
Date: Thu Feb 23 16:19:21 2012 +0100
the "mode" string is now properly parsed, and not only the first
char evaluated. This allows us to do fancy things like
fs.open(file, "rw+"); // read/write/append
Furthermore .read() is adapted such that it will always return the
full file contents, no matter where we have seeked to before (i.e.
by passing + we seek to the end, hence read() would always return
an empty string).
To open a binary file, pass "b" in the mode string to fs.open, e.g.:
fs.open(file, "rb"); // read binary
fs.open(file, "wb"); // write binary
fs.open(file, "rwb+"); // read/write binary, append
alternatively, one can use these shortcuts:
fs.write(file, contents, "b"); // write binary
fs.read(file, "b"); // read binary
Unit tests are extended and the echoToFile.js example fixed (it did not
close the file, which lead to the contents never getting written
on-disk since flush() is never called).
Also note that the FileSystem::open method was cleaned up and at least
one memory leak (if QFile* could not open) was fixed. The code should
now also be more C++-like.
commit 41139951138491459accefab22d48eba7b0b9900
Author: Milian Wolff <milian.wolff@kdab.com>
Date: Wed Feb 15 16:39:23 2012 +0100
use QString instead of QByteArray for raw binary data
QByteArray is simply unusable in JavaScript, since functions like
e.g. window.btoa expect a string. Also there is no sane way to
create a byte array in javascript, as ArrayBuffer e.g. is not
supported by QScript (at least there is no conversion in place).
If we use QString and some custom read/write code this all works
as expected though, we can use window.btoa to base64 encode binary
data and we can create random binary data using String.fromCharCode
also adds a unit test
commit e45673486ef27daf916902153217f9e5001b68c9
Author: Milian Wolff <milian.wolff@kdab.com>
Date: Wed Feb 15 14:39:15 2012 +0100
make it possible to read/write raw/binary files
this adds File::readRaw and File::writeRaw functions,
as well as 'shimmed' versions FS::readRaw and FS::writeRaw
these functions directly use QFile and QByteArray instead of
QTextStream and QString, making it possible to read and write
binary data, e.g. images and such.
Currently trying to use the remote debugger with sub-pages created in
the phantomjs session will result in a segfault inside QtWebKit. With
this patch, it works.
http://code.google.com/p/phantomjs/issues/detail?id=6
Now the left/top/right/bottom print margins can be set separately
using the pageSize.margin property. You can either use
pageSize.margin = "10px"
or use a map to set the margins separately:
pageSize.margin = {
left: "10px",
top: "5cm",
right: "7in",
bottom: "13mm"
};
pageSize.border is now a synonym for pageSize.margin to keep
compatibility to existing scripts.
ISSUE: 388 (http://code.google.com/p/phantomjs/issues/detail?id=388)
For POST and PUT request we now read all data as defined by
the Content-Length header into request.rawData property.
This property is a QByteArray which neatly maps to an array
in javascript.
For POST requests with Content-Type = applicaiton/x-www-form-urlencoded
we furthermore provide a parsed, easy-to-use request.post property.
This one is a QVariantMap of the decoded form data.
There is a new postserver.js example that shows the usage.
The unit test is extended to test the new (and old) features
of the server.
TODO: test that verifies proper decoding of UTF8 data, which
is not yet possible since I see no way to do a post-request
using phantomjs with an explicitly defined charset
ISSUE: 340 (http://code.google.com/p/phantomjs/issues/detail?id=340)
Most command-line programs provide an option to display the usage
message. Currently, this is achieved by passing no options at all.
This change allows for a more intuitive way for users to check the
list of available options.
http://code.google.com/p/phantomjs/issues/detail?id=347
With Qt 4.8, POST request with an empty content type will make the
content type set to "application/octet-stream". Somehow this breaks
POST.
The fix is to set the content type to "application/x-www-form-urlencoded",
like the case with Qt 4.7.
Based on the suggestion by Leo Franchi.
http://code.google.com/p/phantomjs/issues/detail?id=337
Trying to match http://nodejs.org/docs/latest/api/http.html.
For the server response:
* Change writeBody to write
* Change writeHeaders to writeHead
For the request object, 'headers' is now an object containing all
key-value pairs of the actual HTTP headers.
'queryString' is folded into 'url' key.
Non-standard keys in the request: isSSL, remotePort, remoteIP,
remoteUser, are disabled in the mean-time (will be revisited after 1.4
release).
Implementation-wise, the request object is now a simple key-value pair
using QVariant, as opposed to the heavy QObject instance.
http://code.google.com/p/phantomjs/issues/detail?id=115
This adds a new parameter --remote-debugger-port=<port>. When set,
phantomjs is operating in debug mode and will expose a webkit remote
debugger on the desired port. It can be attached to from any WebKit
browser on the given port and debugged.
i.e. if we tried to listen to an already used port, the error
was propagated in the main thread and the blockingqueuedconnection
would deadlock. not anymore
this is the minimal server that gets properly embedded into
the phantomjs space but the .listen api is missing actually
useful options (incoming request and ability to write to client)
* Some code reuse
* Centralised in Utils the loading of resource files
* It is safe to assume, when loading a resource file, that IT'S THERE and IT'S READABLE
* ALSO, I removed the unused 'shims' (we forgot them in there :P)
If Phantom.exit() is called inside the handler for loadFinished(), we
end up in a situation that QWebPage is deleting itself during a signal
emission. This used to be OK in QtWebKit 2.0 (Qt 4.7) but is not OK for
QtWebKit 2.2 (upcoming Qt 4.8).
http://code.google.com/p/phantomjs/issues/detail?id=251
Patch by Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org>.