From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- js/src/tests/ecma_6/Promise/browser.js | 0 js/src/tests/ecma_6/Promise/bug-1287334.js | 12 +++ js/src/tests/ecma_6/Promise/bug-1288382.js | 13 +++ js/src/tests/ecma_6/Promise/bug-1289040.js | 13 +++ js/src/tests/ecma_6/Promise/dependent-promises.js | 41 +++++++++ .../ecma_6/Promise/enqueue-promise-reactions.js | 43 +++++++++ .../ecma_6/Promise/get-wait-for-all-promise.js | 65 +++++++++++++ js/src/tests/ecma_6/Promise/iterator-primitive.js | 28 ++++++ .../tests/ecma_6/Promise/methods-non-enumerable.js | 9 ++ js/src/tests/ecma_6/Promise/promise-all.js | 30 ++++++ js/src/tests/ecma_6/Promise/promise-basics.js | 101 +++++++++++++++++++++ .../ecma_6/Promise/promise-rejection-tracking.js | 36 ++++++++ js/src/tests/ecma_6/Promise/promise-species.js | 13 +++ js/src/tests/ecma_6/Promise/promise-subclassing.js | 67 ++++++++++++++ js/src/tests/ecma_6/Promise/self-resolve.js | 23 +++++ js/src/tests/ecma_6/Promise/shell.js | 0 16 files changed, 494 insertions(+) create mode 100644 js/src/tests/ecma_6/Promise/browser.js create mode 100644 js/src/tests/ecma_6/Promise/bug-1287334.js create mode 100644 js/src/tests/ecma_6/Promise/bug-1288382.js create mode 100644 js/src/tests/ecma_6/Promise/bug-1289040.js create mode 100644 js/src/tests/ecma_6/Promise/dependent-promises.js create mode 100644 js/src/tests/ecma_6/Promise/enqueue-promise-reactions.js create mode 100644 js/src/tests/ecma_6/Promise/get-wait-for-all-promise.js create mode 100644 js/src/tests/ecma_6/Promise/iterator-primitive.js create mode 100644 js/src/tests/ecma_6/Promise/methods-non-enumerable.js create mode 100644 js/src/tests/ecma_6/Promise/promise-all.js create mode 100644 js/src/tests/ecma_6/Promise/promise-basics.js create mode 100644 js/src/tests/ecma_6/Promise/promise-rejection-tracking.js create mode 100644 js/src/tests/ecma_6/Promise/promise-species.js create mode 100644 js/src/tests/ecma_6/Promise/promise-subclassing.js create mode 100644 js/src/tests/ecma_6/Promise/self-resolve.js create mode 100644 js/src/tests/ecma_6/Promise/shell.js (limited to 'js/src/tests/ecma_6/Promise') 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 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 -- cgit v1.2.3