summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_6/Promise
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/ecma_6/Promise')
-rw-r--r--js/src/tests/ecma_6/Promise/browser.js0
-rw-r--r--js/src/tests/ecma_6/Promise/bug-1287334.js12
-rw-r--r--js/src/tests/ecma_6/Promise/bug-1288382.js13
-rw-r--r--js/src/tests/ecma_6/Promise/bug-1289040.js13
-rw-r--r--js/src/tests/ecma_6/Promise/dependent-promises.js41
-rw-r--r--js/src/tests/ecma_6/Promise/enqueue-promise-reactions.js43
-rw-r--r--js/src/tests/ecma_6/Promise/get-wait-for-all-promise.js65
-rw-r--r--js/src/tests/ecma_6/Promise/iterator-primitive.js28
-rw-r--r--js/src/tests/ecma_6/Promise/methods-non-enumerable.js9
-rw-r--r--js/src/tests/ecma_6/Promise/promise-all.js30
-rw-r--r--js/src/tests/ecma_6/Promise/promise-basics.js101
-rw-r--r--js/src/tests/ecma_6/Promise/promise-rejection-tracking.js36
-rw-r--r--js/src/tests/ecma_6/Promise/promise-species.js13
-rw-r--r--js/src/tests/ecma_6/Promise/promise-subclassing.js67
-rw-r--r--js/src/tests/ecma_6/Promise/self-resolve.js23
-rw-r--r--js/src/tests/ecma_6/Promise/shell.js0
16 files changed, 494 insertions, 0 deletions
diff --git a/js/src/tests/ecma_6/Promise/browser.js b/js/src/tests/ecma_6/Promise/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/browser.js
diff --git a/js/src/tests/ecma_6/Promise/bug-1287334.js b/js/src/tests/ecma_6/Promise/bug-1287334.js
new file mode 100644
index 000000000..0bd25decd
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/bug-1287334.js
@@ -0,0 +1,12 @@
+if (!this.Promise) {
+ this.reportCompare && reportCompare(true, true);
+ quit(0);
+}
+
+var promise = Promise.resolve(1);
+var FakeCtor = function(exec){ exec(function(){}, function(){}); };
+Object.defineProperty(Promise, Symbol.species, {value: FakeCtor});
+// This just shouldn't crash. It does without bug 1287334 fixed.
+promise.then(function(){});
+
+this.reportCompare && reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Promise/bug-1288382.js b/js/src/tests/ecma_6/Promise/bug-1288382.js
new file mode 100644
index 000000000..f954d6279
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/bug-1288382.js
@@ -0,0 +1,13 @@
+if (!this.Promise) {
+ this.reportCompare && reportCompare(true, true);
+ quit(0);
+}
+
+// This just shouldn't trigger a failed assert.
+// It does without bug 1288382 fixed.
+Promise.all.call(class {
+ constructor(exec){ exec(()=>{}, ()=>{}); }
+ static resolve() { return {then(){}}; }
+}, [null]);
+
+this.reportCompare && reportCompare(true, true);
diff --git a/js/src/tests/ecma_6/Promise/bug-1289040.js b/js/src/tests/ecma_6/Promise/bug-1289040.js
new file mode 100644
index 000000000..9290d8ad4
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/bug-1289040.js
@@ -0,0 +1,13 @@
+if (!this.Promise) {
+ this.reportCompare && reportCompare(true,true);
+ quit(0);
+}
+
+var global = newGlobal();
+Promise.prototype.then = global.Promise.prototype.then;
+p1 = new Promise(function f(r) {
+ r(1);
+});
+p2 = p1.then(function g(){});
+
+this.reportCompare && reportCompare(true,true);
diff --git a/js/src/tests/ecma_6/Promise/dependent-promises.js b/js/src/tests/ecma_6/Promise/dependent-promises.js
new file mode 100644
index 000000000..36e11a5f6
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/dependent-promises.js
@@ -0,0 +1,41 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs Debugger
+
+if (!this.Promise) {
+ this.reportCompare && reportCompare(true,true);
+ quit(0);
+}
+
+var g = newGlobal();
+var dbg = new Debugger(g);
+var gw = dbg.addDebuggee(g);
+
+g.eval(`
+var p = new Promise(() => {});
+p.name = "p";
+var q = p.then();
+q.name = "q";
+var r = p.then(null, () => {});
+r.name = "r";
+var s = Promise.all([p, q]);
+s.name = "s";
+var t = Promise.race([r, s]);
+t.name = "t";
+`);
+
+function getDependentNames(promise) {
+ return gw.makeDebuggeeValue(promise).promiseDependentPromises.map((p) => p.getOwnPropertyDescriptor('name').value);
+}
+
+function arraysEqual(arr1, arr2, msg) {
+ assertEq(arr1.length, arr2.length, msg + ": length");
+ for (var i = 0; i < arr1.length; ++i) {
+ assertEq(arr1[i], arr2[i], msg + ": [" + i + "]");
+ }
+}
+
+arraysEqual(getDependentNames(g.p), ["q", "r", "s"], "deps for p");
+arraysEqual(getDependentNames(g.q), ["s"], "deps for q");
+arraysEqual(getDependentNames(g.r), ["t"], "deps for r");
+arraysEqual(getDependentNames(g.s), ["t"], "deps for s");
+
+this.reportCompare && reportCompare(true,true);
diff --git a/js/src/tests/ecma_6/Promise/enqueue-promise-reactions.js b/js/src/tests/ecma_6/Promise/enqueue-promise-reactions.js
new file mode 100644
index 000000000..ddb366aba
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/enqueue-promise-reactions.js
@@ -0,0 +1,43 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs getSelfHostedValue and drainJobQueue
+
+if (!this.Promise) {
+ this.reportCompare && reportCompare(true,true);
+ quit(0);
+}
+
+function onResolved(val) {
+ result = 'resolved with ' + val;
+}
+
+function onRejected(val) {
+ result = 'rejected with ' + val;
+}
+
+// Replacing `Promise#then` shouldn't affect addPromiseReactions.
+Promise.prototype.then = 1;
+
+// Replacing Promise@@species shouldn't affect addPromiseReactions.
+Promise[Symbol.species] = function(){};
+
+// Replacing `Promise` shouldn't affect addPromiseReactions.
+let PromiseCtor = Promise;
+Promise = {};
+
+let result;
+let res;
+let rej;
+let p = new PromiseCtor(function(res_, rej_) { res = res_; rej = rej_; });
+
+addPromiseReactions(p, onResolved, onRejected);
+res('foo');
+drainJobQueue();
+assertEq(result, 'resolved with foo')
+
+p = new PromiseCtor(function(res_, rej_) { res = res_; rej = rej_; });
+
+addPromiseReactions(p, onResolved, onRejected);
+rej('bar');
+drainJobQueue();
+assertEq(result, 'rejected with bar');
+
+this.reportCompare && reportCompare(true,true);
diff --git a/js/src/tests/ecma_6/Promise/get-wait-for-all-promise.js b/js/src/tests/ecma_6/Promise/get-wait-for-all-promise.js
new file mode 100644
index 000000000..cebb3ea58
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/get-wait-for-all-promise.js
@@ -0,0 +1,65 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs getSelfHostedValue and drainJobQueue
+
+if (!this.Promise) {
+ this.reportCompare && reportCompare(true,true);
+ quit(0);
+}
+
+function onResolved(val) {
+ result = 'resolved with ' + val;
+}
+
+function onRejected(val) {
+ result = 'rejected with ' + val;
+}
+
+// Replacing `Promise#then` shouldn't affect getWaitForAllPromise.
+let originalThen = Promise.prototype.then;
+Promise.prototype.then = 1;
+
+// Replacing Promise[@@species] shouldn't affect getWaitForAllPromise.
+Promise[Symbol.species] = function(){};
+
+// Replacing `Promise` shouldn't affect getWaitForAllPromise.
+let PromiseCtor = Promise;
+Promise = {};
+
+// Replacing Array[@@iterator] shouldn't affect getWaitForAllPromise.
+Array.prototype[Symbol.iterator] = function(){};
+
+let resolveFunctions = [];
+let rejectFunctions = [];
+let promises = [];
+for (let i = 0; i < 3; i++) {
+ let p = new PromiseCtor(function(res_, rej_) {
+ resolveFunctions.push(res_);
+ rejectFunctions.push(rej_);
+ });
+ promises.push(p);
+}
+
+let allPromise = getWaitForAllPromise(promises);
+let then = originalThen.call(allPromise, onResolved, onRejected);
+
+resolveFunctions.forEach((fun, i)=>fun(i));
+drainJobQueue();
+
+assertEq(result, 'resolved with 0,1,2');
+
+// Empty lists result in a promise resolved with an empty array.
+result = undefined;
+originalThen.call(getWaitForAllPromise([]), v=>(result = v));
+drainJobQueue();
+assertEq(result instanceof Array, true);
+assertEq(result.length, 0);
+
+//Empty lists result in a promise resolved with an empty array.
+result = undefined;
+originalThen.call(getWaitForAllPromise([]), v=>(result = v));
+
+drainJobQueue();
+
+assertEq(result instanceof Array, true);
+assertEq(result.length, 0);
+
+this.reportCompare && reportCompare(true,true);
diff --git a/js/src/tests/ecma_6/Promise/iterator-primitive.js b/js/src/tests/ecma_6/Promise/iterator-primitive.js
new file mode 100644
index 000000000..cfc3a4ed3
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/iterator-primitive.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+
+var BUGNUMBER = 1021835;
+var summary = "Returning non-object from @@iterator should throw";
+
+print(BUGNUMBER + ": " + summary);
+
+let primitives = [
+ 1,
+ true,
+ undefined,
+ null,
+ "foo",
+ Symbol.iterator
+];
+
+for (let primitive of primitives) {
+ let arg = {
+ [Symbol.iterator]() {
+ return primitive;
+ }
+ };
+ assertEventuallyThrows(Promise.all(arg), TypeError);
+ assertEventuallyThrows(Promise.race(arg), TypeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/ecma_6/Promise/methods-non-enumerable.js b/js/src/tests/ecma_6/Promise/methods-non-enumerable.js
new file mode 100644
index 000000000..79c3563b2
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/methods-non-enumerable.js
@@ -0,0 +1,9 @@
+if (!this.Promise) {
+ reportCompare(true,true);
+ quit(0);
+}
+
+assertEq(Object.keys(Promise).length, 0);
+assertEq(Object.keys(Promise.prototype).length, 0);
+
+reportCompare(0, 0, "ok");
diff --git a/js/src/tests/ecma_6/Promise/promise-all.js b/js/src/tests/ecma_6/Promise/promise-all.js
new file mode 100644
index 000000000..46383de78
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/promise-all.js
@@ -0,0 +1,30 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+
+if (!this.Promise) {
+ this.reportCompare && reportCompare(true,true);
+ quit(0);
+}
+
+let results = [];
+
+let p1 = new Promise(res=>res('result'))
+ .then(val=>{results.push('then ' + val); return 'first then rval';})
+ .then(val=>{results.push('chained then with val: ' + val); return 'p1 then, then'});
+
+let p2 = new Promise((res, rej)=>rej('rejection'))
+ .catch(val=> {results.push('catch ' + val); return results.length;})
+ .then(val=>{results.push('then after catch with val: ' + val); return 'p2 catch, then'},
+ val=>{throw new Error("mustn't be called")});
+
+Promise.all([p1, p2]).then(res => results.push(res + ''));
+
+drainJobQueue();
+
+assertEq(results.length, 5);
+assertEq(results[0], 'then result');
+assertEq(results[1], 'catch rejection');
+assertEq(results[2], 'chained then with val: first then rval');
+assertEq(results[3], 'then after catch with val: 2');
+assertEq(results[4], 'p1 then, then,p2 catch, then');
+
+this.reportCompare && reportCompare(true,true);
diff --git a/js/src/tests/ecma_6/Promise/promise-basics.js b/js/src/tests/ecma_6/Promise/promise-basics.js
new file mode 100644
index 000000000..456b00dba
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/promise-basics.js
@@ -0,0 +1,101 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+
+if (!this.Promise) {
+ this.reportCompare && reportCompare(0, 0, "ok");
+ quit(0);
+}
+
+let results = [];
+
+new Promise(res=>res('result'))
+ .then(val=>{results.push('then ' + val); return 'first then rval';})
+ .then(val=>results.push('chained then with val: ' + val));
+
+new Promise((res, rej)=>rej('rejection'))
+ .catch(val=>{results.push('catch ' + val); return results.length;})
+ .then(val=>results.push('then after catch with val: ' + val),
+ val=>{throw new Error("mustn't be called")});
+
+new Promise((res, rej)=> {res('result'); rej('rejection'); })
+ .catch(val=>{throw new Error("mustn't be called");})
+ .then(val=>results.push('then after resolve+reject with val: ' + val),
+ val=>{throw new Error("mustn't be called")});
+
+new Promise((res, rej)=> { rej('rejection'); res('result'); })
+ .catch(val=>{results.push('catch after reject+resolve with val: ' + val);})
+
+
+drainJobQueue();
+
+assertEq(results.length, 6);
+assertEq(results[0], 'then result');
+assertEq(results[1], 'catch rejection');
+assertEq(results[2], 'catch after reject+resolve with val: rejection');
+assertEq(results[3], 'chained then with val: first then rval');
+assertEq(results[4], 'then after catch with val: 2');
+assertEq(results[5], 'then after resolve+reject with val: result');
+
+results = [];
+
+Promise.resolve('resolution').then(res=>results.push(res),
+ rej=>{ throw new Error("mustn't be called"); });
+
+let thenCalled = false;
+Promise.reject('rejection').then(_=>{thenCalled = true},
+ rej=>results.push(rej));
+
+drainJobQueue();
+
+assertEq(thenCalled, false);
+assertEq(results.length, 2);
+assertEq(results[0], 'resolution');
+assertEq(results[1], 'rejection');
+
+
+function callback() {}
+
+// Calling the executor function with content functions shouldn't assert:
+Promise.resolve.call(function(exec) { exec(callback, callback); });
+Promise.reject.call(function(exec) { exec(callback, callback); });
+Promise.all.call(function(exec) { exec(callback, callback); });
+Promise.race.call(function(exec) { exec(callback, callback); });
+
+let resolveResult = undefined;
+function resolveFun() {resolveResult = "resolveCalled";}
+Promise.resolve.call(function(exec) { exec(resolveFun, callback); });
+assertEq(resolveResult, "resolveCalled");
+
+let rejectResult = undefined;
+function rejectFun() {rejectResult = "rejectCalled";}
+Promise.reject.call(function(exec) { exec(callback, rejectFun); });
+assertEq(rejectResult, "rejectCalled");
+
+// These should throw:
+var wasCalled = false;
+var hasThrown = false;
+try {
+ // Calling the executor function twice, providing a resolve callback both times.
+ Promise.resolve.call(function(executor) {
+ wasCalled = true;
+ executor(callback, undefined);
+ executor(callback, callback);
+ });
+} catch (e) {
+ hasThrown = true;
+}
+assertEq(wasCalled, true);
+assertEq(hasThrown, true);
+
+var hasThrown = false;
+try {
+ // Calling the executor function twice, providing a reject callback both times.
+ Promise.resolve.call(function(executor) {
+ executor(undefined, callback);
+ executor(callback, callback);
+ });
+} catch (e) {
+ hasThrown = true;
+}
+assertEq(hasThrown, true);
+
+this.reportCompare && reportCompare(0, 0, "ok");
diff --git a/js/src/tests/ecma_6/Promise/promise-rejection-tracking.js b/js/src/tests/ecma_6/Promise/promise-rejection-tracking.js
new file mode 100644
index 000000000..4531fe0b0
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/promise-rejection-tracking.js
@@ -0,0 +1,36 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs setPromiseRejectionTrackerCallback
+
+if (!this.Promise) {
+ this.reportCompare && reportCompare(true,true);
+ quit(0);
+}
+
+const UNHANDLED = 0;
+const HANDLED = 1;
+
+let rejections = new Map();
+function rejectionTracker(promise, state) {
+ rejections.set(promise, state);
+}
+setPromiseRejectionTrackerCallback(rejectionTracker);
+
+// Unhandled rejections are tracked.
+let reject;
+let p = new Promise((res_, rej_) => (reject = rej_));
+assertEq(rejections.has(p), false);
+reject('reason');
+assertEq(rejections.get(p), UNHANDLED);
+// Later handling updates the tracking.
+p.then(_=>_, _=>_);
+assertEq(rejections.get(p), HANDLED);
+
+rejections.clear();
+
+// Handled rejections aren't tracked at all.
+p = new Promise((res_, rej_) => (reject = rej_));
+assertEq(rejections.has(p), false);
+p.then(_=>_, _=>_);
+reject('reason');
+assertEq(rejections.has(p), false);
+
+this.reportCompare && reportCompare(true,true);
diff --git a/js/src/tests/ecma_6/Promise/promise-species.js b/js/src/tests/ecma_6/Promise/promise-species.js
new file mode 100644
index 000000000..7e033b08b
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/promise-species.js
@@ -0,0 +1,13 @@
+if (!this.Promise) {
+ reportCompare(true,true);
+ quit(0);
+}
+
+assertEq(Promise[Symbol.species], Promise);
+let prop = Object.getOwnPropertyDescriptor(Promise, Symbol.species);
+assertEq('get' in prop, true);
+assertEq(typeof prop.get, 'function');
+assertEq('set' in prop, true);
+assertEq(prop.set, undefined);
+
+reportCompare(0, 0, "ok");
diff --git a/js/src/tests/ecma_6/Promise/promise-subclassing.js b/js/src/tests/ecma_6/Promise/promise-subclassing.js
new file mode 100644
index 000000000..eba15a1d6
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/promise-subclassing.js
@@ -0,0 +1,67 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+
+if (!this.Promise) {
+ this.reportCompare && reportCompare(true,true);
+ quit(0);
+}
+
+let results = [];
+
+class SubPromise extends Promise {
+ constructor(executor) {
+ results.push('SubPromise ctor called');
+ super(executor);
+ }
+ then(res, rej) {
+ results.push('SubPromise#then called');
+ return intermediatePromise = super.then(res, rej);
+ }
+}
+
+let subPromise = new SubPromise(function(res, rej) {
+ results.push('SubPromise ctor called executor');
+ res('result');
+});
+
+let intermediatePromise;
+let allSubPromise = SubPromise.all([subPromise]);
+
+assertEq(subPromise instanceof SubPromise, true);
+assertEq(allSubPromise instanceof SubPromise, true);
+assertEq(intermediatePromise instanceof SubPromise, true);
+
+expected = [
+'SubPromise ctor called',
+'SubPromise ctor called executor',
+'SubPromise ctor called',
+'SubPromise#then called',
+'SubPromise ctor called',
+];
+
+assertEq(results.length, expected.length);
+expected.forEach((expected,i) => assertEq(results[i], expected));
+
+subPromise.then(val=>results.push('subPromise.then with val ' + val));
+allSubPromise.then(val=>results.push('allSubPromise.then with val ' + val));
+
+expected.forEach((expected,i) => assertEq(results[i], expected));
+expected = expected.concat([
+'SubPromise#then called',
+'SubPromise ctor called',
+'SubPromise#then called',
+'SubPromise ctor called',
+]);
+
+assertEq(results.length, expected.length);
+expected.forEach((expected,i) => assertEq(results[i], expected));
+
+drainJobQueue();
+
+expected = expected.concat([
+'subPromise.then with val result',
+'allSubPromise.then with val result',
+]);
+
+assertEq(results.length, expected.length);
+
+this.reportCompare && reportCompare(0, 0, "ok");
diff --git a/js/src/tests/ecma_6/Promise/self-resolve.js b/js/src/tests/ecma_6/Promise/self-resolve.js
new file mode 100644
index 000000000..e16a2ceb3
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/self-resolve.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+
+if (!this.Promise) {
+ this.reportCompare && reportCompare(true,true);
+ quit(0);
+}
+
+let resolve;
+let promise = new Promise(function(x) { resolve = x; });
+resolve(promise)
+
+let results = [];
+promise.then(res => assertEq(true, false, "not reached")).catch(res => {
+ assertEq(res instanceof TypeError, true);
+ results.push("rejected");
+});
+
+drainJobQueue()
+
+assertEq(results.length, 1);
+assertEq(results[0], "rejected");
+
+this.reportCompare && reportCompare(0, 0, "ok");
diff --git a/js/src/tests/ecma_6/Promise/shell.js b/js/src/tests/ecma_6/Promise/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/shell.js