author | Nick Fitzgerald <fitzgen@gmail.com> |
Thu, 23 Oct 2014 15:53:00 +0200 | |
changeset 212445 | 7ab817145c8d390bc3265adc7cbc2e9ea2bc1465 |
parent 212444 | d4ed6c1353b50ab5bd27e84859453dfe9751ee88 |
child 212446 | 2548cc70c191af400eb452e7a219187a4e4bab24 |
push id | 27711 |
push user | cbook@mozilla.com |
push date | Mon, 27 Oct 2014 14:56:47 +0000 |
treeherder | mozilla-central@20408ad61ce5 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | vporof |
bugs | 1033153 |
milestone | 36.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/browser/devtools/debugger/test/browser.ini +++ b/browser/devtools/debugger/test/browser.ini @@ -71,16 +71,17 @@ support-files = doc_minified_bogus_map.html doc_native-event-handler.html doc_no-page-sources.html doc_pause-exceptions.html doc_pretty-print.html doc_pretty-print-2.html doc_pretty-print-3.html doc_pretty-print-on-paused.html + doc_promise.html doc_random-javascript.html doc_recursion-stack.html doc_same-line-functions.html doc_scope-variable.html doc_scope-variable-2.html doc_scope-variable-3.html doc_scope-variable-4.html doc_script-switching-01.html @@ -273,16 +274,17 @@ skip-if = os == "linux" || e10s # Bug 88 [browser_dbg_tracing-06.js] [browser_dbg_tracing-07.js] [browser_dbg_tracing-08.js] [browser_dbg_variables-view-01.js] [browser_dbg_variables-view-02.js] [browser_dbg_variables-view-03.js] [browser_dbg_variables-view-04.js] [browser_dbg_variables-view-05.js] +[browser_dbg_variables-view-06.js] [browser_dbg_variables-view-accessibility.js] [browser_dbg_variables-view-data.js] [browser_dbg_variables-view-edit-cancel.js] [browser_dbg_variables-view-edit-click.js] skip-if = (os == 'mac' || os == 'win') && (debug == false) # Bug 986166 [browser_dbg_variables-view-edit-getset-01.js] [browser_dbg_variables-view-edit-getset-02.js] [browser_dbg_variables-view-edit-value.js]
new file mode 100644 --- /dev/null +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-06.js @@ -0,0 +1,122 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test that Promises get their internal state added as psuedo properties. + */ + +const TAB_URL = EXAMPLE_URL + "doc_promise.html"; + +const test = Task.async(function* () { + const [tab, debuggee, panel] = yield initDebugger(TAB_URL); + yield ensureSourceIs(panel, "doc_promise.html", true); + + const scopes = waitForCaretAndScopes(panel, 21); + executeSoon(debuggee.doPause); + yield scopes; + + const variables = panel.panelWin.DebuggerView.Variables; + ok(variables, "Should get the variables view."); + + const scope = [...variables][0]; + ok(scope, "Should get the current function's scope."); + + const promiseVariables = [...scope].filter(([name]) => + ["p", "f", "r"].indexOf(name) !== -1); + + is(promiseVariables.length, 3, + "Should have our 3 promise variables: p, f, r"); + + for (let [name, item] of promiseVariables) { + info("Expanding variable '" + name + "'"); + let expanded = once(variables, "fetched"); + item.expand(); + yield expanded; + + let foundState = false; + switch (name) { + case "p": + for (let [property, { value }] of item) { + if (property !== "<state>") { + isnot(property, "<value>", + "A pending promise shouldn't have a value"); + isnot(property, "<reason>", + "A pending promise shouldn't have a reason"); + continue; + } + + foundState = true; + is(value, "pending", "The state should be pending."); + } + ok(foundState, "We should have found the <state> property."); + break; + + case "f": + let foundValue = false; + for (let [property, value] of item) { + if (property === "<state>") { + foundState = true; + is(value.value, "fulfilled", "The state should be fulfilled."); + } else if (property === "<value>") { + foundValue = true; + + let expanded = once(variables, "fetched"); + value.expand(); + yield expanded; + + let expectedProps = new Map([["a", 1], ["b", 2], ["c", 3]]); + for (let [prop, val] of value) { + if (prop === "__proto__") { + continue; + } + ok(expectedProps.has(prop), "The property should be expected."); + is(val.value, expectedProps.get(prop), "The property value should be correct."); + expectedProps.delete(prop); + } + is(Object.keys(expectedProps).length, 0, + "Should have found all of the expected properties."); + } else { + isnot(property, "<reason>", + "A fulfilled promise shouldn't have a reason"); + } + } + ok(foundState, "We should have found the <state> property."); + ok(foundValue, "We should have found the <value> property."); + break; + + case "r": + let foundReason = false; + for (let [property, value] of item) { + if (property === "<state>") { + foundState = true; + is(value.value, "rejected", "The state should be rejected."); + } else if (property === "<reason>") { + foundReason = true; + + let expanded = once(variables, "fetched"); + value.expand(); + yield expanded; + + let foundMessage = false; + for (let [prop, val] of value) { + if (prop !== "message") { + continue; + } + foundMessage = true; + is(val.value, "uh oh", "Should have the correct error message."); + } + ok(foundMessage, "Should have found the error's message"); + } else { + isnot(property, "<value>", + "A rejected promise shouldn't have a value"); + } + } + ok(foundState, "We should have found the <state> property."); + break; + } + } + + debugger; + + resumeDebuggerThenCloseAndFinish(panel); +});
new file mode 100644 --- /dev/null +++ b/browser/devtools/debugger/test/doc_promise.html @@ -0,0 +1,30 @@ +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE html> + +<html> + <head> + <meta charset="utf-8"/> + <title>Debugger + Promise test page</title> + </head> + + <body> + <script> + window.pending = new Promise(function () {}); + window.fulfilled = Promise.resolve({ a: 1, b: 2, c: 3 }); + window.rejected = Promise.reject(new Error("uh oh")); + + window.doPause = function () { + var p = window.pending; + var f = window.fulfilled; + var r = window.rejected; + debugger; + }; + + // Attach an error handler so that the logs don't have a warning about an + // unhandled, rejected promise. + window.rejected.then(null, function () {}); + </script> + </body> + +</html>
--- a/browser/devtools/shared/widgets/VariablesViewController.jsm +++ b/browser/devtools/shared/widgets/VariablesViewController.jsm @@ -165,16 +165,26 @@ VariablesViewController.prototype = { * @param Scope aTarget * The Scope where the properties will be placed into. * @param object aGrip * The grip to use to populate the target. */ _populateFromObject: function(aTarget, aGrip) { let deferred = promise.defer(); + if (aGrip.class === "Promise" && aGrip.promiseState) { + const { state, value, reason } = aGrip.promiseState; + aTarget.addItem("<state>", { value: state }); + if (state === "fulfilled") { + this.addExpander(aTarget.addItem("<value>", { value }), value); + } else if (state === "rejected") { + this.addExpander(aTarget.addItem("<reason>", { value: reason }), reason); + } + } + let objectClient = this._getObjectClient(aGrip); objectClient.getPrototypeAndProperties(aResponse => { let { ownProperties, prototype } = aResponse; // 'safeGetterValues' is new and isn't necessary defined on old actors. let safeGetterValues = aResponse.safeGetterValues || {}; let sortable = VariablesView.isSortable(aGrip.class); // Merge the safe getter values into one object such that we can use it