From 0e765f2a95766aaa7cb7152666010316e3beb8bd Mon Sep 17 00:00:00 2001 From: IceArmy Date: Sun, 19 Jun 2011 01:18:26 -0700 Subject: [PATCH 01/11] Exit program properly when we call phantom.exit Previously, calling phantom.exit would set the exit code and finish running the JavaScript until it was done, then exit the program with your code. Basically it didn't actually exit the program. It caused many code fallthrough problems, but is now fixed. :) --- python/pyphantomjs/bootstrap.js | 11 +++++++++++ python/pyphantomjs/phantom.py | 14 ++++++-------- python/pyphantomjs/pyphantomjs.py | 2 +- python/pyphantomjs/utils.py | 17 +++++++++++++++-- src/bootstrap.js | 11 +++++++++++ src/phantom.cpp | 5 ++--- src/phantom.h | 2 +- src/utils.cpp | 21 +++++++++++++++++---- src/utils.h | 2 +- 9 files changed, 65 insertions(+), 20 deletions(-) diff --git a/python/pyphantomjs/bootstrap.js b/python/pyphantomjs/bootstrap.js index d897524f..7e9d50f9 100644 --- a/python/pyphantomjs/bootstrap.js +++ b/python/pyphantomjs/bootstrap.js @@ -74,3 +74,14 @@ window.WebPage = function() { return page; } + +phantom.exit = function(code) { + if (code == null) { + code = 0; + } + + phantom._exit(code); + + // halt javascript execution + throw "phantom.exit"; +} diff --git a/python/pyphantomjs/phantom.py b/python/pyphantomjs/phantom.py index 75ef3911..4cd53638 100644 --- a/python/pyphantomjs/phantom.py +++ b/python/pyphantomjs/phantom.py @@ -82,7 +82,7 @@ class Phantom(QObject): do_action('PhantomInitPost', Bunch(locals())) def execute(self): - injectJsInFrame(self.m_scriptFile, os.path.dirname(os.path.abspath(__file__)), self.m_page.mainFrame()) + injectJsInFrame(self.m_scriptFile, os.path.dirname(os.path.abspath(__file__)), self.m_page.mainFrame(), True) return not self.m_terminated def printConsoleMessage(self, msg): @@ -95,6 +95,11 @@ class Phantom(QObject): # Properties and methods exposed to JavaScript ## + @pyqtSlot(int) + def _exit(self, code): + self.m_terminated = True + self.m_returnValue = code + @pyqtProperty('QStringList') def args(self): return self.m_args @@ -111,13 +116,6 @@ class Phantom(QObject): def defaultPageSettings(self): return self.m_defaultPageSettings - @pyqtSlot() - @pyqtSlot(int) - def exit(self, code=0): - self.m_terminated = True - self.m_returnValue = code - QApplication.instance().exit(code) - @pyqtSlot(str, result=bool) def injectJs(self, filePath): return injectJsInFrame(filePath, self.libraryPath, self.m_page.mainFrame()) diff --git a/python/pyphantomjs/pyphantomjs.py b/python/pyphantomjs/pyphantomjs.py index 1e7d06b0..7a810cd4 100644 --- a/python/pyphantomjs/pyphantomjs.py +++ b/python/pyphantomjs/pyphantomjs.py @@ -95,7 +95,7 @@ def main(): app.setOrganizationDomain('www.umaclan.com') app.setApplicationVersion(version) - phantom = Phantom(args, app) + phantom = Phantom(args) do_action('Main', Bunch(locals())) diff --git a/python/pyphantomjs/utils.py b/python/pyphantomjs/utils.py index 2a0c5d55..0e7fef44 100644 --- a/python/pyphantomjs/utils.py +++ b/python/pyphantomjs/utils.py @@ -106,7 +106,7 @@ def coffee2js(script): return coffeeScriptConverter.convert(script) -def injectJsInFrame(filePath, libraryPath, targetFrame): +def injectJsInFrame(filePath, libraryPath, targetFrame, startingScript=False): try: # if file doesn't exist in the CWD, use the lookup if not os.path.exists(filePath): @@ -118,7 +118,20 @@ def injectJsInFrame(filePath, libraryPath, targetFrame): if script.startswith('#!') and not filePath.lower().endswith('.coffee'): script = '//' + script - targetFrame.evaluateJavaScript(script if not filePath.lower().endswith('.coffee') else coffee2js(script)) + script = script if not filePath.lower().endswith('.coffee') else coffee2js(script) + + # prepare start script for exiting + if startingScript: + script = '''try { + %s + } catch (err) { + if (err !== 'phantom.exit') { + throw err; + } + } + ''' % script + + targetFrame.evaluateJavaScript(script) return True except IOError: qWarning('No such file or directory: \'%s\'' % filePath) diff --git a/src/bootstrap.js b/src/bootstrap.js index d897524f..7e9d50f9 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -74,3 +74,14 @@ window.WebPage = function() { return page; } + +phantom.exit = function(code) { + if (code == null) { + code = 0; + } + + phantom._exit(code); + + // halt javascript execution + throw "phantom.exit"; +} diff --git a/src/phantom.cpp b/src/phantom.cpp index 5906d1cd..77223312 100644 --- a/src/phantom.cpp +++ b/src/phantom.cpp @@ -194,7 +194,7 @@ bool Phantom::execute() if (m_scriptFile.isEmpty()) return false; - if (!Utils::injectJsInFrame(m_scriptFile, QDir::currentPath(), m_page->mainFrame())) { + if (!Utils::injectJsInFrame(m_scriptFile, QDir::currentPath(), m_page->mainFrame(), true)) { m_returnValue = -1; return false; } @@ -225,11 +225,10 @@ QObject *Phantom::createWebPage() return page; } -void Phantom::exit(int code) +void Phantom::_exit(int code) { m_terminated = true; m_returnValue = code; - QApplication::instance()->exit(code); } bool Phantom::injectJs(const QString &jsFilePath) { diff --git a/src/phantom.h b/src/phantom.h index 37fe6b30..044d96af 100644 --- a/src/phantom.h +++ b/src/phantom.h @@ -66,7 +66,7 @@ public: public slots: QObject *createWebPage(); bool injectJs(const QString &jsFilePath); - void exit(int code = 0); + void _exit(int code); private slots: void printConsoleMessage(const QString &msg); diff --git a/src/utils.cpp b/src/utils.cpp index b7ec1ad1..dbf474e4 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -80,7 +80,7 @@ QString Utils::coffee2js(const QString &script) return coffeeScriptConverter->convert(script); } -bool Utils::injectJsInFrame(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame) +bool Utils::injectJsInFrame(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame, const bool startingScript) { // Don't do anything if an empty string is passed if (!jsFilePath.isEmpty()) { @@ -100,10 +100,23 @@ bool Utils::injectJsInFrame(const QString &jsFilePath, const QString &libraryPat scriptBody.prepend("//"); } - // Execute JS code in the context of the document - targetFrame->evaluateJavaScript(jsFile.fileName().endsWith(COFFEE_SCRIPT_EXTENSION) ? + scriptBody = jsFile.fileName().endsWith(COFFEE_SCRIPT_EXTENSION) ? Utils::coffee2js(scriptBody) : //< convert from Coffee Script - scriptBody); + scriptBody; + + // prepare start script for exiting + if (startingScript) { + scriptBody = QString("try {" \ + " %1" \ + "} catch (err) {" \ + " if (err !== 'phantom.exit') {" \ + " throw err;" \ + " }" \ + "}").arg(scriptBody); + } + + // Execute JS code in the context of the document + targetFrame->evaluateJavaScript(scriptBody); jsFile.close(); return true; } else { diff --git a/src/utils.h b/src/utils.h index a5c795b5..b81ce4bb 100644 --- a/src/utils.h +++ b/src/utils.h @@ -46,7 +46,7 @@ public: static void showUsage(); static void messageHandler(QtMsgType type, const char *msg); static QString coffee2js(const QString &script); - static bool injectJsInFrame(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame); + static bool injectJsInFrame(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame, const bool startingScript = false); private: Utils(); //< This class shouldn't be instantiated From 11e29fe45cf64fbdba3058d947b00d1ee4c2abdf Mon Sep 17 00:00:00 2001 From: IceArmy Date: Sun, 19 Jun 2011 01:23:01 -0700 Subject: [PATCH 02/11] Regenerate resources --- python/pyphantomjs/resources.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/python/pyphantomjs/resources.py b/python/pyphantomjs/resources.py index fbc099da..c723b982 100644 --- a/python/pyphantomjs/resources.py +++ b/python/pyphantomjs/resources.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Fri Jun 17 01:01:41 2011 +# Created: Sun Jun 19 00:53:56 2011 # by: The Resource Compiler for PyQt (Qt v4.7.2) # # WARNING! All changes made in this file will be lost! @@ -10,7 +10,7 @@ from PyQt4 import QtCore qt_resource_data = "\ -\x00\x00\x0a\x29\ +\x00\x00\x0a\xd2\ \x2f\ \x2f\x20\x54\x68\x69\x73\x20\x61\x6c\x6c\x6f\x77\x73\x20\x63\x72\ \x65\x61\x74\x69\x6e\x67\x20\x61\x20\x6e\x65\x77\x20\x77\x65\x62\ @@ -174,7 +174,18 @@ qt_resource_data = "\ \x65\x6e\x64\x53\x63\x72\x69\x70\x74\x45\x6c\x65\x6d\x65\x6e\x74\ \x28\x73\x63\x72\x69\x70\x74\x55\x72\x6c\x29\x3b\x0a\x20\x20\x20\ \x20\x7d\x3b\x0a\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\ -\x70\x61\x67\x65\x3b\x0a\x7d\x0a\ +\x70\x61\x67\x65\x3b\x0a\x7d\x0a\x0a\x70\x68\x61\x6e\x74\x6f\x6d\ +\x2e\x65\x78\x69\x74\x20\x3d\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\ +\x28\x63\x6f\x64\x65\x29\x20\x7b\x0a\x20\x20\x20\x20\x69\x66\x20\ +\x28\x63\x6f\x64\x65\x20\x3d\x3d\x20\x6e\x75\x6c\x6c\x29\x20\x7b\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x63\x6f\x64\x65\x20\x3d\x20\ +\x30\x3b\x0a\x20\x20\x20\x20\x7d\x0a\x0a\x20\x20\x20\x20\x70\x68\ +\x61\x6e\x74\x6f\x6d\x2e\x5f\x65\x78\x69\x74\x28\x63\x6f\x64\x65\ +\x29\x3b\x0a\x0a\x20\x20\x20\x20\x2f\x2f\x20\x68\x61\x6c\x74\x20\ +\x6a\x61\x76\x61\x73\x63\x72\x69\x70\x74\x20\x65\x78\x65\x63\x75\ +\x74\x69\x6f\x6e\x0a\x20\x20\x20\x20\x74\x68\x72\x6f\x77\x20\x22\ +\x70\x68\x61\x6e\x74\x6f\x6d\x2e\x65\x78\x69\x74\x22\x3b\x0a\x7d\ +\x0a\ \x00\x00\x56\x27\ \x89\ \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ @@ -4317,8 +4328,8 @@ qt_resource_struct = "\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x01\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ \x00\x00\x00\x1e\x00\x02\x00\x00\x00\x02\x00\x00\x00\x03\ -\x00\x00\x00\x64\x00\x01\x00\x00\x00\x01\x00\x00\x60\x58\ -\x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x2d\ +\x00\x00\x00\x64\x00\x01\x00\x00\x00\x01\x00\x00\x61\x01\ +\x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x0a\xd6\ " def qInitResources(): From 9a85d01687d8773418453d7c01c4ffded4f8b329 Mon Sep 17 00:00:00 2001 From: IceArmy Date: Sun, 19 Jun 2011 01:23:44 -0700 Subject: [PATCH 03/11] Add newline to CSConverter.convert --- python/pyphantomjs/csconverter.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/pyphantomjs/csconverter.py b/python/pyphantomjs/csconverter.py index e0a5d37a..5ad5ed21 100644 --- a/python/pyphantomjs/csconverter.py +++ b/python/pyphantomjs/csconverter.py @@ -43,7 +43,8 @@ class CSConverter(QObject): [true, this.CoffeeScript.compile(converter.source)]; } catch (error) { [false, error.message]; - }''') + } + ''') if result[0] is False: qWarning(result[1]) return '' From 56039cae7f062122bf0dbaef5cf25d35bff371ad Mon Sep 17 00:00:00 2001 From: IceArmy Date: Sun, 19 Jun 2011 02:47:33 -0700 Subject: [PATCH 04/11] Fix issue 131 - 'Properly exit page' causes changed stack trace --- python/pyphantomjs/utils.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/python/pyphantomjs/utils.py b/python/pyphantomjs/utils.py index 0e7fef44..eb3ccc2f 100644 --- a/python/pyphantomjs/utils.py +++ b/python/pyphantomjs/utils.py @@ -122,9 +122,7 @@ def injectJsInFrame(filePath, libraryPath, targetFrame, startingScript=False): # prepare start script for exiting if startingScript: - script = '''try { - %s - } catch (err) { + script = '''try { %s } catch (err) { if (err !== 'phantom.exit') { throw err; } From 7a9e0c85998e34fcdaec7b4d844b34ac7efe4c8e Mon Sep 17 00:00:00 2001 From: IceArmy Date: Sun, 19 Jun 2011 13:37:03 -0700 Subject: [PATCH 05/11] Exit on start script error --- python/pyphantomjs/csconverter.py | 7 ++----- python/pyphantomjs/utils.py | 12 +++++++++++- src/csconverter.cpp | 8 ++------ src/csconverter.h | 2 +- src/utils.cpp | 20 ++++++++++++++++---- src/utils.h | 2 +- 6 files changed, 33 insertions(+), 18 deletions(-) diff --git a/python/pyphantomjs/csconverter.py b/python/pyphantomjs/csconverter.py index 5ad5ed21..ac53d034 100644 --- a/python/pyphantomjs/csconverter.py +++ b/python/pyphantomjs/csconverter.py @@ -19,7 +19,7 @@ import sys -from PyQt4.QtCore import QObject, QFile, qWarning +from PyQt4.QtCore import QObject, QFile from PyQt4.QtWebKit import QWebPage @@ -45,7 +45,4 @@ class CSConverter(QObject): [false, error.message]; } ''') - if result[0] is False: - qWarning(result[1]) - return '' - return result[1] + return result diff --git a/python/pyphantomjs/utils.py b/python/pyphantomjs/utils.py index eb3ccc2f..6ec48eee 100644 --- a/python/pyphantomjs/utils.py +++ b/python/pyphantomjs/utils.py @@ -118,12 +118,22 @@ def injectJsInFrame(filePath, libraryPath, targetFrame, startingScript=False): if script.startswith('#!') and not filePath.lower().endswith('.coffee'): script = '//' + script - script = script if not filePath.lower().endswith('.coffee') else coffee2js(script) + if filePath.lower().endswith('.coffee'): + result = coffee2js(script) + if result[0] is False: + if startingScript: + sys.exit(result[1]) + else: + qWarning(result[1]) + script = '' + else: + script = result[1] # prepare start script for exiting if startingScript: script = '''try { %s } catch (err) { if (err !== 'phantom.exit') { + phantom._exit(1); throw err; } } diff --git a/src/csconverter.cpp b/src/csconverter.cpp index f4b93478..09f58044 100644 --- a/src/csconverter.cpp +++ b/src/csconverter.cpp @@ -49,7 +49,7 @@ CSConverter::CSConverter(QObject *parent) m_webPage.mainFrame()->addToJavaScriptWindowObject("converter", this); } -QString CSConverter::convert(const QString &script) +QVariant CSConverter::convert(const QString &script) { setProperty("source", script); QVariant result = m_webPage.mainFrame()->evaluateJavaScript("try {" \ @@ -57,9 +57,5 @@ QString CSConverter::convert(const QString &script) "} catch (error) {" \ " [false, error.message];" \ "}"); - if (result.toStringList().at(0) == "false") { - qWarning(qPrintable(result.toStringList().at(1))); - return QString(); - } - return result.toStringList().at(1); + return result; } diff --git a/src/csconverter.h b/src/csconverter.h index d5b247d2..9fffce2d 100644 --- a/src/csconverter.h +++ b/src/csconverter.h @@ -37,7 +37,7 @@ class CSConverter: public QObject { public: CSConverter(QObject *parent = 0); - QString convert(const QString &script); + QVariant convert(const QString &script); private: QWebPage m_webPage; diff --git a/src/utils.cpp b/src/utils.cpp index dbf474e4..2f10d0ec 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -69,7 +69,7 @@ void Utils::messageHandler(QtMsgType type, const char *msg) } } -QString Utils::coffee2js(const QString &script) +QVariant Utils::coffee2js(const QString &script) { // We need only one instance of the CSConverter to survive for the whole life of PhantomJS static CSConverter *coffeeScriptConverter = NULL; @@ -100,9 +100,20 @@ bool Utils::injectJsInFrame(const QString &jsFilePath, const QString &libraryPat scriptBody.prepend("//"); } - scriptBody = jsFile.fileName().endsWith(COFFEE_SCRIPT_EXTENSION) ? - Utils::coffee2js(scriptBody) : //< convert from Coffee Script - scriptBody; + if (jsFile.fileName().endsWith(COFFEE_SCRIPT_EXTENSION)) { + QVariant result = Utils::coffee2js(scriptBody); + if (result.toStringList().at(0) == "false") { + if (startingScript) { + std::cerr << qPrintable(result.toStringList().at(1)) << std::endl; + exit(1); + } else { + qWarning() << qPrintable(result.toStringList().at(1)); + scriptBody = QString(); + } + } else { + scriptBody = result.toStringList().at(1); + } + } // prepare start script for exiting if (startingScript) { @@ -110,6 +121,7 @@ bool Utils::injectJsInFrame(const QString &jsFilePath, const QString &libraryPat " %1" \ "} catch (err) {" \ " if (err !== 'phantom.exit') {" \ + " phantom._exit(1);" \ " throw err;" \ " }" \ "}").arg(scriptBody); diff --git a/src/utils.h b/src/utils.h index b81ce4bb..65ea743a 100644 --- a/src/utils.h +++ b/src/utils.h @@ -45,7 +45,7 @@ class Utils public: static void showUsage(); static void messageHandler(QtMsgType type, const char *msg); - static QString coffee2js(const QString &script); + static QVariant coffee2js(const QString &script); static bool injectJsInFrame(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame, const bool startingScript = false); private: From 54478a1154c0c904763d437bda982cd908f6be94 Mon Sep 17 00:00:00 2001 From: IceArmy Date: Sun, 19 Jun 2011 14:00:04 -0700 Subject: [PATCH 06/11] Use qWarning only if script isn't starting script --- src/utils.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils.cpp b/src/utils.cpp index 2f10d0ec..1b87b5d4 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -132,7 +132,11 @@ bool Utils::injectJsInFrame(const QString &jsFilePath, const QString &libraryPat jsFile.close(); return true; } else { - qWarning() << "Can't open '" << qPrintable(jsFilePath) << "'"; + if (startingScript) { + std::cerr << "Can't open '" << qPrintable(jsFilePath) << "'" << std::endl; + } else { + qWarning("Can't open '%s'", qPrintable(jsFilePath)); + } } } return false; From c44838227db9b01af7a804804e55b2a893f510d6 Mon Sep 17 00:00:00 2001 From: IceArmy Date: Sun, 19 Jun 2011 17:26:39 -0700 Subject: [PATCH 07/11] Fix bug where phantom.exit wouldn't exit properly --- python/pyphantomjs/phantom.py | 1 + src/phantom.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/python/pyphantomjs/phantom.py b/python/pyphantomjs/phantom.py index 4cd53638..b45ae6b7 100644 --- a/python/pyphantomjs/phantom.py +++ b/python/pyphantomjs/phantom.py @@ -99,6 +99,7 @@ class Phantom(QObject): def _exit(self, code): self.m_terminated = True self.m_returnValue = code + QApplication.instance().exit(code) @pyqtProperty('QStringList') def args(self): diff --git a/src/phantom.cpp b/src/phantom.cpp index 77223312..fadbeeab 100644 --- a/src/phantom.cpp +++ b/src/phantom.cpp @@ -229,6 +229,7 @@ void Phantom::_exit(int code) { m_terminated = true; m_returnValue = code; + QApplication::instance()->exit(code); } bool Phantom::injectJs(const QString &jsFilePath) { From 1fb67c49e74dec5ec7d200bf435fd6ec6d10034e Mon Sep 17 00:00:00 2001 From: IceArmy Date: Sun, 19 Jun 2011 18:39:57 -0700 Subject: [PATCH 08/11] Fix bug where output couldn't be piped/redirected --- python/pyphantomjs/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pyphantomjs/utils.py b/python/pyphantomjs/utils.py index 6ec48eee..a0065dad 100644 --- a/python/pyphantomjs/utils.py +++ b/python/pyphantomjs/utils.py @@ -170,7 +170,7 @@ class SafeStreamFilter(object): self.target = target self.encoding = 'utf-8' self.errors = 'replace' - self.encode_to = self.target.encoding + self.encode_to = self.target.encoding or 'utf-8' def write(self, s): s = self.encode(s) From 3d0c56af40635dd6990c5d19b47e39f7377301f6 Mon Sep 17 00:00:00 2001 From: IceArmy Date: Sun, 19 Jun 2011 21:18:14 -0700 Subject: [PATCH 09/11] Fix the last problem with setTimeout and setInterval --- python/pyphantomjs/bootstrap.js | 33 +++++++++++++++++++++++++++++++++ src/bootstrap.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/python/pyphantomjs/bootstrap.js b/python/pyphantomjs/bootstrap.js index 7e9d50f9..45eeb87c 100644 --- a/python/pyphantomjs/bootstrap.js +++ b/python/pyphantomjs/bootstrap.js @@ -75,6 +75,39 @@ window.WebPage = function() { return page; } + +// override settimeout/setinterval with a try..catch +window._setTimeout = window.setTimeout; +window._setInterval = window.setInterval; +window.setTimeout = function(func, delay) { + var f = function() { + try { + typeof func === 'function' ? func() : eval(func); + } catch (err) { + if (err !== 'phantom.exit') { + throw err; + } + } + } + + return window._setTimeout(f, delay); +} + +window.setInterval = function(func, delay, lang) { + var f = function() { + try { + typeof func === 'function' ? func() : eval(func); + } catch (err) { + if (err !== 'phantom.exit') { + throw err; + } + } + } + + return window._setInterval(f, delay, lang); +} + + phantom.exit = function(code) { if (code == null) { code = 0; diff --git a/src/bootstrap.js b/src/bootstrap.js index 7e9d50f9..45eeb87c 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -75,6 +75,39 @@ window.WebPage = function() { return page; } + +// override settimeout/setinterval with a try..catch +window._setTimeout = window.setTimeout; +window._setInterval = window.setInterval; +window.setTimeout = function(func, delay) { + var f = function() { + try { + typeof func === 'function' ? func() : eval(func); + } catch (err) { + if (err !== 'phantom.exit') { + throw err; + } + } + } + + return window._setTimeout(f, delay); +} + +window.setInterval = function(func, delay, lang) { + var f = function() { + try { + typeof func === 'function' ? func() : eval(func); + } catch (err) { + if (err !== 'phantom.exit') { + throw err; + } + } + } + + return window._setInterval(f, delay, lang); +} + + phantom.exit = function(code) { if (code == null) { code = 0; From 1be23d0be96f4cd9eb91ebb5757c65cca07311bf Mon Sep 17 00:00:00 2001 From: IceArmy Date: Sun, 19 Jun 2011 21:18:40 -0700 Subject: [PATCH 10/11] Regenerate resources --- python/pyphantomjs/resources.py | 80 ++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 16 deletions(-) diff --git a/python/pyphantomjs/resources.py b/python/pyphantomjs/resources.py index c723b982..bf7f954b 100644 --- a/python/pyphantomjs/resources.py +++ b/python/pyphantomjs/resources.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Sun Jun 19 00:53:56 2011 +# Created: Sun Jun 19 21:18:36 2011 # by: The Resource Compiler for PyQt (Qt v4.7.2) # # WARNING! All changes made in this file will be lost! @@ -10,7 +10,7 @@ from PyQt4 import QtCore qt_resource_data = "\ -\x00\x00\x0a\xd2\ +\x00\x00\x0d\xdb\ \x2f\ \x2f\x20\x54\x68\x69\x73\x20\x61\x6c\x6c\x6f\x77\x73\x20\x63\x72\ \x65\x61\x74\x69\x6e\x67\x20\x61\x20\x6e\x65\x77\x20\x77\x65\x62\ @@ -174,18 +174,66 @@ qt_resource_data = "\ \x65\x6e\x64\x53\x63\x72\x69\x70\x74\x45\x6c\x65\x6d\x65\x6e\x74\ \x28\x73\x63\x72\x69\x70\x74\x55\x72\x6c\x29\x3b\x0a\x20\x20\x20\ \x20\x7d\x3b\x0a\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\ -\x70\x61\x67\x65\x3b\x0a\x7d\x0a\x0a\x70\x68\x61\x6e\x74\x6f\x6d\ -\x2e\x65\x78\x69\x74\x20\x3d\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\ -\x28\x63\x6f\x64\x65\x29\x20\x7b\x0a\x20\x20\x20\x20\x69\x66\x20\ -\x28\x63\x6f\x64\x65\x20\x3d\x3d\x20\x6e\x75\x6c\x6c\x29\x20\x7b\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x63\x6f\x64\x65\x20\x3d\x20\ -\x30\x3b\x0a\x20\x20\x20\x20\x7d\x0a\x0a\x20\x20\x20\x20\x70\x68\ -\x61\x6e\x74\x6f\x6d\x2e\x5f\x65\x78\x69\x74\x28\x63\x6f\x64\x65\ -\x29\x3b\x0a\x0a\x20\x20\x20\x20\x2f\x2f\x20\x68\x61\x6c\x74\x20\ -\x6a\x61\x76\x61\x73\x63\x72\x69\x70\x74\x20\x65\x78\x65\x63\x75\ -\x74\x69\x6f\x6e\x0a\x20\x20\x20\x20\x74\x68\x72\x6f\x77\x20\x22\ -\x70\x68\x61\x6e\x74\x6f\x6d\x2e\x65\x78\x69\x74\x22\x3b\x0a\x7d\ -\x0a\ +\x70\x61\x67\x65\x3b\x0a\x7d\x0a\x0a\x0a\x2f\x2f\x20\x6f\x76\x65\ +\x72\x72\x69\x64\x65\x20\x73\x65\x74\x74\x69\x6d\x65\x6f\x75\x74\ +\x2f\x73\x65\x74\x69\x6e\x74\x65\x72\x76\x61\x6c\x20\x77\x69\x74\ +\x68\x20\x61\x20\x74\x72\x79\x2e\x2e\x63\x61\x74\x63\x68\x0a\x77\ +\x69\x6e\x64\x6f\x77\x2e\x5f\x73\x65\x74\x54\x69\x6d\x65\x6f\x75\ +\x74\x20\x3d\x20\x77\x69\x6e\x64\x6f\x77\x2e\x73\x65\x74\x54\x69\ +\x6d\x65\x6f\x75\x74\x3b\x0a\x77\x69\x6e\x64\x6f\x77\x2e\x5f\x73\ +\x65\x74\x49\x6e\x74\x65\x72\x76\x61\x6c\x20\x3d\x20\x77\x69\x6e\ +\x64\x6f\x77\x2e\x73\x65\x74\x49\x6e\x74\x65\x72\x76\x61\x6c\x3b\ +\x0a\x77\x69\x6e\x64\x6f\x77\x2e\x73\x65\x74\x54\x69\x6d\x65\x6f\ +\x75\x74\x20\x3d\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x28\x66\x75\ +\x6e\x63\x2c\x20\x64\x65\x6c\x61\x79\x29\x20\x7b\x0a\x20\x20\x20\ +\x20\x76\x61\x72\x20\x66\x20\x3d\x20\x66\x75\x6e\x63\x74\x69\x6f\ +\x6e\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\ +\x79\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x74\x79\x70\x65\x6f\x66\x20\x66\x75\x6e\x63\x20\x3d\x3d\x3d\x20\ +\x27\x66\x75\x6e\x63\x74\x69\x6f\x6e\x27\x20\x3f\x20\x66\x75\x6e\ +\x63\x28\x29\x20\x3a\x20\x65\x76\x61\x6c\x28\x66\x75\x6e\x63\x29\ +\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x63\x61\x74\x63\ +\x68\x20\x28\x65\x72\x72\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x20\x21\x3d\ +\x3d\x20\x27\x70\x68\x61\x6e\x74\x6f\x6d\x2e\x65\x78\x69\x74\x27\ +\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x74\x68\x72\x6f\x77\x20\x65\x72\x72\x3b\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x7d\x0a\x20\x20\x20\x20\x7d\x0a\x0a\x20\x20\ +\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x77\x69\x6e\x64\x6f\x77\x2e\ +\x5f\x73\x65\x74\x54\x69\x6d\x65\x6f\x75\x74\x28\x66\x2c\x20\x64\ +\x65\x6c\x61\x79\x29\x3b\x0a\x7d\x0a\x0a\x77\x69\x6e\x64\x6f\x77\ +\x2e\x73\x65\x74\x49\x6e\x74\x65\x72\x76\x61\x6c\x20\x3d\x20\x66\ +\x75\x6e\x63\x74\x69\x6f\x6e\x28\x66\x75\x6e\x63\x2c\x20\x64\x65\ +\x6c\x61\x79\x2c\x20\x6c\x61\x6e\x67\x29\x20\x7b\x0a\x20\x20\x20\ +\x20\x76\x61\x72\x20\x66\x20\x3d\x20\x66\x75\x6e\x63\x74\x69\x6f\ +\x6e\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\ +\x79\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x74\x79\x70\x65\x6f\x66\x20\x66\x75\x6e\x63\x20\x3d\x3d\x3d\x20\ +\x27\x66\x75\x6e\x63\x74\x69\x6f\x6e\x27\x20\x3f\x20\x66\x75\x6e\ +\x63\x28\x29\x20\x3a\x20\x65\x76\x61\x6c\x28\x66\x75\x6e\x63\x29\ +\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x63\x61\x74\x63\ +\x68\x20\x28\x65\x72\x72\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x20\x21\x3d\ +\x3d\x20\x27\x70\x68\x61\x6e\x74\x6f\x6d\x2e\x65\x78\x69\x74\x27\ +\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x74\x68\x72\x6f\x77\x20\x65\x72\x72\x3b\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x7d\x0a\x20\x20\x20\x20\x7d\x0a\x0a\x20\x20\ +\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x77\x69\x6e\x64\x6f\x77\x2e\ +\x5f\x73\x65\x74\x49\x6e\x74\x65\x72\x76\x61\x6c\x28\x66\x2c\x20\ +\x64\x65\x6c\x61\x79\x2c\x20\x6c\x61\x6e\x67\x29\x3b\x0a\x7d\x0a\ +\x0a\x0a\x70\x68\x61\x6e\x74\x6f\x6d\x2e\x65\x78\x69\x74\x20\x3d\ +\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x28\x63\x6f\x64\x65\x29\x20\ +\x7b\x0a\x20\x20\x20\x20\x69\x66\x20\x28\x63\x6f\x64\x65\x20\x3d\ +\x3d\x20\x6e\x75\x6c\x6c\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x63\x6f\x64\x65\x20\x3d\x20\x30\x3b\x0a\x20\x20\x20\x20\ +\x7d\x0a\x0a\x20\x20\x20\x20\x70\x68\x61\x6e\x74\x6f\x6d\x2e\x5f\ +\x65\x78\x69\x74\x28\x63\x6f\x64\x65\x29\x3b\x0a\x0a\x20\x20\x20\ +\x20\x2f\x2f\x20\x68\x61\x6c\x74\x20\x6a\x61\x76\x61\x73\x63\x72\ +\x69\x70\x74\x20\x65\x78\x65\x63\x75\x74\x69\x6f\x6e\x0a\x20\x20\ +\x20\x20\x74\x68\x72\x6f\x77\x20\x22\x70\x68\x61\x6e\x74\x6f\x6d\ +\x2e\x65\x78\x69\x74\x22\x3b\x0a\x7d\x0a\ \x00\x00\x56\x27\ \x89\ \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ @@ -4328,8 +4376,8 @@ qt_resource_struct = "\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x01\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ \x00\x00\x00\x1e\x00\x02\x00\x00\x00\x02\x00\x00\x00\x03\ -\x00\x00\x00\x64\x00\x01\x00\x00\x00\x01\x00\x00\x61\x01\ -\x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x0a\xd6\ +\x00\x00\x00\x64\x00\x01\x00\x00\x00\x01\x00\x00\x64\x0a\ +\x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xdf\ " def qInitResources(): From d29c6732b5460956554ba59b6bad730a4d342aaf Mon Sep 17 00:00:00 2001 From: IceArmy Date: Sun, 19 Jun 2011 22:33:48 -0700 Subject: [PATCH 11/11] Pass source and lineNumber for console redirection. onConsoleMessage callback can handle two (optional) arguments, e.g. page.onConsoleMessage = function (msg, lineNo, source) { .... }; --- python/pyphantomjs/phantom.py | 6 ++++-- python/pyphantomjs/webpage.py | 6 ++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/python/pyphantomjs/phantom.py b/python/pyphantomjs/phantom.py index b45ae6b7..9d1ec696 100644 --- a/python/pyphantomjs/phantom.py +++ b/python/pyphantomjs/phantom.py @@ -85,8 +85,10 @@ class Phantom(QObject): injectJsInFrame(self.m_scriptFile, os.path.dirname(os.path.abspath(__file__)), self.m_page.mainFrame(), True) return not self.m_terminated - def printConsoleMessage(self, msg): - print msg + def printConsoleMessage(self, message, lineNumber, source): + if source: + message = '%s:%d %s' % (source, lineNumber, message) + print message def returnValue(self): return self.m_returnValue diff --git a/python/pyphantomjs/webpage.py b/python/pyphantomjs/webpage.py index 7b2b9d00..ba584192 100644 --- a/python/pyphantomjs/webpage.py +++ b/python/pyphantomjs/webpage.py @@ -58,9 +58,7 @@ class CustomPage(QWebPage): self.parent.javaScriptAlertSent.emit(msg) def javaScriptConsoleMessage(self, message, lineNumber, sourceID): - if sourceID: - message = '%s:%d %s' % (sourceID, lineNumber, message) - self.parent.javaScriptConsoleMessageSent.emit(message) + self.parent.javaScriptConsoleMessageSent.emit(message, lineNumber, sourceID) def userAgentForUrl(self, url): return self.m_userAgent @@ -70,7 +68,7 @@ class CustomPage(QWebPage): class WebPage(QObject): javaScriptAlertSent = pyqtSignal(str) - javaScriptConsoleMessageSent = pyqtSignal(str) + javaScriptConsoleMessageSent = pyqtSignal(str, int, str) loadStarted = pyqtSignal() loadFinished = pyqtSignal(str) resourceReceived = pyqtSignal('QVariantMap')