mirror of https://github.com/vitalif/phantomjs
support for backtraces (part 2).
add a default error handler on all pages. people can override if they need. ensure error handler can be removed without errors. Hack ScriptSourceCode so we can pass in a raw string and not have it validated as a URL change source location hint for webpage.evaluate(). http://code.google.com/p/phantomjs/issues/detail?id=166 Please enter the commit message for your changes. Lines starting1.5
parent
afe570484f
commit
a48770cba3
|
@ -34,7 +34,6 @@
|
|||
*/
|
||||
|
||||
function require(name) {
|
||||
|
||||
var code, func, exports;
|
||||
|
||||
if (name === 'webpage' || name === 'fs' || name === 'webserver' || name === 'system') {
|
||||
|
@ -55,5 +54,35 @@ function require(name) {
|
|||
}
|
||||
}
|
||||
|
||||
(function() {
|
||||
var handler;
|
||||
var signal = phantom.page.javaScriptErrorSent;
|
||||
|
||||
phantom.__defineSetter__('onError', function(f) {
|
||||
if (handler && typeof handler === 'function') {
|
||||
try { signal.disconnect(handler) } catch (e) {}
|
||||
}
|
||||
|
||||
handler = f;
|
||||
|
||||
if (typeof f === 'function') {
|
||||
signal.connect(f);
|
||||
}
|
||||
})
|
||||
})();
|
||||
|
||||
// TODO: Make this output to STDERR
|
||||
phantom.defaultErrorHandler = function(error, backtrace) {
|
||||
console.log(error + "\n");
|
||||
|
||||
backtrace.forEach(function(item) {
|
||||
var message = item.file + ":" + item.line;
|
||||
if (item.function) message += " in " + item.function
|
||||
console.log(" " + message);
|
||||
})
|
||||
}
|
||||
|
||||
phantom.onError = phantom.defaultErrorHandler;
|
||||
|
||||
// Legacy way to use WebPage
|
||||
window.WebPage = require('webpage').create;
|
||||
|
|
|
@ -205,7 +205,7 @@ void Config::loadJsonFile(const QString &filePath)
|
|||
// Add this object to the global scope
|
||||
webPage.mainFrame()->addToJavaScriptWindowObject("config", this);
|
||||
// Apply the JSON config settings to this very object
|
||||
webPage.mainFrame()->evaluateJavaScript(configurator.arg(jsonConfig));
|
||||
webPage.mainFrame()->evaluateJavaScript(configurator.arg(jsonConfig), QString());
|
||||
}
|
||||
|
||||
bool Config::autoLoadImages() const
|
||||
|
|
|
@ -48,17 +48,23 @@ CSConverter *CSConverter::instance()
|
|||
CSConverter::CSConverter()
|
||||
: QObject(QCoreApplication::instance())
|
||||
{
|
||||
m_webPage.mainFrame()->evaluateJavaScript(Utils::readResourceFileUtf8(":/coffee-script.js"));
|
||||
m_webPage.mainFrame()->evaluateJavaScript(
|
||||
Utils::readResourceFileUtf8(":/coffee-script.js"),
|
||||
QString("phantomjs://coffee-script.js")
|
||||
);
|
||||
m_webPage.mainFrame()->addToJavaScriptWindowObject("converter", this);
|
||||
}
|
||||
|
||||
QVariant CSConverter::convert(const QString &script)
|
||||
{
|
||||
setProperty("source", script);
|
||||
QVariant result = m_webPage.mainFrame()->evaluateJavaScript("try {" \
|
||||
" [true, this.CoffeeScript.compile(converter.source)];" \
|
||||
"} catch (error) {" \
|
||||
" [false, error.message];" \
|
||||
"}");
|
||||
QVariant result = m_webPage.mainFrame()->evaluateJavaScript(
|
||||
"try {" \
|
||||
" [true, this.CoffeeScript.compile(converter.source)];" \
|
||||
"} catch (error) {" \
|
||||
" [false, error.message];" \
|
||||
"}",
|
||||
QString()
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -99,8 +99,12 @@ exports.create = function (opts) {
|
|||
this[signalName].disconnect(handlers[signalName]);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
handlers[signalName] = f;
|
||||
this[signalName].connect(handlers[signalName]);
|
||||
|
||||
if (typeof f === 'function') {
|
||||
this[signalName].connect(f);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -121,6 +125,10 @@ exports.create = function (opts) {
|
|||
|
||||
defineSetter("onConsoleMessage", "javaScriptConsoleMessageSent");
|
||||
|
||||
defineSetter("onError", "javaScriptErrorSent");
|
||||
|
||||
page.onError = phantom.defaultErrorHandler;
|
||||
|
||||
page.open = function (url, arg1, arg2, arg3, arg4) {
|
||||
if (arguments.length === 1) {
|
||||
this.openUrl(url, 'get', this.settings);
|
||||
|
|
|
@ -122,8 +122,6 @@ Phantom::Phantom(QObject *parent)
|
|||
m_page->applySettings(m_defaultPageSettings);
|
||||
|
||||
setLibraryPath(QFileInfo(m_config.scriptFile()).dir().absolutePath());
|
||||
|
||||
onInitialized();
|
||||
}
|
||||
|
||||
Phantom::~Phantom()
|
||||
|
@ -208,6 +206,11 @@ QVariantMap Phantom::version() const
|
|||
return result;
|
||||
}
|
||||
|
||||
QObject *Phantom::page() const
|
||||
{
|
||||
return m_page;
|
||||
}
|
||||
|
||||
// public slots:
|
||||
QObject *Phantom::createWebPage()
|
||||
{
|
||||
|
@ -287,10 +290,7 @@ void Phantom::debugExit(int code)
|
|||
// private slots:
|
||||
void Phantom::printConsoleMessage(const QString &message, int lineNumber, const QString &source)
|
||||
{
|
||||
QString msg = message;
|
||||
if (!source.isEmpty())
|
||||
msg = source + ":" + QString::number(lineNumber) + " " + msg;
|
||||
Terminal::instance()->cout(msg);
|
||||
Terminal::instance()->cout(message);
|
||||
}
|
||||
|
||||
void Phantom::onInitialized()
|
||||
|
@ -299,7 +299,10 @@ void Phantom::onInitialized()
|
|||
m_page->mainFrame()->addToJavaScriptWindowObject("phantom", this);
|
||||
|
||||
// Bootstrap the PhantomJS scope
|
||||
m_page->mainFrame()->evaluateJavaScript(Utils::readResourceFileUtf8(":/bootstrap.js"));
|
||||
m_page->mainFrame()->evaluateJavaScript(
|
||||
Utils::readResourceFileUtf8(":/bootstrap.js"),
|
||||
QString("phantomjs://bootstrap.js")
|
||||
);
|
||||
}
|
||||
|
||||
// private:
|
||||
|
|
|
@ -52,6 +52,7 @@ class Phantom: public REPLCompletable
|
|||
Q_PROPERTY(QString outputEncoding READ outputEncoding WRITE setOutputEncoding)
|
||||
Q_PROPERTY(QString scriptName READ scriptName)
|
||||
Q_PROPERTY(QVariantMap version READ version)
|
||||
Q_PROPERTY(QObject *page READ page)
|
||||
|
||||
public:
|
||||
Phantom(QObject *parent = 0);
|
||||
|
@ -74,6 +75,8 @@ public:
|
|||
|
||||
QVariantMap version() const;
|
||||
|
||||
QObject* page() const;
|
||||
|
||||
public slots:
|
||||
QObject *createWebPage();
|
||||
QObject *createWebServer();
|
||||
|
|
|
@ -99,7 +99,7 @@ REPL::REPL(QWebFrame *webframe, Phantom *parent)
|
|||
linenoiseSetCompletionCallback(REPL::offerCompletion);
|
||||
|
||||
// Inject REPL utility functions
|
||||
m_webframe->evaluateJavaScript(Utils::readResourceFileUtf8(":/repl.js"));
|
||||
m_webframe->evaluateJavaScript(Utils::readResourceFileUtf8(":/repl.js"), QString("phantomjs://repl.js"));
|
||||
|
||||
// Start the REPL's loop
|
||||
QTimer::singleShot(0, this, SLOT(startLoop()));
|
||||
|
@ -133,7 +133,8 @@ void REPL::offerCompletion(const char *buf, linenoiseCompletions *lc)
|
|||
QStringList completions = REPL::getInstance()->m_webframe->evaluateJavaScript(
|
||||
QString(JS_RETURN_POSSIBLE_COMPLETIONS).arg(
|
||||
toInspect,
|
||||
toComplete)
|
||||
toComplete),
|
||||
QString()
|
||||
).toStringList();
|
||||
|
||||
foreach (QString c, completions) {
|
||||
|
@ -158,7 +159,7 @@ void REPL::startLoop()
|
|||
// Send the user input to the main Phantom frame for evaluation
|
||||
m_webframe->evaluateJavaScript(
|
||||
QString(JS_EVAL_USER_INPUT).arg(
|
||||
QString(userInput).replace('"', "\\\"")));
|
||||
QString(userInput).replace('"', "\\\"")), QString("phantomjs://repl-input"));
|
||||
|
||||
// Save command in the REPL history
|
||||
linenoiseHistoryAdd(userInput);
|
||||
|
|
|
@ -94,7 +94,7 @@ bool Utils::injectJsInFrame(const QString &jsFilePath, const Encoding &jsFileEnc
|
|||
return false;
|
||||
}
|
||||
// Execute JS code in the context of the document
|
||||
targetFrame->evaluateJavaScript(scriptBody);
|
||||
targetFrame->evaluateJavaScript(scriptBody, jsFilePath);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ bool Utils::loadJSForDebug(const QString& jsFilePath, const Encoding& jsFileEnc,
|
|||
targetFrame->setHtml(remoteDebuggerHarnessSrc);
|
||||
|
||||
if (autorun) {
|
||||
targetFrame->evaluateJavaScript("__run()");
|
||||
targetFrame->evaluateJavaScript("__run()", QString());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -92,6 +92,10 @@ protected:
|
|||
m_webPage->emitConsoleMessage(message, lineNumber, sourceID);
|
||||
}
|
||||
|
||||
void javaScriptError(const QWebPage::JavaScriptError& error) {
|
||||
m_webPage->emitError(error);
|
||||
}
|
||||
|
||||
QString userAgentForUrl(const QUrl &url) const {
|
||||
Q_UNUSED(url);
|
||||
return m_userAgent;
|
||||
|
@ -287,7 +291,7 @@ QVariantMap WebPage::paperSize() const
|
|||
QVariant WebPage::evaluate(const QString &code)
|
||||
{
|
||||
QString function = "(" + code + ")()";
|
||||
return m_mainFrame->evaluateJavaScript(function);
|
||||
return m_mainFrame->evaluateJavaScript(function, QString("phantomjs://webpage.evaluate()"));
|
||||
}
|
||||
|
||||
void WebPage::emitAlert(const QString &msg)
|
||||
|
@ -300,6 +304,25 @@ void WebPage::emitConsoleMessage(const QString &message, int lineNumber, const Q
|
|||
emit javaScriptConsoleMessageSent(message, lineNumber, source);
|
||||
}
|
||||
|
||||
void WebPage::emitError(const QWebPage::JavaScriptError& error)
|
||||
{
|
||||
QList<QWebPage::JavaScriptFrame> backtrace = error.backtrace();
|
||||
QVariantList newBacktrace = QVariantList();
|
||||
|
||||
for (int i = 0; i < backtrace.size(); ++i) {
|
||||
QWebPage::JavaScriptFrame frame = backtrace.at(i);
|
||||
|
||||
QVariantMap newFrame = QVariantMap();
|
||||
newFrame["file"] = frame.file();
|
||||
newFrame["line"] = frame.line();
|
||||
newFrame["function"] = frame.function();
|
||||
|
||||
newBacktrace << newFrame;
|
||||
}
|
||||
|
||||
emit javaScriptErrorSent(error.message(), newBacktrace);
|
||||
}
|
||||
|
||||
void WebPage::finish(bool ok)
|
||||
{
|
||||
QString status = ok ? "success" : "fail";
|
||||
|
@ -349,7 +372,7 @@ void WebPage::openUrl(const QString &address, const QVariant &op, const QVariant
|
|||
networkOp = QNetworkAccessManager::DeleteOperation;
|
||||
|
||||
if (networkOp == QNetworkAccessManager::UnknownOperation) {
|
||||
m_mainFrame->evaluateJavaScript("console.error('Unknown network operation: " + operation + "');");
|
||||
m_mainFrame->evaluateJavaScript("console.error('Unknown network operation: " + operation + "');", QString());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -598,7 +621,7 @@ bool WebPage::injectJs(const QString &jsFilePath) {
|
|||
}
|
||||
|
||||
void WebPage::_appendScriptElement(const QString &scriptUrl) {
|
||||
m_mainFrame->evaluateJavaScript( QString(JS_APPEND_SCRIPT_ELEMENT).arg(scriptUrl) );
|
||||
m_mainFrame->evaluateJavaScript( QString(JS_APPEND_SCRIPT_ELEMENT).arg(scriptUrl), scriptUrl );
|
||||
}
|
||||
|
||||
void WebPage::sendEvent(const QString &type, const QVariant &arg1, const QVariant &arg2)
|
||||
|
|
|
@ -102,6 +102,7 @@ signals:
|
|||
void loadFinished(const QString &status);
|
||||
void javaScriptAlertSent(const QString &msg);
|
||||
void javaScriptConsoleMessageSent(const QString &message, int lineNumber, const QString &source);
|
||||
void javaScriptErrorSent(const QString &message, const QVariantList &backtrace);
|
||||
void resourceRequested(const QVariant &req);
|
||||
void resourceReceived(const QVariant &resource);
|
||||
|
||||
|
@ -116,6 +117,7 @@ private:
|
|||
|
||||
void emitAlert(const QString &msg);
|
||||
void emitConsoleMessage(const QString &msg, int lineNumber, const QString &source);
|
||||
void emitError(const QWebPage::JavaScriptError& error);
|
||||
|
||||
virtual void initCompletions();
|
||||
|
||||
|
|
Loading…
Reference in New Issue