author | Brian Grinstead <bgrinstead@mozilla.com> |
Fri, 27 Mar 2015 07:28:19 -0700 | |
changeset 236155 | 697c11bd51f6ad213e375efa2e1fd2c253f98544 |
parent 236154 | ef364246350a5f0af2b57fcfac7fb23188e8384e |
child 236156 | 9630284e15e6ff436a1ec2b0a9c2e884eac69d04 |
push id | 28490 |
push user | kwierso@gmail.com |
push date | Fri, 27 Mar 2015 23:52:50 +0000 |
treeherder | mozilla-central@5bc74f6fa5c8 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | past |
bugs | 792063 |
milestone | 39.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/toolkit/devtools/server/actors/webconsole.js +++ b/toolkit/devtools/server/actors/webconsole.js @@ -66,16 +66,17 @@ function WebConsoleActor(aConnection, aP this._prefs = {}; this.dbg = this.parentActor.makeDebugger(); this._netEvents = new Map(); this._gripDepth = 0; this._listeners = new Set(); + this._lastConsoleInputEvaluation = undefined; this._onWillNavigate = this._onWillNavigate.bind(this); this._onChangedToplevelDocument = this._onChangedToplevelDocument.bind(this); events.on(this.parentActor, "changed-toplevel-document", this._onChangedToplevelDocument); this._onObserverNotification = this._onObserverNotification.bind(this); if (this.parentActor.isRootActor) { Services.obs.addObserver(this._onObserverNotification, "last-pb-context-exited", false); @@ -353,16 +354,17 @@ WebConsoleActor.prototype = this.conn.removeActorPool(this._actorPool); if (this.parentActor.isRootActor) { Services.obs.removeObserver(this._onObserverNotification, "last-pb-context-exited"); } this._actorPool = null; this._jstermHelpersCache = null; + this._lastConsoleInputEvaluation = null; this._evalWindow = null; this._netEvents.clear(); this.dbg.enabled = false; this.dbg = null; this.conn = null; }, /** @@ -498,16 +500,27 @@ WebConsoleActor.prototype = * @param object aActor * The actor instance you want to release. */ releaseActor: function WCA_releaseActor(aActor) { this._actorPool.removeActor(aActor.actorID); }, + /** + * Returns the latest web console input evaluation. + * This is undefined if no evaluations have been completed. + * + * @return object + */ + getLastConsoleInputEvaluation: function WCU_getLastConsoleInputEvaluation() + { + return this._lastConsoleInputEvaluation; + }, + ////////////////// // Request handlers for known packet types. ////////////////// /** * Handler for the "startListeners" request. * * @param object aRequest @@ -811,16 +824,18 @@ WebConsoleActor.prototype = // the console should remain functional. let resultGrip; try { resultGrip = this.createValueGrip(result); } catch (e) { errorMessage = e; } + this._lastConsoleInputEvaluation = result; + return { from: this.actorID, input: input, result: resultGrip, timestamp: timestamp, exception: errorGrip, exceptionMessage: this._createStringGrip(errorMessage), helperResult: helperResult,
--- a/toolkit/devtools/webconsole/test/chrome.ini +++ b/toolkit/devtools/webconsole/test/chrome.ini @@ -10,20 +10,21 @@ support-files = [test_basics.html] [test_bug819670_getter_throws.html] [test_cached_messages.html] [test_consoleapi.html] [test_consoleapi_innerID.html] [test_file_uri.html] [test_reflow.html] [test_jsterm.html] +[test_jsterm_cd_iframe.html] +[test_jsterm_last_result.html] [test_network_get.html] [test_network_longstring.html] [test_network_post.html] [test_network_security-hpkp.html] [test_network_security-hsts.html] [test_nsiconsolemessage.html] [test_object_actor.html] [test_object_actor_native_getters.html] [test_object_actor_native_getters_lenient_this.html] [test_page_errors.html] [test_throw.html] -[test_jsterm_cd_iframe.html]
--- a/toolkit/devtools/webconsole/test/common.js +++ b/toolkit/devtools/webconsole/test/common.js @@ -3,16 +3,20 @@ "use strict"; const {classes: Cc, interfaces: Ci, utils: Cu} = Components; const XHTML_NS = "http://www.w3.org/1999/xhtml"; Cu.import("resource://gre/modules/Services.jsm"); +const {Task} = Cu.import("resource://gre/modules/Task.jsm", {}); + +// This gives logging to stdout for tests +var {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {}); let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools; let WebConsoleUtils = devtools.require("devtools/toolkit/webconsole/utils").Utils; let ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"] .getService(Ci.nsIConsoleAPIStorage); let {ConsoleServiceListener, ConsoleAPIListener} =
new file mode 100644 --- /dev/null +++ b/toolkit/devtools/webconsole/test/test_jsterm_last_result.html @@ -0,0 +1,130 @@ +<!DOCTYPE HTML> +<html lang="en"> +<head> + <meta charset="utf8"> + <title>Test for the $_ getter</title> + <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript;version=1.8" src="common.js"></script> + <!-- Any copyright is dedicated to the Public Domain. + - http://creativecommons.org/publicdomain/zero/1.0/ --> +</head> +<body> +<p>Test for the $_ getter</p> + +<iframe id="content-iframe" src="http://example.com/chrome/toolkit/devtools/webconsole/test/sandboxed_iframe.html"></iframe> + +<script class="testbody" type="text/javascript;version=1.8"> +SimpleTest.waitForExplicitFinish(); +let gState; + +function evaluateJS(input, callback) { + return new Promise((resolve, reject) => { + gState.client.evaluateJSAsync(input, response => { + if (callback) { + callback(response); + } + resolve(response); + }); + }); +} + +function startTest() +{ + removeEventListener("load", startTest); + attachConsole([], state => { + gState = state; + let tests = [checkUndefinedResult,checkAdditionResult,checkObjectResult]; + runTests(tests, testEnd); + }, true); +} + +let checkUndefinedResult = Task.async(function*() { + info ("$_ returns undefined if nothing has evaluated yet"); + let response = yield evaluateJS("$_"); + basicResultCheck(response, "$_", undefined); + nextTest(); +}); + +let checkAdditionResult = Task.async(function*() { + info ("$_ returns last value and performs basic arithmetic"); + let response = yield evaluateJS("2+2"); + basicResultCheck(response, "2+2", 4); + + response = yield evaluateJS("$_"); + basicResultCheck(response, "$_", 4); + + response = yield evaluateJS("$_ + 2"); + basicResultCheck(response, "$_ + 2", 6); + + response = yield evaluateJS("$_ + 4"); + basicResultCheck(response, "$_ + 4", 10); + + nextTest(); +}); + +let checkObjectResult = Task.async(function*() { + info ("$_ has correct references to objects"); + + let response = yield evaluateJS("var foo = {bar:1}; foo;"); + basicResultCheck(response, "var foo = {bar:1}; foo;", { + type: "object", + class: "Object", + actor: /[a-z]/, + }); + checkObject(response.result.preview.ownProperties, { + bar: { + value: 1 + } + }); + + response = yield evaluateJS("$_"); + basicResultCheck(response, "$_", { + type: "object", + class: "Object", + actor: /[a-z]/, + }); + checkObject(response.result.preview.ownProperties, { + bar: { + value: 1 + } + }); + + top.foo.bar = 2; + + response = yield evaluateJS("$_"); + basicResultCheck(response, "$_", { + type: "object", + class: "Object", + actor: /[a-z]/, + }); + checkObject(response.result.preview.ownProperties, { + bar: { + value: 2 + } + }); + + nextTest(); +}); + +function basicResultCheck(response, input, output) { + checkObject(response, { + from: gState.actor, + input: input, + result: output, + }); + ok(!response.exception, "no eval exception"); + ok(!response.helperResult, "no helper result"); +} + +function testEnd() +{ + closeDebugger(gState, function() { + gState = null; + SimpleTest.finish(); + }); +} + +addEventListener("load", startTest); +</script> +</body> +</html>
--- a/toolkit/devtools/webconsole/utils.js +++ b/toolkit/devtools/webconsole/utils.js @@ -1545,16 +1545,30 @@ function JSTermHelpers(aOwner) * Returns the result of document.querySelectorAll(aSelector). */ aOwner.sandbox.$$ = function JSTH_$$(aSelector) { return aOwner.window.document.querySelectorAll(aSelector); }; /** + * Returns the result of the last console input evaluation + * + * @return object|undefined + * Returns last console evaluation or undefined + */ + Object.defineProperty(aOwner.sandbox, "$_", { + get: function() { + return aOwner.consoleActor.getLastConsoleInputEvaluation(); + }, + enumerable: true, + configurable: true + }); + + /** * Runs an xPath query and returns all matched nodes. * * @param string aXPath * xPath search query to execute. * @param [optional] nsIDOMNode aContext * Context to run the xPath query on. Uses window.document if not set. * @return array of nsIDOMNode */