mirror of https://github.com/vitalif/phantomjs
Compare commits
16 Commits
Author | SHA1 | Date |
---|---|---|
Ariya Hidayat | cbc9be0a7f | |
Ariya Hidayat | 1ee0a4ce44 | |
Ariya Hidayat | fa4309e381 | |
Ariya Hidayat | 724d28863b | |
Ariya Hidayat | bfc16995b4 | |
Ariya Hidayat | 3c13b9dca1 | |
Ariya Hidayat | c32d78747c | |
Ariya Hidayat | 62811468e4 | |
Ariya Hidayat | eb33e89e7a | |
Ariya Hidayat | f4f59b2319 | |
Ariya Hidayat | 56a5641b0e | |
Ariya Hidayat | cd590f2524 | |
Ariya Hidayat | 2e2fef788d | |
Ariya Hidayat | dea72dcbd3 | |
Ariya Hidayat | ec57f2e2f1 | |
Ariya Hidayat | d6219e16d6 |
|
@ -2,6 +2,7 @@
|
||||||
*.pro.user*
|
*.pro.user*
|
||||||
*.xcodeproj
|
*.xcodeproj
|
||||||
Makefile*
|
Makefile*
|
||||||
|
bin/phantomjs
|
||||||
*~
|
*~
|
||||||
*.moc
|
*.moc
|
||||||
moc_*
|
moc_*
|
||||||
|
@ -9,53 +10,10 @@ qrc_*
|
||||||
*.o
|
*.o
|
||||||
*.swp
|
*.swp
|
||||||
*.pyc
|
*.pyc
|
||||||
*.a
|
debian/*.debhelper
|
||||||
/debian/*.debhelper
|
debian/files
|
||||||
/debian/files
|
debian/*.log
|
||||||
/debian/*.log
|
debian/*.substvars
|
||||||
/debian/*.substvars
|
debian/*/
|
||||||
/debian/*/
|
python/build/
|
||||||
/deploy/qt-*.tar.gz
|
python/*.egg-info/
|
||||||
/deploy/Qt-*
|
|
||||||
/symbols
|
|
||||||
/src/qt/qtc-debugging-helper
|
|
||||||
/src/phantomjs_plugin_import.cpp
|
|
||||||
|
|
||||||
# ignore ctags
|
|
||||||
/tags
|
|
||||||
/tools/dump_syms.app/
|
|
||||||
|
|
||||||
# Ignore Visual Studio temporary files, build results, etc
|
|
||||||
*.suo
|
|
||||||
*.user
|
|
||||||
*.sln.docstates
|
|
||||||
*_i.c
|
|
||||||
*_p.c
|
|
||||||
*.ilk
|
|
||||||
*.meta
|
|
||||||
*.obj
|
|
||||||
*.pch
|
|
||||||
*.pdb
|
|
||||||
*.pgc
|
|
||||||
*.pgd
|
|
||||||
*.rsp
|
|
||||||
*.sbr
|
|
||||||
*.tlb
|
|
||||||
*.tli
|
|
||||||
*.tlh
|
|
||||||
*.tmp
|
|
||||||
*.log
|
|
||||||
*.sdf
|
|
||||||
*.vcxproj
|
|
||||||
*.vcxproj.filters
|
|
||||||
*.lib
|
|
||||||
*.prl
|
|
||||||
*.intermediate.manifest
|
|
||||||
|
|
||||||
# Build results
|
|
||||||
[Dd]ebug*/
|
|
||||||
[Rr]elease/
|
|
||||||
bin/
|
|
||||||
*.class
|
|
||||||
build/
|
|
||||||
.gradle/
|
|
||||||
|
|
29
.travis.yml
29
.travis.yml
|
@ -1,29 +0,0 @@
|
||||||
language: cpp
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
cache: apt
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- sudo apt-get -yqq update #< Suggested by the Travis CI doc
|
|
||||||
- sudo apt-get -fyq install #< Fixes inconsistency of packages installed previously
|
|
||||||
|
|
||||||
install:
|
|
||||||
- sudo apt-get -yq install build-essential chrpath libssl-dev libfontconfig1-dev sqlite3 libsqlite3-dev ruby gperf bison flex libicu48 libicu-dev #< Build Dependencies
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- chmod +x ./build.sh
|
|
||||||
- chmod +x ./test/run-tests.sh
|
|
||||||
- chmod +x ./test/run-tests-ghostdriver.sh
|
|
||||||
|
|
||||||
script:
|
|
||||||
- ./build.sh --confirm --silent #< Build
|
|
||||||
- ./test/run-tests.sh #< Test (PhantomJS)
|
|
||||||
- ./test/run-tests-ghostdriver.sh #< Test (GhostDriver / PhantomJSDriver)
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
irc:
|
|
||||||
channels:
|
|
||||||
- "irc.freenode.org#phantomjs"
|
|
||||||
on_success: always
|
|
||||||
on_failure: always
|
|
||||||
use_notice: true
|
|
|
@ -1,88 +0,0 @@
|
||||||
# Contribution Guide
|
|
||||||
|
|
||||||
This page describes how to contribute changes to PhantomJS.
|
|
||||||
|
|
||||||
Please do **not** create a pull request without reading this guide first. Failure to do so may result in the **rejection** of the pull request.
|
|
||||||
|
|
||||||
## For The Impatients
|
|
||||||
|
|
||||||
**Work on a feature branch**.
|
|
||||||
If your changes need to be modified due to some reviews, it is less clutter to tweak an isolated feature branch and push it again.
|
|
||||||
|
|
||||||
**Create a ticket in the issue tracker**.
|
|
||||||
This serves as a placeholder for important feedback, review, or any future updates.
|
|
||||||
|
|
||||||
In the commit message:
|
|
||||||
|
|
||||||
* **Keep the first line < 72 characters**. Write additional paragraphs
|
|
||||||
if necessary.
|
|
||||||
* **Put the link to the issue** (see above). This is important for cross-referencing purposes.
|
|
||||||
|
|
||||||
## Communicate
|
|
||||||
|
|
||||||
*Second opinion is always important.*
|
|
||||||
|
|
||||||
**Bug fixing**. If you have a fix for a bug, please attach your patch in the corresponding issue in the [issue tracker](https://github.com/ariya/phantomjs/issues). If there is no entry for the bug yet, then please create a new one. If you are confident working with Git, see the Get Ready section below on how to submit your change.
|
|
||||||
|
|
||||||
**Improvement and feature request**. If you have an improvement idea, please send an email to the [mailing list](http://groups.google.com/group/phantomjs) (rather than contacting the developers directly) so that other people can give their insights and opinions. This is also important to avoid duplicate work.
|
|
||||||
|
|
||||||
**Task management**. Once the feature idea is agreed upon and translated into concrete actions and tasks, please use the [issue tracker](https://github.com/ariya/phantomjs/issues) to create an issue for each individual task. Further technical discussion about the task and the implementation details should be carried out in the issue tracker.
|
|
||||||
|
|
||||||
**Extending with new API**. Whenever you want to introduce a new API, please send an email to the mailing list along with the link to the issue. Consider good API name for the object or function, read the [API Design Principle](http://developer.qt.nokia.com/wiki/API_Design_Principles) article. It may require few iterations to agree on the final API and hence it is important to engage all interested parties as early as possible.
|
|
||||||
|
|
||||||
## Get Ready
|
|
||||||
|
|
||||||
For your proposed change, you need to have:
|
|
||||||
|
|
||||||
* **an issue** (in the issue tracker) which describe your bug or feature
|
|
||||||
* **a feature branch** in your git fork
|
|
||||||
|
|
||||||
### Refer the Issue
|
|
||||||
|
|
||||||
The commit message needs to link to the issue. This cross-reference is [very important](http://ariya.ofilabs.com/2012/01/small-scale-software-craftsmanship.html) for the following reasons.
|
|
||||||
|
|
||||||
First, the commit log is frozen and can not be changed. If it contains a mistake or outdated information, the log can not be amended. However, further updates can be still posted to the linked issue, which can be followed from the commit log itself.
|
|
||||||
|
|
||||||
Second, it provides a placeholder for code review and other feedback.
|
|
||||||
|
|
||||||
An example of a bad commit log:
|
|
||||||
|
|
||||||
Fix Mountain Lion
|
|
||||||
|
|
||||||
The above log is too short and useless in the long run. A better version (and note the issue link):
|
|
||||||
|
|
||||||
Better support for OS X Mountain Lion.
|
|
||||||
|
|
||||||
require('system').os.version should give "10.8 (Mountain Lion)".
|
|
||||||
|
|
||||||
https://github.com/ariya/phantomjs/issues/10688
|
|
||||||
|
|
||||||
### Use Feature Branch
|
|
||||||
|
|
||||||
To isolate your change, please avoid working on the master branch. Instead, work on a *feature branch* (often also known as *topic branch*). You can create a new branch (example here crash-fix) off the master branch by using:
|
|
||||||
|
|
||||||
git checkout -b crash-fix master
|
|
||||||
|
|
||||||
Refer to your favorite Git tutorial/book for further detailed help.
|
|
||||||
|
|
||||||
Some good practices for the feature branch:
|
|
||||||
|
|
||||||
* Give it a meaningful name instead of, e.g. `prevent-zero-divide` instead of just `fix`
|
|
||||||
* Make *granular* and *atomic* commits, e.g. do not mix a typo fix with some major refactoring
|
|
||||||
* Keep one branch for one specific issue. If you need to work on other unrelated issues, create another branch.
|
|
||||||
|
|
||||||
## Review and Merge
|
|
||||||
|
|
||||||
When your branch is ready, send the pull request.
|
|
||||||
|
|
||||||
While it is not always the case, often it is necessary to improve parts of your code in the branch. This is the actual review process.
|
|
||||||
|
|
||||||
Here is a check list for the review:
|
|
||||||
|
|
||||||
* It does not break the test suite
|
|
||||||
* There is no typo
|
|
||||||
* The coding style follows the existing one
|
|
||||||
* There is a reasonable amount of comment
|
|
||||||
* The license header is intact
|
|
||||||
* All examples are still working
|
|
||||||
|
|
245
ChangeLog
245
ChangeLog
|
@ -1,247 +1,4 @@
|
||||||
Please see also http://phantomjs.org/releases.html.
|
Please see also http://code.google.com/p/phantomjs/wiki/ReleaseNotes.
|
||||||
|
|
||||||
2015-01-23: Version 2.0.0
|
|
||||||
|
|
||||||
New features
|
|
||||||
|
|
||||||
* Switched to Qt 5 and updated WebKit (issue 10448)
|
|
||||||
* Implemented clearing of memory cache (issue 10357)
|
|
||||||
* Added support for HTTP header change for every request (issue 11299)
|
|
||||||
|
|
||||||
Improvements
|
|
||||||
|
|
||||||
* Fixed rendering of CJK text by always linking the codecs (issue 10249)
|
|
||||||
* Ensured onResourceReceived is still fired on an error (issue 11163)
|
|
||||||
* Fixed possible crash in handling network requests (issue 11252)
|
|
||||||
* Removed hardcoded GhostDriver launching message (issue 12681)
|
|
||||||
* Allowed disk cache more than 2 GB (issue 12303)
|
|
||||||
|
|
||||||
Examples
|
|
||||||
|
|
||||||
* Netsniff example should exit when fails to load (issue 11333)
|
|
||||||
|
|
||||||
2014-01-25: Version 1.9.7
|
|
||||||
|
|
||||||
* Reverted to GhostDriver 1.1.0 instead of 1.1.1 (issue 11915)
|
|
||||||
* Fixed another warning of obsolete userSpaceScaleFactor on OS X 10.9 (issue 11612)
|
|
||||||
|
|
||||||
2014-01-20: Version 1.9.6
|
|
||||||
|
|
||||||
* Updated GhostDriver to version 1.1.1 (issue 11877, 11893)
|
|
||||||
|
|
||||||
2014-01-19: Version 1.9.3
|
|
||||||
|
|
||||||
* Fixed CoreText performance note on OS X 10.9 (issue 11418)
|
|
||||||
* Fixed warning of obsolete userSpaceScaleFactor on OS X 10.9 (issue 11612)
|
|
||||||
|
|
||||||
2013-09-06: Version 1.9.2
|
|
||||||
|
|
||||||
* Fixed graphical artifacts with transparent background on Windows (issue 11276, 11007, 11366)
|
|
||||||
* Updated GhostDriver to version 1.0.4 (issue 11452)
|
|
||||||
|
|
||||||
2013-06-04: Version 1.9.1
|
|
||||||
|
|
||||||
Critical bug fixes:
|
|
||||||
|
|
||||||
* Fixed problems with specifying proxy server (issue 10811, 11117)
|
|
||||||
* Fixed UTF-8 encoding with system.stdout and system.stderr (issue 11162)
|
|
||||||
* Ensured that onResourceReceived will be always invoked (issue 11163)
|
|
||||||
* Fixed module loading from an absolute path on Windows (issue 11165)
|
|
||||||
* Fixed typo in the command-line option for setting the cache size (11219)
|
|
||||||
* Fixed possible crash when handling network requests (issue 11252, 11338)
|
|
||||||
|
|
||||||
2013-03-20: Version 1.9.0 "Sakura"
|
|
||||||
|
|
||||||
New features
|
|
||||||
|
|
||||||
* Added spawn and execFile to execute external programs (issue 10219)
|
|
||||||
* Added the ability to abort network requests (issue 10230)
|
|
||||||
* Added system access to stdin, stdout, and stderr (issue 10333)
|
|
||||||
* Added support for custom CA certificates location (issue 10916)
|
|
||||||
* Added seek function to the File stream (issue 10937)
|
|
||||||
* Implemented file read for a specified number of bytes (issue 10938)
|
|
||||||
* Added a callback to handle network error (issue 10954, 10997)
|
|
||||||
* Added custom encoding support when opening a page (issue 11043)
|
|
||||||
* Implemented require.stub() support for a factory function (issue 11044)
|
|
||||||
* Added page loading indicator and progress (issue 11091)
|
|
||||||
* Added a timeout option for network requests (issue 11129)
|
|
||||||
|
|
||||||
Improvements
|
|
||||||
|
|
||||||
* Fixed the build on FreeBSD (issue 10597)
|
|
||||||
* Ensured a consistent 72 dpi for Linux headless rendering (issue 10659)
|
|
||||||
* Fixed possible PDF error due to invalid CreationDate field (issue 10663)
|
|
||||||
* Fixed crash when uploading non existing files (issue 10941)
|
|
||||||
* Improved the autocomplete internal of the interactive/REPL mode (issue 10943)
|
|
||||||
* Fixed possible crash when accessing inline frames (issue 10947)
|
|
||||||
* Changed Linux binary package setup to be built on CentOS 5 (issue 10963)
|
|
||||||
* Extended SSL ignore setting to synchronous XHR (issue 10985)
|
|
||||||
* Added convenient constants for modifier keys (issue 11056)
|
|
||||||
* Fixed incorrect date handling in the cookies (issue 11068)
|
|
||||||
* Updated GhostDriver to version 1.0.3 (issue 11146)
|
|
||||||
|
|
||||||
Examples
|
|
||||||
|
|
||||||
* Fixed invalid data URI in the netsniff example (issue 10740)
|
|
||||||
* Implemented a new weather example (issue 10794)
|
|
||||||
* Fixed rendering issues in render_multi_url (issue 11021)
|
|
||||||
* Fixed proper event sequence in page_events example (issue 11028)
|
|
||||||
* Miscellanous tweaks (issue 11082)
|
|
||||||
|
|
||||||
2013-03-02: Version 1.8.2
|
|
||||||
|
|
||||||
Critical bug fixes:
|
|
||||||
|
|
||||||
* Fixed possible PDF error due to invalid CreationDate field (issue 663)
|
|
||||||
* Fixed crash when uploading non existing files (issue 941)
|
|
||||||
* Fixed possible crash when accessing inline frames (issue 947)
|
|
||||||
* Extended SSL ignore setting to synchronous XHR (issue 985)
|
|
||||||
* Fixed incorrect date handling in the cookies (issue 1068)
|
|
||||||
|
|
||||||
2013-01-06: Version 1.8.1
|
|
||||||
|
|
||||||
Critical bug fix:
|
|
||||||
|
|
||||||
* Mac OS X: Fix possible crash when using some TrueType fonts (issue 690)
|
|
||||||
|
|
||||||
2012-12-21: Version 1.8.0 "Blue Winter Rose"
|
|
||||||
|
|
||||||
New features
|
|
||||||
|
|
||||||
* Integrated GhostDriver as the WebDriver implementation (issue 49)
|
|
||||||
* Added an option to specify the SSL protocol (issue 174)
|
|
||||||
* Added encoding support for WebServer's response (issue 505)
|
|
||||||
* Added process ID (PID) to the System module (issue 769)
|
|
||||||
* Added properties to obtain page and frame title (issue 799)
|
|
||||||
* Added page navigation methods (issue 808)
|
|
||||||
* Added support for modifier keys in keyboard events (issue 835)
|
|
||||||
* Added onFilePicker callback for more generic file upload API (issue 843)
|
|
||||||
* Added the ability to set the page content and location (issue 909)
|
|
||||||
|
|
||||||
Improvements
|
|
||||||
|
|
||||||
* Fixed date parsing in ISO8601 format (issue 187, 267)
|
|
||||||
* Fixed window.location (issue 530, 632)
|
|
||||||
* Deregistered multiple callback handler (issue 807)
|
|
||||||
* Fixed sending of double-click events (issue 848)
|
|
||||||
* Increases maximum number of redirects (issue 849)
|
|
||||||
* Fixed keycodes sent for lowercase characters (issue 852)
|
|
||||||
* Fixed a regression in table row page break (issue 880)
|
|
||||||
* Completed the CoffeeScript version of the examples (issue 907)
|
|
||||||
* Updated Qt to version 4.8.4 (issue 918)
|
|
||||||
* Fixed potential hang in some example scripts (issue 922)
|
|
||||||
|
|
||||||
2012-09-22: Version 1.7.0 "Blazing Star"
|
|
||||||
|
|
||||||
New features
|
|
||||||
|
|
||||||
* Added a module system modelled after CommonJS/Node.js (issue 47)
|
|
||||||
* Added support for window pop-up (issue 151)
|
|
||||||
* Static build on Linux (issue 413)
|
|
||||||
* Added run-time detection of SSL support (issue 484)
|
|
||||||
* Added more events support (issue 492, 712)
|
|
||||||
* Added support for disabling automatic proxy detection (issue 580)
|
|
||||||
* Provided page closing callback (issue 678)
|
|
||||||
* Added methods to access URL, frames URL, frame Content (issue 758)
|
|
||||||
* Added more cookies-related API (issue 761)
|
|
||||||
|
|
||||||
Improvements
|
|
||||||
|
|
||||||
* Refactored command-line options handling (issue 55)
|
|
||||||
* Improved the workflow for producing release builds (issue 599)
|
|
||||||
* Improved cookies API and implementation (issue 603, 761)
|
|
||||||
* Improved frame switching API (issue 654)
|
|
||||||
* Fixed iframe handling regression (issue 683)
|
|
||||||
* Fixed OS version number with Windows 8 and Mountain Lion (issue 684, 688)
|
|
||||||
* Fixed HAR navigation info in the netsniff example (issue 733)
|
|
||||||
* Fixed compile warnings with Visual Studio (issue 744)
|
|
||||||
* Removed hacks for static linking on Windows (issue 753)
|
|
||||||
* Added ICO image handling on Windows (issue 779)
|
|
||||||
* Fixed font antialiasing on Windows (issue 785)
|
|
||||||
* Improved Jasmine test runner for Jasmine 1.2 (issue 792)
|
|
||||||
|
|
||||||
2012-07-22: Version 1.6.1
|
|
||||||
|
|
||||||
Bug fixes
|
|
||||||
|
|
||||||
* Don't build the deploy in debug mode (issue 599)
|
|
||||||
* Fixed building on Windows (issue 424)
|
|
||||||
* Fixed remote inspector when building statically (issue 430)
|
|
||||||
|
|
||||||
2012-06-20: Version 1.6.0 "Lavender"
|
|
||||||
|
|
||||||
New features
|
|
||||||
|
|
||||||
* Added support for passing arguments to WebPage's evaluate (issue 132)
|
|
||||||
* Added callbacks for JavaScript onConfirm and onPrompt (issue 133)
|
|
||||||
* Added stack trace when error occurs (issue 166)
|
|
||||||
* Added support for local storage path and quota (issue 300)
|
|
||||||
* Added initial support for cookies handling (issue 354)
|
|
||||||
* Added support for header footer when printing the page (issue 410, 512)
|
|
||||||
* Added headers support in the loading request (issue 452)
|
|
||||||
* Added support to render the web page as base64-encoded string (issue 547)
|
|
||||||
* Added hooks for navigation event (issue 562)
|
|
||||||
* Added command-line option to show debug messages (issue 575)
|
|
||||||
* Added support for the zoom factor for web page rendering (issue 579)
|
|
||||||
* Added crash reporter for Mac OS X and Linux, based on Google Breakpad (issue 576)
|
|
||||||
* Added 'os' object to the system module (issue 585)
|
|
||||||
* Added support for asynchronous evaluation (issue 593)
|
|
||||||
|
|
||||||
Improvements
|
|
||||||
|
|
||||||
* Fixed remote debugging to work on Mac OS X and Windows (issue 430)
|
|
||||||
* Fixed web server getting the dropped connection for empty response (issue 451)
|
|
||||||
* Fixed text rendered as boxes (squares) on headless Linux (issue 460)
|
|
||||||
* Updated Qt to version 4.8.2 (issue 495)
|
|
||||||
* Updated CoffeeScript compiler to version 1.3.3 (issue 496)
|
|
||||||
* Fixed the build script to detect and use MAKEFLAGS (issue 503)
|
|
||||||
* Fixed the build script to properly pass Qt config flags (issue 507)
|
|
||||||
* Changed Info.plist to be embedded in Mac OS X executable (issue 528)
|
|
||||||
* Fixed wrong module require in the imagebin example (issue 536)
|
|
||||||
* Fixed example scripts to exit with the right exit code (issue 544)
|
|
||||||
* Fixed build failure with glib 2.31.0+ (issue 559)
|
|
||||||
* Fixed error handler failures in some cases (issue 589)
|
|
||||||
* Fixed Twitter-related examples to work with the new site (issue 609)
|
|
||||||
|
|
||||||
2012-03-20: Version 1.5.0 "Ghost Flower"
|
|
||||||
|
|
||||||
New features
|
|
||||||
|
|
||||||
* Added interactive mode, also known as REPL (issue 252)
|
|
||||||
* Added setting for web security, to allow cross domain XHR (issue 28)
|
|
||||||
* Added error handler for WebPage object (issue 166)
|
|
||||||
* Added support for custom HTTP header in the network request (issue 77)
|
|
||||||
* Added support for read write encoding in the file system module (issue 367)
|
|
||||||
* Added remote debugging support on Linux (issue 6)
|
|
||||||
* Added support for proxy authentication (issue 105)
|
|
||||||
* Added System module, to retrieve environment variables (issue 271) and arguments (issue 276)
|
|
||||||
* Added fs.readLink function (issue 329)
|
|
||||||
* Added support for reading and writing binary data (issue 400)
|
|
||||||
* Added support to retrieve request data in the WebServer? module (issue 340)
|
|
||||||
* Added support for individual top/bottom/left/right print margins (issue 388)
|
|
||||||
* Added command-line option --help (issue 347)
|
|
||||||
* Added short command-line options -v and -h (issue 408)
|
|
||||||
* Removed support for Flash and other plugins (issue 418)
|
|
||||||
|
|
||||||
Bug fixes
|
|
||||||
|
|
||||||
* Fixed multiple console.log arguments (issue 36)
|
|
||||||
* Fixed file upload (issue 307)
|
|
||||||
* Fixed the web server instance to be asynchronous (issue 326) and still support Keep Alive (issue 416)
|
|
||||||
* Workaround Qt 4.8.0 crash due to empty URL scheme (issue 365)
|
|
||||||
* Fixed a Content-Type problem where POST does not work (issue 337)
|
|
||||||
* Fixed reading body request in the web server even without specific Content-Type (issue 439)
|
|
||||||
* Fixed Jasmine test runner with Jasmine 1.1 (issue 402)
|
|
||||||
* Fixed request URL formatting in the web server (issue 437)
|
|
||||||
* Don't display debugging and warning messages (issue 323)
|
|
||||||
|
|
||||||
2011-12-31: Version 1.4.1
|
|
||||||
|
|
||||||
Bug fixes
|
|
||||||
|
|
||||||
* Fix setting the proxy type (issue 266)
|
|
||||||
* Workaround for file upload regression (issue 307)
|
|
||||||
* Fix extraneous messsages in non-debug mode (issue 323)
|
|
||||||
|
|
||||||
2011-12-22: Version 1.4.0 "Glory of the Snow"
|
2011-12-22: Version 1.4.0 "Glory of the Snow"
|
||||||
|
|
||||||
|
|
59
README.md
59
README.md
|
@ -1,46 +1,33 @@
|
||||||
# [PhantomJS](http://phantomjs.org) - Scriptable Headless WebKit
|
PhantomJS ([www.phantomjs.org](http://phantomjs.org)) is a headless WebKit with JavaScript API.
|
||||||
|
|
||||||
PhantomJS ([www.phantomjs.org](http://phantomjs.org)) is a headless WebKit scriptable with JavaScript. It is used by hundreds of [developers](http://phantomjs.org/buzz.html) and dozens of [organizations](http://phantomjs.org/users.html) for web-related development workflow.
|
It has **fast** and **native** support for DOM handling, CSS selector, JSON, Canvas, and SVG.
|
||||||
|
|
||||||
The latest [stable release](http://phantomjs.org/release-2.0.html) is version 2.0.
|
PhantomJS is cross-platform, it can be compiled for Linux, Windows, FreeBSD, and Mac OS X.
|
||||||
|
Refer to the [build instructions](http://code.google.com/p/phantomjs/wiki/BuildInstructions)
|
||||||
|
for details.
|
||||||
|
|
||||||
**Note**: Please **do not** create a GitHub pull request **without** reading the [Contribution Guide](https://github.com/ariya/phantomjs/blob/master/CONTRIBUTING.md) first. Failure to do so may result in the rejection of the pull request.
|
**Note**: If you are on Mac OS X, [read the notice](http://code.google.com/p/phantomjs/wiki/BuildInstructions#Mac_OS_X)
|
||||||
|
before you start using `brew` or `port` to install Qt and/or PhantomJS.
|
||||||
|
|
||||||
## Use Cases
|
PhantomJS scripts can be written in JavaScript or [CoffeeScript](http://jashkenas.github.com/coffee-script/).
|
||||||
|
|
||||||
- **Headless web testing**. Lightning-fast testing without the browser is now possible! Various [test frameworks](http://phantomjs.org/headless-testing.html) such as Jasmine, Capybara, QUnit, Mocha, WebDriver, YUI Test, BusterJS, FuncUnit, Robot Framework, and many others are supported.
|
See also [quick start guide](http://code.google.com/p/phantomjs/wiki/QuickStart)
|
||||||
- **Page automation**. [Access and manipulate](http://phantomjs.org/page-automation.html) web pages with the standard DOM API, or with usual libraries like jQuery.
|
and more [advanced examples](http://code.google.com/p/phantomjs/wiki/ServiceIntegration)
|
||||||
- **Screen capture**. Programmatically [capture web contents](http://phantomjs.org/screen-capture.html), including CSS, SVG and Canvas. Build server-side web graphics apps, from a screenshot service to a vector chart rasterizer.
|
which show various PhantomJS scripts, covering:
|
||||||
- **Network monitoring**. Automate performance analysis, track [page loading](http://phantomjs.org/network-monitoring.html) and export as standard HAR format.
|
|
||||||
|
|
||||||
## Features
|
* getting driving direction
|
||||||
|
* showing weather forecast conditions
|
||||||
|
* finding pizza in New York
|
||||||
|
* looking up approximate location based on IP address
|
||||||
|
* pulling the list of seasonal food
|
||||||
|
* running regression tests from command line
|
||||||
|
* producing PDF version of a Wikipedia article
|
||||||
|
* rasterizing SVG to image
|
||||||
|
|
||||||
- **Multiplatform**, available on major operating systems: Windows, Mac OS X, Linux, and other Unices.
|
Do not forget to consult the concise [API Reference](http://code.google.com/p/phantomjs/wiki/Interface).
|
||||||
- **Fast and native implementation** of web standards: DOM, CSS, JavaScript, Canvas, and SVG. No emulation!
|
|
||||||
- **Pure headless (no X11) on Linux**, ideal for continuous integration systems. Also runs on Amazon EC2, Heroku, and Iron.io.
|
|
||||||
- **Easy to install**: [Download](http://phantomjs.org/download.html), unpack, and start having fun in just 5 minutes.
|
|
||||||
|
|
||||||
## Ecosystem
|
PhantomJS is based on [Qt](http://qt.nokia.com). There are two implementations, using C++ and Python.
|
||||||
|
|
||||||
PhantomJS needs not be used only as a stand-alone tool. Check also some excellent related projects:
|
|
||||||
|
|
||||||
- [CasperJS](http://casperjs.org) enables easy navigation scripting and common high-level testing.
|
|
||||||
- [Poltergeist](https://github.com/jonleighton/poltergeist) allows running Capybara tests headlessly.
|
|
||||||
- [Guard::Jasmine](https://github.com/netzpirat/guard-jasmine) automatically tests Jasmine specs on Rails when files are modified.
|
|
||||||
- [GhostDriver](http://github.com/detro/ghostdriver/) complements Selenium tests with a PhantomJS WebDriver implementation.
|
|
||||||
- [PhantomRobot](https://github.com/datakurre/phantomrobot) runs Robot Framework acceptance tests in the background via PhantomJS.
|
|
||||||
- [Mocha-PhantomJS](https://github.com/metaskills/mocha-phantomjs) run Mocha tests using PhantomJS.
|
|
||||||
|
|
||||||
and many others [related projects](http://phantomjs.org/related-projects.html).
|
|
||||||
|
|
||||||
## Questions?
|
|
||||||
|
|
||||||
- Explore the complete [documentation](http://phantomjs.org/documentation/).
|
|
||||||
- Read tons of [user articles](http://phantomjs.org/buzz.html) on using PhantomJS.
|
|
||||||
- Join the [mailing-list](http://groups.google.com/group/phantomjs) and discuss with other PhantomJS fans.
|
|
||||||
|
|
||||||
PhantomJS is free software/open source, and is distributed under the [BSD license](http://opensource.org/licenses/BSD-3-Clause). It contains third-party code, see the included `third-party.txt` file for the license information on third-party code.
|
|
||||||
|
|
||||||
PhantomJS is created and maintained by [Ariya Hidayat](http://ariya.ofilabs.com/about) (Twitter: [@ariyahidayat](http://twitter.com/ariyahidayat)), with the help of [many contributors](https://github.com/ariya/phantomjs/contributors). Follow the official Twitter stream [@PhantomJS](http://twitter.com/PhantomJS) to get the frequent development updates.
|
|
||||||
|
|
||||||
|
The latest [stable release](http://code.google.com/p/phantomjs/wiki/ReleaseNotes) is version 1.4 ("Glory of the Snow").
|
||||||
|
|
||||||
|
If you want to contribute, please read the [Contribution Guide](http://code.google.com/p/phantomjs/wiki/ContributionGuide).
|
||||||
|
|
128
build.cmd
128
build.cmd
|
@ -1,128 +0,0 @@
|
||||||
@echo off
|
|
||||||
SETLOCAL EnableExtensions EnableDelayedExpansion
|
|
||||||
|
|
||||||
set BUILD_TYPE=release
|
|
||||||
if /i "%1" == "debug" (
|
|
||||||
SET BUILD_TYPE=debug
|
|
||||||
)
|
|
||||||
set ROOT_DIR=%CD%
|
|
||||||
set 3RD_PARTY_LIBRARIES_REPO_URL=https://github.com/Vitallium/phantomjs-3rdparty-win
|
|
||||||
set 3RD_PARTY_LIBRARIES_REPO_BRANCH=msvc2013
|
|
||||||
|
|
||||||
if /i BUILD_TYPE == "debug" (
|
|
||||||
set 3RD_PARTY_LIBRARIES_REPO_BRANCH=msvc2013_debug
|
|
||||||
)
|
|
||||||
|
|
||||||
set BUILD_DATESTAMP=%date:~-4,4%%date:~-7,2%%date:~-10,2%
|
|
||||||
set BUILD_TIMESTAMP=%time:~-11,2%%time:~-8,2%
|
|
||||||
|
|
||||||
:: replace leading space with 0
|
|
||||||
set BUILD_TIMESTAMP=%BUILD_TIMESTAMP: =0%
|
|
||||||
set QT_LOG_FILE=!ROOT_DIR!\build_qt_!BUILD_DATESTAMP!-!BUILD_TIMESTAMP!.log
|
|
||||||
set WEBKIT_LOG_FILE=!ROOT_DIR!\build_webkit_!BUILD_DATESTAMP!_!BUILD_TIMESTAMP!.log
|
|
||||||
set PHANTOMJS_LOG_FILE=!ROOT_DIR!\build_phantomjs_!BUILD_DATESTAMP!_!BUILD_TIMESTAMP!.log
|
|
||||||
set MAKE_TOOL=nmake
|
|
||||||
|
|
||||||
echo:
|
|
||||||
echo Build type: !BUILD_TYPE!
|
|
||||||
call :build
|
|
||||||
ENDLOCAL
|
|
||||||
|
|
||||||
@exit /B 0
|
|
||||||
|
|
||||||
rem ========================================================================================================
|
|
||||||
:build
|
|
||||||
SETLOCAL EnableExtensions EnableDelayedExpansion
|
|
||||||
set _3RDPARTY=!ROOT_DIR!\src\qt\3rdparty
|
|
||||||
|
|
||||||
for %%X in (git.exe) do (set GIT_FOUND=%%~$PATH:X)
|
|
||||||
if defined GIT_FOUND (
|
|
||||||
echo.
|
|
||||||
echo GIT found. Getting 3rd party libraries.
|
|
||||||
if not exist !_3RDPARTY! call git clone -b !3RD_PARTY_LIBRARIES_REPO_BRANCH! !3RD_PARTY_LIBRARIES_REPO_URL! !_3RDPARTY!
|
|
||||||
) else (
|
|
||||||
ECHO.
|
|
||||||
CALL :exitB "Git is missing! Can't proceed. Please install Git."
|
|
||||||
GOTO :eof
|
|
||||||
)
|
|
||||||
|
|
||||||
:: prepare 3rdparty libraries
|
|
||||||
:: setup INCLUDE and LIB environment variables
|
|
||||||
:: OpenSSL
|
|
||||||
set OPENSSL_DIR=!_3RDPARTY!\openssl
|
|
||||||
set OPENSSL_LIB=!OPENSSL_DIR!\lib
|
|
||||||
set OPENSSL_INCLUDE=!OPENSSL_DIR!\include
|
|
||||||
|
|
||||||
:: ICU
|
|
||||||
set ICU_DIR=!_3RDPARTY!\libicu
|
|
||||||
set ICU_LIB=!ICU_DIR!\lib
|
|
||||||
set ICU_INCLUDE=!ICU_DIR!\include
|
|
||||||
|
|
||||||
:: libxml
|
|
||||||
set LIBXML_DIR=!_3RDPARTY!\libxml
|
|
||||||
set LIBXML_LIB=!LIBXML_DIR!\lib
|
|
||||||
set LIBXML_INCLUDE=!LIBXML_DIR!\include\libxml2
|
|
||||||
|
|
||||||
:: sqlite
|
|
||||||
set SQLITE3SRCDIR=!ROOT_DIR!\src\qt\qtbase\src\3rdparty\sqlite
|
|
||||||
|
|
||||||
set LIB=!OPENSSL_LIB!;!ICU_LIB!;!LIBXML_LIB!;%LIB%
|
|
||||||
set INCLUDE=!OPENSSL_INCLUDE!;!ICU_INCLUDE!;!LIBXML_INCLUDE!;%INCLUDE%
|
|
||||||
set PATH=!_3RDPARTY!\gnuwin32\bin;%PATH%
|
|
||||||
|
|
||||||
echo LIB: %LIB%
|
|
||||||
echo INCLUDE: %INCLUDE%
|
|
||||||
|
|
||||||
for %%X in (jom.exe) do (set JOMFOUND=%%~$PATH:X)
|
|
||||||
if defined JOMFOUND (
|
|
||||||
set MAKE_TOOL=jom
|
|
||||||
) else (
|
|
||||||
set MAKE_TOOL=nmake
|
|
||||||
)
|
|
||||||
|
|
||||||
pushd !ROOT_DIR!\src\qt
|
|
||||||
call preconfig.cmd !BUILD_TYPE! 2>&1 >> !QT_LOG_FILE!
|
|
||||||
popd
|
|
||||||
|
|
||||||
set PATH=!ROOT_DIR!\src\qt\qtbase\bin;%PATH%
|
|
||||||
for %%X in (qmake.exe) do (set QMAKE_FOUND=%%~$PATH:X)
|
|
||||||
if defined QMAKE_FOUND (
|
|
||||||
echo.
|
|
||||||
echo qmake found. Building QtWebkit
|
|
||||||
) else (
|
|
||||||
ECHO.
|
|
||||||
CALL :exitB "qmake.exe is missing! Can't proceed."
|
|
||||||
GOTO :eof
|
|
||||||
)
|
|
||||||
|
|
||||||
pushd !ROOT_DIR!\src\qt\qtwebkit
|
|
||||||
call qmake.exe
|
|
||||||
%MAKE_TOOL% %BUILD_TYPE% 2>&1 >> !WEBKIT_LOG_FILE!
|
|
||||||
popd
|
|
||||||
|
|
||||||
pushd !ROOT_DIR!\src
|
|
||||||
call qmake.exe
|
|
||||||
%MAKE_TOOL% %BUILD_TYPE% 2>&1 >> !PHANTOMJS_LOG_FILE!
|
|
||||||
popd
|
|
||||||
if EXIST !ROOT_DIR!\bin\phantomjs.exe (
|
|
||||||
echo.
|
|
||||||
echo Build has finished
|
|
||||||
echo.
|
|
||||||
) else (
|
|
||||||
echo:
|
|
||||||
echo Unable to find phantomjs.exe. Please, check log files:
|
|
||||||
echo Qt: !QT_LOG_FILE!
|
|
||||||
echo Webkit: !WEBKIT_LOG_FILE!
|
|
||||||
echo PhantomJS: !PHANTOMJS_LOG_FILE!
|
|
||||||
echo:
|
|
||||||
)
|
|
||||||
EXIT /b
|
|
||||||
|
|
||||||
rem ========================================================================================================
|
|
||||||
:: %1 an error message
|
|
||||||
:exitB
|
|
||||||
echo:
|
|
||||||
echo Error: %1
|
|
||||||
echo:
|
|
||||||
echo Contact vitaliy.slobodin@gmail.com
|
|
||||||
@exit /B 0
|
|
82
build.sh
82
build.sh
|
@ -1,82 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
COMPILE_JOBS=1
|
|
||||||
MAKEFLAGS_JOBS=''
|
|
||||||
|
|
||||||
if [[ "$MAKEFLAGS" != "" ]]; then
|
|
||||||
MAKEFLAGS_JOBS=$(echo $MAKEFLAGS | egrep -o '\-j[0-9]+' | egrep -o '[0-9]+')
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$MAKEFLAGS_JOBS" != "" ]]; then
|
|
||||||
# user defined number of jobs in MAKEFLAGS, re-use that number
|
|
||||||
COMPILE_JOBS=$MAKEFLAGS_JOBS
|
|
||||||
elif [[ $OSTYPE = darwin* ]]; then
|
|
||||||
# We only support modern Mac machines, they are at least using
|
|
||||||
# hyperthreaded dual-core CPU.
|
|
||||||
COMPILE_JOBS=4
|
|
||||||
elif [[ $OSTYPE == freebsd* ]]; then
|
|
||||||
COMPILE_JOBS=`sysctl -n hw.ncpu`
|
|
||||||
else
|
|
||||||
CPU_CORES=`grep -c ^processor /proc/cpuinfo`
|
|
||||||
if [[ "$CPU_CORES" -gt 1 ]]; then
|
|
||||||
COMPILE_JOBS=$CPU_CORES
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$COMPILE_JOBS" -gt 8 ]]; then
|
|
||||||
# Safety net.
|
|
||||||
COMPILE_JOBS=8
|
|
||||||
fi
|
|
||||||
|
|
||||||
SILENT=
|
|
||||||
|
|
||||||
until [[ -z "$1" ]]; do
|
|
||||||
case $1 in
|
|
||||||
(--qmake-args)
|
|
||||||
shift
|
|
||||||
QMAKE_ARGS=$1
|
|
||||||
shift;;
|
|
||||||
(--jobs)
|
|
||||||
shift
|
|
||||||
COMPILE_JOBS=$1
|
|
||||||
shift;;
|
|
||||||
(--silent)
|
|
||||||
SILENT=silent
|
|
||||||
shift;;
|
|
||||||
|
|
||||||
"--help")
|
|
||||||
cat <<EOF
|
|
||||||
Usage: $0 [--jobs NUM]
|
|
||||||
|
|
||||||
--silent Produce less verbose output.
|
|
||||||
--jobs NUM How many parallel compile jobs to use.
|
|
||||||
Defaults to the number of CPU cores you have,
|
|
||||||
with a maximum of 8.
|
|
||||||
EOF
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unrecognised option: $1" >&2
|
|
||||||
exit 1;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
|
|
||||||
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
|
|
||||||
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
|
|
||||||
|
|
||||||
echo "System architecture... ($UNAME_SYSTEM $UNAME_RELEASE $UNAME_MACHINE)"
|
|
||||||
|
|
||||||
export QMAKE=qmake
|
|
||||||
# some Linux distros (e.g. Debian) allow you to parallel-install
|
|
||||||
# Qt4 and Qt5, using this environment variable to declare which
|
|
||||||
# one you want
|
|
||||||
export QT_SELECT=qt5
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo "Building main PhantomJS application..."
|
|
||||||
echo
|
|
||||||
$QMAKE $QMAKE_ARGS
|
|
||||||
make -j$COMPILE_JOBS
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
phantomjs (1.3-1~git20110703) unstable; urgency=low
|
||||||
|
|
||||||
|
* Initial release.
|
||||||
|
|
||||||
|
-- Dennis Kaarsemaker <dennis@kaarsemaker.net> Sun, 03 Jul 2011 20:45:52 +0200
|
|
@ -0,0 +1 @@
|
||||||
|
7
|
|
@ -0,0 +1,24 @@
|
||||||
|
Source: phantomjs
|
||||||
|
Section: python
|
||||||
|
Priority: extra
|
||||||
|
Maintainer: Dennis Kaarsemaker <dennis@kaarsemaker.net>
|
||||||
|
Build-Depends: debhelper (>= 7), libqt4-dev (>= 4.6), libqtwebkit-dev, qt4-qmake, python-support (>= 0.6.4), python-all-dev (>= 2.5), python-qt4-dev, python-qt4
|
||||||
|
Standards-Version: 3.8.4
|
||||||
|
XS-Python-Version: >= 2.6
|
||||||
|
Vcs-Git: http://github.com/ariya/phantomjs
|
||||||
|
|
||||||
|
Package: phantomjs
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||||
|
Description: phantomjs - minimalistic headless WebKit-based JavaScript-driven tool
|
||||||
|
PhantomJS is a minimalistic, headless, WebKit-based, JavaScript-driven tool.
|
||||||
|
PhantomJs has native support for different web technologies: DOM handling,
|
||||||
|
CSS selector, JSON, Canvas, SVG, and of course JavaScript.
|
||||||
|
|
||||||
|
Package: python-pyphantomjs
|
||||||
|
Architecture: all
|
||||||
|
Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, python-qt4, python-argparse
|
||||||
|
Description: phantomjs - minimalistic headless WebKit-based JavaScript-driven tool
|
||||||
|
PhantomJS is a minimalistic, headless, WebKit-based, JavaScript-driven tool.
|
||||||
|
PhantomJs has native support for different web technologies: DOM handling,
|
||||||
|
CSS selector, JSON, Canvas, SVG, and of course JavaScript.
|
|
@ -0,0 +1,35 @@
|
||||||
|
Format-Specification: http://anonscm.debian.org/viewvc/dep/web/deps/dep5.mdwn?revision=174&view=co&pathrev=174
|
||||||
|
Name: phantomjs
|
||||||
|
Maintainer: Dennis Kaarsemaker <dennis@kaarsemaker.net>
|
||||||
|
Source: http://github.com/ariya/phantomjs
|
||||||
|
|
||||||
|
Copyright: 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
|
||||||
|
License: BSD-3-clause
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2011 Dennis Kaarsemaker <dennis@kaarsemaker.net>
|
||||||
|
License: BSD-3-clause
|
||||||
|
|
||||||
|
License: BSD-3-clause
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
.
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the <organization> nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,2 @@
|
||||||
|
README.md
|
||||||
|
examples
|
|
@ -0,0 +1 @@
|
||||||
|
debian/tmp/usr/bin/phantomjs
|
|
@ -0,0 +1 @@
|
||||||
|
python/README.md
|
|
@ -0,0 +1,2 @@
|
||||||
|
debian/tmp/usr/bin/pyphantomjs
|
||||||
|
debian/tmp/usr/lib
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@
|
||||||
|
|
||||||
|
override_dh_auto_build:
|
||||||
|
qmake-qt4
|
||||||
|
$(MAKE)
|
||||||
|
cd python && python setup.py build
|
||||||
|
|
||||||
|
override_dh_auto_install:
|
||||||
|
$(MAKE) install
|
||||||
|
mkdir -p debian/tmp/usr/bin
|
||||||
|
cp bin/* debian/tmp/usr/bin
|
||||||
|
cd python && python setup.py install --root=../debian/tmp --install-layout=deb
|
||||||
|
|
||||||
|
override_dh_auto_clean:
|
||||||
|
if [ -f Makefile ]; then $(MAKE) distclean; fi
|
||||||
|
cd python && python setup.py clean
|
|
@ -0,0 +1 @@
|
||||||
|
1.0
|
|
@ -1,2 +0,0 @@
|
||||||
.vagrant
|
|
||||||
/brandelf
|
|
|
@ -1,60 +0,0 @@
|
||||||
Packaging PhantomJS
|
|
||||||
===================
|
|
||||||
|
|
||||||
This directory contains various scripts to assist with making PhantomJS
|
|
||||||
packages.
|
|
||||||
|
|
||||||
Packaging for Linux
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Linux building/packaging is best done in a virtual machine to ensure
|
|
||||||
isolation and clean state. This is also necessary to build for different
|
|
||||||
architectures.
|
|
||||||
|
|
||||||
We use [Vagrant](http://vagrantup.com/) to help with this. Please see
|
|
||||||
the [Vagrant
|
|
||||||
documentation](http://vagrantup.com/v1/docs/getting-started/index.html)
|
|
||||||
for instructions on how to install VirtualBox and Vagrant.
|
|
||||||
|
|
||||||
Once you have Vagrant installed, building should be as simple as
|
|
||||||
running:
|
|
||||||
|
|
||||||
$ export PHANTOMJS_VERSION=1.6.0 # change as necessary
|
|
||||||
$ vagrant up $ARCH
|
|
||||||
|
|
||||||
Where $ARCH is either `i686` or `x86_64`.
|
|
||||||
|
|
||||||
This runs the `provision_vm.sh` script, which installs the necessary
|
|
||||||
dependencies, checks out a fresh copy of the PhantomJS repository,
|
|
||||||
switches to the relevant tag, builds and packages the software and the
|
|
||||||
associated debugging symbols tarball, and copies the tarballs out of the
|
|
||||||
VM onto your host machine.
|
|
||||||
|
|
||||||
If it runs successfully, you will see the tarballs in this directory,
|
|
||||||
ready for upload.
|
|
||||||
|
|
||||||
If there are any problems, you can re-run the script with:
|
|
||||||
|
|
||||||
$ vagrant provision $ARCH
|
|
||||||
|
|
||||||
Or SSH into the VM:
|
|
||||||
|
|
||||||
$ vagrant ssh $ARCH
|
|
||||||
|
|
||||||
Once you're done, you can destroy the VM with:
|
|
||||||
|
|
||||||
$ vagrant destroy $ARCH
|
|
||||||
|
|
||||||
If you need to build a new version, you should destroy the VM and start
|
|
||||||
again to ensure a clean state. (Or SSH in and do a git clean.)
|
|
||||||
|
|
||||||
Packaging for OS X
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Run `deploy/build-and-package.sh`. That's it.
|
|
||||||
|
|
||||||
However, if you have previously built the sources in release mode, you
|
|
||||||
should clean your tree to make sure all the debugging symbols gets
|
|
||||||
compiled:
|
|
||||||
|
|
||||||
$ make clean && cd src/qt && make clean && cd ../..
|
|
|
@ -1,42 +0,0 @@
|
||||||
# -*- mode: ruby -*-
|
|
||||||
# vi: set ft=ruby :
|
|
||||||
|
|
||||||
unless ENV['PHANTOMJS_VERSION']
|
|
||||||
STDERR.puts 'Please specify PhantomJS version in the PHANTOMJS_VERSION environment variable.'
|
|
||||||
STDERR.puts '(This can be any git ref, e.g. "1.5.0", "master", "origin/1.5", etc.)'
|
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
|
|
||||||
Vagrant::Config.run do |config|
|
|
||||||
config.vm.define :i686 do |c|
|
|
||||||
c.vm.box_url = "https://opscode-vm.s3.amazonaws.com/vagrant/boxes/opscode-centos-5.8-i386.box"
|
|
||||||
c.vm.box = "centos_58_32bit"
|
|
||||||
c.vm.customize ["modifyvm", :id, "--ostype", "RedHat"]
|
|
||||||
end
|
|
||||||
|
|
||||||
config.vm.define :x86_64 do |c|
|
|
||||||
c.vm.box_url = "https://opscode-vm.s3.amazonaws.com/vagrant/boxes/opscode-centos-5.8.box"
|
|
||||||
c.vm.box = "centos_58_64bit"
|
|
||||||
c.vm.customize ["modifyvm", :id, "--ostype", "RedHat_64"]
|
|
||||||
end
|
|
||||||
|
|
||||||
config.vm.define :lucid32 do |c|
|
|
||||||
c.vm.box_url = "http://files.vagrantup.com/lucid32.box"
|
|
||||||
c.vm.box = "lucid32"
|
|
||||||
end
|
|
||||||
|
|
||||||
config.vm.define :lucid64 do |c|
|
|
||||||
c.vm.box_url = "http://files.vagrantup.com/lucid64.box"
|
|
||||||
c.vm.box = "lucid64"
|
|
||||||
end
|
|
||||||
|
|
||||||
config.vm.provision :shell do |s|
|
|
||||||
s.path = "provision-vm.sh"
|
|
||||||
s.args = ENV['PHANTOMJS_VERSION']
|
|
||||||
end
|
|
||||||
|
|
||||||
# You may wish to tweak these, but be aware that you need quite a lot of
|
|
||||||
# memory for the linking stage.
|
|
||||||
config.vm.customize ["modifyvm", :id, "--memory", 3072]
|
|
||||||
config.vm.customize ["modifyvm", :id, "--cpus", 2]
|
|
||||||
end
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
--- configure 2011-03-29 22:16:21.000000000 -0700
|
||||||
|
+++ configure.new 2011-08-21 22:11:16.000000000 -0700
|
||||||
|
@@ -7160,13 +7160,6 @@ if [ "$CFG_GUI" = "no" ]; then
|
||||||
|
canBuildWebKit="no"
|
||||||
|
fi
|
||||||
|
|
||||||
|
-if [ "$CFG_SHARED" = "no" ]; then
|
||||||
|
- echo
|
||||||
|
- echo "WARNING: Using static linking will disable the WebKit module."
|
||||||
|
- echo
|
||||||
|
- canBuildWebKit="no"
|
||||||
|
-fi
|
||||||
|
-
|
||||||
|
CFG_CONCURRENT="yes"
|
||||||
|
if [ "$canBuildQtConcurrent" = "no" ]; then
|
||||||
|
QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_CONCURRENT"
|
|
@ -1,213 +0,0 @@
|
||||||
/*-
|
|
||||||
* Copyright (c) 2000, 2001 David O'Brien
|
|
||||||
* Copyright (c) 1996 Søren Schmidt
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer
|
|
||||||
* in this position and unchanged.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
//NOTE: commented out to make it compile on linux
|
|
||||||
// __FBSDID("$FreeBSD: src/usr.bin/brandelf/brandelf.c,v 1.25.22.2 2012/03/16 03:22:37 eadler Exp $");
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
//NOTE: changed path to make it compile on linux
|
|
||||||
#include <elf.h>
|
|
||||||
#include <sys/errno.h>
|
|
||||||
#include <err.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
static int elftype(const char *);
|
|
||||||
static const char *iselftype(int);
|
|
||||||
static void printelftypes(void);
|
|
||||||
static void usage(void);
|
|
||||||
|
|
||||||
struct ELFtypes {
|
|
||||||
const char *str;
|
|
||||||
int value;
|
|
||||||
};
|
|
||||||
/* XXX - any more types? */
|
|
||||||
static struct ELFtypes elftypes[] = {
|
|
||||||
{ "FreeBSD", ELFOSABI_FREEBSD },
|
|
||||||
{ "Linux", ELFOSABI_LINUX },
|
|
||||||
{ "Solaris", ELFOSABI_SOLARIS },
|
|
||||||
{ "SVR4", ELFOSABI_SYSV }
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
|
|
||||||
const char *strtype = "FreeBSD";
|
|
||||||
int type = ELFOSABI_FREEBSD;
|
|
||||||
int retval = 0;
|
|
||||||
int ch, change = 0, force = 0, listed = 0;
|
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "f:lt:v")) != -1)
|
|
||||||
switch (ch) {
|
|
||||||
case 'f':
|
|
||||||
if (change)
|
|
||||||
errx(1, "f option incompatible with t option");
|
|
||||||
force = 1;
|
|
||||||
type = atoi(optarg);
|
|
||||||
if (errno == ERANGE || type < 0 || type > 255) {
|
|
||||||
warnx("invalid argument to option f: %s",
|
|
||||||
optarg);
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
printelftypes();
|
|
||||||
listed = 1;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
/* does nothing */
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
if (force)
|
|
||||||
errx(1, "t option incompatible with f option");
|
|
||||||
change = 1;
|
|
||||||
strtype = optarg;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
if (!argc) {
|
|
||||||
if (listed)
|
|
||||||
exit(0);
|
|
||||||
else {
|
|
||||||
warnx("no file(s) specified");
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!force && (type = elftype(strtype)) == -1) {
|
|
||||||
warnx("invalid ELF type '%s'", strtype);
|
|
||||||
printelftypes();
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (argc) {
|
|
||||||
int fd;
|
|
||||||
char buffer[EI_NIDENT];
|
|
||||||
|
|
||||||
if ((fd = open(argv[0], change || force ? O_RDWR : O_RDONLY, 0)) < 0) {
|
|
||||||
warn("error opening file %s", argv[0]);
|
|
||||||
retval = 1;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) {
|
|
||||||
warnx("file '%s' too short", argv[0]);
|
|
||||||
retval = 1;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 ||
|
|
||||||
buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) {
|
|
||||||
warnx("file '%s' is not ELF format", argv[0]);
|
|
||||||
retval = 1;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (!change && !force) {
|
|
||||||
fprintf(stdout,
|
|
||||||
"File '%s' is of brand '%s' (%u).\n",
|
|
||||||
argv[0], iselftype(buffer[EI_OSABI]),
|
|
||||||
buffer[EI_OSABI]);
|
|
||||||
if (!iselftype(type)) {
|
|
||||||
warnx("ELF ABI Brand '%u' is unknown",
|
|
||||||
type);
|
|
||||||
printelftypes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
buffer[EI_OSABI] = type;
|
|
||||||
lseek(fd, 0, SEEK_SET);
|
|
||||||
if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) {
|
|
||||||
warn("error writing %s %d", argv[0], fd);
|
|
||||||
retval = 1;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fail:
|
|
||||||
close(fd);
|
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
(void)fprintf(stderr,
|
|
||||||
"usage: brandelf [-lv] [-f ELF_ABI_number] [-t string] file ...\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
iselftype(int etype)
|
|
||||||
{
|
|
||||||
size_t elfwalk;
|
|
||||||
|
|
||||||
for (elfwalk = 0;
|
|
||||||
elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
|
|
||||||
elfwalk++)
|
|
||||||
if (etype == elftypes[elfwalk].value)
|
|
||||||
return elftypes[elfwalk].str;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
elftype(const char *elfstrtype)
|
|
||||||
{
|
|
||||||
size_t elfwalk;
|
|
||||||
|
|
||||||
for (elfwalk = 0;
|
|
||||||
elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
|
|
||||||
elfwalk++)
|
|
||||||
if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0)
|
|
||||||
return elftypes[elfwalk].value;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
printelftypes(void)
|
|
||||||
{
|
|
||||||
size_t elfwalk;
|
|
||||||
|
|
||||||
fprintf(stderr, "known ELF types are: ");
|
|
||||||
for (elfwalk = 0;
|
|
||||||
elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
|
|
||||||
elfwalk++)
|
|
||||||
fprintf(stderr, "%s(%u) ", elftypes[elfwalk].str,
|
|
||||||
elftypes[elfwalk].value);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
cd `dirname $0`/..
|
|
||||||
|
|
||||||
echo "Building Qt and PhantomJS with debugging symbols. If you have previously" \
|
|
||||||
"built without debugging symbols, you should run:"
|
|
||||||
echo
|
|
||||||
echo " $ git clean -xdff"
|
|
||||||
echo
|
|
||||||
|
|
||||||
# This incantation will cause Qt and WebKit and PhantomJS to all build in "release"
|
|
||||||
# mode, with compiler optimisations, but also with debug symbols. (We will strip the
|
|
||||||
# symbols in package.sh.)
|
|
||||||
CFLAGS=-g CXXFLAGS=-g ./build.sh --confirm --qt-config '-webkit-debug' --qmake-args "QMAKE_CFLAGS=-g QMAKE_CXXFLAGS=-g" || exit 1
|
|
||||||
|
|
||||||
# Package the release tarball
|
|
||||||
rm deploy/*.tar.bz2 2>/dev/null
|
|
||||||
./deploy/package.sh || exit 1
|
|
||||||
|
|
||||||
# Build the dump_syms program for dumping breakpad debugging symbols
|
|
||||||
if [[ $OSTYPE = darwin* ]]; then
|
|
||||||
pushd tools
|
|
||||||
../src/qt/bin/qmake dump-syms-mac.pro && make
|
|
||||||
popd
|
|
||||||
else
|
|
||||||
pushd src/breakpad
|
|
||||||
./configure && make || exit 1
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Dump and package the breakpad debugging symbols...
|
|
||||||
|
|
||||||
./tools/dump-symbols.sh
|
|
||||||
|
|
||||||
version=$(bin/phantomjs --version | sed 's/ /-/' | sed 's/[()]//g')
|
|
||||||
if [[ $OSTYPE = darwin* ]]; then
|
|
||||||
symbols="phantomjs-$version-macosx-symbols"
|
|
||||||
else
|
|
||||||
symbols="phantomjs-$version-linux-$(uname -m)-symbols"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cp -r symbols/ $symbols
|
|
||||||
|
|
||||||
# The minidump_stackwalk program is architecture-specific, so copy the
|
|
||||||
# binary for later use. This means that e.g. a developer on x86_64 can
|
|
||||||
# analyse a crash dump produced by a i686 user.
|
|
||||||
#
|
|
||||||
# We don't yet have a process for building minidump_stackwalk on OS X
|
|
||||||
if [[ $OSTYPE != darwin* ]]; then
|
|
||||||
cp src/breakpad/src/processor/minidump_stackwalk $symbols
|
|
||||||
|
|
||||||
read -r -d '' README <<EOT
|
|
||||||
These are symbols files that can be used to analyse a crash dump
|
|
||||||
produced by the corresponding binary. To generate a crash report,
|
|
||||||
run:
|
|
||||||
|
|
||||||
./minidump_stackwalk /path/to/crash.dmp .
|
|
||||||
EOT
|
|
||||||
|
|
||||||
echo "$README" > $symbols/README
|
|
||||||
fi
|
|
||||||
|
|
||||||
tar -cjf deploy/$symbols.tar.bz2 $symbols
|
|
||||||
rm -r $symbols
|
|
||||||
|
|
||||||
echo "PhantomJS built and packaged:"
|
|
||||||
echo
|
|
||||||
cd deploy
|
|
||||||
ls -1 *.tar.bz2
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
QT_VERSION=0
|
||||||
|
QT_FOLDER=""
|
||||||
|
COMPILE_JOBS=4
|
||||||
|
|
||||||
|
if [ "$1" = "--qt-4.8" ]
|
||||||
|
then
|
||||||
|
echo "Building Qt 4.8"
|
||||||
|
QT_VERSION=4.8
|
||||||
|
QT_FOLDER=Qt-$QT_VERSION
|
||||||
|
QT_URL=git://gitorious.org/qt/qt.git
|
||||||
|
|
||||||
|
echo "Cloning Qt from gitorious into $QT_FOLDER..."
|
||||||
|
if [ ! -d $QT_FOLDER ]
|
||||||
|
then
|
||||||
|
git clone $QT_URL $QT_FOLDER
|
||||||
|
pushd $QT_FOLDER
|
||||||
|
git checkout -b 4.8 origin/4.8
|
||||||
|
else
|
||||||
|
pushd $QT_FOLDER
|
||||||
|
git checkout -f
|
||||||
|
git clean -xdf
|
||||||
|
git checkout 4.8
|
||||||
|
fi
|
||||||
|
|
||||||
|
popd
|
||||||
|
else
|
||||||
|
echo "Building Qt 4.7"
|
||||||
|
|
||||||
|
QT_VERSION=4.7.4
|
||||||
|
QT_FOLDER=Qt-$QT_VERSION
|
||||||
|
QT_TARBALL=qt-everywhere-opensource-src-$QT_VERSION.tar.gz
|
||||||
|
|
||||||
|
# Tip: change this to local/shared mirror
|
||||||
|
QT_URL=http://get.qt.nokia.com/qt/source/$QT_TARBALL
|
||||||
|
|
||||||
|
|
||||||
|
# Step 1: Download Qt source tarball
|
||||||
|
# Note: only if it does not exist yet in the current directory
|
||||||
|
if [ ! -f $QT_TARBALL ]
|
||||||
|
then
|
||||||
|
echo "Downloading Qt $QT_VERSION from Nokia. Please wait..."
|
||||||
|
if ! curl -C - -O -S $QT_URL
|
||||||
|
then
|
||||||
|
echo
|
||||||
|
echo "Fatal error: fail to download from $QT_URL !"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 2: Extract Qt source
|
||||||
|
|
||||||
|
[ -d $QT_FOLDER ] && rm -rf $QT_FOLDER
|
||||||
|
echo "Extracting Qt $QT_VERSION source tarball..."
|
||||||
|
echo
|
||||||
|
tar xzf $QT_TARBALL
|
||||||
|
mv qt-everywhere-opensource-src-$QT_VERSION Qt-$QT_VERSION
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Step 3: Build Qt
|
||||||
|
|
||||||
|
pushd $QT_FOLDER
|
||||||
|
|
||||||
|
EXTRA_FLAGS=""
|
||||||
|
if [ $QT_VERSION = 4.8 ] ; then
|
||||||
|
echo "Patching Qt 4.8"
|
||||||
|
patch -p1 < ../qt48_enable_debugger.patch
|
||||||
|
patch -p1 < ../qt48_fix_inspector.patch
|
||||||
|
patch -p1 < ../qt48_headless_and_pdf_fixes.patch
|
||||||
|
# Build in lighthose mode for an x-less build
|
||||||
|
if [ "$2" = "--headless" ] ; then
|
||||||
|
echo "Building 4.8 in qpa headless mode"
|
||||||
|
EXTRA_FLAGS="-qpa"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Patching Qt 4.7"
|
||||||
|
patch configure ../allow-static-qtwebkit.patch
|
||||||
|
# Qt 4.8 doesn't allow static builds of QtWebkit-2.2
|
||||||
|
EXTRA_FLAGS="-static"
|
||||||
|
fi
|
||||||
|
|
||||||
|
patch -p1 < ../qapplication_skip_qtmenu.patch
|
||||||
|
echo "Building Qt $QT_VERSION. Please wait..."
|
||||||
|
echo
|
||||||
|
./configure -opensource -confirm-license -release -webkit -graphicssystem raster -no-exceptions -no-dbus -no-glib -no-gstreamer -no-stl -no-xmlpatterns -no-phonon -no-multimedia -no-qt3support -no-opengl -no-openvg -no-svg -no-declarative -no-gtkstyle -no-xkb -no-xinput -no-xinerama -no-sm -no-cups -qt-libpng -qt-libjpeg -no-libmng -no-libtiff -D QT_NO_STYLE_CDE -D QT_NO_STYLE_CLEANLOOKS -D QT_NO_STYLE_MOTIF -D QT_NO_STYLE_PLASTIQUE -prefix $PWD -nomake demos -nomake examples -nomake tools -nomake docs -nomake translations $EXTRA_FLAGS
|
||||||
|
make -j$COMPILE_JOBS
|
||||||
|
popd
|
||||||
|
|
||||||
|
|
||||||
|
if [ $QT_VERSION != 4.8 ] ; then
|
||||||
|
# Extra step: copy JavaScriptCore/release, needed for jscore static lib
|
||||||
|
mkdir ../JavaScriptCore
|
||||||
|
cp -rp $QT_FOLDER/src/3rdparty/webkit/JavaScriptCore/release ../JavaScriptCore/
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 4: Build PhantomJS
|
||||||
|
|
||||||
|
echo "Building PhantomJS. Please wait..."
|
||||||
|
echo
|
||||||
|
cd ..
|
||||||
|
[ -f Makefile ] && make distclean
|
||||||
|
deploy/$QT_FOLDER/bin/qmake
|
||||||
|
make -j$COMPILE_JOBS
|
||||||
|
|
||||||
|
# Step 5: Prepare for deployment
|
||||||
|
|
||||||
|
echo "Compressing PhantomJS executable..."
|
||||||
|
echo
|
||||||
|
strip bin/phantomjs
|
||||||
|
if [ `command -v upx` ]; then
|
||||||
|
upx -9 bin/phantomjs
|
||||||
|
else
|
||||||
|
echo "You don't have UPX. Consider installing it to reduce the executable size."
|
||||||
|
fi
|
|
@ -0,0 +1,133 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
QT_VERSION=4.8.0
|
||||||
|
QT_FOLDER=Qt-$QT_VERSION
|
||||||
|
QT_TARBALL=qt-everywhere-opensource-src-$QT_VERSION.tar.gz
|
||||||
|
|
||||||
|
# Tip: change this to local/shared mirror
|
||||||
|
QT_URL=http://get.qt.nokia.com/qt/source/$QT_TARBALL
|
||||||
|
|
||||||
|
COMPILE_JOBS=4
|
||||||
|
|
||||||
|
# Step 1: Download Qt source tarball
|
||||||
|
# Note: only if it does not exist yet in the current directory
|
||||||
|
|
||||||
|
if [ ! -f $QT_TARBALL ]
|
||||||
|
then
|
||||||
|
echo "Downloading Qt $QT_VERSION from Nokia. Please wait..."
|
||||||
|
if ! curl -C - -O -S $QT_URL
|
||||||
|
then
|
||||||
|
echo
|
||||||
|
echo "Fatal error: fail to download from $QT_URL !"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 2: Extract Qt source
|
||||||
|
|
||||||
|
[ -d $QT_FOLDER ] && rm -rf $QT_FOLDER
|
||||||
|
echo "Extracting Qt $QT_VERSION source tarball..."
|
||||||
|
echo
|
||||||
|
tar xzf $QT_TARBALL
|
||||||
|
mv qt-everywhere-opensource-src-$QT_VERSION Qt-$QT_VERSION
|
||||||
|
|
||||||
|
# Step 3: Apply some patches
|
||||||
|
|
||||||
|
cd $QT_FOLDER
|
||||||
|
patch configure ../allow-static-qtwebkit.patch
|
||||||
|
patch -p1 < ../qapplication_skip_qtmenu.patch
|
||||||
|
|
||||||
|
rm -rf src/3rdparty/webkit/Source/WebKit/qt/tests
|
||||||
|
|
||||||
|
# Step 4: Build Qt
|
||||||
|
|
||||||
|
echo "Building Qt $QT_VERSION. Please wait..."
|
||||||
|
echo
|
||||||
|
|
||||||
|
CFG=''
|
||||||
|
|
||||||
|
CFG+=' -opensource' # Use the open-source license
|
||||||
|
CFG+=' -confirm-license' # Silently acknowledge the license confirmation
|
||||||
|
|
||||||
|
CFG+=' -release' # Build only for release (no debugging support)
|
||||||
|
CFG+=' -static' # Compile for static libraries
|
||||||
|
CFG+=' -fast' # Accelerate Makefiles generation
|
||||||
|
CFG+=' -nomake demos' # Don't build with the demos
|
||||||
|
CFG+=' -nomake docs' # Don't generate the documentatio
|
||||||
|
CFG+=' -nomake examples' # Don't build any examples
|
||||||
|
CFG+=' -nomake translations' # Ignore the translations
|
||||||
|
CFG+=' -nomake tools' # Don't built the tools
|
||||||
|
|
||||||
|
CFG+=' -no-exceptions' # Don't use C++ exception
|
||||||
|
CFG+=' -no-stl' # No need for STL compatibility
|
||||||
|
|
||||||
|
# Irrelevant Qt features
|
||||||
|
CFG+=' -no-libmng'
|
||||||
|
CFG+=' -no-libtiff'
|
||||||
|
|
||||||
|
# Unnecessary Qt modules
|
||||||
|
CFG+=' -no-declarative'
|
||||||
|
CFG+=' -no-multimedia'
|
||||||
|
CFG+=' -no-opengl'
|
||||||
|
CFG+=' -no-openvg'
|
||||||
|
CFG+=' -no-phonon'
|
||||||
|
CFG+=' -no-qt3support'
|
||||||
|
CFG+=' -no-script'
|
||||||
|
CFG+=' -no-scripttools'
|
||||||
|
CFG+=' -no-svg'
|
||||||
|
CFG+=' -no-xmlpatterns'
|
||||||
|
|
||||||
|
# Sets the default graphics system to the raster engine
|
||||||
|
CFG+=' -graphicssystem raster'
|
||||||
|
|
||||||
|
# Mac
|
||||||
|
CFG+=' -cocoa' # Cocoa only, ignore Carbon
|
||||||
|
CFG+=' -no-cups' # Disable CUPS support
|
||||||
|
CFG+=' -no-dwarf2'
|
||||||
|
|
||||||
|
# Unix
|
||||||
|
CFG+=' -no-dbus' # Disable D-Bus feature
|
||||||
|
CFG+=' -no-glib' # No need for Glib integration
|
||||||
|
CFG+=' -no-gstreamer' # Turn off GStreamer support
|
||||||
|
CFG+=' -no-gtkstyle' # Disable theming integration with Gtk+
|
||||||
|
CFG+=' -no-sm'
|
||||||
|
CFG+=' -no-xinerama'
|
||||||
|
CFG+=' -no-xkb'
|
||||||
|
|
||||||
|
# Use the bundled libraries, vs system-installed
|
||||||
|
CFG+=' -qt-libjpeg'
|
||||||
|
CFG+=' -qt-libpng'
|
||||||
|
|
||||||
|
# Useless styles
|
||||||
|
CFG+=' -D QT_NO_STYLESHEET'
|
||||||
|
CFG+=' -D QT_NO_STYLE_CDE'
|
||||||
|
CFG+=' -D QT_NO_STYLE_CLEANLOOKS'
|
||||||
|
CFG+=' -D QT_NO_STYLE_MOTIF'
|
||||||
|
|
||||||
|
./configure -prefix $PWD $CFG -arch x86
|
||||||
|
make -j$COMPILE_JOBS
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Extra step to ensure the static libraries are found
|
||||||
|
cp -rp $QT_FOLDER/src/3rdparty/webkit/Source/JavaScriptCore/release/* $QT_FOLDER/lib
|
||||||
|
cp -rp $QT_FOLDER/src/3rdparty/webkit/Source/WebCore/release/* $QT_FOLDER/lib
|
||||||
|
|
||||||
|
# Step 5: Build PhantomJS
|
||||||
|
|
||||||
|
echo "Building PhantomJS. Please wait..."
|
||||||
|
echo
|
||||||
|
cd ..
|
||||||
|
[ -f Makefile ] && make distclean
|
||||||
|
deploy/$QT_FOLDER/bin/qmake
|
||||||
|
make -j$COMPILE_JOBS
|
||||||
|
|
||||||
|
# Step 6: Prepare for deployment
|
||||||
|
|
||||||
|
echo "Compressing PhantomJS executable..."
|
||||||
|
echo
|
||||||
|
strip bin/phantomjs
|
||||||
|
if [ `command -v upx` ]; then
|
||||||
|
upx -9 bin/phantomjs
|
||||||
|
else
|
||||||
|
echo "You don't have UPX. Consider installing it to reduce the executable size."
|
||||||
|
fi
|
|
@ -1,120 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
#
|
|
||||||
# usage: just run this script (after having run build.sh)
|
|
||||||
# and deploy the created tarball to your target machine.
|
|
||||||
#
|
|
||||||
# It creates a phantomjs-$version folder and copies the binary,
|
|
||||||
# example, license etc. together with all shared library dependencies
|
|
||||||
# to that folder. Furthermore brandelf is used to make the lib
|
|
||||||
# and binary compatible with older unix/linux machines that don't
|
|
||||||
# know the new Linux ELF ABI.
|
|
||||||
#
|
|
||||||
|
|
||||||
cd $(dirname $0)
|
|
||||||
|
|
||||||
if [[ ! -f ../bin/phantomjs ]]; then
|
|
||||||
echo "phantomjs was not built yet, please run build.sh first"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$1" = "--bundle-libs" ]]; then
|
|
||||||
bundle_libs=1
|
|
||||||
else
|
|
||||||
bundle_libs=0
|
|
||||||
fi
|
|
||||||
|
|
||||||
version=$(../bin/phantomjs --version | sed 's/ /-/' | sed 's/[()]//g')
|
|
||||||
src=..
|
|
||||||
|
|
||||||
echo "packaging phantomjs $version"
|
|
||||||
|
|
||||||
if [[ $OSTYPE = darwin* ]]; then
|
|
||||||
dest="phantomjs-$version-macosx"
|
|
||||||
else
|
|
||||||
dest="phantomjs-$version-linux-$(uname -m)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -Rf $dest{.tar.bz2,} &> /dev/null
|
|
||||||
mkdir -p $dest/bin
|
|
||||||
|
|
||||||
echo
|
|
||||||
|
|
||||||
echo -n "copying files..."
|
|
||||||
cp $src/bin/phantomjs $dest/bin
|
|
||||||
cp -r $src/{ChangeLog,examples,LICENSE.BSD,third-party.txt,README.md} $dest/
|
|
||||||
echo "done"
|
|
||||||
echo
|
|
||||||
|
|
||||||
phantomjs=$dest/bin/phantomjs
|
|
||||||
|
|
||||||
if [[ "$bundle_libs" = "1" ]]; then
|
|
||||||
mkdir -p $dest/lib
|
|
||||||
|
|
||||||
if [[ ! -f brandelf ]]; then
|
|
||||||
echo
|
|
||||||
echo "brandelf executable not found in current dir"
|
|
||||||
echo -n "compiling it now..."
|
|
||||||
g++ brandelf.c -o brandelf || exit 1
|
|
||||||
echo "done"
|
|
||||||
fi
|
|
||||||
|
|
||||||
libs=$(ldd $phantomjs | egrep -o "/[^ ]+ ")
|
|
||||||
|
|
||||||
echo -n "copying shared libs..."
|
|
||||||
libld=
|
|
||||||
for l in $libs; do
|
|
||||||
ll=$(basename $l)
|
|
||||||
cp $l $dest/lib/$ll
|
|
||||||
|
|
||||||
if [[ "$bundle_libs" = "1" ]]; then
|
|
||||||
# ensure OS ABI compatibility
|
|
||||||
./brandelf -t SVR4 $dest/lib/$ll
|
|
||||||
if [[ "$l" == *"ld-linux"* ]]; then
|
|
||||||
libld=$ll
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo "done"
|
|
||||||
echo
|
|
||||||
|
|
||||||
echo -n "writing run script..."
|
|
||||||
mv $phantomjs $phantomjs.bin
|
|
||||||
phantomjs=$phantomjs.bin
|
|
||||||
run=$dest/bin/phantomjs
|
|
||||||
echo '#!/bin/sh' >> $run
|
|
||||||
echo 'path=$(dirname $(dirname $(readlink -f $0)))' >> $run
|
|
||||||
echo 'export LD_LIBRARY_PATH=$path/lib' >> $run
|
|
||||||
echo 'exec $path/lib/'$libld' $phantomjs $@' >> $run
|
|
||||||
chmod +x $run
|
|
||||||
echo "done"
|
|
||||||
echo
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -n "stripping binary and libs..."
|
|
||||||
if [[ $OSTYPE = darwin* ]]; then
|
|
||||||
strip -x $phantomjs
|
|
||||||
else
|
|
||||||
strip -s $phantomjs
|
|
||||||
[[ -d $dest/lib ]] && strip -s $dest/lib/*
|
|
||||||
fi
|
|
||||||
echo "done"
|
|
||||||
echo
|
|
||||||
|
|
||||||
echo -n "compressing binary..."
|
|
||||||
if type upx >/dev/null 2>&1; then
|
|
||||||
upx -qqq -9 $phantomjs
|
|
||||||
echo "done"
|
|
||||||
else
|
|
||||||
echo "upx not found"
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
|
|
||||||
echo -n "creating archive..."
|
|
||||||
if [[ $OSTYPE = darwin* ]]; then
|
|
||||||
zip -r $dest.zip $dest
|
|
||||||
else
|
|
||||||
tar -cjf $dest{.tar.bz2,}
|
|
||||||
fi
|
|
||||||
echo "done"
|
|
||||||
echo
|
|
|
@ -1,42 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
export PATH=$HOME/git/bin:$PATH
|
|
||||||
|
|
||||||
if type apt-get >/dev/null 2>&1; then
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y build-essential git-core libssl-dev libfontconfig1-dev gdb binutils-gold
|
|
||||||
fi
|
|
||||||
|
|
||||||
if type yum >/dev/null 2>&1; then
|
|
||||||
yum -y update
|
|
||||||
yum -y install gcc gcc-c++ make openssl-devel freetype-devel fontconfig-devel
|
|
||||||
if type git >/dev/null 2>&1; then
|
|
||||||
echo "Git is already available."
|
|
||||||
else
|
|
||||||
yum -y install cpio expat-devel gettext-devel zlib-devel
|
|
||||||
echo "Downloading and building git..."
|
|
||||||
rm -rf git-*
|
|
||||||
wget -nv https://git-core.googlecode.com/files/git-1.8.0.3.tar.gz
|
|
||||||
tar -xzvf git-1.8.0.3.tar.gz
|
|
||||||
cd git-1.8.0.3
|
|
||||||
./configure --prefix=$HOME/git && make -j2 && make install
|
|
||||||
cd ..
|
|
||||||
sleep 3
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -d phantomjs ]]; then
|
|
||||||
git clone git://github.com/ariya/phantomjs.git
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd phantomjs
|
|
||||||
git fetch origin
|
|
||||||
git reset --hard
|
|
||||||
git checkout $1
|
|
||||||
|
|
||||||
cp /vagrant/build-and-package.sh deploy/
|
|
||||||
cp /vagrant/package.sh deploy/
|
|
||||||
|
|
||||||
deploy/build-and-package.sh
|
|
||||||
|
|
||||||
cp deploy/*.tar.bz2 /vagrant
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm
|
||||||
|
index ed9e9ce..ca35249 100644
|
||||||
|
--- a/src/gui/kernel/qapplication_mac.mm
|
||||||
|
+++ b/src/gui/kernel/qapplication_mac.mm
|
||||||
|
@@ -1253,11 +1253,14 @@ void qt_init(QApplicationPrivate *priv, int)
|
||||||
|
[newDelegate setReflectionDelegate:oldDelegate];
|
||||||
|
[cocoaApp setDelegate:newDelegate];
|
||||||
|
|
||||||
|
+// https://bugreports.qt.nokia.com/browse/QTBUG-5952
|
||||||
|
QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader = [[QT_MANGLE_NAMESPACE(QCocoaMenuLoader) alloc] init];
|
||||||
|
if ([NSBundle loadNibNamed:@"qt_menu" owner:qtMenuLoader] == false) {
|
||||||
|
+#if 0
|
||||||
|
qFatal("Qt internal error: qt_menu.nib could not be loaded. The .nib file"
|
||||||
|
" should be placed in QtGui.framework/Versions/Current/Resources/ "
|
||||||
|
" or in the resources directory of your application bundle.");
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
[cocoaApp setMenu:[qtMenuLoader menu]];
|
|
@ -0,0 +1,35 @@
|
||||||
|
diff --git a/src/3rdparty/webkit/Source/WebCore/inspector/front-end/Settings.js b/src/3rdparty/webkit/Source/WebCore/inspector/front-end/Settings.js
|
||||||
|
index 62bf84a..e830f85 100644
|
||||||
|
--- a/src/3rdparty/webkit/Source/WebCore/inspector/front-end/Settings.js
|
||||||
|
+++ b/src/3rdparty/webkit/Source/WebCore/inspector/front-end/Settings.js
|
||||||
|
@@ -40,7 +40,7 @@ var Preferences = {
|
||||||
|
showMissingLocalizedStrings: false,
|
||||||
|
samplingCPUProfiler: false,
|
||||||
|
showColorNicknames: true,
|
||||||
|
- debuggerAlwaysEnabled: false,
|
||||||
|
+ debuggerAlwaysEnabled: true,
|
||||||
|
profilerAlwaysEnabled: false,
|
||||||
|
onlineDetectionEnabled: true,
|
||||||
|
nativeInstrumentationEnabled: false,
|
||||||
|
@@ -58,7 +58,7 @@ WebInspector.Settings = function()
|
||||||
|
{
|
||||||
|
this.installApplicationSetting("colorFormat", "hex");
|
||||||
|
this.installApplicationSetting("consoleHistory", []);
|
||||||
|
- this.installApplicationSetting("debuggerEnabled", false);
|
||||||
|
+ this.installApplicationSetting("debuggerEnabled", true);
|
||||||
|
this.installApplicationSetting("domWordWrap", true);
|
||||||
|
this.installApplicationSetting("profilerEnabled", false);
|
||||||
|
this.installApplicationSetting("eventListenersFilter", "all");
|
||||||
|
diff --git a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebinspector.cpp b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebinspector.cpp
|
||||||
|
index 6706f2a..bec3d1c 100644
|
||||||
|
--- a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebinspector.cpp
|
||||||
|
+++ b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebinspector.cpp
|
||||||
|
@@ -161,7 +161,7 @@ void QWebInspector::showEvent(QShowEvent* event)
|
||||||
|
#if ENABLE(INSPECTOR)
|
||||||
|
// Allows QWebInspector::show() to init the inspector.
|
||||||
|
if (d->page)
|
||||||
|
- d->page->d->inspectorController()->show();
|
||||||
|
+ d->page->d->inspectorController()->showAndEnableDebugger();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,268 @@
|
||||||
|
diff --git a/src/3rdparty/webkit/Source/WebKit/qt/WebCoreSupport/InspectorServerQt.cpp b/src/3rdparty/webkit/Source/WebKit/qt/WebCoreSupport/InspectorServerQt.cpp
|
||||||
|
index 92b7d5c..c5e5bd5 100644
|
||||||
|
--- a/src/3rdparty/webkit/Source/WebKit/qt/WebCoreSupport/InspectorServerQt.cpp
|
||||||
|
+++ b/src/3rdparty/webkit/Source/WebKit/qt/WebCoreSupport/InspectorServerQt.cpp
|
||||||
|
@@ -22,7 +22,8 @@
|
||||||
|
|
||||||
|
#include "InspectorClientQt.h"
|
||||||
|
#include "InspectorController.h"
|
||||||
|
-#include "MD5.h"
|
||||||
|
+#include "Base64.h"
|
||||||
|
+#include "SHA1.h"
|
||||||
|
#include "Page.h"
|
||||||
|
#include "qwebpage.h"
|
||||||
|
#include "qwebpage_p.h"
|
||||||
|
@@ -44,43 +45,17 @@ namespace WebCore {
|
||||||
|
/*!
|
||||||
|
Computes the WebSocket handshake response given the two challenge numbers and key3.
|
||||||
|
*/
|
||||||
|
-static void generateWebSocketChallengeResponse(uint32_t number1, uint32_t number2, const unsigned char key3[8], unsigned char response[16])
|
||||||
|
+static QByteArray generateWebSocketChallengeResponse(const QByteArray& key)
|
||||||
|
{
|
||||||
|
- uint8_t challenge[16];
|
||||||
|
- qToBigEndian<qint32>(number1, &challenge[0]);
|
||||||
|
- qToBigEndian<qint32>(number2, &challenge[4]);
|
||||||
|
- memcpy(&challenge[8], key3, 8);
|
||||||
|
- MD5 md5;
|
||||||
|
- md5.addBytes(challenge, sizeof(challenge));
|
||||||
|
- Vector<uint8_t, 16> digest;
|
||||||
|
- md5.checksum(digest);
|
||||||
|
- memcpy(response, digest.data(), 16);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-/*!
|
||||||
|
- Parses and returns a WebSocket challenge number according to the
|
||||||
|
- method specified in the WebSocket protocol.
|
||||||
|
-
|
||||||
|
- The field contains numeric digits interspersed with spaces and
|
||||||
|
- non-numeric digits. The protocol ignores the characters that are
|
||||||
|
- neither digits nor spaces. The digits are concatenated and
|
||||||
|
- interpreted as a long int. The result is this number divided by
|
||||||
|
- the number of spaces.
|
||||||
|
- */
|
||||||
|
-static quint32 parseWebSocketChallengeNumber(QString field)
|
||||||
|
-{
|
||||||
|
- QString nString;
|
||||||
|
- int numSpaces = 0;
|
||||||
|
- for (int i = 0; i < field.size(); i++) {
|
||||||
|
- QChar c = field[i];
|
||||||
|
- if (c == QLatin1Char(' '))
|
||||||
|
- numSpaces++;
|
||||||
|
- else if ((c >= QLatin1Char('0')) && (c <= QLatin1Char('9')))
|
||||||
|
- nString.append(c);
|
||||||
|
- }
|
||||||
|
- quint32 num = nString.toLong();
|
||||||
|
- quint32 result = (numSpaces ? (num / numSpaces) : num);
|
||||||
|
- return result;
|
||||||
|
+ SHA1 sha1;
|
||||||
|
+ Vector<uint8_t, 20> digest;
|
||||||
|
+ Vector<char> encoded;
|
||||||
|
+ QByteArray toHash("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||||
|
+ toHash.prepend(key);
|
||||||
|
+ sha1.addBytes((uint8_t*)toHash.data(), toHash.size());
|
||||||
|
+ sha1.computeHash(digest);
|
||||||
|
+ base64Encode((char*)digest.data(), digest.size(), encoded);
|
||||||
|
+ return QByteArray(encoded.data(), encoded.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
static InspectorServerQt* s_inspectorServer;
|
||||||
|
@@ -194,7 +169,7 @@ void InspectorServerRequestHandlerQt::tcpReadyRead()
|
||||||
|
m_path = header.path();
|
||||||
|
m_contentType = header.contentType().toLatin1();
|
||||||
|
m_contentLength = header.contentLength();
|
||||||
|
- if (header.hasKey(QLatin1String("Upgrade")) && (header.value(QLatin1String("Upgrade")) == QLatin1String("WebSocket")))
|
||||||
|
+ if (header.hasKey(QLatin1String("Upgrade")) && (header.value(QLatin1String("Upgrade")) == QLatin1String("websocket")))
|
||||||
|
isWebSocket = true;
|
||||||
|
|
||||||
|
m_data.clear();
|
||||||
|
@@ -211,25 +186,19 @@ void InspectorServerRequestHandlerQt::tcpReadyRead()
|
||||||
|
// switch to websocket-style WebSocketService messaging
|
||||||
|
if (m_tcpConnection) {
|
||||||
|
m_tcpConnection->disconnect(SIGNAL(readyRead()));
|
||||||
|
- connect(m_tcpConnection, SIGNAL(readyRead()), SLOT(webSocketReadyRead()));
|
||||||
|
-
|
||||||
|
- QByteArray key3 = m_tcpConnection->read(8);
|
||||||
|
-
|
||||||
|
- quint32 number1 = parseWebSocketChallengeNumber(header.value(QLatin1String("Sec-WebSocket-Key1")));
|
||||||
|
- quint32 number2 = parseWebSocketChallengeNumber(header.value(QLatin1String("Sec-WebSocket-Key2")));
|
||||||
|
-
|
||||||
|
- char responseData[16];
|
||||||
|
- generateWebSocketChallengeResponse(number1, number2, (unsigned char*)key3.data(), (unsigned char*)responseData);
|
||||||
|
- QByteArray response(responseData, sizeof(responseData));
|
||||||
|
+ connect(m_tcpConnection, SIGNAL(readyRead()), SLOT(webSocketReadyRead()), Qt::QueuedConnection);
|
||||||
|
+
|
||||||
|
+ QByteArray key = header.value(QLatin1String("Sec-WebSocket-Key")).toLatin1();
|
||||||
|
+ QString accept = QString::fromLatin1(generateWebSocketChallengeResponse(key));
|
||||||
|
|
||||||
|
QHttpResponseHeader responseHeader(101, QLatin1String("WebSocket Protocol Handshake"), 1, 1);
|
||||||
|
responseHeader.setValue(QLatin1String("Upgrade"), header.value(QLatin1String("Upgrade")));
|
||||||
|
responseHeader.setValue(QLatin1String("Connection"), header.value(QLatin1String("Connection")));
|
||||||
|
- responseHeader.setValue(QLatin1String("Sec-WebSocket-Origin"), header.value(QLatin1String("Origin")));
|
||||||
|
- responseHeader.setValue(QLatin1String("Sec-WebSocket-Location"), (QLatin1String("ws://") + header.value(QLatin1String("Host")) + m_path));
|
||||||
|
- responseHeader.setContentLength(response.size());
|
||||||
|
+ responseHeader.setValue(QLatin1String("Sec-WebSocket-Accept"), accept);
|
||||||
|
+ // responseHeader.setValue(QLatin1String("Sec-WebSocket-Origin"), header.value(QLatin1String("Sec-WebSocket-Origin")));
|
||||||
|
+ // responseHeader.setValue(QLatin1String("Sec-WebSocket-Location"), (QLatin1String("ws://") + header.value(QLatin1String("Host")) + m_path));
|
||||||
|
m_tcpConnection->write(responseHeader.toString().toLatin1());
|
||||||
|
- m_tcpConnection->write(response);
|
||||||
|
+ //m_tcpConnection->write(response);
|
||||||
|
m_tcpConnection->flush();
|
||||||
|
|
||||||
|
if ((words.size() == 4)
|
||||||
|
@@ -308,26 +277,54 @@ void InspectorServerRequestHandlerQt::tcpConnectionDisconnected()
|
||||||
|
m_tcpConnection = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int InspectorServerRequestHandlerQt::webSocketSend(QByteArray payload)
|
||||||
|
+int InspectorServerRequestHandlerQt::webSocketSend(const QString& message)
|
||||||
|
{
|
||||||
|
- Q_ASSERT(m_tcpConnection);
|
||||||
|
- m_tcpConnection->putChar(0x00);
|
||||||
|
- int nBytes = m_tcpConnection->write(payload);
|
||||||
|
- m_tcpConnection->putChar(0xFF);
|
||||||
|
- m_tcpConnection->flush();
|
||||||
|
- return nBytes;
|
||||||
|
+ QByteArray payload = message.toUtf8();
|
||||||
|
+ return webSocketSend(payload.data(), payload.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int InspectorServerRequestHandlerQt::webSocketSend(const char* data, size_t length)
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_tcpConnection);
|
||||||
|
- m_tcpConnection->putChar(0x00);
|
||||||
|
+ m_tcpConnection->putChar(0x81);
|
||||||
|
+ if (length <= 125)
|
||||||
|
+ m_tcpConnection->putChar(static_cast<uint8_t>(length));
|
||||||
|
+ else if (length <= pow(2,16)) {
|
||||||
|
+ m_tcpConnection->putChar(126);
|
||||||
|
+ quint16 length16 = qToBigEndian<quint16>(static_cast<quint16>(length));
|
||||||
|
+ m_tcpConnection->write(reinterpret_cast<char*>(&length16), 2);
|
||||||
|
+ } else {
|
||||||
|
+ m_tcpConnection->putChar(127);
|
||||||
|
+ quint64 length64 = qToBigEndian<quint64>(static_cast<quint64>(length));
|
||||||
|
+ m_tcpConnection->write(reinterpret_cast<char*>(&length64), 8);
|
||||||
|
+ }
|
||||||
|
int nBytes = m_tcpConnection->write(data, length);
|
||||||
|
- m_tcpConnection->putChar(0xFF);
|
||||||
|
m_tcpConnection->flush();
|
||||||
|
return nBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static QByteArray applyMask(const QByteArray& payload, const QByteArray& maskingKey)
|
||||||
|
+{
|
||||||
|
+ Q_ASSERT(maskingKey.size() == 4);
|
||||||
|
+ QByteArray unmaskedPayload;
|
||||||
|
+ for (int i = 0; i < payload.size(); ++i) {
|
||||||
|
+ char unmaskedByte = payload[i] ^ maskingKey[i % 4];
|
||||||
|
+ unmaskedPayload.append(unmaskedByte);
|
||||||
|
+ }
|
||||||
|
+ return unmaskedPayload;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#define BYTETOBINARYPATTERN "%d%d%d%d%d%d%d%d"
|
||||||
|
+#define BYTETOBINARY(byte) \
|
||||||
|
+ (byte & 0x80 ? 1 : 0), \
|
||||||
|
+ (byte & 0x40 ? 1 : 0), \
|
||||||
|
+ (byte & 0x20 ? 1 : 0), \
|
||||||
|
+ (byte & 0x10 ? 1 : 0), \
|
||||||
|
+ (byte & 0x08 ? 1 : 0), \
|
||||||
|
+ (byte & 0x04 ? 1 : 0), \
|
||||||
|
+ (byte & 0x02 ? 1 : 0), \
|
||||||
|
+ (byte & 0x01 ? 1 : 0)
|
||||||
|
+
|
||||||
|
void InspectorServerRequestHandlerQt::webSocketReadyRead()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_tcpConnection);
|
||||||
|
@@ -336,38 +333,49 @@ void InspectorServerRequestHandlerQt::webSocketReadyRead()
|
||||||
|
QByteArray content = m_tcpConnection->read(m_tcpConnection->bytesAvailable());
|
||||||
|
m_data.append(content);
|
||||||
|
while (m_data.size() > 0) {
|
||||||
|
- // first byte in websocket frame should be 0
|
||||||
|
- Q_ASSERT(!m_data[0]);
|
||||||
|
+ bool isMasked = m_data[1] & 0x80;
|
||||||
|
+ quint64 payloadLen = m_data[1] & 0x7F;
|
||||||
|
+ int pos = 2;
|
||||||
|
|
||||||
|
- // Start of WebSocket frame is indicated by 0
|
||||||
|
- if (m_data[0]) {
|
||||||
|
- qCritical() << "webSocketReadyRead: unknown frame type" << m_data[0];
|
||||||
|
- m_data.clear();
|
||||||
|
- m_tcpConnection->close();
|
||||||
|
- return;
|
||||||
|
+ if (payloadLen == 126) {
|
||||||
|
+ payloadLen = qFromBigEndian<quint16>(*reinterpret_cast<quint16*>(m_data.mid(pos, 2).data()));
|
||||||
|
+ pos = 4;
|
||||||
|
+ } else if (payloadLen == 127) {
|
||||||
|
+ payloadLen = qFromBigEndian<quint64>(*reinterpret_cast<quint64*>(m_data.mid(pos, 8).data()));
|
||||||
|
+ pos = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
- // End of WebSocket frame indicated by 0xff.
|
||||||
|
- int pos = m_data.indexOf(0xff, 1);
|
||||||
|
- if (pos < 1)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- // After above checks, length will be >= 0.
|
||||||
|
- size_t length = pos - 1;
|
||||||
|
- if (length <= 0)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- QByteArray payload = m_data.mid(1, length);
|
||||||
|
+ QByteArray payload;
|
||||||
|
+ if (isMasked) {
|
||||||
|
+ QByteArray maskingKey = m_data.mid(pos, 4);
|
||||||
|
+ pos += 4;
|
||||||
|
+ payload = applyMask(m_data.mid(pos, payloadLen), maskingKey);
|
||||||
|
+ } else {
|
||||||
|
+ payload = m_data.mid(pos, payloadLen);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
+ // Handle fragmentation
|
||||||
|
+ if ((m_data[0] & 0x80) == 0) { // Non-last fragmented payload
|
||||||
|
+ m_fragmentedPayload.append(payload);
|
||||||
|
+
|
||||||
|
+ m_data = m_data.mid(pos + payloadLen);
|
||||||
|
+ continue;
|
||||||
|
+ } else {
|
||||||
|
+ if ((m_data[0] & 0x0F) == 0) { // Last fragment
|
||||||
|
+ m_fragmentedPayload.append(payload);
|
||||||
|
+ payload = m_fragmentedPayload;
|
||||||
|
+ m_fragmentedPayload.clear();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Remove this WebSocket message from m_data (payload, start-of-frame byte, end-of-frame byte).
|
||||||
|
+ m_data = m_data.mid(pos + payloadLen);
|
||||||
|
#if ENABLE(INSPECTOR)
|
||||||
|
if (m_inspectorClient) {
|
||||||
|
InspectorController* inspectorController = m_inspectorClient->m_inspectedWebPage->d->page->inspectorController();
|
||||||
|
inspectorController->dispatchMessageFromFrontend(QString::fromUtf8(payload));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
-
|
||||||
|
- // Remove this WebSocket message from m_data (payload, start-of-frame byte, end-of-frame byte).
|
||||||
|
- m_data = m_data.mid(length + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/src/3rdparty/webkit/Source/WebKit/qt/WebCoreSupport/InspectorServerQt.h b/src/3rdparty/webkit/Source/WebKit/qt/WebCoreSupport/InspectorServerQt.h
|
||||||
|
index 922b63e..e1265b9 100644
|
||||||
|
--- a/src/3rdparty/webkit/Source/WebKit/qt/WebCoreSupport/InspectorServerQt.h
|
||||||
|
+++ b/src/3rdparty/webkit/Source/WebKit/qt/WebCoreSupport/InspectorServerQt.h
|
||||||
|
@@ -83,7 +83,7 @@ public:
|
||||||
|
|
||||||
|
InspectorServerRequestHandlerQt(QTcpSocket *tcpConnection, InspectorServerQt *server);
|
||||||
|
virtual ~InspectorServerRequestHandlerQt();
|
||||||
|
- virtual int webSocketSend(QByteArray payload);
|
||||||
|
+ virtual int webSocketSend(const QString& message);
|
||||||
|
virtual int webSocketSend(const char *payload, size_t length);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
@@ -100,6 +100,7 @@ private:
|
||||||
|
int m_contentLength;
|
||||||
|
bool m_endOfHeaders;
|
||||||
|
QByteArray m_data;
|
||||||
|
+ QByteArray m_fragmentedPayload;
|
||||||
|
InspectorClientQt* m_inspectorClient;
|
||||||
|
|
||||||
|
void handleInspectorRequest(QStringList words);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
||||||
|
if phantom.args.length is 0
|
||||||
|
console.log 'Try to pass some args when invoking this script!'
|
||||||
|
else
|
||||||
|
for arg, i in phantom.args
|
||||||
|
console.log i + ': ' + arg
|
||||||
|
phantom.exit()
|
|
@ -1,8 +1,7 @@
|
||||||
var system = require('system');
|
if (phantom.args.length === 0) {
|
||||||
if (system.args.length === 1) {
|
|
||||||
console.log('Try to pass some args when invoking this script!');
|
console.log('Try to pass some args when invoking this script!');
|
||||||
} else {
|
} else {
|
||||||
system.args.forEach(function (arg, i) {
|
phantom.args.forEach(function (arg, i) {
|
||||||
console.log(i + ': ' + arg);
|
console.log(i + ': ' + arg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
var spawn = require("child_process").spawn
|
|
||||||
var execFile = require("child_process").execFile
|
|
||||||
|
|
||||||
var child = spawn("ls", ["-lF", "/rooot"])
|
|
||||||
|
|
||||||
child.stdout.on("data", function (data) {
|
|
||||||
console.log("spawnSTDOUT:", JSON.stringify(data))
|
|
||||||
})
|
|
||||||
|
|
||||||
child.stderr.on("data", function (data) {
|
|
||||||
console.log("spawnSTDERR:", JSON.stringify(data))
|
|
||||||
})
|
|
||||||
|
|
||||||
child.on("exit", function (code) {
|
|
||||||
console.log("spawnEXIT:", code)
|
|
||||||
})
|
|
||||||
|
|
||||||
//child.kill("SIGKILL")
|
|
||||||
|
|
||||||
execFile("ls", ["-lF", "/usr"], null, function (err, stdout, stderr) {
|
|
||||||
console.log("execFileSTDOUT:", JSON.stringify(stdout))
|
|
||||||
console.log("execFileSTDERR:", JSON.stringify(stderr))
|
|
||||||
})
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
phantom.exit(0)
|
|
||||||
}, 2000)
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
page.viewportSize = { width: 400, height : 400 }
|
||||||
|
page.content = '<html><body><canvas id="surface"></canvas></body></html>'
|
||||||
|
|
||||||
|
page.evaluate ->
|
||||||
|
el = document.getElementById 'surface'
|
||||||
|
context = el.getContext '2d'
|
||||||
|
width = window.innerWidth
|
||||||
|
height = window.innerHeight
|
||||||
|
cx = width / 2
|
||||||
|
cy = height / 2
|
||||||
|
radius = width / 2.3
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
el.width = width
|
||||||
|
el.height = height
|
||||||
|
imageData = context.createImageData(width, height)
|
||||||
|
pixels = imageData.data
|
||||||
|
|
||||||
|
for y in [0...height]
|
||||||
|
for x in [0...width]
|
||||||
|
i = i + 4
|
||||||
|
rx = x - cx
|
||||||
|
ry = y - cy
|
||||||
|
d = rx * rx + ry * ry
|
||||||
|
if d < radius * radius
|
||||||
|
hue = 6 * (Math.atan2(ry, rx) + Math.PI) / (2 * Math.PI)
|
||||||
|
sat = Math.sqrt(d) / radius
|
||||||
|
g = Math.floor(hue)
|
||||||
|
f = hue - g
|
||||||
|
u = 255 * (1 - sat)
|
||||||
|
v = 255 * (1 - sat * f)
|
||||||
|
w = 255 * (1 - sat * (1 - f))
|
||||||
|
pixels[i] = [255, v, u, u, w, 255, 255][g]
|
||||||
|
pixels[i + 1] = [w, 255, 255, v, u, u, w][g]
|
||||||
|
pixels[i + 2] = [u, u, w, 255, 255, v, u][g]
|
||||||
|
pixels[i + 3] = 255
|
||||||
|
|
||||||
|
context.putImageData imageData, 0, 0
|
||||||
|
document.body.style.backgroundColor = 'white'
|
||||||
|
document.body.style.margin = '0px'
|
||||||
|
|
||||||
|
page.render('colorwheel.png')
|
||||||
|
|
||||||
|
phantom.exit()
|
|
@ -0,0 +1,8 @@
|
||||||
|
t = 10
|
||||||
|
interval = setInterval ->
|
||||||
|
if t > 0
|
||||||
|
console.log t--
|
||||||
|
else
|
||||||
|
console.log 'BLAST OFF!'
|
||||||
|
phantom.exit()
|
||||||
|
, 1000
|
|
@ -0,0 +1,40 @@
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
page.onInitialized = ->
|
||||||
|
page.evaluate ->
|
||||||
|
userAgent = window.navigator.userAgent
|
||||||
|
platform = window.navigator.platform
|
||||||
|
window.navigator =
|
||||||
|
appCodeName: 'Mozilla'
|
||||||
|
appName: 'Netscape'
|
||||||
|
cookieEnabled: false
|
||||||
|
sniffed: false
|
||||||
|
|
||||||
|
window.navigator.__defineGetter__ 'userAgent', ->
|
||||||
|
window.navigator.sniffed = true
|
||||||
|
userAgent
|
||||||
|
|
||||||
|
window.navigator.__defineGetter__ 'platform', ->
|
||||||
|
window.navigator.sniffed = true
|
||||||
|
platform
|
||||||
|
|
||||||
|
if phantom.args.length is 0
|
||||||
|
console.log 'Usage: unsniff.js <some URL>'
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
address = phantom.args[0]
|
||||||
|
console.log 'Checking ' + address + '...'
|
||||||
|
page.open address, (status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'FAIL to load the address'
|
||||||
|
else
|
||||||
|
window.setTimeout ->
|
||||||
|
sniffed = page.evaluate(->
|
||||||
|
navigator.sniffed
|
||||||
|
)
|
||||||
|
if sniffed
|
||||||
|
console.log 'The page tried to sniff the user agent.'
|
||||||
|
else
|
||||||
|
console.log 'The page did not try to sniff the user agent.'
|
||||||
|
phantom.exit()
|
||||||
|
, 1500
|
|
@ -1,7 +1,6 @@
|
||||||
// Detect if a web page sniffs the user agent or not.
|
// Detect if a web page sniffs the user agent or not.
|
||||||
|
|
||||||
var page = require('webpage').create(),
|
var page = require('webpage').create(),
|
||||||
system = require('system'),
|
|
||||||
sniffed,
|
sniffed,
|
||||||
address;
|
address;
|
||||||
|
|
||||||
|
@ -32,16 +31,15 @@ page.onInitialized = function () {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (system.args.length === 1) {
|
if (phantom.args.length === 0) {
|
||||||
console.log('Usage: detectsniff.js <some URL>');
|
console.log('Usage: unsniff.js <some URL>');
|
||||||
phantom.exit(1);
|
phantom.exit();
|
||||||
} else {
|
} else {
|
||||||
address = system.args[1];
|
address = phantom.args[0];
|
||||||
console.log('Checking ' + address + '...');
|
console.log('Checking ' + address + '...');
|
||||||
page.open(address, function (status) {
|
page.open(address, function (status) {
|
||||||
if (status !== 'success') {
|
if (status !== 'success') {
|
||||||
console.log('FAIL to load the address');
|
console.log('FAIL to load the address');
|
||||||
phantom.exit();
|
|
||||||
} else {
|
} else {
|
||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
sniffed = page.evaluate(function () {
|
sniffed = page.evaluate(function () {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Get driving direction using Google Directions API.
|
||||||
|
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
if phantom.args.length < 2
|
||||||
|
console.log 'Usage: direction.js origin destination'
|
||||||
|
console.log 'Example: direction.js "San Diego" "Palo Alto"'
|
||||||
|
phantom.exit(1)
|
||||||
|
else
|
||||||
|
origin = phantom.args[0]
|
||||||
|
dest = phantom.args[1]
|
||||||
|
page.open encodeURI('http://maps.googleapis.com/maps/api/directions/xml?origin=' + origin +
|
||||||
|
'&destination=' + dest + '&units=imperial&mode=driving&sensor=false'),
|
||||||
|
(status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'Unable to access network'
|
||||||
|
else
|
||||||
|
steps = page.content.match(/<html_instructions>(.*)<\/html_instructions>/ig)
|
||||||
|
if not steps
|
||||||
|
console.log 'No data available for ' + origin + ' to ' + dest
|
||||||
|
else
|
||||||
|
for ins in steps
|
||||||
|
ins = ins.replace(/\</ig, '<').replace(/\>/ig, '>')
|
||||||
|
ins = ins.replace(/\<div/ig, '\n<div')
|
||||||
|
ins = ins.replace(/<.*?>/g, '')
|
||||||
|
console.log(ins)
|
||||||
|
console.log ''
|
||||||
|
console.log page.content.match(/<copyrights>.*<\/copyrights>/ig).join('').replace(/<.*?>/g, '')
|
||||||
|
phantom.exit()
|
|
@ -1,16 +1,15 @@
|
||||||
// Get driving direction using Google Directions API.
|
// Get driving direction using Google Directions API.
|
||||||
|
|
||||||
var page = require('webpage').create(),
|
var page = require('webpage').create(),
|
||||||
system = require('system'),
|
|
||||||
origin, dest, steps;
|
origin, dest, steps;
|
||||||
|
|
||||||
if (system.args.length < 3) {
|
if (phantom.args.length < 2) {
|
||||||
console.log('Usage: direction.js origin destination');
|
console.log('Usage: direction.js origin destination');
|
||||||
console.log('Example: direction.js "San Diego" "Palo Alto"');
|
console.log('Example: direction.js "San Diego" "Palo Alto"');
|
||||||
phantom.exit(1);
|
phantom.exit(1);
|
||||||
} else {
|
} else {
|
||||||
origin = system.args[1];
|
origin = phantom.args[0];
|
||||||
dest = system.args[2];
|
dest = phantom.args[1];
|
||||||
page.open(encodeURI('http://maps.googleapis.com/maps/api/directions/xml?origin=' + origin +
|
page.open(encodeURI('http://maps.googleapis.com/maps/api/directions/xml?origin=' + origin +
|
||||||
'&destination=' + dest + '&units=imperial&mode=driving&sensor=false'), function (status) {
|
'&destination=' + dest + '&units=imperial&mode=driving&sensor=false'), function (status) {
|
||||||
if (status !== 'success') {
|
if (status !== 'success') {
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
# echoToFile.coffee - Write in a given file all the parameters passed on the CLI
|
||||||
|
fs = require 'fs'
|
||||||
|
|
||||||
|
if phantom.args.length < 2
|
||||||
|
console.log "Usage: echoToFile.js DESTINATION_FILE <arguments to echo...>"
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
content = ""
|
||||||
|
f = null
|
||||||
|
i = 1
|
||||||
|
while i < phantom.args.length
|
||||||
|
content += phantom.args[i] + (if i == phantom.args.length - 1 then "" else " ")
|
||||||
|
++i
|
||||||
|
try
|
||||||
|
f = fs.open(phantom.args[0], "w")
|
||||||
|
f.writeLine content
|
||||||
|
catch e
|
||||||
|
console.log e
|
||||||
|
phantom.exit()
|
|
@ -1,21 +1,20 @@
|
||||||
// echoToFile.js - Write in a given file all the parameters passed on the CLI
|
// echoToFile.js - Write in a given file all the parameters passed on the CLI
|
||||||
var fs = require('fs'),
|
var fs = require('fs');
|
||||||
system = require('system');
|
|
||||||
|
|
||||||
if (system.args.length < 3) {
|
if (phantom.args.length < 2) {
|
||||||
console.log("Usage: echoToFile.js DESTINATION_FILE <arguments to echo...>");
|
console.log("Usage: echoToFile.js DESTINATION_FILE <arguments to echo...>");
|
||||||
phantom.exit(1);
|
phantom.exit();
|
||||||
} else {
|
} else {
|
||||||
var content = '',
|
var content = '',
|
||||||
f = null,
|
f = null;
|
||||||
i;
|
for ( i= 1; i < phantom.args.length; ++i ) {
|
||||||
for ( i= 2; i < system.args.length; ++i ) {
|
content += phantom.args[i] + (i === phantom.args.length-1 ? '' : ' ');
|
||||||
content += system.args[i] + (i === system.args.length-1 ? '' : ' ');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.write(system.args[1], content, 'w');
|
f = fs.open(phantom.args[0], "w");
|
||||||
} catch(e) {
|
f.writeLine(content);
|
||||||
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
fibs = [0, 1]
|
||||||
|
f = ->
|
||||||
|
console.log fibs[fibs.length - 1]
|
||||||
|
fibs.push fibs[fibs.length - 1] + fibs[fibs.length - 2]
|
||||||
|
if fibs.length > 10
|
||||||
|
window.clearInterval ticker
|
||||||
|
phantom.exit()
|
||||||
|
ticker = window.setInterval(f, 300)
|
|
@ -0,0 +1,54 @@
|
||||||
|
# List following and followers from several accounts
|
||||||
|
|
||||||
|
users= [
|
||||||
|
'sencha'
|
||||||
|
'aconran'
|
||||||
|
'adityabansod'
|
||||||
|
'ambisinister'
|
||||||
|
'arnebech'
|
||||||
|
'ariyahidayat'
|
||||||
|
'arthurakay'
|
||||||
|
'bmoeskau'
|
||||||
|
'darrellmeyer'
|
||||||
|
'davidfoelber'
|
||||||
|
'DavidKaneda'
|
||||||
|
'donovanerba'
|
||||||
|
'edspencer'
|
||||||
|
'evantrimboli'
|
||||||
|
'ExtAnimal'
|
||||||
|
'jamieavins'
|
||||||
|
'jarrednicholls'
|
||||||
|
'jayrobinson'
|
||||||
|
'lojjic'
|
||||||
|
'luckymethod'
|
||||||
|
'merrells'
|
||||||
|
'mmullany'
|
||||||
|
'philogb'
|
||||||
|
'philstrong'
|
||||||
|
'rdougan'
|
||||||
|
'SubtleGradient'
|
||||||
|
'__ted__'
|
||||||
|
'tmaintz'
|
||||||
|
'WesleyMoy'
|
||||||
|
'whereisthysting'
|
||||||
|
]
|
||||||
|
|
||||||
|
follow = (user, callback) ->
|
||||||
|
page = require('webpage').create()
|
||||||
|
page.open 'http://mobile.twitter.com/' + user, (status) ->
|
||||||
|
if status is 'fail'
|
||||||
|
console.log user + ': ?'
|
||||||
|
else
|
||||||
|
data = page.evaluate -> document.querySelector('div.timeline-following').innerText
|
||||||
|
console.log user + ': ' + data
|
||||||
|
callback.apply()
|
||||||
|
|
||||||
|
process = () ->
|
||||||
|
if (users.length > 0)
|
||||||
|
user = users[0]
|
||||||
|
users.splice(0, 1)
|
||||||
|
follow(user, process)
|
||||||
|
else
|
||||||
|
phantom.exit()
|
||||||
|
|
||||||
|
process()
|
|
@ -1,13 +1,35 @@
|
||||||
// List following and followers from several accounts
|
// List following and followers from several accounts
|
||||||
|
|
||||||
var users = ['PhantomJS',
|
var users = ['sencha',
|
||||||
|
'aconran',
|
||||||
|
'adityabansod',
|
||||||
|
'ambisinister',
|
||||||
|
'arnebech',
|
||||||
'ariyahidayat',
|
'ariyahidayat',
|
||||||
'detronizator',
|
'arthurakay',
|
||||||
'KDABQt',
|
'bmoeskau',
|
||||||
'lfranchi',
|
'darrellmeyer',
|
||||||
'jonleighton',
|
'davidfoelber',
|
||||||
'_jamesmgreene',
|
'DavidKaneda',
|
||||||
'Vitalliumm'];
|
'donovanerba',
|
||||||
|
'edspencer',
|
||||||
|
'evantrimboli',
|
||||||
|
'ExtAnimal',
|
||||||
|
'jamieavins',
|
||||||
|
'jarrednicholls',
|
||||||
|
'jayrobinson',
|
||||||
|
'lojjic',
|
||||||
|
'luckymethod',
|
||||||
|
'merrells',
|
||||||
|
'mmullany',
|
||||||
|
'philogb',
|
||||||
|
'philstrong',
|
||||||
|
'rdougan',
|
||||||
|
'SubtleGradient',
|
||||||
|
'__ted__',
|
||||||
|
'tmaintz',
|
||||||
|
'WesleyMoy',
|
||||||
|
'whereisthysting'];
|
||||||
|
|
||||||
function follow(user, callback) {
|
function follow(user, callback) {
|
||||||
var page = require('webpage').create();
|
var page = require('webpage').create();
|
||||||
|
@ -16,11 +38,10 @@ function follow(user, callback) {
|
||||||
console.log(user + ': ?');
|
console.log(user + ': ?');
|
||||||
} else {
|
} else {
|
||||||
var data = page.evaluate(function () {
|
var data = page.evaluate(function () {
|
||||||
return document.querySelector('div.profile td.stat.stat-last div.statnum').innerText;
|
return document.querySelector('div.timeline-following').innerText;
|
||||||
});
|
});
|
||||||
console.log(user + ': ' + data);
|
console.log(user + ': ' + data);
|
||||||
}
|
}
|
||||||
page.close();
|
|
||||||
callback.apply();
|
callback.apply();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
console.log 'Hello, world!'
|
||||||
|
phantom.exit()
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Upload an image to imagebin.org
|
||||||
|
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
if phantom.args.length isnt 1
|
||||||
|
console.log 'Usage: imagebin.coffee filename'
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
fname = phantom.args[0]
|
||||||
|
page.open 'http://imagebin.org/index.php?page=add', ->
|
||||||
|
page.uploadFile 'input[name=image]', fname
|
||||||
|
page.evaluate ->
|
||||||
|
document.querySelector('input[name=nickname]').value = 'phantom'
|
||||||
|
document.querySelector('input[name=disclaimer_agree]').click()
|
||||||
|
document.querySelector('form').submit()
|
||||||
|
|
||||||
|
window.setTimeout ->
|
||||||
|
phantom.exit()
|
||||||
|
, 3000
|
|
@ -1,14 +1,13 @@
|
||||||
// Upload an image to imagebin.org
|
// Upload an image to imagebin.org
|
||||||
|
|
||||||
var page = require('webpage').create(),
|
var page = require('webpage').create(),
|
||||||
system = require('system'),
|
|
||||||
fname;
|
fname;
|
||||||
|
|
||||||
if (system.args.length !== 2) {
|
if (phantom.args.length !== 1) {
|
||||||
console.log('Usage: imagebin.js filename');
|
console.log('Usage: imagebin.js filename');
|
||||||
phantom.exit(1);
|
phantom.exit();
|
||||||
} else {
|
} else {
|
||||||
fname = system.args[1];
|
fname = phantom.args[0];
|
||||||
page.open("http://imagebin.org/index.php?page=add", function () {
|
page.open("http://imagebin.org/index.php?page=add", function () {
|
||||||
page.uploadFile('input[name=image]', fname);
|
page.uploadFile('input[name=image]', fname);
|
||||||
page.evaluate(function () {
|
page.evaluate(function () {
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Use 'page.injectJs()' to load the script itself in the Page context
|
||||||
|
|
||||||
|
if phantom?
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
# Route "console.log()" calls from within the Page context to the main
|
||||||
|
# Phantom context (i.e. current "this")
|
||||||
|
page.onConsoleMessage = (msg) -> console.log(msg)
|
||||||
|
|
||||||
|
page.onAlert = (msg) -> console.log(msg)
|
||||||
|
|
||||||
|
console.log "* Script running in the Phantom context."
|
||||||
|
console.log "* Script will 'inject' itself in a page..."
|
||||||
|
page.open "about:blank", (status) ->
|
||||||
|
if status is "success"
|
||||||
|
if page.injectJs("injectme.coffee")
|
||||||
|
console.log "... done injecting itself!"
|
||||||
|
else
|
||||||
|
console.log "... fail! Check the $PWD?!"
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
alert "* Script running in the Page context."
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Give the estimated location based on the IP address.
|
||||||
|
|
||||||
|
window.cb = (data) ->
|
||||||
|
loc = data.city
|
||||||
|
if data.region_name.length > 0
|
||||||
|
loc = loc + ', ' + data.region_name
|
||||||
|
console.log 'IP address: ' + data.ip
|
||||||
|
console.log 'Estimated location: ' + loc
|
||||||
|
phantom.exit()
|
||||||
|
|
||||||
|
el = document.createElement 'script'
|
||||||
|
el.src = 'http://freegeoip.net/json/?callback=window.cb'
|
||||||
|
document.body.appendChild el
|
|
@ -0,0 +1,17 @@
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
if phantom.args.length is 0
|
||||||
|
console.log 'Usage: loadspeed.js <some URL>'
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
t = Date.now()
|
||||||
|
address = phantom.args[0]
|
||||||
|
page.open address, (status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log('FAIL to load the address')
|
||||||
|
else
|
||||||
|
t = Date.now() - t
|
||||||
|
console.log('Page title is ' + page.evaluate( (-> document.title) ))
|
||||||
|
console.log('Loading time ' + t + ' msec')
|
||||||
|
phantom.exit()
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
var page = require('webpage').create(),
|
var page = require('webpage').create(),
|
||||||
system = require('system'),
|
|
||||||
t, address;
|
t, address;
|
||||||
|
|
||||||
if (system.args.length === 1) {
|
if (phantom.args.length === 0) {
|
||||||
console.log('Usage: loadspeed.js <some URL>');
|
console.log('Usage: loadspeed.js <some URL>');
|
||||||
phantom.exit(1);
|
phantom.exit();
|
||||||
} else {
|
} else {
|
||||||
t = Date.now();
|
t = Date.now();
|
||||||
address = system.args[1];
|
address = phantom.args[0];
|
||||||
page.open(address, function (status) {
|
page.open(address, function (status) {
|
||||||
if (status !== 'success') {
|
if (status !== 'success') {
|
||||||
console.log('FAIL to load the address');
|
console.log('FAIL to load the address');
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
var page = require('webpage').create(),
|
|
||||||
system = require('system');
|
|
||||||
|
|
||||||
if (system.args.length < 2) {
|
|
||||||
console.log('Usage: loadurlwithoutcss.js URL');
|
|
||||||
phantom.exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var address = system.args[1];
|
|
||||||
|
|
||||||
page.onResourceRequested = function(requestData, request) {
|
|
||||||
if ((/http:\/\/.+?\.css/gi).test(requestData['url']) || requestData.headers['Content-Type'] == 'text/css') {
|
|
||||||
console.log('The url of the request is matching. Aborting: ' + requestData['url']);
|
|
||||||
request.abort();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
page.open(address, function(status) {
|
|
||||||
if (status === 'success') {
|
|
||||||
phantom.exit();
|
|
||||||
} else {
|
|
||||||
console.log('Unable to load the address!');
|
|
||||||
phantom.exit();
|
|
||||||
}
|
|
||||||
});
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +0,0 @@
|
||||||
var universe = require('./universe');
|
|
||||||
universe.start();
|
|
||||||
console.log('The answer is' + universe.answer);
|
|
||||||
phantom.exit();
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# List movies from kids-in-mind.com
|
||||||
|
|
||||||
|
window.cbfunc = (data) ->
|
||||||
|
globaldata = data
|
||||||
|
list = data.query.results.movie
|
||||||
|
for item in list
|
||||||
|
console.log item.title + ' [' + item.rating.MPAA.content + ']'
|
||||||
|
phantom.exit()
|
||||||
|
|
||||||
|
el = document.createElement 'script'
|
||||||
|
el.src =
|
||||||
|
"http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20movies.kids-in-mind&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=window.cbfunc"
|
||||||
|
document.body.appendChild el
|
|
@ -0,0 +1,17 @@
|
||||||
|
page = require('webpage').create()
|
||||||
|
address = phantom.args[0]
|
||||||
|
|
||||||
|
if phantom.args.length is 0
|
||||||
|
console.log 'Usage: netlog.coffee <some URL>'
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
page.onResourceRequested = (req) ->
|
||||||
|
console.log 'requested ' + JSON.stringify(req, undefined, 4)
|
||||||
|
|
||||||
|
page.onResourceReceived = (res) ->
|
||||||
|
console.log 'received ' + JSON.stringify(res, undefined, 4)
|
||||||
|
|
||||||
|
page.open address, (status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'FAIL to load the address'
|
||||||
|
phantom.exit()
|
|
@ -1,12 +1,10 @@
|
||||||
var page = require('webpage').create(),
|
var page = require('webpage').create(),
|
||||||
system = require('system'),
|
address = phantom.args[0];
|
||||||
address;
|
|
||||||
|
|
||||||
if (system.args.length === 1) {
|
if (phantom.args.length === 0) {
|
||||||
console.log('Usage: netlog.js <some URL>');
|
console.log('Usage: netlog.js <some URL>');
|
||||||
phantom.exit(1);
|
phantom.exit();
|
||||||
} else {
|
} else {
|
||||||
address = system.args[1];
|
|
||||||
|
|
||||||
page.onResourceRequested = function (req) {
|
page.onResourceRequested = function (req) {
|
||||||
console.log('requested: ' + JSON.stringify(req, undefined, 4));
|
console.log('requested: ' + JSON.stringify(req, undefined, 4));
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
if not Date::toISOString
|
||||||
|
Date::toISOString = ->
|
||||||
|
pad = (n) ->
|
||||||
|
if n < 10 then '0' + n else n
|
||||||
|
ms = (n) ->
|
||||||
|
if n < 10 then '00' + n else (if n < 100 then '0' + n else n)
|
||||||
|
@getFullYear() + '-' +
|
||||||
|
pad(@getMonth() + 1) + '-' +
|
||||||
|
pad(@getDate()) + 'T' +
|
||||||
|
pad(@getHours()) + ':' +
|
||||||
|
pad(@getMinutes()) + ':' +
|
||||||
|
pad(@getSeconds()) + '.' +
|
||||||
|
ms(@getMilliseconds()) + 'Z'
|
||||||
|
|
||||||
|
createHAR = (address, title, startTime, resources) ->
|
||||||
|
entries = []
|
||||||
|
|
||||||
|
resources.forEach (resource) ->
|
||||||
|
request = resource.request
|
||||||
|
startReply = resource.startReply
|
||||||
|
endReply = resource.endReply
|
||||||
|
|
||||||
|
if not request or not startReply or not endReply
|
||||||
|
return
|
||||||
|
|
||||||
|
entries.push
|
||||||
|
startedDateTime: request.time.toISOString()
|
||||||
|
time: endReply.time - request.time
|
||||||
|
request:
|
||||||
|
method: request.method
|
||||||
|
url: request.url
|
||||||
|
httpVersion: 'HTTP/1.1'
|
||||||
|
cookies: []
|
||||||
|
headers: request.headers
|
||||||
|
queryString: []
|
||||||
|
headersSize: -1
|
||||||
|
bodySize: -1
|
||||||
|
|
||||||
|
response:
|
||||||
|
status: endReply.status
|
||||||
|
statusText: endReply.statusText
|
||||||
|
httpVersion: 'HTTP/1.1'
|
||||||
|
cookies: []
|
||||||
|
headers: endReply.headers
|
||||||
|
redirectURL: ''
|
||||||
|
headersSize: -1
|
||||||
|
bodySize: startReply.bodySize
|
||||||
|
content:
|
||||||
|
size: startReply.bodySize
|
||||||
|
mimeType: endReply.contentType
|
||||||
|
|
||||||
|
cache: {}
|
||||||
|
timings:
|
||||||
|
blocked: 0
|
||||||
|
dns: -1
|
||||||
|
connect: -1
|
||||||
|
send: 0
|
||||||
|
wait: startReply.time - request.time
|
||||||
|
receive: endReply.time - startReply.time
|
||||||
|
ssl: -1
|
||||||
|
|
||||||
|
log:
|
||||||
|
version: '1.2'
|
||||||
|
creator:
|
||||||
|
name: 'PhantomJS'
|
||||||
|
version: phantom.version.major + '.' + phantom.version.minor + '.' + phantom.version.patch
|
||||||
|
|
||||||
|
pages: [
|
||||||
|
startedDateTime: startTime.toISOString()
|
||||||
|
id: address
|
||||||
|
title: title
|
||||||
|
pageTimings: {}
|
||||||
|
]
|
||||||
|
entries: entries
|
||||||
|
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
if phantom.args.length is 0
|
||||||
|
console.log 'Usage: netsniff.js <some URL>'
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
page.address = phantom.args[0]
|
||||||
|
page.resources = []
|
||||||
|
|
||||||
|
page.onLoadStarted = ->
|
||||||
|
page.startTime = new Date()
|
||||||
|
|
||||||
|
page.onResourceRequested = (req) ->
|
||||||
|
page.resources[req.id] =
|
||||||
|
request: req
|
||||||
|
startReply: null
|
||||||
|
endReply: null
|
||||||
|
|
||||||
|
page.onResourceReceived = (res) ->
|
||||||
|
if res.stage is 'start'
|
||||||
|
page.resources[res.id].startReply = res
|
||||||
|
if res.stage is 'end'
|
||||||
|
page.resources[res.id].endReply = res
|
||||||
|
|
||||||
|
page.open page.address, (status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'FAIL to load the address'
|
||||||
|
else
|
||||||
|
page.title = page.evaluate ->
|
||||||
|
document.title
|
||||||
|
|
||||||
|
har = createHAR page.address, page.title, page.startTime, page.resources
|
||||||
|
console.log JSON.stringify har, undefined, 4
|
||||||
|
phantom.exit()
|
|
@ -25,12 +25,6 @@ function createHAR(address, title, startTime, resources)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude Data URI from HAR file because
|
|
||||||
// they aren't included in specification
|
|
||||||
if (request.url.match(/(^data:image\/.*)/i)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entries.push({
|
entries.push({
|
||||||
startedDateTime: request.time.toISOString(),
|
startedDateTime: request.time.toISOString(),
|
||||||
time: endReply.time - request.time,
|
time: endReply.time - request.time,
|
||||||
|
@ -67,8 +61,7 @@ function createHAR(address, title, startTime, resources)
|
||||||
wait: startReply.time - request.time,
|
wait: startReply.time - request.time,
|
||||||
receive: endReply.time - startReply.time,
|
receive: endReply.time - startReply.time,
|
||||||
ssl: -1
|
ssl: -1
|
||||||
},
|
}
|
||||||
pageref: address
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -84,24 +77,21 @@ function createHAR(address, title, startTime, resources)
|
||||||
startedDateTime: startTime.toISOString(),
|
startedDateTime: startTime.toISOString(),
|
||||||
id: address,
|
id: address,
|
||||||
title: title,
|
title: title,
|
||||||
pageTimings: {
|
pageTimings: {}
|
||||||
onLoad: page.endTime - page.startTime
|
|
||||||
}
|
|
||||||
}],
|
}],
|
||||||
entries: entries
|
entries: entries
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var page = require('webpage').create(),
|
var page = require('webpage').create();
|
||||||
system = require('system');
|
|
||||||
|
|
||||||
if (system.args.length === 1) {
|
if (phantom.args.length === 0) {
|
||||||
console.log('Usage: netsniff.js <some URL>');
|
console.log('Usage: netsniff.js <some URL>');
|
||||||
phantom.exit(1);
|
phantom.exit();
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
page.address = system.args[1];
|
page.address = phantom.args[0];
|
||||||
page.resources = [];
|
page.resources = [];
|
||||||
|
|
||||||
page.onLoadStarted = function () {
|
page.onLoadStarted = function () {
|
||||||
|
@ -129,15 +119,13 @@ if (system.args.length === 1) {
|
||||||
var har;
|
var har;
|
||||||
if (status !== 'success') {
|
if (status !== 'success') {
|
||||||
console.log('FAIL to load the address');
|
console.log('FAIL to load the address');
|
||||||
phantom.exit(1);
|
|
||||||
} else {
|
} else {
|
||||||
page.endTime = new Date();
|
|
||||||
page.title = page.evaluate(function () {
|
page.title = page.evaluate(function () {
|
||||||
return document.title;
|
return document.title;
|
||||||
});
|
});
|
||||||
har = createHAR(page.address, page.title, page.startTime, page.resources);
|
har = createHAR(page.address, page.title, page.startTime, page.resources);
|
||||||
console.log(JSON.stringify(har, undefined, 4));
|
console.log(JSON.stringify(har, undefined, 4));
|
||||||
phantom.exit();
|
|
||||||
}
|
}
|
||||||
|
phantom.exit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
var page = require('webpage').create(),
|
|
||||||
system = require('system'),
|
|
||||||
host, port, address;
|
|
||||||
|
|
||||||
if (system.args.length < 4) {
|
|
||||||
console.log('Usage: openurlwithproxy.js <proxyHost> <proxyPort> <URL>');
|
|
||||||
phantom.exit(1);
|
|
||||||
} else {
|
|
||||||
host = system.args[1];
|
|
||||||
port = system.args[2];
|
|
||||||
address = system.args[3];
|
|
||||||
phantom.setProxy(host, port, 'manual', '', '');
|
|
||||||
page.open(address, function (status) {
|
|
||||||
if (status !== 'success') {
|
|
||||||
console.log('FAIL to load the address "' +
|
|
||||||
address + '" using proxy "' + host + ':' + port + '"');
|
|
||||||
} else {
|
|
||||||
console.log('Page title is ' + page.evaluate(function () {
|
|
||||||
return document.title;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
phantom.exit();
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
helloWorld = () -> console.log phantom.outputEncoding + ": こんにちは、世界!"
|
||||||
|
|
||||||
|
console.log "Using default encoding..."
|
||||||
|
helloWorld()
|
||||||
|
|
||||||
|
console.log "\nUsing other encodings..."
|
||||||
|
for enc in ["euc-jp", "sjis", "utf8", "System"]
|
||||||
|
do (enc) ->
|
||||||
|
phantom.outputEncoding = enc
|
||||||
|
helloWorld()
|
||||||
|
|
||||||
|
phantom.exit()
|
|
@ -1,146 +0,0 @@
|
||||||
// The purpose of this is to show how and when events fire, considering 5 steps
|
|
||||||
// happening as follows:
|
|
||||||
//
|
|
||||||
// 1. Load URL
|
|
||||||
// 2. Load same URL, but adding an internal FRAGMENT to it
|
|
||||||
// 3. Click on an internal Link, that points to another internal FRAGMENT
|
|
||||||
// 4. Click on an external Link, that will send the page somewhere else
|
|
||||||
// 5. Close page
|
|
||||||
//
|
|
||||||
// Take particular care when going through the output, to understand when
|
|
||||||
// things happen (and in which order). Particularly, notice what DOESN'T
|
|
||||||
// happen during step 3.
|
|
||||||
//
|
|
||||||
// If invoked with "-v" it will print out the Page Resources as they are
|
|
||||||
// Requested and Received.
|
|
||||||
//
|
|
||||||
// NOTE.1: The "onConsoleMessage/onAlert/onPrompt/onConfirm" events are
|
|
||||||
// registered but not used here. This is left for you to have fun with.
|
|
||||||
// NOTE.2: This script is not here to teach you ANY JavaScript. It's aweful!
|
|
||||||
// NOTE.3: Main audience for this are people new to PhantomJS.
|
|
||||||
|
|
||||||
var sys = require("system"),
|
|
||||||
page = require("webpage").create(),
|
|
||||||
logResources = false,
|
|
||||||
step1url = "http://en.wikipedia.org/wiki/DOM_events",
|
|
||||||
step2url = "http://en.wikipedia.org/wiki/DOM_events#Event_flow";
|
|
||||||
|
|
||||||
if (sys.args.length > 1 && sys.args[1] === "-v") {
|
|
||||||
logResources = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function printArgs() {
|
|
||||||
var i, ilen;
|
|
||||||
for (i = 0, ilen = arguments.length; i < ilen; ++i) {
|
|
||||||
console.log(" arguments[" + i + "] = " + JSON.stringify(arguments[i]));
|
|
||||||
}
|
|
||||||
console.log("");
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
page.onInitialized = function() {
|
|
||||||
console.log("page.onInitialized");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
page.onLoadStarted = function() {
|
|
||||||
console.log("page.onLoadStarted");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
page.onLoadFinished = function() {
|
|
||||||
console.log("page.onLoadFinished");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
page.onUrlChanged = function() {
|
|
||||||
console.log("page.onUrlChanged");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
page.onNavigationRequested = function() {
|
|
||||||
console.log("page.onNavigationRequested");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
page.onRepaintRequested = function() {
|
|
||||||
console.log("page.onRepaintRequested");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (logResources === true) {
|
|
||||||
page.onResourceRequested = function() {
|
|
||||||
console.log("page.onResourceRequested");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
page.onResourceReceived = function() {
|
|
||||||
console.log("page.onResourceReceived");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
page.onClosing = function() {
|
|
||||||
console.log("page.onClosing");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
// window.console.log(msg);
|
|
||||||
page.onConsoleMessage = function() {
|
|
||||||
console.log("page.onConsoleMessage");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
// window.alert(msg);
|
|
||||||
page.onAlert = function() {
|
|
||||||
console.log("page.onAlert");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
// var confirmed = window.confirm(msg);
|
|
||||||
page.onConfirm = function() {
|
|
||||||
console.log("page.onConfirm");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
// var user_value = window.prompt(msg, default_value);
|
|
||||||
page.onPrompt = function() {
|
|
||||||
console.log("page.onPrompt");
|
|
||||||
printArgs.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
console.log("");
|
|
||||||
console.log("### STEP 1: Load '" + step1url + "'");
|
|
||||||
page.open(step1url);
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
console.log("");
|
|
||||||
console.log("### STEP 2: Load '" + step2url + "' (load same URL plus FRAGMENT)");
|
|
||||||
page.open(step2url);
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
console.log("");
|
|
||||||
console.log("### STEP 3: Click on page internal link (aka FRAGMENT)");
|
|
||||||
page.evaluate(function() {
|
|
||||||
var ev = document.createEvent("MouseEvents");
|
|
||||||
ev.initEvent("click", true, true);
|
|
||||||
document.querySelector("a[href='#Event_object']").dispatchEvent(ev);
|
|
||||||
});
|
|
||||||
}, 10000);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
console.log("");
|
|
||||||
console.log("### STEP 4: Click on page external link");
|
|
||||||
page.evaluate(function() {
|
|
||||||
var ev = document.createEvent("MouseEvents");
|
|
||||||
ev.initEvent("click", true, true);
|
|
||||||
document.querySelector("a[title='JavaScript']").dispatchEvent(ev);
|
|
||||||
});
|
|
||||||
}, 15000);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
console.log("");
|
|
||||||
console.log("### STEP 5: Close page and shutdown (with a delay)");
|
|
||||||
page.close();
|
|
||||||
setTimeout(function(){
|
|
||||||
phantom.exit();
|
|
||||||
}, 100);
|
|
||||||
}, 20000);
|
|
|
@ -1,17 +0,0 @@
|
||||||
var p = require("webpage").create();
|
|
||||||
|
|
||||||
p.onConsoleMessage = function(msg) { console.log(msg); };
|
|
||||||
|
|
||||||
// Calls to "callPhantom" within the page 'p' arrive here
|
|
||||||
p.onCallback = function(msg) {
|
|
||||||
console.log("Received by the 'phantom' main context: "+msg);
|
|
||||||
return "Hello there, I'm coming to you from the 'phantom' context instead";
|
|
||||||
};
|
|
||||||
|
|
||||||
p.evaluate(function() {
|
|
||||||
// Return-value of the "onCallback" handler arrive here
|
|
||||||
var callbackResponse = window.callPhantom("Hello, I'm coming to you from the 'page' context");
|
|
||||||
console.log("Received by the 'page' context: "+callbackResponse);
|
|
||||||
});
|
|
||||||
|
|
||||||
phantom.exit();
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Read the Phantom webpage '#intro' element text using jQuery and "includeJs"
|
||||||
|
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
page.onConsoleMessage = (msg) -> console.log msg
|
||||||
|
|
||||||
|
page.open "http://www.phantomjs.org", (status) ->
|
||||||
|
if status is "success"
|
||||||
|
page.includeJs "http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", ->
|
||||||
|
page.evaluate ->
|
||||||
|
console.log "$(\"#intro\").text() -> " + $("#intro").text()
|
||||||
|
phantom.exit()
|
||||||
|
|
|
@ -10,7 +10,7 @@ page.open("http://www.phantomjs.org", function(status) {
|
||||||
if ( status === "success" ) {
|
if ( status === "success" ) {
|
||||||
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
|
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
|
||||||
page.evaluate(function() {
|
page.evaluate(function() {
|
||||||
console.log("$(\".explanation\").text() -> " + $(".explanation").text());
|
console.log("$(\"#intro\").text() -> " + $("#intro").text());
|
||||||
});
|
});
|
||||||
phantom.exit();
|
phantom.exit();
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Find pizza in Mountain View using Yelp
|
||||||
|
|
||||||
|
page = require('webpage').create()
|
||||||
|
url = 'http://lite.yelp.com/search?find_desc=pizza&find_loc=94040&find_submit=Search'
|
||||||
|
|
||||||
|
page.open url,
|
||||||
|
(status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'Unable to access network'
|
||||||
|
else
|
||||||
|
results = page.evaluate ->
|
||||||
|
pizza = []
|
||||||
|
list = document.querySelectorAll 'span.address'
|
||||||
|
for item in list
|
||||||
|
pizza.push(item.innerText)
|
||||||
|
return pizza
|
||||||
|
console.log results.join('\n')
|
||||||
|
phantom.exit()
|
|
@ -8,7 +8,7 @@ page.open(url, function (status) {
|
||||||
console.log('Unable to access network');
|
console.log('Unable to access network');
|
||||||
} else {
|
} else {
|
||||||
var results = page.evaluate(function() {
|
var results = page.evaluate(function() {
|
||||||
var list = document.querySelectorAll('address'), pizza = [], i;
|
var list = document.querySelectorAll('span.address'), pizza = [], i;
|
||||||
for (i = 0; i < list.length; i++) {
|
for (i = 0; i < list.length; i++) {
|
||||||
pizza.push(list[i].innerText);
|
pizza.push(list[i].innerText);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Example using HTTP POST operation
|
||||||
|
|
||||||
|
page = require('webpage').create()
|
||||||
|
server = 'http://posttestserver.com/post.php?dump'
|
||||||
|
data = 'universe=expanding&answer=42'
|
||||||
|
|
||||||
|
page.open server, 'post', data, (status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'Unable to post!'
|
||||||
|
else
|
||||||
|
console.log page.content
|
||||||
|
phantom.exit()
|
|
@ -1,18 +0,0 @@
|
||||||
// Example using HTTP POST operation
|
|
||||||
|
|
||||||
var page = require('webpage').create(),
|
|
||||||
server = 'http://posttestserver.com/post.php?dump',
|
|
||||||
data = '{"universe": "expanding", "answer": 42}';
|
|
||||||
|
|
||||||
var headers = {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
}
|
|
||||||
|
|
||||||
page.open(server, 'post', data, headers, function (status) {
|
|
||||||
if (status !== 'success') {
|
|
||||||
console.log('Unable to post!');
|
|
||||||
} else {
|
|
||||||
console.log(page.content);
|
|
||||||
}
|
|
||||||
phantom.exit();
|
|
||||||
});
|
|
|
@ -1,34 +0,0 @@
|
||||||
// Example using HTTP POST operation
|
|
||||||
|
|
||||||
var page = require('webpage').create(),
|
|
||||||
server = require('webserver').create(),
|
|
||||||
system = require('system'),
|
|
||||||
data = 'universe=expanding&answer=42';
|
|
||||||
|
|
||||||
if (system.args.length !== 2) {
|
|
||||||
console.log('Usage: postserver.js <portnumber>');
|
|
||||||
phantom.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var port = system.args[1];
|
|
||||||
|
|
||||||
service = server.listen(port, function (request, response) {
|
|
||||||
console.log('Request received at ' + new Date());
|
|
||||||
|
|
||||||
response.statusCode = 200;
|
|
||||||
response.headers = {
|
|
||||||
'Cache': 'no-cache',
|
|
||||||
'Content-Type': 'text/plain;charset=utf-8'
|
|
||||||
};
|
|
||||||
response.write(JSON.stringify(request, null, 4));
|
|
||||||
response.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
page.open('http://localhost:' + port + '/', 'post', data, function (status) {
|
|
||||||
if (status !== 'success') {
|
|
||||||
console.log('Unable to post!');
|
|
||||||
} else {
|
|
||||||
console.log(page.plainText);
|
|
||||||
}
|
|
||||||
phantom.exit();
|
|
||||||
});
|
|
|
@ -1,10 +0,0 @@
|
||||||
var system = require('system'),
|
|
||||||
env = system.env,
|
|
||||||
key;
|
|
||||||
|
|
||||||
for (key in env) {
|
|
||||||
if (env.hasOwnProperty(key)) {
|
|
||||||
console.log(key + '=' + env[key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
phantom.exit();
|
|
|
@ -1,89 +0,0 @@
|
||||||
var page = require('webpage').create(),
|
|
||||||
system = require('system');
|
|
||||||
|
|
||||||
function someCallback(pageNum, numPages) {
|
|
||||||
return "<h1> someCallback: " + pageNum + " / " + numPages + "</h1>";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (system.args.length < 3) {
|
|
||||||
console.log('Usage: printheaderfooter.js URL filename');
|
|
||||||
phantom.exit(1);
|
|
||||||
} else {
|
|
||||||
var address = system.args[1];
|
|
||||||
var output = system.args[2];
|
|
||||||
page.viewportSize = { width: 600, height: 600 };
|
|
||||||
page.paperSize = {
|
|
||||||
format: 'A4',
|
|
||||||
margin: "1cm",
|
|
||||||
/* default header/footer for pages that don't have custom overwrites (see below) */
|
|
||||||
header: {
|
|
||||||
height: "1cm",
|
|
||||||
contents: phantom.callback(function(pageNum, numPages) {
|
|
||||||
if (pageNum == 1) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return "<h1>Header <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
|
|
||||||
})
|
|
||||||
},
|
|
||||||
footer: {
|
|
||||||
height: "1cm",
|
|
||||||
contents: phantom.callback(function(pageNum, numPages) {
|
|
||||||
if (pageNum == numPages) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return "<h1>Footer <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
page.open(address, function (status) {
|
|
||||||
if (status !== 'success') {
|
|
||||||
console.log('Unable to load the address!');
|
|
||||||
} else {
|
|
||||||
/* check whether the loaded page overwrites the header/footer setting,
|
|
||||||
i.e. whether a PhantomJSPriting object exists. Use that then instead
|
|
||||||
of our defaults above.
|
|
||||||
|
|
||||||
example:
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<script type="text/javascript">
|
|
||||||
var PhantomJSPrinting = {
|
|
||||||
header: {
|
|
||||||
height: "1cm",
|
|
||||||
contents: function(pageNum, numPages) { return pageNum + "/" + numPages; }
|
|
||||||
},
|
|
||||||
footer: {
|
|
||||||
height: "1cm",
|
|
||||||
contents: function(pageNum, numPages) { return pageNum + "/" + numPages; }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body><h1>asdfadsf</h1><p>asdfadsfycvx</p></body>
|
|
||||||
</html>
|
|
||||||
*/
|
|
||||||
if (page.evaluate(function(){return typeof PhantomJSPrinting == "object";})) {
|
|
||||||
paperSize = page.paperSize;
|
|
||||||
paperSize.header.height = page.evaluate(function() {
|
|
||||||
return PhantomJSPrinting.header.height;
|
|
||||||
});
|
|
||||||
paperSize.header.contents = phantom.callback(function(pageNum, numPages) {
|
|
||||||
return page.evaluate(function(pageNum, numPages){return PhantomJSPrinting.header.contents(pageNum, numPages);}, pageNum, numPages);
|
|
||||||
});
|
|
||||||
paperSize.footer.height = page.evaluate(function() {
|
|
||||||
return PhantomJSPrinting.footer.height;
|
|
||||||
});
|
|
||||||
paperSize.footer.contents = phantom.callback(function(pageNum, numPages) {
|
|
||||||
return page.evaluate(function(pageNum, numPages){return PhantomJSPrinting.footer.contents(pageNum, numPages);}, pageNum, numPages);
|
|
||||||
});
|
|
||||||
page.paperSize = paperSize;
|
|
||||||
console.log(page.paperSize.header.height);
|
|
||||||
console.log(page.paperSize.footer.height);
|
|
||||||
}
|
|
||||||
window.setTimeout(function () {
|
|
||||||
page.render(output);
|
|
||||||
phantom.exit();
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
var page = require('webpage').create(),
|
|
||||||
system = require('system');
|
|
||||||
|
|
||||||
if (system.args.length < 7) {
|
|
||||||
console.log('Usage: printmargins.js URL filename LEFT TOP RIGHT BOTTOM');
|
|
||||||
console.log(' margin examples: "1cm", "10px", "7mm", "5in"');
|
|
||||||
phantom.exit(1);
|
|
||||||
} else {
|
|
||||||
var address = system.args[1];
|
|
||||||
var output = system.args[2];
|
|
||||||
var marginLeft = system.args[3];
|
|
||||||
var marginTop = system.args[4];
|
|
||||||
var marginRight = system.args[5];
|
|
||||||
var marginBottom = system.args[6];
|
|
||||||
page.viewportSize = { width: 600, height: 600 };
|
|
||||||
page.paperSize = {
|
|
||||||
format: 'A4',
|
|
||||||
margin: {
|
|
||||||
left: marginLeft,
|
|
||||||
top: marginTop,
|
|
||||||
right: marginRight,
|
|
||||||
bottom: marginBottom
|
|
||||||
}
|
|
||||||
};
|
|
||||||
page.open(address, function (status) {
|
|
||||||
if (status !== 'success') {
|
|
||||||
console.log('Unable to load the address!');
|
|
||||||
} else {
|
|
||||||
window.setTimeout(function () {
|
|
||||||
page.render(output);
|
|
||||||
phantom.exit();
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
if phantom.args.length < 2 or phantom.args.length > 3
|
||||||
|
console.log 'Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat]'
|
||||||
|
console.log ' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"'
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
address = phantom.args[0]
|
||||||
|
output = phantom.args[1]
|
||||||
|
page.viewportSize = { width: 600, height: 600 }
|
||||||
|
if phantom.args.length is 3 and phantom.args[1].substr(-4) is ".pdf"
|
||||||
|
size = phantom.args[2].split '*'
|
||||||
|
if size.length is 2
|
||||||
|
page.paperSize = { width: size[0], height: size[1], border: '0px' }
|
||||||
|
else
|
||||||
|
page.paperSize = { format: phantom.args[2], orientation: 'portrait', border: '1cm' }
|
||||||
|
page.open address, (status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'Unable to load the address!'
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
window.setTimeout (-> page.render output; phantom.exit()), 200
|
|
@ -1,43 +1,22 @@
|
||||||
var page = require('webpage').create(),
|
var page = require('webpage').create(),
|
||||||
system = require('system'),
|
|
||||||
address, output, size;
|
address, output, size;
|
||||||
|
|
||||||
if (system.args.length < 3 || system.args.length > 5) {
|
if (phantom.args.length < 2 || phantom.args.length > 3) {
|
||||||
console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]');
|
console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat]');
|
||||||
console.log(' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
|
console.log(' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
|
||||||
console.log(' image (png/jpg output) examples: "1920px" entire page, window width 1920px');
|
phantom.exit();
|
||||||
console.log(' "800px*600px" window, clipped to 800x600');
|
|
||||||
phantom.exit(1);
|
|
||||||
} else {
|
} else {
|
||||||
address = system.args[1];
|
address = phantom.args[0];
|
||||||
output = system.args[2];
|
output = phantom.args[1];
|
||||||
page.viewportSize = { width: 600, height: 600 };
|
page.viewportSize = { width: 600, height: 600 };
|
||||||
if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") {
|
if (phantom.args.length === 3 && phantom.args[1].substr(-4) === ".pdf") {
|
||||||
size = system.args[3].split('*');
|
size = phantom.args[2].split('*');
|
||||||
page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' }
|
page.paperSize = size.length === 2 ? { width: size[0], height: size[1], border: '0px' }
|
||||||
: { format: system.args[3], orientation: 'portrait', margin: '1cm' };
|
: { format: phantom.args[2], orientation: 'portrait', border: '1cm' };
|
||||||
} else if (system.args.length > 3 && system.args[3].substr(-2) === "px") {
|
|
||||||
size = system.args[3].split('*');
|
|
||||||
if (size.length === 2) {
|
|
||||||
pageWidth = parseInt(size[0], 10);
|
|
||||||
pageHeight = parseInt(size[1], 10);
|
|
||||||
page.viewportSize = { width: pageWidth, height: pageHeight };
|
|
||||||
page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight };
|
|
||||||
} else {
|
|
||||||
console.log("size:", system.args[3]);
|
|
||||||
pageWidth = parseInt(system.args[3], 10);
|
|
||||||
pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any
|
|
||||||
console.log ("pageHeight:",pageHeight);
|
|
||||||
page.viewportSize = { width: pageWidth, height: pageHeight };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (system.args.length > 4) {
|
|
||||||
page.zoomFactor = system.args[4];
|
|
||||||
}
|
}
|
||||||
page.open(address, function (status) {
|
page.open(address, function (status) {
|
||||||
if (status !== 'success') {
|
if (status !== 'success') {
|
||||||
console.log('Unable to load the address!');
|
console.log('Unable to load the address!');
|
||||||
phantom.exit(1);
|
|
||||||
} else {
|
} else {
|
||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
page.render(output);
|
page.render(output);
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
# Render Multiple URLs to file
|
||||||
|
# FIXME: For now it is fine with pure domain names: don't think it would work with paths and stuff like that
|
||||||
|
|
||||||
|
# Extend the Array Prototype with a 'foreach'
|
||||||
|
Array.prototype.forEach = (action) ->
|
||||||
|
for i, j in this
|
||||||
|
action j, i, _len
|
||||||
|
|
||||||
|
# Render a given url to a given file
|
||||||
|
# @param url URL to render
|
||||||
|
# @param file File to render to
|
||||||
|
# @param callback Callback function
|
||||||
|
renderUrlToFile = (url, file, callback) ->
|
||||||
|
page = require('webpage').create()
|
||||||
|
page.viewportSize = { width: 800, height : 600 }
|
||||||
|
page.settings.userAgent = 'Phantom.js bot'
|
||||||
|
|
||||||
|
page.open url, (status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log "Unable to render '#{url}'"
|
||||||
|
else
|
||||||
|
page.render file
|
||||||
|
|
||||||
|
delete page
|
||||||
|
callback url, file
|
||||||
|
|
||||||
|
# Read the passed args
|
||||||
|
if phantom.args.length > 0
|
||||||
|
arrayOfUrls = phantom.args
|
||||||
|
else
|
||||||
|
# Default (no args passed)
|
||||||
|
console.log 'Usage: phantomjs render_multi_url.coffee [domain.name1, domain.name2, ...]'
|
||||||
|
arrayOfUrls = [
|
||||||
|
'www.google.com',
|
||||||
|
'www.bbc.co.uk',
|
||||||
|
'www.phantomjs.org'
|
||||||
|
]
|
||||||
|
|
||||||
|
# For each URL
|
||||||
|
arrayOfUrls.forEach (pos, url, total) ->
|
||||||
|
file_name = "./#{url}.png"
|
||||||
|
|
||||||
|
# Render to a file
|
||||||
|
renderUrlToFile "http://#{url}", file_name, (url, file) ->
|
||||||
|
console.log "Rendered '#{url}' at '#{file}'"
|
||||||
|
if pos is total - 1
|
||||||
|
# Close Phantom if it's the last URL
|
||||||
|
phantom.exit()
|
|
@ -1,73 +1,60 @@
|
||||||
// Render Multiple URLs to file
|
// Render Multiple URLs to file
|
||||||
|
// FIXME: For now it is fine with pure domain names: don't think it would work with paths and stuff like that
|
||||||
|
|
||||||
var RenderUrlsToFile, arrayOfUrls, system;
|
// Extend the Array Prototype with a 'foreach'
|
||||||
|
Array.prototype.forEach = function (action) {
|
||||||
system = require("system");
|
var i, len;
|
||||||
|
for ( i = 0, len = this.length; i < len; ++i ) {
|
||||||
/*
|
action(i, this[i], len);
|
||||||
Render given urls
|
|
||||||
@param array of URLs to render
|
|
||||||
@param callbackPerUrl Function called after finishing each URL, including the last URL
|
|
||||||
@param callbackFinal Function called after finishing everything
|
|
||||||
*/
|
|
||||||
RenderUrlsToFile = function(urls, callbackPerUrl, callbackFinal) {
|
|
||||||
var getFilename, next, page, retrieve, urlIndex, webpage;
|
|
||||||
urlIndex = 0;
|
|
||||||
webpage = require("webpage");
|
|
||||||
page = null;
|
|
||||||
getFilename = function() {
|
|
||||||
return "rendermulti-" + urlIndex + ".png";
|
|
||||||
};
|
|
||||||
next = function(status, url, file) {
|
|
||||||
page.close();
|
|
||||||
callbackPerUrl(status, url, file);
|
|
||||||
return retrieve();
|
|
||||||
};
|
|
||||||
retrieve = function() {
|
|
||||||
var url;
|
|
||||||
if (urls.length > 0) {
|
|
||||||
url = urls.shift();
|
|
||||||
urlIndex++;
|
|
||||||
page = webpage.create();
|
|
||||||
page.viewportSize = {
|
|
||||||
width: 800,
|
|
||||||
height: 600
|
|
||||||
};
|
|
||||||
page.settings.userAgent = "Phantom.js bot";
|
|
||||||
return page.open("http://" + url, function(status) {
|
|
||||||
var file;
|
|
||||||
file = getFilename();
|
|
||||||
if (status === "success") {
|
|
||||||
return window.setTimeout((function() {
|
|
||||||
page.render(file);
|
|
||||||
return next(status, url, file);
|
|
||||||
}), 200);
|
|
||||||
} else {
|
|
||||||
return next(status, url, file);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return callbackFinal();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return retrieve();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
arrayOfUrls = null;
|
/**
|
||||||
|
* Render a given url to a given file
|
||||||
|
* @param url URL to render
|
||||||
|
* @param file File to render to
|
||||||
|
* @param callback Callback function
|
||||||
|
*/
|
||||||
|
function renderUrlToFile(url, file, callback) {
|
||||||
|
var page = require('webpage').create();
|
||||||
|
page.viewportSize = { width: 800, height : 600 };
|
||||||
|
page.settings.userAgent = "Phantom.js bot";
|
||||||
|
|
||||||
if (system.args.length > 1) {
|
page.open(url, function(status){
|
||||||
arrayOfUrls = Array.prototype.slice.call(system.args, 1);
|
if ( status !== "success") {
|
||||||
} else {
|
console.log("Unable to render '"+url+"'");
|
||||||
console.log("Usage: phantomjs render_multi_url.js [domain.name1, domain.name2, ...]");
|
} else {
|
||||||
arrayOfUrls = ["www.google.com", "www.bbc.co.uk", "www.phantomjs.org"];
|
page.render(file);
|
||||||
|
}
|
||||||
|
delete page;
|
||||||
|
callback(url, file);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderUrlsToFile(arrayOfUrls, (function(status, url, file) {
|
// Read the passed args
|
||||||
if (status !== "success") {
|
var arrayOfUrls;
|
||||||
return console.log("Unable to render '" + url + "'");
|
if ( phantom.args.length > 0 ) {
|
||||||
} else {
|
arrayOfUrls = phantom.args;
|
||||||
return console.log("Rendered '" + url + "' at '" + file + "'");
|
} else {
|
||||||
|
// Default (no args passed)
|
||||||
|
console.log("Usage: phantomjs render_multi_url.js [domain.name1, domain.name2, ...]");
|
||||||
|
arrayOfUrls = [
|
||||||
|
'www.google.com',
|
||||||
|
'www.bbc.co.uk',
|
||||||
|
'www.phantomjs.org'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each URL
|
||||||
|
arrayOfUrls.forEach(function(pos, url, total){
|
||||||
|
var file_name = "./" + url + ".png";
|
||||||
|
|
||||||
|
// Render to a file
|
||||||
|
renderUrlToFile("http://"+url, file_name, function(url, file){
|
||||||
|
console.log("Rendered '"+url+"' at '"+file+"'");
|
||||||
|
if ( pos === total-1 ) {
|
||||||
|
// Close Phantom if it's the last URL
|
||||||
|
phantom.exit();
|
||||||
}
|
}
|
||||||
}), function() {
|
});
|
||||||
return phantom.exit();
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
##
|
||||||
|
# Wait until the test condition is true or a timeout occurs. Useful for waiting
|
||||||
|
# on a server response or for a ui change (fadeIn, etc.) to occur.
|
||||||
|
#
|
||||||
|
# @param testFx javascript condition that evaluates to a boolean,
|
||||||
|
# it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
|
||||||
|
# as a callback function.
|
||||||
|
# @param onReady what to do when testFx condition is fulfilled,
|
||||||
|
# it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
|
||||||
|
# as a callback function.
|
||||||
|
# @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
|
||||||
|
##
|
||||||
|
waitFor = (testFx, onReady, timeOutMillis=3000) ->
|
||||||
|
start = new Date().getTime()
|
||||||
|
condition = false
|
||||||
|
f = ->
|
||||||
|
if (new Date().getTime() - start < timeOutMillis) and not condition
|
||||||
|
# If not time-out yet and condition not yet fulfilled
|
||||||
|
condition = (if typeof testFx is 'string' then eval testFx else testFx()) #< defensive code
|
||||||
|
else
|
||||||
|
if not condition
|
||||||
|
# If condition still not fulfilled (timeout but condition is 'false')
|
||||||
|
console.log "'waitFor()' timeout"
|
||||||
|
phantom.exit(1)
|
||||||
|
else
|
||||||
|
# Condition fulfilled (timeout and/or condition is 'true')
|
||||||
|
console.log "'waitFor()' finished in #{new Date().getTime() - start}ms."
|
||||||
|
if typeof onReady is 'string' then eval onReady else onReady() #< Do what it's supposed to do once the condition is fulfilled
|
||||||
|
clearInterval interval #< Stop this interval
|
||||||
|
interval = setInterval f, 100 #< repeat check every 100ms
|
||||||
|
|
||||||
|
if phantom.args.length isnt 1
|
||||||
|
console.log 'Usage: run-jasmine.coffee URL'
|
||||||
|
phantom.exit()
|
||||||
|
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
# Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
|
||||||
|
page.onConsoleMessage = (msg) ->
|
||||||
|
console.log msg
|
||||||
|
|
||||||
|
page.open phantom.args[0], (status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'Unable to access network'
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
waitFor ->
|
||||||
|
page.evaluate ->
|
||||||
|
if document.body.querySelector '.finished-at'
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
, ->
|
||||||
|
page.evaluate ->
|
||||||
|
console.log document.body.querySelector('.description').innerText
|
||||||
|
list = document.body.querySelectorAll('.failed > .description, .failed > .messages > .resultMessage')
|
||||||
|
for el in list
|
||||||
|
console.log el.innerText
|
||||||
|
|
||||||
|
phantom.exit()
|
|
@ -1,5 +1,3 @@
|
||||||
var system = require('system');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait until the test condition is true or a timeout occurs. Useful for waiting
|
* Wait until the test condition is true or a timeout occurs. Useful for waiting
|
||||||
* on a server response or for a ui change (fadeIn, etc.) to occur.
|
* on a server response or for a ui change (fadeIn, etc.) to occur.
|
||||||
|
@ -36,9 +34,9 @@ function waitFor(testFx, onReady, timeOutMillis) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (system.args.length !== 2) {
|
if (phantom.args.length === 0 || phantom.args.length > 2) {
|
||||||
console.log('Usage: run-jasmine.js URL');
|
console.log('Usage: run-jasmine.js URL');
|
||||||
phantom.exit(1);
|
phantom.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
var page = require('webpage').create();
|
var page = require('webpage').create();
|
||||||
|
@ -48,44 +46,32 @@ page.onConsoleMessage = function(msg) {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
page.open(system.args[1], function(status){
|
page.open(phantom.args[0], function(status){
|
||||||
if (status !== "success") {
|
if (status !== "success") {
|
||||||
console.log("Unable to open " + system.args[1]);
|
console.log("Unable to access network");
|
||||||
phantom.exit(1);
|
phantom.exit();
|
||||||
} else {
|
} else {
|
||||||
waitFor(function(){
|
waitFor(function(){
|
||||||
return page.evaluate(function(){
|
return page.evaluate(function(){
|
||||||
return document.body.querySelector('.symbolSummary .pending') === null
|
if (document.body.querySelector('.finished-at')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
}, function(){
|
}, function(){
|
||||||
var exitCode = page.evaluate(function(){
|
page.evaluate(function(){
|
||||||
try {
|
|
||||||
console.log('');
|
|
||||||
console.log(document.body.querySelector('.description').innerText);
|
console.log(document.body.querySelector('.description').innerText);
|
||||||
var list = document.body.querySelectorAll('.results > #details > .specDetail.failed');
|
list = document.body.querySelectorAll('div.jasmine_reporter > div.suite.failed');
|
||||||
if (list && list.length > 0) {
|
|
||||||
console.log('');
|
|
||||||
console.log(list.length + ' test(s) FAILED:');
|
|
||||||
for (i = 0; i < list.length; ++i) {
|
for (i = 0; i < list.length; ++i) {
|
||||||
var el = list[i],
|
el = list[i];
|
||||||
desc = el.querySelector('.description'),
|
desc = el.querySelectorAll('.description');
|
||||||
msg = el.querySelector('.resultMessage.fail');
|
|
||||||
console.log('');
|
|
||||||
console.log(desc.innerText);
|
|
||||||
console.log(msg.innerText);
|
|
||||||
console.log('');
|
console.log('');
|
||||||
|
for (j = 0; j < desc.length; ++j) {
|
||||||
|
console.log(desc[j].innerText);
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
console.log(document.body.querySelector('.alert > .passingAlert.bar').innerText);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
console.log(ex);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
phantom.exit(exitCode);
|
phantom.exit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
var system = require('system');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait until the test condition is true or a timeout occurs. Useful for waiting
|
|
||||||
* on a server response or for a ui change (fadeIn, etc.) to occur.
|
|
||||||
*
|
|
||||||
* @param testFx javascript condition that evaluates to a boolean,
|
|
||||||
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
|
|
||||||
* as a callback function.
|
|
||||||
* @param onReady what to do when testFx condition is fulfilled,
|
|
||||||
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
|
|
||||||
* as a callback function.
|
|
||||||
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
|
|
||||||
*/
|
|
||||||
function waitFor(testFx, onReady, timeOutMillis) {
|
|
||||||
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timeout is 3s
|
|
||||||
start = new Date().getTime(),
|
|
||||||
condition = false,
|
|
||||||
interval = setInterval(function() {
|
|
||||||
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
|
|
||||||
// If not time-out yet and condition not yet fulfilled
|
|
||||||
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
|
|
||||||
} else {
|
|
||||||
if(!condition) {
|
|
||||||
// If condition still not fulfilled (timeout but condition is 'false')
|
|
||||||
console.log("'waitFor()' timeout");
|
|
||||||
phantom.exit(1);
|
|
||||||
} else {
|
|
||||||
// Condition fulfilled (timeout and/or condition is 'true')
|
|
||||||
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
|
|
||||||
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
|
|
||||||
clearInterval(interval); //< Stop this interval
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 100); //< repeat check every 100ms
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
if (system.args.length !== 2) {
|
|
||||||
console.log('Usage: run-jasmine.js URL');
|
|
||||||
phantom.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var page = require('webpage').create();
|
|
||||||
|
|
||||||
// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
|
|
||||||
page.onConsoleMessage = function(msg) {
|
|
||||||
console.log(msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
page.open(system.args[1], function(status){
|
|
||||||
if (status !== "success") {
|
|
||||||
console.log("Unable to access network");
|
|
||||||
phantom.exit();
|
|
||||||
} else {
|
|
||||||
waitFor(function(){
|
|
||||||
return page.evaluate(function(){
|
|
||||||
return document.body.querySelector('.symbolSummary .pending') === null
|
|
||||||
});
|
|
||||||
}, function(){
|
|
||||||
var exitCode = page.evaluate(function(){
|
|
||||||
console.log('');
|
|
||||||
|
|
||||||
var el = document.body.querySelector('.banner');
|
|
||||||
var banner = el.querySelector('.title').innerText + " " +
|
|
||||||
el.querySelector('.version').innerText + " " +
|
|
||||||
el.querySelector('.duration').innerText;
|
|
||||||
console.log(banner);
|
|
||||||
|
|
||||||
var list = document.body.querySelectorAll('.results > .failures > .spec-detail.failed');
|
|
||||||
if (list && list.length > 0) {
|
|
||||||
console.log('');
|
|
||||||
console.log(list.length + ' test(s) FAILED:');
|
|
||||||
for (i = 0; i < list.length; ++i) {
|
|
||||||
var el = list[i],
|
|
||||||
desc = el.querySelector('.description'),
|
|
||||||
msg = el.querySelector('.messages > .result-message');
|
|
||||||
console.log('');
|
|
||||||
console.log(desc.innerText);
|
|
||||||
console.log(msg.innerText);
|
|
||||||
console.log('');
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
console.log(document.body.querySelector('.alert > .bar.passed').innerText);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
phantom.exit(exitCode);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
##
|
||||||
|
# Wait until the test condition is true or a timeout occurs. Useful for waiting
|
||||||
|
# on a server response or for a ui change (fadeIn, etc.) to occur.
|
||||||
|
#
|
||||||
|
# @param testFx javascript condition that evaluates to a boolean,
|
||||||
|
# it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
|
||||||
|
# as a callback function.
|
||||||
|
# @param onReady what to do when testFx condition is fulfilled,
|
||||||
|
# it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
|
||||||
|
# as a callback function.
|
||||||
|
# @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
|
||||||
|
##
|
||||||
|
waitFor = (testFx, onReady, timeOutMillis=3000) ->
|
||||||
|
start = new Date().getTime()
|
||||||
|
condition = false
|
||||||
|
f = ->
|
||||||
|
if (new Date().getTime() - start < timeOutMillis) and not condition
|
||||||
|
# If not time-out yet and condition not yet fulfilled
|
||||||
|
condition = (if typeof testFx is 'string' then eval testFx else testFx()) #< defensive code
|
||||||
|
else
|
||||||
|
if not condition
|
||||||
|
# If condition still not fulfilled (timeout but condition is 'false')
|
||||||
|
console.log "'waitFor()' timeout"
|
||||||
|
phantom.exit(1)
|
||||||
|
else
|
||||||
|
# Condition fulfilled (timeout and/or condition is 'true')
|
||||||
|
console.log "'waitFor()' finished in #{new Date().getTime() - start}ms."
|
||||||
|
if typeof onReady is 'string' then eval onReady else onReady() #< Do what it's supposed to do once the condition is fulfilled
|
||||||
|
clearInterval interval #< Stop this interval
|
||||||
|
interval = setInterval f, 100 #< repeat check every 100ms
|
||||||
|
|
||||||
|
if phantom.args.length isnt 1
|
||||||
|
console.log 'Usage: run-qunit.coffee URL'
|
||||||
|
phantom.exit(1)
|
||||||
|
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
# Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
|
||||||
|
page.onConsoleMessage = (msg) ->
|
||||||
|
console.log msg
|
||||||
|
|
||||||
|
page.open phantom.args[0], (status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'Unable to access network'
|
||||||
|
phantom.exit(1)
|
||||||
|
else
|
||||||
|
waitFor ->
|
||||||
|
page.evaluate ->
|
||||||
|
el = document.getElementById 'qunit-testresult'
|
||||||
|
if el and el.innerText.match 'completed'
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
, ->
|
||||||
|
failedNum = page.evaluate ->
|
||||||
|
el = document.getElementById 'qunit-testresult'
|
||||||
|
console.log el.innerText
|
||||||
|
try
|
||||||
|
return el.getElementsByClassName('failed')[0].innerHTML
|
||||||
|
catch e
|
||||||
|
return 10000
|
||||||
|
|
||||||
|
phantom.exit if parseInt(failedNum, 10) > 0 then 1 else 0
|
|
@ -1,5 +1,3 @@
|
||||||
var system = require('system');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait until the test condition is true or a timeout occurs. Useful for waiting
|
* Wait until the test condition is true or a timeout occurs. Useful for waiting
|
||||||
* on a server response or for a ui change (fadeIn, etc.) to occur.
|
* on a server response or for a ui change (fadeIn, etc.) to occur.
|
||||||
|
@ -36,7 +34,7 @@ function waitFor(testFx, onReady, timeOutMillis) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (system.args.length !== 2) {
|
if (phantom.args.length === 0 || phantom.args.length > 2) {
|
||||||
console.log('Usage: run-qunit.js URL');
|
console.log('Usage: run-qunit.js URL');
|
||||||
phantom.exit(1);
|
phantom.exit(1);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +46,7 @@ page.onConsoleMessage = function(msg) {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
page.open(system.args[1], function(status){
|
page.open(phantom.args[0], function(status){
|
||||||
if (status !== "success") {
|
if (status !== "success") {
|
||||||
console.log("Unable to access network");
|
console.log("Unable to access network");
|
||||||
phantom.exit(1);
|
phantom.exit(1);
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# List all the files in a Tree of Directories
|
||||||
|
|
||||||
|
if phantom.args.length != 1
|
||||||
|
console.log "Usage: phantomjs scandir.js DIRECTORY_TO_SCAN"
|
||||||
|
phantom.exit()
|
||||||
|
scanDirectory = (path) ->
|
||||||
|
fs = require 'fs'
|
||||||
|
if fs.exists(path) and fs.isFile(path)
|
||||||
|
console.log path
|
||||||
|
else if fs.isDirectory(path)
|
||||||
|
fs.list(path).forEach (e) ->
|
||||||
|
scanDirectory path + "/" + e if e != "." and e != ".."
|
||||||
|
|
||||||
|
scanDirectory phantom.args[0]
|
||||||
|
phantom.exit()
|
|
@ -1,9 +1,8 @@
|
||||||
// List all the files in a Tree of Directories
|
// List all the files in a Tree of Directories
|
||||||
var system = require('system');
|
|
||||||
|
|
||||||
if (system.args.length !== 2) {
|
if (phantom.args.length !== 1) {
|
||||||
console.log("Usage: phantomjs scandir.js DIRECTORY_TO_SCAN");
|
console.log("Usage: phantomjs scandir.js DIRECTORY_TO_SCAN");
|
||||||
phantom.exit(1);
|
phantom.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
var scanDirectory = function (path) {
|
var scanDirectory = function (path) {
|
||||||
|
@ -18,5 +17,5 @@ var scanDirectory = function (path) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
scanDirectory(system.args[1]);
|
scanDirectory(phantom.args[0]);
|
||||||
phantom.exit();
|
phantom.exit();
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Show BBC seasonal food list.
|
||||||
|
|
||||||
|
window.cbfunc = (data) ->
|
||||||
|
list = data.query.results.results.result
|
||||||
|
names = ['January', 'February', 'March',
|
||||||
|
'April', 'May', 'June',
|
||||||
|
'July', 'August', 'September',
|
||||||
|
'October', 'November', 'December']
|
||||||
|
for item in list
|
||||||
|
console.log [item.name.replace(/\s/ig, ' '), ':',
|
||||||
|
names[item.atItsBestUntil], 'to',
|
||||||
|
names[item.atItsBestFrom]].join(' ')
|
||||||
|
phantom.exit()
|
||||||
|
|
||||||
|
el = document.createElement 'script'
|
||||||
|
el.src = 'http://query.yahooapis.com/v1/public/yql?q=SELECT%20*%20FROM%20bbc.goodfood.seasonal%3B&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=window.cbfunc'
|
||||||
|
document.body.appendChild el
|
|
@ -1,43 +0,0 @@
|
||||||
var page = require('webpage').create();
|
|
||||||
var server = require('webserver').create();
|
|
||||||
var system = require('system');
|
|
||||||
var host, port;
|
|
||||||
|
|
||||||
if (system.args.length !== 2) {
|
|
||||||
console.log('Usage: server.js <some port>');
|
|
||||||
phantom.exit(1);
|
|
||||||
} else {
|
|
||||||
port = system.args[1];
|
|
||||||
var listening = server.listen(port, function (request, response) {
|
|
||||||
console.log("GOT HTTP REQUEST");
|
|
||||||
console.log(JSON.stringify(request, null, 4));
|
|
||||||
|
|
||||||
// we set the headers here
|
|
||||||
response.statusCode = 200;
|
|
||||||
response.headers = {"Cache": "no-cache", "Content-Type": "text/html"};
|
|
||||||
// this is also possible:
|
|
||||||
response.setHeader("foo", "bar");
|
|
||||||
// now we write the body
|
|
||||||
// note: the headers above will now be sent implictly
|
|
||||||
response.write("<html><head><title>YES!</title></head>");
|
|
||||||
// note: writeBody can be called multiple times
|
|
||||||
response.write("<body><p>pretty cool :)</body></html>");
|
|
||||||
response.close();
|
|
||||||
});
|
|
||||||
if (!listening) {
|
|
||||||
console.log("could not create web server listening on port " + port);
|
|
||||||
phantom.exit();
|
|
||||||
}
|
|
||||||
var url = "http://localhost:" + port + "/foo/bar.php?asdf=true";
|
|
||||||
console.log("SENDING REQUEST TO:");
|
|
||||||
console.log(url);
|
|
||||||
page.open(url, function (status) {
|
|
||||||
if (status !== 'success') {
|
|
||||||
console.log('FAIL to load the address');
|
|
||||||
} else {
|
|
||||||
console.log("GOT REPLY FROM SERVER:");
|
|
||||||
console.log(page.content);
|
|
||||||
}
|
|
||||||
phantom.exit();
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
var port, server, service,
|
|
||||||
system = require('system');
|
|
||||||
|
|
||||||
if (system.args.length !== 2) {
|
|
||||||
console.log('Usage: serverkeepalive.js <portnumber>');
|
|
||||||
phantom.exit(1);
|
|
||||||
} else {
|
|
||||||
port = system.args[1];
|
|
||||||
server = require('webserver').create();
|
|
||||||
|
|
||||||
service = server.listen(port, { keepAlive: true }, function (request, response) {
|
|
||||||
console.log('Request at ' + new Date());
|
|
||||||
console.log(JSON.stringify(request, null, 4));
|
|
||||||
|
|
||||||
var body = JSON.stringify(request, null, 4);
|
|
||||||
response.statusCode = 200;
|
|
||||||
response.headers = {
|
|
||||||
'Cache': 'no-cache',
|
|
||||||
'Content-Type': 'text/plain',
|
|
||||||
'Connection': 'Keep-Alive',
|
|
||||||
'Keep-Alive': 'timeout=5, max=100',
|
|
||||||
'Content-Length': body.length
|
|
||||||
};
|
|
||||||
response.write(body);
|
|
||||||
response.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (service) {
|
|
||||||
console.log('Web server running on port ' + port);
|
|
||||||
} else {
|
|
||||||
console.log('Error: Could not create web server listening on port ' + port);
|
|
||||||
phantom.exit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
if phantom.args.length is 0
|
||||||
|
console.log "Usage: simpleserver.js <portnumber>"
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
port = phantom.args[0]
|
||||||
|
server = require("webserver").create()
|
||||||
|
|
||||||
|
service = server.listen(port, (request, response) ->
|
||||||
|
|
||||||
|
console.log "Request at " + new Date()
|
||||||
|
console.log JSON.stringify(request, null, 4)
|
||||||
|
|
||||||
|
response.statusCode = 200
|
||||||
|
response.headers =
|
||||||
|
Cache: "no-cache"
|
||||||
|
"Content-Type": "text/html"
|
||||||
|
|
||||||
|
response.write "<html>"
|
||||||
|
response.write "<head>"
|
||||||
|
response.write "<title>Hello, world!</title>"
|
||||||
|
response.write "</head>"
|
||||||
|
response.write "<body>"
|
||||||
|
response.write "<p>This is from PhantomJS web server.</p>"
|
||||||
|
response.write "<p>Request data:</p>"
|
||||||
|
response.write "<pre>"
|
||||||
|
response.write JSON.stringify(request, null, 4)
|
||||||
|
response.write "</pre>"
|
||||||
|
response.write "</body>"
|
||||||
|
response.write "</html>"
|
||||||
|
)
|
||||||
|
if service
|
||||||
|
console.log "Web server running on port " + port
|
||||||
|
else
|
||||||
|
console.log "Error: Could not create web server listening on port " + port
|
||||||
|
phantom.exit()
|
|
@ -1,11 +1,10 @@
|
||||||
var port, server, service,
|
var port, server, service;
|
||||||
system = require('system');
|
|
||||||
|
|
||||||
if (system.args.length !== 2) {
|
if (phantom.args.length !== 1) {
|
||||||
console.log('Usage: simpleserver.js <portnumber>');
|
console.log('Usage: simpleserver.js <portnumber>');
|
||||||
phantom.exit(1);
|
phantom.exit();
|
||||||
} else {
|
} else {
|
||||||
port = system.args[1];
|
port = phantom.args[0];
|
||||||
server = require('webserver').create();
|
server = require('webserver').create();
|
||||||
|
|
||||||
service = server.listen(port, function (request, response) {
|
service = server.listen(port, function (request, response) {
|
||||||
|
@ -30,7 +29,6 @@ if (system.args.length !== 2) {
|
||||||
response.write('</pre>');
|
response.write('</pre>');
|
||||||
response.write('</body>');
|
response.write('</body>');
|
||||||
response.write('</html>');
|
response.write('</html>');
|
||||||
response.close();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (service) {
|
if (service) {
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
###
|
||||||
|
Sort integers from the command line in a very ridiculous way: leveraging timeouts :P
|
||||||
|
###
|
||||||
|
|
||||||
|
if phantom.args < 1
|
||||||
|
console.log "Usage: phantomjs sleepsort.js PUT YOUR INTEGERS HERE SEPARATED BY SPACES"
|
||||||
|
phantom.exit()
|
||||||
|
else
|
||||||
|
sortedCount = 0
|
||||||
|
for int in phantom.args
|
||||||
|
setTimeout ((j) ->
|
||||||
|
->
|
||||||
|
console.log j
|
||||||
|
++sortedCount
|
||||||
|
phantom.exit() if sortedCount is phantom.args.length)(int),
|
||||||
|
int
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// sleepsort.js - Sort integers from the commandline in a very ridiculous way: leveraging timeouts :P
|
// sleepsort.js - Sort integers from the commandline in a very ridiculous way: leveraging timeouts :P
|
||||||
var system = require('system');
|
|
||||||
|
|
||||||
function sleepSort(array, callback) {
|
function sleepSort(array, callback) {
|
||||||
var sortedCount = 0,
|
var sortedCount = 0,
|
||||||
|
@ -15,11 +14,11 @@ function sleepSort(array, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( system.args.length < 2 ) {
|
if ( phantom.args < 1 ) {
|
||||||
console.log("Usage: phantomjs sleepsort.js PUT YOUR INTEGERS HERE SEPARATED BY SPACES");
|
console.log("Usage: phantomjs sleepsort.js PUT YOUR INTEGERS HERE SEPARATED BY SPACES");
|
||||||
phantom.exit(1);
|
phantom.exit();
|
||||||
} else {
|
} else {
|
||||||
sleepSort(system.args.slice(1), function() {
|
sleepSort(phantom.args, function() {
|
||||||
phantom.exit();
|
phantom.exit();
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
var system = require('system');
|
|
||||||
|
|
||||||
system.stdout.write('Hello, system.stdout.write!');
|
|
||||||
system.stdout.writeLine('\nHello, system.stdout.writeLine!');
|
|
||||||
|
|
||||||
system.stderr.write('Hello, system.stderr.write!');
|
|
||||||
system.stderr.writeLine('\nHello, system.stderr.writeLine!');
|
|
||||||
|
|
||||||
system.stdout.writeLine('system.stdin.readLine(): ');
|
|
||||||
var line = system.stdin.readLine();
|
|
||||||
system.stdout.writeLine(JSON.stringify(line));
|
|
||||||
|
|
||||||
// This is essentially a `readAll`
|
|
||||||
system.stdout.writeLine('system.stdin.read(5): (ctrl+D to end)');
|
|
||||||
var input = system.stdin.read(5);
|
|
||||||
system.stdout.writeLine(JSON.stringify(input));
|
|
||||||
|
|
||||||
phantom.exit(0);
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
page.viewportSize = { width: 320, height: 480 }
|
||||||
|
|
||||||
|
page.open 'http://news.google.com/news/i/section?&topic=t',
|
||||||
|
(status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'Unable to access the network!'
|
||||||
|
else
|
||||||
|
page.evaluate ->
|
||||||
|
body = document.body
|
||||||
|
body.style.backgroundColor = '#fff'
|
||||||
|
body.querySelector('div#title-block').style.display = 'none'
|
||||||
|
body.querySelector('form#edition-picker-form')
|
||||||
|
.parentElement.parentElement.style.display = 'none'
|
||||||
|
page.render 'technews.png'
|
||||||
|
phantom.exit()
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Get twitter status for given account (or for the default one, "sencha")
|
||||||
|
|
||||||
|
page = require('webpage').create()
|
||||||
|
twitterId = 'sencha' #< default value
|
||||||
|
|
||||||
|
# Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
|
||||||
|
page.onConsoleMessage = (msg) ->
|
||||||
|
console.log msg
|
||||||
|
|
||||||
|
# Print usage message, if no twitter ID is passed
|
||||||
|
if phantom.args.length < 1
|
||||||
|
console.log 'Usage: tweets.coffee [twitter ID]'
|
||||||
|
else
|
||||||
|
twitterId = phantom.args[0]
|
||||||
|
|
||||||
|
# Heading
|
||||||
|
console.log "*** Latest tweets from @#{twitterId} ***\n"
|
||||||
|
|
||||||
|
# Open Twitter Mobile and, onPageLoad, do...
|
||||||
|
page.open encodeURI("http://mobile.twitter.com/#{twitterId}"), (status) ->
|
||||||
|
# Check for page load success
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'Unable to access network'
|
||||||
|
else
|
||||||
|
# Execute some DOM inspection within the page context
|
||||||
|
page.evaluate ->
|
||||||
|
list = document.querySelectorAll 'span.status'
|
||||||
|
for i, j in list
|
||||||
|
console.log "#{j + 1}: #{i.innerHTML.replace /<.*?>/g, ''}"
|
||||||
|
phantom.exit()
|
|
@ -1,8 +1,7 @@
|
||||||
// Get twitter status for given account (or for the default one, "PhantomJS")
|
// Get twitter status for given account (or for the default one, "sencha")
|
||||||
|
|
||||||
var page = require('webpage').create(),
|
var page = require('webpage').create(),
|
||||||
system = require('system'),
|
twitterId = "sencha"; //< default value
|
||||||
twitterId = "PhantomJS"; //< default value
|
|
||||||
|
|
||||||
// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
|
// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
|
||||||
page.onConsoleMessage = function(msg) {
|
page.onConsoleMessage = function(msg) {
|
||||||
|
@ -10,10 +9,10 @@ page.onConsoleMessage = function(msg) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Print usage message, if no twitter ID is passed
|
// Print usage message, if no twitter ID is passed
|
||||||
if (system.args.length < 2) {
|
if (phantom.args.length < 1) {
|
||||||
console.log("Usage: tweets.js [twitter ID]");
|
console.log("Usage: tweets.js [twitter ID]");
|
||||||
} else {
|
} else {
|
||||||
twitterId = system.args[1];
|
twitterId = phantom.args[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Heading
|
// Heading
|
||||||
|
@ -27,9 +26,9 @@ page.open(encodeURI("http://mobile.twitter.com/" + twitterId), function (status)
|
||||||
} else {
|
} else {
|
||||||
// Execute some DOM inspection within the page context
|
// Execute some DOM inspection within the page context
|
||||||
page.evaluate(function() {
|
page.evaluate(function() {
|
||||||
var list = document.querySelectorAll('div.tweet-text');
|
var list = document.querySelectorAll('span.status');
|
||||||
for (var i = 0; i < list.length; ++i) {
|
for (var i = 0; i < list.length; ++i) {
|
||||||
console.log((i + 1) + ": " + list[i].innerText);
|
console.log((i + 1) + ": " + list[i].innerHTML.replace(/<.*?>/g, ''));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
// This is to be used by "module.js" (and "module.coffee") example(s).
|
|
||||||
// There should NOT be a "universe.coffee" as only 1 of the 2 would
|
|
||||||
// ever be loaded unless the file extension was specified.
|
|
||||||
|
|
||||||
exports.answer = 42;
|
|
||||||
|
|
||||||
exports.start = function () {
|
|
||||||
console.log('Starting the universe....');
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Modify global object at the page initialization.
|
||||||
|
# In this example, effectively Math.random() always returns 0.42.
|
||||||
|
|
||||||
|
page = require('webpage').create()
|
||||||
|
page.onInitialized = ->
|
||||||
|
page.evaluate ->
|
||||||
|
Math.random = ->
|
||||||
|
42 / 100
|
||||||
|
|
||||||
|
page.open "http://ariya.github.com/js/random/", (status) ->
|
||||||
|
if status != "success"
|
||||||
|
console.log "Network error."
|
||||||
|
else
|
||||||
|
console.log page.evaluate(->
|
||||||
|
document.getElementById("numbers").textContent
|
||||||
|
)
|
||||||
|
phantom.exit()
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
page = require('webpage').create()
|
||||||
|
|
||||||
|
console.log 'The default user agent is ' + page.settings.userAgent
|
||||||
|
|
||||||
|
page.settings.userAgent = 'SpecialAgent'
|
||||||
|
page.open 'http://www.httpuseragent.org', (status) ->
|
||||||
|
if status isnt 'success'
|
||||||
|
console.log 'Unable to access network'
|
||||||
|
else
|
||||||
|
console.log page.evaluate -> document.getElementById('myagent').innerText
|
||||||
|
phantom.exit()
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue