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:
Till Schneidereit 2016-07-21 00:44:16 +02:00
Родитель 24a9c077f4
Коммит f8bc4fae19
28 изменённых файлов: 196 добавлений и 107 удалений

Просмотреть файл

@ -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);
}