Source code

Revision control

Copy as Markdown

Other Tools

/*
* This file is meant to provide common infrastructure for several consumers.
* The consumer is expected to define the following things:
*
* 1) An verifyPromiseGlobal function which does whatever test the consumer
* wants.
* 2) An isXrayArgumentTest global boolean, because some of these tests act
* differenly based on that boolean.
* 3) A function named getPromise. This function is given a global object and a
* single argument to use for getting the promise. The getPromise function
* is expected to trigger the canonical Promise.resolve for the given global
* with the given argument in some way that depends on the test, and return
* the result.
* 4) A subframe (frames[0]) which can be used as a second global for creating
* promises.
*/
/* global verifyPromiseGlobal, getPromise, isXrayArgumentTest */
var label = "parent";
function passBasicPromise() {
var p1 = Promise.resolve();
verifyPromiseGlobal(p1, window, "Promise.resolve return value 1");
var p2 = getPromise(window, p1);
is(p1, p2, "Basic promise should just pass on through");
return p2;
}
function passPrimitive(global) {
var p = getPromise(global, 5);
verifyPromiseGlobal(p, global, "Promise wrapping primitive");
return p.then(function (arg) {
is(arg, 5, "Should have the arg we passed in");
});
}
function passThenable(global) {
var called = false;
var thenable = {
then(f) {
called = true;
f(7);
},
};
var p = getPromise(global, thenable);
verifyPromiseGlobal(p, global, "Promise wrapping thenable");
return p.then(function (arg) {
ok(called, "Thenable should have been called");
is(arg, 7, "Should have the arg our thenable passed in");
});
}
function passWrongPromiseWithMatchingConstructor() {
var p1 = Promise.resolve();
verifyPromiseGlobal(p1, window, "Promise.resolve() return value 2");
p1.constructor = frames[0].Promise;
var p2 = getPromise(frames[0], p1);
// The behavior here will depend on whether we're touching frames[0] via Xrays
// or not. If we are not, the current compartment while getting our promise
// will be that of frames[0]. If we are, it will be our window's compartment.
if (isXrayArgumentTest) {
isnot(
p1,
p2,
"Should have wrapped the Promise in a new promise, because its constructor is not matching the current-compartment Promise constructor"
);
verifyPromiseGlobal(
p2,
window,
"Promise wrapping xrayed promise with therefore non-matching constructor"
);
} else {
is(
p1,
p2,
"Should have left the Promise alone because its constructor matched"
);
}
return p2;
}
function passCorrectPromiseWithMismatchedConstructor() {
var p1 = Promise.resolve(9);
verifyPromiseGlobal(p1, window, "Promise.resolve() return value 3");
p1.constructor = frames[0].Promise;
var p2 = getPromise(window, p1);
isnot(
p1,
p2,
"Should have wrapped promise in a new promise, since its .constructor was wrong"
);
verifyPromiseGlobal(
p2,
window,
"Promise wrapping passed-in promise with mismatched constructor"
);
return p2.then(function (arg) {
is(arg, 9, "Should have propagated along our resolution value");
});
}
function passPromiseToOtherGlobal() {
var p1 = Promise.resolve();
verifyPromiseGlobal(p1, window, "Promise.resolve() return value 4");
var p2 = getPromise(frames[0], p1);
// The behavior here will depend on whether we're touching frames[0] via Xrays
// or not. If we are not, the current compartment while getting our promise
// will be that of frames[0]. If we are, it will be our window's compartment.
if (isXrayArgumentTest) {
is(
p1,
p2,
"Should have left the Promise alone, because its constructor matches the current compartment's constructor"
);
} else {
isnot(
p1,
p2,
"Should have wrapped promise in a promise from the other global"
);
verifyPromiseGlobal(
p2,
frames[0],
"Promise wrapping passed-in basic promise"
);
}
return p2;
}
function passPromiseSubclass() {
class PromiseSubclass extends Promise {
constructor(func) {
super(func);
}
}
var p1 = PromiseSubclass.resolve(11);
verifyPromiseGlobal(p1, window, "PromiseSubclass.resolve() return value");
var p2 = getPromise(window, p1);
isnot(p1, p2, "Should have wrapped promise subclass in a new promise");
verifyPromiseGlobal(
p2,
window,
"Promise wrapping passed-in promise subclass"
);
return p2.then(function (arg) {
is(
arg,
11,
"Should have propagated along our resolution value from subclass"
);
});
}
function runPromiseArgumentTests(finishFunc) {
Promise.resolve()
.then(passBasicPromise)
.then(passPrimitive.bind(undefined, window))
.then(passPrimitive.bind(undefined, frames[0]))
.then(passThenable.bind(undefined, window))
.then(passThenable.bind(undefined, frames[0]))
.then(passWrongPromiseWithMatchingConstructor)
.then(passCorrectPromiseWithMismatchedConstructor)
.then(passPromiseToOtherGlobal)
.then(passPromiseSubclass)
.then(finishFunc)
.catch(function (e) {
ok(
false,
`Exception thrown: ${e}@${location.pathname}:${e.lineNumber}:${e.columnNumber}`
);
finishFunc();
});
}