зеркало из https://github.com/mozilla/gecko-dev.git
Bug 911216 - Part 30: Enable SpiderMonkey Promise implementation. r=bz,efaust,bholley,Paolo,tromey,shu
Also contains folded version of the following patches that have to land at the same time with enabling the new implementation (or be backed out at the same time, if it comes to that): Add Promise checks to test_xrayToJS.xul. r=bholley Change Promise debugger hook tests to use Promise ctor instead of makeFakePromise. r=shu Change DOM interface tests to assume Promise is an ES builtin, not a DOM one. r=bz Remove some PromiseDebugging references. r=bz Adapt promise rejections test to new xray-unwrapping error. r=bz Fix expectations in browser_timelineMarkers tests. r=tromey
This commit is contained in:
Родитель
24a9c077f4
Коммит
f8bc4fae19
|
@ -19,7 +19,6 @@ const { ActorClassWithSpec } = require("devtools/shared/protocol");
|
|||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const { assert, dumpn, update, fetch } = DevToolsUtils;
|
||||
const promise = require("promise");
|
||||
const PromiseDebugging = require("PromiseDebugging");
|
||||
const xpcInspector = require("xpcInspector");
|
||||
const ScriptStore = require("./utils/ScriptStore");
|
||||
const { DevToolsWorker } = require("devtools/shared/worker/worker");
|
||||
|
|
|
@ -317,12 +317,6 @@ this.WorkerDebuggerLoader = WorkerDebuggerLoader;
|
|||
// does not provide alternative definitions for them. Consequently, they are
|
||||
// stubbed out both on the main thread and worker threads.
|
||||
|
||||
var PromiseDebugging = {
|
||||
getState: function () {
|
||||
throw new Error("PromiseDebugging is not available in workers!");
|
||||
}
|
||||
};
|
||||
|
||||
var chrome = {
|
||||
CC: undefined,
|
||||
Cc: undefined,
|
||||
|
@ -496,7 +490,6 @@ this.worker = new WorkerDebuggerLoader({
|
|||
loadSubScript: loadSubScript,
|
||||
modules: {
|
||||
"Debugger": Debugger,
|
||||
"PromiseDebugging": PromiseDebugging,
|
||||
"Services": Object.create(null),
|
||||
"chrome": chrome,
|
||||
"xpcInspector": xpcInspector
|
||||
|
|
|
@ -50,7 +50,11 @@ if (Services.prefs.getBoolPref("javascript.options.asyncstack")) {
|
|||
ok(frame.asyncParent !== null, "Parent frame has async parent");
|
||||
is(frame.asyncParent.asyncCause, "promise callback",
|
||||
"Async parent has correct cause");
|
||||
is(frame.asyncParent.functionDisplayName, "do_promise",
|
||||
let asyncFrame = frame.asyncParent;
|
||||
// Skip over self-hosted parts of our Promise implementation.
|
||||
while (asyncFrame.source === 'self-hosted')
|
||||
asyncFrame = asyncFrame.parent;
|
||||
is(asyncFrame.functionDisplayName, "do_promise",
|
||||
"Async parent has correct function name");
|
||||
}
|
||||
}, {
|
||||
|
@ -71,7 +75,11 @@ if (Services.prefs.getBoolPref("javascript.options.asyncstack")) {
|
|||
ok(frame.asyncParent !== null, "Parent frame has async parent");
|
||||
is(frame.asyncParent.asyncCause, "promise callback",
|
||||
"Async parent has correct cause");
|
||||
is(frame.asyncParent.functionDisplayName, "do_promise_script",
|
||||
let asyncFrame = frame.asyncParent;
|
||||
// Skip over self-hosted parts of our Promise implementation.
|
||||
while (asyncFrame.source === 'self-hosted')
|
||||
asyncFrame = asyncFrame.parent;
|
||||
is(asyncFrame.functionDisplayName, "do_promise_script",
|
||||
"Async parent has correct function name");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -91,12 +91,24 @@ if (Services.prefs.getBoolPref("javascript.options.asyncstack")) {
|
|||
check: function(markers) {
|
||||
markers = markers.filter(m => m.name == "ConsoleTime");
|
||||
ok(markers.length > 0, "Promise marker includes stack");
|
||||
|
||||
ok(markers[0].stack.functionDisplayName == "testConsoleTime",
|
||||
"testConsoleTime is on the stack");
|
||||
let frame = markers[0].endStack;
|
||||
ok(frame.parent.asyncParent !== null, "Parent frame has async parent");
|
||||
is(frame.parent.asyncParent.asyncCause, "promise callback",
|
||||
ok(frame.functionDisplayName == "testConsoleTimeEnd",
|
||||
"testConsoleTimeEnd is on the stack");
|
||||
|
||||
frame = frame.parent;
|
||||
ok(frame.functionDisplayName == "makePromise/<",
|
||||
"makePromise/< is on the stack");
|
||||
let asyncFrame = frame.asyncParent;
|
||||
ok(asyncFrame !== null, "Frame has async parent");
|
||||
is(asyncFrame.asyncCause, "promise callback",
|
||||
"Async parent has correct cause");
|
||||
is(frame.parent.asyncParent.functionDisplayName, "makePromise",
|
||||
// Skip over self-hosted parts of our Promise implementation.
|
||||
while (asyncFrame.source === 'self-hosted') {
|
||||
asyncFrame = asyncFrame.parent;
|
||||
}
|
||||
is(asyncFrame.functionDisplayName, "makePromise",
|
||||
"Async parent has correct function name");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -25,7 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107592
|
|||
"Should have the right message in test " + testNumber);
|
||||
is(exn.code, code, "Should have the right .code in test " + testNumber);
|
||||
if (message === "") {
|
||||
is(exn.name, "NS_ERROR_UNEXPECTED",
|
||||
is(exn.name, "InternalError",
|
||||
"Should have one of our synthetic exceptions in test " + testNumber);
|
||||
}
|
||||
is(exn.stack, stack, "Should have the right stack in test " + testNumber);
|
||||
|
@ -41,79 +41,88 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107592
|
|||
var isE10S = !SpecialPowers.isMainProcess();
|
||||
var asyncStack = SpecialPowers.getBoolPref("javascript.options.asyncstack");
|
||||
var ourFile = location.href;
|
||||
var parentFrame = (asyncStack && !isE10S) ? `Async*@${ourFile}:121:3
|
||||
var unwrapError = "Promise rejection value is a non-unwrappable cross-compartment wrapper.";
|
||||
var parentFrame = (asyncStack && !isE10S) ? `Async*@${ourFile}:130:3
|
||||
` : "";
|
||||
|
||||
Promise.all([
|
||||
t.testPromiseWithThrowingChromePromiseInit().then(
|
||||
ensurePromiseFail.bind(null, 1),
|
||||
checkExn.bind(null, 48, "NS_ERROR_UNEXPECTED", "", undefined,
|
||||
ourFile, 1,
|
||||
`doTest@${ourFile}:48:7
|
||||
checkExn.bind(null, 49, "InternalError", unwrapError,
|
||||
undefined, ourFile, 1,
|
||||
`doTest@${ourFile}:49:7
|
||||
` +
|
||||
parentFrame)),
|
||||
t.testPromiseWithThrowingContentPromiseInit(function() {
|
||||
thereIsNoSuchContentFunction1();
|
||||
}).then(
|
||||
ensurePromiseFail.bind(null, 2),
|
||||
checkExn.bind(null, 56, "ReferenceError",
|
||||
checkExn.bind(null, 57, "ReferenceError",
|
||||
"thereIsNoSuchContentFunction1 is not defined",
|
||||
undefined, ourFile, 2,
|
||||
`doTest/<@${ourFile}:56:11
|
||||
doTest@${ourFile}:55:7
|
||||
`doTest/<@${ourFile}:57:11
|
||||
doTest@${ourFile}:56:7
|
||||
` +
|
||||
parentFrame)),
|
||||
t.testPromiseWithThrowingChromeThenFunction().then(
|
||||
ensurePromiseFail.bind(null, 3),
|
||||
checkExn.bind(null, 0, "NS_ERROR_UNEXPECTED", "", undefined, "", 3, "")),
|
||||
checkExn.bind(null, 0, "InternalError", unwrapError, undefined, "", 3, asyncStack ? (`Async*doTest@${ourFile}:67:7
|
||||
` +
|
||||
parentFrame) : "")),
|
||||
t.testPromiseWithThrowingContentThenFunction(function() {
|
||||
thereIsNoSuchContentFunction2();
|
||||
}).then(
|
||||
ensurePromiseFail.bind(null, 4),
|
||||
checkExn.bind(null, 70, "ReferenceError",
|
||||
checkExn.bind(null, 73, "ReferenceError",
|
||||
"thereIsNoSuchContentFunction2 is not defined",
|
||||
undefined, ourFile, 4,
|
||||
`doTest/<@${ourFile}:70:11
|
||||
`doTest/<@${ourFile}:73:11
|
||||
` +
|
||||
(asyncStack ? `Async*doTest@${ourFile}:69:7
|
||||
(asyncStack ? `Async*doTest@${ourFile}:72:7
|
||||
` : "") +
|
||||
parentFrame)),
|
||||
t.testPromiseWithThrowingChromeThenable().then(
|
||||
ensurePromiseFail.bind(null, 5),
|
||||
checkExn.bind(null, 0, "NS_ERROR_UNEXPECTED", "", undefined, "", 5, "")),
|
||||
checkExn.bind(null, 0, "InternalError", unwrapError, undefined, "", 5, asyncStack ? (`Async*doTest@${ourFile}:84:7
|
||||
` +
|
||||
parentFrame) : "")),
|
||||
t.testPromiseWithThrowingContentThenable({
|
||||
then: function() { thereIsNoSuchContentFunction3(); }
|
||||
}).then(
|
||||
ensurePromiseFail.bind(null, 6),
|
||||
checkExn.bind(null, 85, "ReferenceError",
|
||||
checkExn.bind(null, 90, "ReferenceError",
|
||||
"thereIsNoSuchContentFunction3 is not defined",
|
||||
undefined, ourFile, 6,
|
||||
`doTest/<.then@${ourFile}:85:32
|
||||
`)),
|
||||
`doTest/<.then@${ourFile}:90:32
|
||||
` + (asyncStack ? `Async*doTest@${ourFile}:89:7\n` + parentFrame : ""))),
|
||||
t.testPromiseWithDOMExceptionThrowingPromiseInit().then(
|
||||
ensurePromiseFail.bind(null, 7),
|
||||
checkExn.bind(null, 93, "NotFoundError",
|
||||
checkExn.bind(null, 98, "NotFoundError",
|
||||
"We are a second DOMException",
|
||||
DOMException.NOT_FOUND_ERR, ourFile, 7,
|
||||
`doTest@${ourFile}:93:7
|
||||
`doTest@${ourFile}:98:7
|
||||
` +
|
||||
parentFrame)),
|
||||
t.testPromiseWithDOMExceptionThrowingThenFunction().then(
|
||||
ensurePromiseFail.bind(null, 8),
|
||||
checkExn.bind(null, asyncStack ? 101 : 0, "NetworkError",
|
||||
checkExn.bind(null, asyncStack ? 106 : 0, "NetworkError",
|
||||
"We are a third DOMException",
|
||||
DOMException.NETWORK_ERR, asyncStack ? ourFile : "", 8,
|
||||
(asyncStack ? `Async*doTest@${ourFile}:101:7
|
||||
(asyncStack ? `Async*doTest@${ourFile}:106:7
|
||||
` +
|
||||
parentFrame : ""))),
|
||||
t.testPromiseWithDOMExceptionThrowingThenable().then(
|
||||
ensurePromiseFail.bind(null, 9),
|
||||
checkExn.bind(null, 0, "TypeMismatchError",
|
||||
checkExn.bind(null, asyncStack ? 114 : 0, "TypeMismatchError",
|
||||
"We are a fourth DOMException",
|
||||
DOMException.TYPE_MISMATCH_ERR, "", 9, "")),
|
||||
DOMException.TYPE_MISMATCH_ERR,
|
||||
asyncStack ? ourFile : "", 9,
|
||||
(asyncStack ? `Async*doTest@${ourFile}:114:7
|
||||
` +
|
||||
parentFrame : ""))),
|
||||
]).then(SimpleTest.finish,
|
||||
function() {
|
||||
ok(false, "One of our catch statements totally failed");
|
||||
function(err) {
|
||||
ok(false, "One of our catch statements totally failed with err" + err + ', stack: ' + (err ? err.stack : ''));
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ var ecmaGlobals =
|
|||
{name: "NaN", xbl: false},
|
||||
"Number",
|
||||
"Object",
|
||||
"Promise",
|
||||
"Proxy",
|
||||
"RangeError",
|
||||
"ReferenceError",
|
||||
|
@ -961,8 +962,6 @@ var interfaceNamesInGlobalScope =
|
|||
"ProcessingInstruction",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"ProgressEvent",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Promise",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "PushManager", b2g: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -47,6 +47,7 @@ var ecmaGlobals =
|
|||
"NaN",
|
||||
"Number",
|
||||
"Object",
|
||||
"Promise",
|
||||
"Proxy",
|
||||
"RangeError",
|
||||
"ReferenceError",
|
||||
|
@ -174,8 +175,6 @@ var interfaceNamesInGlobalScope =
|
|||
{ name: "PerformanceObserver", nightly: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "PerformanceObserverEntryList", nightly: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Promise",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "PushEvent", b2g: false },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -47,6 +47,7 @@ var ecmaGlobals =
|
|||
"NaN",
|
||||
"Number",
|
||||
"Object",
|
||||
"Promise",
|
||||
"Proxy",
|
||||
"RangeError",
|
||||
"ReferenceError",
|
||||
|
@ -166,8 +167,6 @@ var interfaceNamesInGlobalScope =
|
|||
{ name: "PerformanceObserver", nightly: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "PerformanceObserverEntryList", nightly: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Promise",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "PushManager", b2g: false },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -39,7 +39,8 @@ set_config('JS_DISABLE_SHELL', js_disable_shell)
|
|||
|
||||
# Use SpiderMonkey Promise implementation if it's enabled
|
||||
# =======================================================
|
||||
js_option('--enable-sm-promise', help='Enable SpiderMonkey promises')
|
||||
js_option('--enable-sm-promise', default=True,
|
||||
help='Enable SpiderMonkey promises')
|
||||
|
||||
@depends('--enable-sm-promise')
|
||||
def sm_promise(value):
|
||||
|
|
|
@ -32,14 +32,16 @@ function testDebuggerHooksNX(dbg, g, testHook) {
|
|||
testDebuggerHook("onNewGlobalObject",
|
||||
() => { newGlobal(); });
|
||||
|
||||
testDebuggerHook("onNewPromise",
|
||||
() => { g.makeFakePromise(); });
|
||||
if ('Promise' in g) {
|
||||
testDebuggerHook("onNewPromise",
|
||||
() => { new g.Promise(()=>{}); });
|
||||
|
||||
testDebuggerHook("onPromiseSettled",
|
||||
() => {
|
||||
var p = g.makeFakePromise();
|
||||
g.settleFakePromise(p);
|
||||
});
|
||||
testDebuggerHook("onPromiseSettled",
|
||||
() => {
|
||||
var p = new g.Promise(()=>{});
|
||||
g.settlePromiseNow(p);
|
||||
});
|
||||
}
|
||||
|
||||
// Hooks on frames.
|
||||
var onStepHit = false;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// Test that the onNewPromise hook gets called when promises are allocated in
|
||||
// the scope of debuggee globals.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger();
|
||||
|
@ -9,9 +11,9 @@ var gw = dbg.addDebuggee(g);
|
|||
let promisesFound = [];
|
||||
dbg.onNewPromise = p => { promisesFound.push(p); };
|
||||
|
||||
let p1 = g.makeFakePromise()
|
||||
let p1 = new g.Promise(function (){});
|
||||
dbg.enabled = false;
|
||||
let p2 = g.makeFakePromise();
|
||||
let p2 = new g.Promise(function (){});
|
||||
|
||||
assertEq(promisesFound.indexOf(gw.makeDebuggeeValue(p1)) != -1, true);
|
||||
assertEq(promisesFound.indexOf(gw.makeDebuggeeValue(p2)) == -1, true);
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
// onNewPromise handlers fire, until they are removed.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
var log;
|
||||
|
||||
log = '';
|
||||
g.makeFakePromise();
|
||||
new g.Promise(function (){});
|
||||
assertEq(log, '');
|
||||
|
||||
dbg.onNewPromise = function (promise) {
|
||||
|
@ -15,10 +17,10 @@ dbg.onNewPromise = function (promise) {
|
|||
};
|
||||
|
||||
log = '';
|
||||
g.makeFakePromise();
|
||||
new g.Promise(function (){});
|
||||
assertEq(log, 'n');
|
||||
|
||||
log = '';
|
||||
dbg.onNewPromise = undefined;
|
||||
g.makeFakePromise();
|
||||
new g.Promise(function (){});
|
||||
assertEq(log, '');
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// onNewPromise handlers on different Debugger instances are independent.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg1 = new Debugger(g);
|
||||
|
@ -18,24 +20,24 @@ function h2(promise) {
|
|||
}
|
||||
|
||||
log1 = log2 = '';
|
||||
g.makeFakePromise();
|
||||
new g.Promise(function (){});
|
||||
assertEq(log1, '');
|
||||
assertEq(log2, '');
|
||||
|
||||
log1 = log2 = '';
|
||||
dbg1.onNewPromise = h1;
|
||||
g.makeFakePromise();
|
||||
new g.Promise(function (){});
|
||||
assertEq(log1, 'n');
|
||||
assertEq(log2, '');
|
||||
|
||||
log1 = log2 = '';
|
||||
dbg2.onNewPromise = h2;
|
||||
g.makeFakePromise();
|
||||
new g.Promise(function (){});
|
||||
assertEq(log1, 'n');
|
||||
assertEq(log2, 'n');
|
||||
|
||||
log1 = log2 = '';
|
||||
dbg1.onNewPromise = undefined;
|
||||
g.makeFakePromise();
|
||||
new g.Promise(function (){});
|
||||
assertEq(log1, '');
|
||||
assertEq(log2, 'n');
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// An onNewPromise handler can disable itself.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
|
@ -10,6 +12,6 @@ dbg.onNewPromise = function (promise) {
|
|||
};
|
||||
|
||||
log = '';
|
||||
g.makeFakePromise();
|
||||
g.makeFakePromise();
|
||||
new g.Promise(function (){});
|
||||
new g.Promise(function (){});
|
||||
assertEq(log, 'n');
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
// Creating a promise within an onNewPromise handler causes a recursive handler
|
||||
// invocation.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
var dbg = new Debugger();
|
||||
var gw = dbg.addDebuggee(g);
|
||||
var log;
|
||||
var depth;
|
||||
|
||||
|
@ -13,12 +16,12 @@ dbg.onNewPromise = function (promise) {
|
|||
promise.seen = true;
|
||||
|
||||
if (depth < 3)
|
||||
g.makeFakePromise();
|
||||
gw.executeInGlobal(`new Promise(_=>{})`);
|
||||
|
||||
log += ')'; depth--;
|
||||
};
|
||||
|
||||
log = '';
|
||||
depth = 0;
|
||||
g.makeFakePromise();
|
||||
new g.Promise(function (){});
|
||||
assertEq(log, '((()))');
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Resumption values from onNewPromise handlers are disallowed.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
load(libdir + 'asserts.js');
|
||||
|
||||
|
@ -8,28 +10,28 @@ var log;
|
|||
|
||||
dbg.onNewPromise = function (g) { log += 'n'; return undefined; };
|
||||
log = '';
|
||||
assertEq(typeof g.makeFakePromise(), "object");
|
||||
assertEq(typeof new g.Promise(function (){}), "object");
|
||||
assertEq(log, 'n');
|
||||
|
||||
dbg.uncaughtExceptionHook = function (ex) { assertEq(/disallowed/.test(ex), true); log += 'u'; }
|
||||
dbg.onNewPromise = function (g) { log += 'n'; return { return: "snoo" }; };
|
||||
log = '';
|
||||
assertEq(typeof g.makeFakePromise(), "object");
|
||||
assertEq(typeof new g.Promise(function (){}), "object");
|
||||
assertEq(log, 'nu');
|
||||
|
||||
dbg.onNewPromise = function (g) { log += 'n'; return { throw: "snoo" }; };
|
||||
log = '';
|
||||
assertEq(typeof g.makeFakePromise(), "object");
|
||||
assertEq(typeof new g.Promise(function (){}), "object");
|
||||
assertEq(log, 'nu');
|
||||
|
||||
dbg.onNewPromise = function (g) { log += 'n'; return null; };
|
||||
log = '';
|
||||
assertEq(typeof g.makeFakePromise(), "object");
|
||||
assertEq(typeof new g.Promise(function (){}), "object");
|
||||
assertEq(log, 'nu');
|
||||
|
||||
dbg.uncaughtExceptionHook = function (ex) { assertEq(/foopy/.test(ex), true); log += 'u'; }
|
||||
dbg.onNewPromise = function (g) { log += 'n'; throw "foopy"; };
|
||||
log = '';
|
||||
assertEq(typeof g.makeFakePromise(), "object");
|
||||
assertEq(typeof new g.Promise(function (){}), "object");
|
||||
assertEq(log, 'nu');
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// Errors in onNewPromise handlers are reported correctly, and don't mess up the
|
||||
// promise creation.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
|
@ -8,6 +10,6 @@ let e;
|
|||
dbg.uncaughtExceptionHook = ee => { e = ee; };
|
||||
dbg.onNewPromise = () => { throw new Error("woops!"); };
|
||||
|
||||
assertEq(typeof g.makeFakePromise(), "object");
|
||||
assertEq(typeof new g.Promise(function (){}), "object");
|
||||
assertEq(!!e, true);
|
||||
assertEq(!!e.message.match(/woops/), true);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Test that the onPromiseSettled hook gets called when a promise settles.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger();
|
||||
|
@ -11,15 +13,15 @@ dbg.onPromiseSettled = pw_ => {
|
|||
log += "s";
|
||||
};
|
||||
|
||||
let p = g.makeFakePromise();
|
||||
g.settleFakePromise(p);
|
||||
let p = new g.Promise(function (){});
|
||||
g.settlePromiseNow(p);
|
||||
|
||||
assertEq(log, "s");
|
||||
assertEq(pw, gw.makeDebuggeeValue(p));
|
||||
|
||||
log = "";
|
||||
dbg.enabled = false;
|
||||
p = g.makeFakePromise();
|
||||
g.settleFakePromise(p);
|
||||
p = new g.Promise(function (){});
|
||||
g.settlePromiseNow(p);
|
||||
|
||||
assertEq(log, "");
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
// onPromiseSettled handlers fire, until they are removed.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
var log;
|
||||
|
||||
log = '';
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log, '');
|
||||
|
||||
dbg.onPromiseSettled = function (promise) {
|
||||
|
@ -15,10 +17,10 @@ dbg.onPromiseSettled = function (promise) {
|
|||
};
|
||||
|
||||
log = '';
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log, 's');
|
||||
|
||||
log = '';
|
||||
dbg.onPromiseSettled = undefined;
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log, '');
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// onPromiseSettled handlers on different Debugger instances are independent.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg1 = new Debugger(g);
|
||||
|
@ -18,24 +20,24 @@ function h2(promise) {
|
|||
}
|
||||
|
||||
log1 = log2 = '';
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log1, '');
|
||||
assertEq(log2, '');
|
||||
|
||||
log1 = log2 = '';
|
||||
dbg1.onPromiseSettled = h1;
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log1, 's');
|
||||
assertEq(log2, '');
|
||||
|
||||
log1 = log2 = '';
|
||||
dbg2.onPromiseSettled = h2;
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log1, 's');
|
||||
assertEq(log2, 's');
|
||||
|
||||
log1 = log2 = '';
|
||||
dbg1.onPromiseSettled = undefined;
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log1, '');
|
||||
assertEq(log2, 's');
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// An onPromiseSettled handler can disable itself.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
|
@ -10,6 +12,6 @@ dbg.onPromiseSettled = function (promise) {
|
|||
};
|
||||
|
||||
log = '';
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log, 's');
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
// Settling a promise within an onPromiseSettled handler causes a recursive
|
||||
// handler invocation.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
var dbg = new Debugger();
|
||||
var gw = dbg.addDebuggee(g);
|
||||
var log;
|
||||
var depth;
|
||||
|
||||
|
@ -12,13 +15,13 @@ dbg.onPromiseSettled = function (promise) {
|
|||
assertEq(promise.seen, undefined);
|
||||
promise.seen = true;
|
||||
|
||||
if (depth < 3)
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
|
||||
if (depth < 3) {
|
||||
gw.executeInGlobal(`settlePromiseNow(new Promise(_=>{}));`);
|
||||
}
|
||||
log += ')'; depth--;
|
||||
};
|
||||
|
||||
log = '';
|
||||
depth = 0;
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(_=>{}));
|
||||
assertEq(log, '((()))');
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Resumption values from onPromiseSettled handlers are disallowed.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
load(libdir + 'asserts.js');
|
||||
|
||||
|
@ -8,28 +10,28 @@ var log;
|
|||
|
||||
dbg.onPromiseSettled = function (g) { log += 's'; return undefined; };
|
||||
log = '';
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log, 's');
|
||||
|
||||
dbg.uncaughtExceptionHook = function (ex) { assertEq(/disallowed/.test(ex), true); log += 'u'; }
|
||||
dbg.onPromiseSettled = function (g) { log += 's'; return { return: "snoo" }; };
|
||||
log = '';
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log, 'su');
|
||||
|
||||
dbg.onPromiseSettled = function (g) { log += 's'; return { throw: "snoo" }; };
|
||||
log = '';
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log, 'su');
|
||||
|
||||
dbg.onPromiseSettled = function (g) { log += 's'; return null; };
|
||||
log = '';
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log, 'su');
|
||||
|
||||
dbg.uncaughtExceptionHook = function (ex) { assertEq(/foopy/.test(ex), true); log += 'u'; }
|
||||
dbg.onPromiseSettled = function (g) { log += 's'; throw "foopy"; };
|
||||
log = '';
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
assertEq(log, 'su');
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Test drainAllocationsLog() and [[Class]] names.
|
||||
if (!('Promise' in this))
|
||||
quit(0);
|
||||
|
||||
const root = newGlobal();
|
||||
const dbg = new Debugger();
|
||||
|
@ -12,7 +14,7 @@ root.eval(
|
|||
{ expected: "Date", test: () => new Date },
|
||||
{ expected: "RegExp", test: () => /problems/ },
|
||||
{ expected: "Int8Array", test: () => new Int8Array },
|
||||
{ expected: "Promise", test: makeFakePromise },
|
||||
{ expected: "Promise", test: () => new Promise(function (){})},
|
||||
];
|
||||
`
|
||||
);
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
// |jit-test| error: log is not defined
|
||||
|
||||
if (!this.Promise)
|
||||
throw new Error('log is not defined');
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
dbg.onPromiseSettled = function (g) { log += 's'; throw "foopy"; };
|
||||
g.settleFakePromise(g.makeFakePromise());
|
||||
g.settlePromiseNow(new g.Promise(function (){}));
|
||||
|
|
|
@ -16,7 +16,9 @@ static bool executor_called = false;
|
|||
static bool
|
||||
PromiseExecutor(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
#endif // DEBUG
|
||||
MOZ_ASSERT(args.length() == 2);
|
||||
MOZ_ASSERT(args[0].toObject().is<JSFunction>());
|
||||
MOZ_ASSERT(args[1].toObject().is<JSFunction>());
|
||||
|
|
|
@ -40,25 +40,37 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
|
|||
'Uint8ClampedArray'];
|
||||
errorObjectClasses = ['Error', 'InternalError', 'EvalError', 'RangeError', 'ReferenceError',
|
||||
'SyntaxError', 'TypeError', 'URIError'];
|
||||
|
||||
// A simpleConstructors entry can either be the name of a constructor as a
|
||||
// string, or an object containing the properties `name`, and `args`.
|
||||
// In the former case, the constructor is invoked without any args; in the
|
||||
// latter case, it is invoked with `args` as the arguments list.
|
||||
simpleConstructors = ['Object', 'Function', 'Array', 'Boolean', 'Date', 'Number',
|
||||
'String', 'RegExp', 'ArrayBuffer', 'WeakMap', 'Map', 'Set'].concat(typedArrayClasses)
|
||||
.concat(errorObjectClasses);
|
||||
'String', 'RegExp', 'ArrayBuffer', 'WeakMap', 'Map', 'Set',
|
||||
{name: 'Promise', args: [function(){}]}].concat(typedArrayClasses)
|
||||
.concat(errorObjectClasses);
|
||||
|
||||
function go() {
|
||||
window.iwin = document.getElementById('ifr').contentWindow;
|
||||
|
||||
// Test constructors that can be instantiated with zero arguments.
|
||||
// Test constructors that can be instantiated with zero arguments, or with
|
||||
// a fixed set of arguments provided using `...rest`.
|
||||
for (var c of simpleConstructors) {
|
||||
var args = [];
|
||||
if (typeof c === 'object') {
|
||||
args = c.args;
|
||||
c = c.name;
|
||||
}
|
||||
ok(iwin[c], "Constructors appear: " + c);
|
||||
is(iwin[c], Cu.unwaiveXrays(iwin.wrappedJSObject[c]),
|
||||
"we end up with the appropriate constructor: " + c);
|
||||
is(Cu.unwaiveXrays(Cu.waiveXrays(new iwin[c]).constructor), iwin[c],
|
||||
is(Cu.unwaiveXrays(Cu.waiveXrays(new iwin[c](...args)).constructor), iwin[c],
|
||||
"constructor property is set up right: " + c);
|
||||
let expectedProto = /Opaque/.test(new iwin[c]) ? iwin['Object'].prototype
|
||||
let expectedProto = /Opaque/.test(new iwin[c](...args)) ? iwin['Object'].prototype
|
||||
: iwin[c].prototype;
|
||||
is(Object.getPrototypeOf(new iwin[c]), expectedProto,
|
||||
is(Object.getPrototypeOf(new iwin[c](...args)), expectedProto,
|
||||
"prototype is correct: " + c);
|
||||
is(global(new iwin[c]), iwin, "Got the right global: " + c);
|
||||
is(global(new iwin[c](...args)), iwin, "Got the right global: " + c);
|
||||
}
|
||||
|
||||
// Test Object in more detail.
|
||||
|
@ -132,6 +144,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
|
|||
|
||||
testRegExp();
|
||||
|
||||
testPromise();
|
||||
|
||||
// We could also test DataView and Iterator here for completeness, but it's
|
||||
// more trouble than it's worth.
|
||||
|
||||
|
@ -228,6 +242,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
|
|||
"$5", "$6", "$7", "$8", "$9", "$_", "$&", "$+",
|
||||
"$`", "$'", Symbol.species])
|
||||
|
||||
gPrototypeProperties['Promise'] =
|
||||
["constructor", "catch", "then"];
|
||||
gConstructorProperties['Promise'] =
|
||||
constructorProps(["resolve", "reject", "all", "race", Symbol.species]);
|
||||
|
||||
// Sort an array that may contain symbols as well as strings.
|
||||
function sortProperties(arr) {
|
||||
function sortKey(prop) {
|
||||
|
@ -846,6 +865,21 @@ for (var prop of props) {
|
|||
}
|
||||
}
|
||||
|
||||
// Note: this is a small set of basic tests. More in-depth tests are located
|
||||
// in test_promise_xrays.html.
|
||||
function testPromise() {
|
||||
testXray('Promise', new iwin.Promise(function(){}), new iwin.Promise(function(){}));
|
||||
|
||||
// Test catch and then.
|
||||
var pr = new iwin.Promise(function(){});
|
||||
isnot(pr.catch, Cu.unwaiveXrays(pr.wrappedJSObject.catch), "Different function identities");
|
||||
is(Cu.getGlobalForObject(pr.catch), window, "Xray global is correct");
|
||||
is(Cu.getGlobalForObject(pr.wrappedJSObject.catch), iwin, "Underlying global is correct");
|
||||
|
||||
isnot(pr.then, Cu.unwaiveXrays(pr.wrappedJSObject.then), "Different function identities");
|
||||
is(Cu.getGlobalForObject(pr.then), window, "Xray global is correct");
|
||||
is(Cu.getGlobalForObject(pr.wrappedJSObject.then), iwin, "Underlying global is correct");
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
|
|
@ -334,10 +334,8 @@ class BaseContext {
|
|||
* belonging to the target scope. Otherwise, undefined.
|
||||
*/
|
||||
wrapPromise(promise, callback = null) {
|
||||
// Note: `promise instanceof this.cloneScope.Promise` returns true
|
||||
// here even for promises that do not belong to the content scope.
|
||||
let runSafe = this.runSafe.bind(this);
|
||||
if (promise.constructor === this.cloneScope.Promise) {
|
||||
if (promise instanceof this.cloneScope.Promise) {
|
||||
runSafe = this.runSafeWithoutClone.bind(this);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче