From 27fdf4903a5bffec6af39032c07bd8f22f255ca6 Mon Sep 17 00:00:00 2001 From: Martin Tournoij Date: Fri, 29 May 2015 18:36:39 +0200 Subject: [PATCH 1/4] Implement :jseval (Issue #334) TODO: - Tests - Doesn't show errors --- qutebrowser/misc/utilcmds.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/qutebrowser/misc/utilcmds.py b/qutebrowser/misc/utilcmds.py index ea6fdf1cc..1c7e40d99 100644 --- a/qutebrowser/misc/utilcmds.py +++ b/qutebrowser/misc/utilcmds.py @@ -111,6 +111,19 @@ def message_warning(win_id, text): message.warning(win_id, text) +@cmdutils.register(maxsplit=0, no_cmd_split=True) +def jseval(s): + """Evaluate a JavaScript string. + + Args: + s: The string to evaluate. + """ + tabbed_browser = objreg.get('tabbed-browser', scope='window', + window='last-focused') + message_info(tabbed_browser.widget(0) + .page().mainFrame().evaluateJavaScript(s)) + + @cmdutils.register(debug=True) def debug_crash(typ: {'type': ('exception', 'segfault')}='exception'): """Crash for debugging purposes. From 85eea17b183751a89ddc8bb4bb82a3a0ccdf5ba5 Mon Sep 17 00:00:00 2001 From: Martin Tournoij Date: Wed, 3 Jun 2015 22:31:15 +0200 Subject: [PATCH 2/4] Try to get the error ... not sure about this ... source is undefined when you type stuff in the console, I *think* this is the only scenario? But maybe not? --- qutebrowser/browser/commands.py | 20 ++++++++++++++++++++ qutebrowser/browser/webpage.py | 11 +++++++++++ qutebrowser/misc/utilcmds.py | 13 ------------- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 0c01260d7..bc2159843 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -1510,3 +1510,23 @@ class CommandDispatcher: view = self._current_widget() for _ in range(count): view.triggerPageAction(member) + + @cmdutils.register(instance='command-dispatcher', scope='window', + maxsplit=0, no_cmd_split=True) + def jseval(self, js): + """Evaluate a JavaScript string. + + Args: + s: The string to evaluate. + """ + tabbed_browser = objreg.get('tabbed-browser', scope='window', + window='last-focused') + out = tabbed_browser.widget(0).page().mainFrame().evaluateJavaScript( + 'window.__qute_jseval__ = true;\n' + js) + + if out is not None: + message.info(self._win_id, out) + elif tabbed_browser.widget(0).page().jseval_error: + message.error(self._win_id, + tabbed_browser.widget(0).page().jseval_error) + tabbed_browser.widget(0).page().jseval_error = None diff --git a/qutebrowser/browser/webpage.py b/qutebrowser/browser/webpage.py index 005a6e300..9e49032df 100644 --- a/qutebrowser/browser/webpage.py +++ b/qutebrowser/browser/webpage.py @@ -63,6 +63,7 @@ class BrowserPage(QWebPage): def __init__(self, win_id, tab_id, parent=None): super().__init__(parent) self._win_id = win_id + self.jseval_error = None self._is_shutting_down = False self._extension_handlers = { QWebPage.ErrorPageExtension: self._handle_errorpage, @@ -497,6 +498,16 @@ class BrowserPage(QWebPage): def javaScriptConsoleMessage(self, msg, line, source): """Override javaScriptConsoleMessage to use debug log.""" + + jseval = self.mainFrame().evaluateJavaScript('window.__qute_jseval__') + if jseval: + self.mainFrame().evaluateJavaScript('window.__qute_jseval__ = undefined;') + if source == 'undefined' and jseval: + self.mainFrame().evaluateJavaScript('window.__qute_jseval__ = false;') + print('jseval errror ->', jseval) + self.jseval_error = 'Error on line {}: {}'.format(line, msg) + print('other js error ->', msg, line, source) + if config.get('general', 'log-javascript-console'): log.js.debug("[{}:{}] {}".format(source, line, msg)) diff --git a/qutebrowser/misc/utilcmds.py b/qutebrowser/misc/utilcmds.py index 1c7e40d99..ea6fdf1cc 100644 --- a/qutebrowser/misc/utilcmds.py +++ b/qutebrowser/misc/utilcmds.py @@ -111,19 +111,6 @@ def message_warning(win_id, text): message.warning(win_id, text) -@cmdutils.register(maxsplit=0, no_cmd_split=True) -def jseval(s): - """Evaluate a JavaScript string. - - Args: - s: The string to evaluate. - """ - tabbed_browser = objreg.get('tabbed-browser', scope='window', - window='last-focused') - message_info(tabbed_browser.widget(0) - .page().mainFrame().evaluateJavaScript(s)) - - @cmdutils.register(debug=True) def debug_crash(typ: {'type': ('exception', 'segfault')}='exception'): """Crash for debugging purposes. From 94178c558abf0d5da0bdd6a5ec81348022d72a23 Mon Sep 17 00:00:00 2001 From: Martin Tournoij Date: Fri, 5 Jun 2015 20:07:47 +0200 Subject: [PATCH 3/4] Well, getting the error doesn't work... --- doc/help/commands.asciidoc | 14 ++++++++++++++ qutebrowser/browser/commands.py | 28 ++++++++++++++++++---------- qutebrowser/browser/webpage.py | 11 ----------- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc index c33bccaaf..287620867 100644 --- a/doc/help/commands.asciidoc +++ b/doc/help/commands.asciidoc @@ -20,6 +20,7 @@ |<>|Start hinting. |<>|Open main startpage in current tab. |<>|Toggle the web inspector. +|<>|Evaluate a JavaScript string. |<>|Execute a command after some time. |<>|Open typical prev/next links or navigate using the URL path. |<>|Open a URL in the current/[count]th tab. @@ -241,6 +242,19 @@ Open main startpage in current tab. === inspector Toggle the web inspector. +[[jseval]] +=== jseval +Syntax: +:jseval 'js_code'+ + +Evaluate a JavaScript string. + +==== positional arguments +* +'js_code'+: The string to evaluate. + +==== note +* This command does not split arguments after the last argument and handles quotes literally. +* With this command, +;;+ is interpreted literally instead of splitting off a second command. + [[later]] === later Syntax: +:later 'ms' 'command'+ diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index bc2159843..aa8430127 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -1513,20 +1513,28 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', scope='window', maxsplit=0, no_cmd_split=True) - def jseval(self, js): + def jseval(self, js_code): """Evaluate a JavaScript string. Args: - s: The string to evaluate. + js_code: The string to evaluate. """ tabbed_browser = objreg.get('tabbed-browser', scope='window', window='last-focused') - out = tabbed_browser.widget(0).page().mainFrame().evaluateJavaScript( - 'window.__qute_jseval__ = true;\n' + js) + frame = tabbed_browser.widget(0).page().mainFrame() + out = frame.evaluateJavaScript(js_code) - if out is not None: - message.info(self._win_id, out) - elif tabbed_browser.widget(0).page().jseval_error: - message.error(self._win_id, - tabbed_browser.widget(0).page().jseval_error) - tabbed_browser.widget(0).page().jseval_error = None + if out is None: + # Getting the actual error (if any) seems to be difficult. The + # error does end up in BrowserPage.javaScriptConsoleMessage(), but + # distinguishing between :jseval errors and errors from the webpage + # is not trivial... + message.info(self._win_id, 'No output or error') + else: + # The output can be a string, number, dict, array, etc. But *don't* + # output too much data, as this will make qutebrowser hang + out = str(out) + if len(out) > 5000: + message.info(self._win_id, out[:5000] + ' [...trimmed...]') + else: + message.info(self._win_id, out) diff --git a/qutebrowser/browser/webpage.py b/qutebrowser/browser/webpage.py index 9e49032df..005a6e300 100644 --- a/qutebrowser/browser/webpage.py +++ b/qutebrowser/browser/webpage.py @@ -63,7 +63,6 @@ class BrowserPage(QWebPage): def __init__(self, win_id, tab_id, parent=None): super().__init__(parent) self._win_id = win_id - self.jseval_error = None self._is_shutting_down = False self._extension_handlers = { QWebPage.ErrorPageExtension: self._handle_errorpage, @@ -498,16 +497,6 @@ class BrowserPage(QWebPage): def javaScriptConsoleMessage(self, msg, line, source): """Override javaScriptConsoleMessage to use debug log.""" - - jseval = self.mainFrame().evaluateJavaScript('window.__qute_jseval__') - if jseval: - self.mainFrame().evaluateJavaScript('window.__qute_jseval__ = undefined;') - if source == 'undefined' and jseval: - self.mainFrame().evaluateJavaScript('window.__qute_jseval__ = false;') - print('jseval errror ->', jseval) - self.jseval_error = 'Error on line {}: {}'.format(line, msg) - print('other js error ->', msg, line, source) - if config.get('general', 'log-javascript-console'): log.js.debug("[{}:{}] {}".format(source, line, msg)) From b0880df695867bc60a8ac9edd79bd8fee671a393 Mon Sep 17 00:00:00 2001 From: Martin Tournoij Date: Fri, 5 Jun 2015 23:24:47 +0200 Subject: [PATCH 4/4] Execute in the current tab, and not the first one --- qutebrowser/browser/commands.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index aa8430127..774cbaaa9 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -1519,10 +1519,8 @@ class CommandDispatcher: Args: js_code: The string to evaluate. """ - tabbed_browser = objreg.get('tabbed-browser', scope='window', - window='last-focused') - frame = tabbed_browser.widget(0).page().mainFrame() - out = frame.evaluateJavaScript(js_code) + out = self._current_widget().page().mainFrame().evaluateJavaScript( + js_code) if out is None: # Getting the actual error (if any) seems to be difficult. The