summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/built-ins/Promise/prototype
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /js/src/tests/test262/built-ins/Promise/prototype
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/test262/built-ins/Promise/prototype')
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js18
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/S25.4.5_A3.1_T1.js17
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/Symbol.toStringTag.js23
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js16
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js19
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js22
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js22
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/invokes-then.js54
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/length.js27
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/name.js28
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/not-a-constructor.js35
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/prop-desc.js19
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-non-object.js32
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-obj-coercible.js53
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-not-callable.js75
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-poisoned.js35
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-throws.js42
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-function.js69
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-non-function.js51
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-function.js22
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-method.js18
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/length.js30
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/name.js30
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/not-a-constructor.js35
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/prop-desc.js21
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-PromiseResolve.js57
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-argument.js69
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls.js40
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-no-fulfill.js30
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-override-with-throw.js30
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/resolution-value-no-override.js26
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-PromiseResolve.js46
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-argument.js55
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls.js40
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/species-constructor.js25
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-reject-count.js24
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-resolve-count.js22
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-reject-count.js21
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-resolve-count.js21
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-non-object.js21
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-proxy.js21
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-not-callable.js56
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-poisoned.js26
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-throws.js25
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-thenable.js19
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/no-promise-state.js28
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/prop-desc.js16
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/proto.js16
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A1.1_T1.js42
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T1.js37
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T2.js41
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T3.js43
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js16
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js17
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T1.js18
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T2.js20
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T1.js21
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T2.js22
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T1.js21
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T2.js22
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.1_T1.js43
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.2_T1.js45
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.3_T1.js49
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-called-twice.js99
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-not-callable.js104
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/context-check-on-entry.js26
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/ctor-access-count.js52
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/ctor-custom.js51
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/ctor-null.js22
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/ctor-poisoned.js29
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/ctor-throws.js45
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/ctor-undef.js22
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/deferred-is-resolved-value.js68
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/length.js27
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/name.js28
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/not-a-constructor.js35
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/prfm-fulfilled.js36
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-fulfulled.js39
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-rejected.js39
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/prfm-rejected.js36
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/prop-desc.js19
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-fulfilled.js49
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-rejected.js50
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-fulfilled.js54
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-rejected.js54
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-obj.js46
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-thenable.js54
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-poisoned-then.js54
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-prms-cstm-then.js61
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-self.js53
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-thenable.js57
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-obj.js47
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-thenable.js55
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-poisoned-then.js55
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-prms-cstm-then.js62
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-self.js54
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-thenable.js58
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-obj.js50
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-thenable.js58
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-poisoned-then.js58
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-prms-cstm-then.js65
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-self.js57
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-thenable.js61
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-obj.js50
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-thenable.js58
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-poisoned-then.js58
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-prms-cstm-then.js65
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-self.js57
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-thenable.js61
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-nonstrict.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-strict-strict.js39
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next-abrupt.js46
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next.js54
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-abrupt.js51
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-normal.js51
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-identity.js25
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-nonstrict.js38
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-strict-strict.js39
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next-abrupt.js46
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next.js54
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-abrupt.js51
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-normal.js51
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-thrower.js25
-rw-r--r--js/src/tests/test262/built-ins/Promise/prototype/then/shell.js0
131 files changed, 4950 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js
new file mode 100644
index 0000000000..3c08a74243
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.4.2_A1.1_T1.js
@@ -0,0 +1,18 @@
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Promise prototype object exists, is object, not enumerable, writable,
+ or configurable
+es6id: S25.4.4.2_A1.1_T1
+author: Sam Mikes
+description: Promise prototype exists
+---*/
+assert.notSameValue(
+ Promise.prototype,
+ undefined,
+ 'The value of Promise.prototype is expected to not equal ``undefined``'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/S25.4.5_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.5_A3.1_T1.js
new file mode 100644
index 0000000000..5095976ce7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/S25.4.5_A3.1_T1.js
@@ -0,0 +1,17 @@
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Promise.prototype.constructor is the Promise constructor
+es6id: S25.4.5_A3.1_T1
+author: Sam Mikes
+description: Promise.prototype.constructor is the Promise constructor
+---*/
+assert.sameValue(
+ Promise.prototype.constructor,
+ Promise,
+ 'The value of Promise.prototype.constructor is expected to equal the value of Promise'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/Symbol.toStringTag.js b/js/src/tests/test262/built-ins/Promise/prototype/Symbol.toStringTag.js
new file mode 100644
index 0000000000..0d7d71d804
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/Symbol.toStringTag.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.4
+description: >
+ `Symbol.toStringTag` property descriptor
+info: |
+ The initial value of the @@toStringTag property is the String value
+ "Promise".
+
+ This property has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [Symbol.toStringTag]
+---*/
+
+assert.sameValue(Promise.prototype[Symbol.toStringTag], 'Promise');
+
+verifyNotEnumerable(Promise.prototype, Symbol.toStringTag);
+verifyNotWritable(Promise.prototype, Symbol.toStringTag);
+verifyConfigurable(Promise.prototype, Symbol.toStringTag);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/browser.js b/js/src/tests/test262/built-ins/Promise/prototype/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/browser.js
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js
new file mode 100644
index 0000000000..0f145ac2b2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A1.1_T1.js
@@ -0,0 +1,16 @@
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Promise prototype.catch is a function
+es6id: S25.4.5.1_A1.1_T1
+author: Sam Mikes
+description: Promise.prototype.catch is a function
+---*/
+assert(
+ !!(Promise.prototype.catch instanceof Function),
+ 'The value of !!(Promise.prototype.catch instanceof Function) is expected to be true'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js
new file mode 100644
index 0000000000..efdf80c4a8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js
@@ -0,0 +1,19 @@
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ catch is a method on a Promise
+es6id: S25.4.5.1_A2.1_T1
+author: Sam Mikes
+description: catch is a method on a Promise
+---*/
+
+var p = Promise.resolve(3);
+
+assert(
+ !!(p.catch instanceof Function),
+ 'The value of !!(p.catch instanceof Function) is expected to be true'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js
new file mode 100644
index 0000000000..415daf47ab
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js
@@ -0,0 +1,22 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ catch(arg) is equivalent to then(undefined, arg)
+es6id: S25.4.5.1_A3.1_T1
+author: Sam Mikes
+description: catch is implemented in terms of then
+flags: [async]
+---*/
+
+var arg = {};
+
+var p = Promise.resolve(arg);
+
+p.catch(function() {
+ throw new Test262Error("Should not be called - promise is fulfilled");
+}).then(function(result) {
+ assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg');
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js
new file mode 100644
index 0000000000..df555fd774
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js
@@ -0,0 +1,22 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ catch(arg) is equivalent to then(undefined, arg)
+es6id: S25.4.5.1_A3.1_T2
+author: Sam Mikes
+description: catch is implemented in terms of then
+flags: [async]
+---*/
+
+var arg = {};
+
+var p = Promise.reject(arg);
+
+p.then(function() {
+ throw new Test262Error("Should not be called: did not expect promise to be fulfilled");
+}).catch(function(result) {
+ assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg');
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/browser.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/browser.js
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/invokes-then.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/invokes-then.js
new file mode 100644
index 0000000000..e02959e8db
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/invokes-then.js
@@ -0,0 +1,54 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.1
+description: Promise.prototype.catch invokes `then` method
+info: |
+ 1. Let promise be the this value.
+ 2. Return Invoke(promise, "then", «undefined, onRejected»).
+---*/
+
+var target = {};
+var returnValue = {};
+var callCount = 0;
+var thisValue = null;
+var argCount = null;
+var firstArg = null;
+var secondArg = null;
+var result = null;
+
+target.then = function(a, b) {
+ callCount += 1;
+
+ thisValue = this;
+ argCount = arguments.length;
+ firstArg = a;
+ secondArg = b;
+
+ return returnValue;
+};
+
+result = Promise.prototype.catch.call(target, 1, 2, 3);
+
+assert.sameValue(callCount, 1, 'Invokes `then` method exactly once');
+assert.sameValue(
+ thisValue,
+ target,
+ 'Invokes `then` method with the instance as the `this` value'
+);
+assert.sameValue(
+ argCount, 2, 'Invokes `then` method with exactly two single arguments'
+);
+assert.sameValue(
+ firstArg,
+ undefined,
+ 'Invokes `then` method with `undefined` as the first argument'
+);
+assert.sameValue(
+ secondArg, 1, 'Invokes `then` method with the provided argument'
+);
+assert.sameValue(
+ result, returnValue, 'Returns the result of the invocation of `then`'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/length.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/length.js
new file mode 100644
index 0000000000..1b487e62d9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/length.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.1
+description: Promise.prototype.catch `length` property
+info: |
+ ES6 Section 17:
+ Every built-in Function object, including constructors, has a length
+ property whose value is an integer. Unless otherwise specified, this value
+ is equal to the largest number of named arguments shown in the subclause
+ headings for the function description, including optional parameters.
+
+ [...]
+
+ Unless otherwise specified, the length property of a built-in Function
+ object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+ [[Configurable]]: true }.
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(Promise.prototype.catch.length, 1);
+
+verifyNotEnumerable(Promise.prototype.catch, 'length');
+verifyNotWritable(Promise.prototype.catch, 'length');
+verifyConfigurable(Promise.prototype.catch, 'length');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/name.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/name.js
new file mode 100644
index 0000000000..25a93a3bb9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/name.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.1
+description: Promise.prototype.catch `name` property
+info: |
+ ES6 Section 17:
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ [...]
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(Promise.prototype.catch.name, 'catch');
+
+verifyNotEnumerable(Promise.prototype.catch, 'name');
+verifyNotWritable(Promise.prototype.catch, 'name');
+verifyConfigurable(Promise.prototype.catch, 'name');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/not-a-constructor.js
new file mode 100644
index 0000000000..2ff5558742
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/not-a-constructor.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-ecmascript-standard-built-in-objects
+description: >
+ Promise.prototype.catch does not implement [[Construct]], is not new-able
+info: |
+ ECMAScript Function Objects
+
+ Built-in function objects that are not identified as constructors do not
+ implement the [[Construct]] internal method unless otherwise specified in
+ the description of a particular function.
+
+ sec-evaluatenew
+
+ ...
+ 7. If IsConstructor(constructor) is false, throw a TypeError exception.
+ ...
+includes: [isConstructor.js]
+features: [Reflect.construct, arrow-function]
+---*/
+
+assert.sameValue(
+ isConstructor(Promise.prototype.catch),
+ false,
+ 'isConstructor(Promise.prototype.catch) must return false'
+);
+
+assert.throws(TypeError, () => {
+ let p = new Promise(() => {}); new p.catch();
+}, '`let p = new Promise(() => {}); new p.catch()` throws TypeError');
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/prop-desc.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/prop-desc.js
new file mode 100644
index 0000000000..2866aaa2d4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/prop-desc.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.1
+description: Promise.prototype.catch property descriptor
+info: |
+ Every other data property described in clauses 18 through 26 and in Annex
+ B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(typeof Promise.prototype.catch, 'function');
+
+verifyNotEnumerable(Promise.prototype, 'catch');
+verifyWritable(Promise.prototype, 'catch');
+verifyConfigurable(Promise.prototype, 'catch');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/shell.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/shell.js
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-non-object.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-non-object.js
new file mode 100644
index 0000000000..888c8b39f5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-non-object.js
@@ -0,0 +1,32 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-promise.prototype.catch
+description: >
+ Promise.prototype.catch called with a non-object-coercible `this` value
+info: |
+ 1. Let promise be the this value.
+ 2. Return ? Invoke(promise, "then", «undefined, onRejected»).
+
+ 7.3.18 Invoke
+
+ 1. Assert: IsPropertyKey(P) is true.
+ 2. If argumentsList was not passed, let argumentsList be a new empty List.
+ 3. Let func be ? GetV(V, P).
+ 4. Return ? Call(func, V, argumentsList).
+
+ 7.3.2 GetV
+
+ 1. Assert: IsPropertyKey(P) is true.
+ 2. Let O be ? ToObject(V).
+---*/
+
+assert.throws(TypeError, function() {
+ Promise.prototype.catch.call(undefined);
+}, 'undefined');
+
+assert.throws(TypeError, function() {
+ Promise.prototype.catch.call(null);
+}, 'null');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-obj-coercible.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-obj-coercible.js
new file mode 100644
index 0000000000..4f71abec7a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-obj-coercible.js
@@ -0,0 +1,53 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-promise.prototype.catch
+description: >
+ Promise.prototype.catch called with an object-coercible `this` value
+info: |
+ 1. Let promise be the this value.
+ 2. Return ? Invoke(promise, "then", «undefined, onRejected»).
+
+ 7.3.18 Invoke
+
+ 1. Assert: IsPropertyKey(P) is true.
+ 2. If argumentsList was not passed, let argumentsList be a new empty List.
+ 3. Let func be ? GetV(V, P).
+ 4. Return ? Call(func, V, argumentsList).
+
+ 7.3.2 GetV
+
+ 1. Assert: IsPropertyKey(P) is true.
+ 2. Let O be ? ToObject(V).
+features: [Symbol]
+---*/
+
+var booleanCount = 0;
+Boolean.prototype.then = function() {
+ booleanCount += 1;
+};
+Promise.prototype.catch.call(true);
+assert.sameValue(booleanCount, 1, 'boolean');
+
+var numberCount = 0;
+Number.prototype.then = function() {
+ numberCount += 1;
+};
+Promise.prototype.catch.call(34);
+assert.sameValue(numberCount, 1, 'number');
+
+var stringCount = 0;
+String.prototype.then = function() {
+ stringCount += 1;
+};
+Promise.prototype.catch.call('');
+assert.sameValue(stringCount, 1, 'string');
+
+var symbolCount = 0;
+Symbol.prototype.then = function() {
+ symbolCount += 1;
+};
+Promise.prototype.catch.call(Symbol());
+assert.sameValue(symbolCount, 1, 'symbol');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-not-callable.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-not-callable.js
new file mode 100644
index 0000000000..861f78bd9a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-not-callable.js
@@ -0,0 +1,75 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-promise.prototype.catch
+description: >
+ Promise.prototype.catch called with a `this` value that does not define a
+ callable `this` property
+info: |
+ 1. Let promise be the this value.
+ 2. Return ? Invoke(promise, "then", «undefined, onRejected»).
+
+ 7.3.18 Invoke
+
+ 1. Assert: IsPropertyKey(P) is true.
+ 2. If argumentsList was not passed, let argumentsList be a new empty List.
+ 3. Let func be ? GetV(V, P).
+ 4. Return ? Call(func, V, argumentsList).
+
+ 7.3.2 GetV
+
+ 1. Assert: IsPropertyKey(P) is true.
+ 2. Let O be ? ToObject(V).
+ 3. Return ? O.[[Get]](P, V).
+
+ 7.3.12 Call (F, V [ , argumentsList ])
+
+ 1. If argumentsList was not passed, let argumentsList be a new empty List.
+ 2. If IsCallable(F) is false, throw a TypeError exception.
+ 3. Return ? F.[[Call]](V, argumentsList).
+features: [Symbol]
+---*/
+
+var symbol = Symbol();
+
+assert.throws(TypeError, function() {
+ Promise.prototype.catch.call({});
+}, 'undefined');
+
+assert.throws(TypeError, function() {
+ Promise.prototype.catch.call({
+ then: null
+ });
+}, 'null');
+
+assert.throws(TypeError, function() {
+ Promise.prototype.catch.call({
+ then: 1
+ });
+}, 'number');
+
+assert.throws(TypeError, function() {
+ Promise.prototype.catch.call({
+ then: ''
+ });
+}, 'string');
+
+assert.throws(TypeError, function() {
+ Promise.prototype.catch.call({
+ then: true
+ });
+}, 'boolean');
+
+assert.throws(TypeError, function() {
+ Promise.prototype.catch.call({
+ then: symbol
+ });
+}, 'symbol');
+
+assert.throws(TypeError, function() {
+ Promise.prototype.catch.call({
+ then: {}
+ });
+}, 'ordinary object');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-poisoned.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-poisoned.js
new file mode 100644
index 0000000000..190776f246
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-poisoned.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-promise.prototype.catch
+description: >
+ Promise.prototype.catch called with a `this` value whose `then` property is
+ an accessor property that returns an abrupt completion
+info: |
+ 1. Let promise be the this value.
+ 2. Return ? Invoke(promise, "then", «undefined, onRejected»).
+
+ 7.3.18 Invoke
+
+ 1. Assert: IsPropertyKey(P) is true.
+ 2. If argumentsList was not passed, let argumentsList be a new empty List.
+ 3. Let func be ? GetV(V, P).
+
+ 7.3.2 GetV
+
+ 1. Assert: IsPropertyKey(P) is true.
+ 2. Let O be ? ToObject(V).
+ 3. Return ? O.[[Get]](P, V).
+---*/
+
+var poisonedThen = Object.defineProperty({}, 'then', {
+ get: function() {
+ throw new Test262Error();
+ }
+});
+
+assert.throws(Test262Error, function() {
+ Promise.prototype.catch.call(poisonedThen);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-throws.js b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-throws.js
new file mode 100644
index 0000000000..39cd7cf5de
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/catch/this-value-then-throws.js
@@ -0,0 +1,42 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-promise.prototype.catch
+description: >
+ Promise.prototype.catch called with a `this` value that defines a `then`
+ method which returns an abrupt completion.
+info: |
+ 1. Let promise be the this value.
+ 2. Return ? Invoke(promise, "then", «undefined, onRejected»).
+
+ 7.3.18 Invoke
+
+ 1. Assert: IsPropertyKey(P) is true.
+ 2. If argumentsList was not passed, let argumentsList be a new empty List.
+ 3. Let func be ? GetV(V, P).
+ 4. Return ? Call(func, V, argumentsList).
+
+ 7.3.2 GetV
+
+ 1. Assert: IsPropertyKey(P) is true.
+ 2. Let O be ? ToObject(V).
+ 3. Return ? O.[[Get]](P, V).
+
+ 7.3.12 Call (F, V [ , argumentsList ])
+
+ 1. If argumentsList was not passed, let argumentsList be a new empty List.
+ 2. If IsCallable(F) is false, throw a TypeError exception.
+ 3. Return ? F.[[Call]](V, argumentsList).
+---*/
+
+var thrower = {
+ then: function() {
+ throw new Test262Error();
+ }
+};
+
+assert.throws(Test262Error, function() {
+ Promise.prototype.catch.call(thrower);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/browser.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/browser.js
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-function.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-function.js
new file mode 100644
index 0000000000..c4597f9cb8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-function.js
@@ -0,0 +1,69 @@
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: Promise.prototype.finally invokes `then` method
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally, Reflect.construct, arrow-function]
+includes: [isConstructor.js]
+---*/
+
+var target = new Promise(function() {});
+var returnValue = {};
+var callCount = 0;
+var thisValue = null;
+var argCount = null;
+var resolve = null;
+var reject = null;
+
+target.then = function(a, b) {
+ callCount += 1;
+
+ thisValue = this;
+ argCount = arguments.length;
+ resolve = a;
+ reject = b;
+
+ return returnValue;
+};
+
+var originalFinallyHandler = function() {};
+var result = Promise.prototype.finally.call(target, originalFinallyHandler, 2, 3);
+
+assert.sameValue(callCount, 1, 'The value of `callCount` is 1');
+assert.sameValue(
+ thisValue,
+ target,
+ 'The value of `thisValue` is expected to equal the value of target'
+);
+assert.sameValue(argCount, 2, 'The value of `argCount` is 2');
+assert.sameValue(
+ typeof resolve,
+ 'function',
+ 'The value of `typeof resolve` is "function"'
+);
+assert.notSameValue(resolve, originalFinallyHandler, 'The value of `resolve` is expected to not equal the value of `originalFinallyHandler`');
+assert.sameValue(resolve.length, 1, 'The value of resolve.length is 1');
+assert.sameValue(resolve.name, '', 'The value of resolve.name is ""');
+assert.sameValue(isConstructor(resolve), false, 'isConstructor(resolve) must return false');
+assert.throws(TypeError, () => {
+ new resolve();
+}, '`new resolve()` throws TypeError');
+
+
+assert.sameValue(
+ typeof reject,
+ 'function',
+ 'The value of `typeof reject` is "function"'
+);
+assert.notSameValue(reject, originalFinallyHandler, 'The value of `reject` is expected to not equal the value of `originalFinallyHandler`');
+assert.sameValue(reject.length, 1, 'The value of reject.length is 1');
+assert.sameValue(reject.name, '', 'The value of reject.name is ""');
+assert.sameValue(isConstructor(reject), false, 'isConstructor(reject) must return false');
+assert.throws(TypeError, () => {
+ new reject();
+}, '`new reject()` throws TypeError');
+
+assert.sameValue(result, returnValue, 'The value of `result` is expected to equal the value of returnValue');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-non-function.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-non-function.js
new file mode 100644
index 0000000000..ca7b36445c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/invokes-then-with-non-function.js
@@ -0,0 +1,51 @@
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: Promise.prototype.finally invokes `then` method
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+---*/
+
+var target = new Promise(function() {});
+var returnValue = {};
+var callCount = 0;
+var thisValue = null;
+var argCount = null;
+var firstArg = null;
+var secondArg = null;
+var result = null;
+
+target.then = function(a, b) {
+ callCount += 1;
+
+ thisValue = this;
+ argCount = arguments.length;
+ firstArg = a;
+ secondArg = b;
+
+ return returnValue;
+};
+
+result = Promise.prototype.finally.call(target, 1, 2, 3);
+
+assert.sameValue(callCount, 1, 'Invokes `then` method exactly once');
+assert.sameValue(
+ thisValue,
+ target,
+ 'Invokes `then` method with the instance as the `this` value'
+);
+assert.sameValue(argCount, 2, 'Invokes `then` method with exactly two single arguments');
+assert.sameValue(
+ firstArg,
+ 1,
+ 'Invokes `then` method with the provided non-callable first argument'
+);
+assert.sameValue(
+ secondArg,
+ 1,
+ 'Invokes `then` method with the provided non-callable first argument'
+);
+assert.sameValue(result, returnValue, 'Returns the result of the invocation of `then`');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-function.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-function.js
new file mode 100644
index 0000000000..19abfde2fa
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-function.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: Promise.prototype.finally is a function
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+---*/
+
+assert.sameValue(
+ Promise.prototype.finally instanceof Function,
+ true,
+ 'Expected Promise.prototype.finally to be instanceof Function'
+);
+
+assert.sameValue(
+ typeof Promise.prototype.finally,
+ 'function',
+ 'Expected Promise.prototype.finally to be a function'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-method.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-method.js
new file mode 100644
index 0000000000..741b127248
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/is-a-method.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: finally is a method on a Promise
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+---*/
+
+var p = Promise.resolve(3);
+
+assert.sameValue(
+ p.finally,
+ Promise.prototype.finally,
+ 'Expected the `finally` method on a Promise to be `Promise.prototype.finally`'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/length.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/length.js
new file mode 100644
index 0000000000..1146a91f1d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/length.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: Promise.prototype.finally `length` property
+esid: sec-promise.prototype.finally
+info: |
+ ES6 Section 17:
+ Every built-in Function object, including constructors, has a length
+ property whose value is an integer. Unless otherwise specified, this value
+ is equal to the largest number of named arguments shown in the subclause
+ headings for the function description, including optional parameters.
+
+ [...]
+
+ Unless otherwise specified, the length property of a built-in Function
+ object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+ [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [Promise.prototype.finally]
+---*/
+
+verifyProperty(Promise.prototype.finally, "length", {
+ value: 1,
+ enumerable: false,
+ configurable: true,
+ writable: false,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/name.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/name.js
new file mode 100644
index 0000000000..82020c1381
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/name.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: Promise.prototype.finally `name` property
+esid: sec-promise.prototype.finally
+info: |
+ ES Section 17:
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ [...]
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [Promise.prototype.finally]
+---*/
+
+assert.sameValue(Promise.prototype.finally.name, 'finally');
+
+verifyNotEnumerable(Promise.prototype.finally, 'name');
+verifyNotWritable(Promise.prototype.finally, 'name');
+verifyConfigurable(Promise.prototype.finally, 'name');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/not-a-constructor.js
new file mode 100644
index 0000000000..25bb9a6554
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/not-a-constructor.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-ecmascript-standard-built-in-objects
+description: >
+ Promise.prototype.finally does not implement [[Construct]], is not new-able
+info: |
+ ECMAScript Function Objects
+
+ Built-in function objects that are not identified as constructors do not
+ implement the [[Construct]] internal method unless otherwise specified in
+ the description of a particular function.
+
+ sec-evaluatenew
+
+ ...
+ 7. If IsConstructor(constructor) is false, throw a TypeError exception.
+ ...
+includes: [isConstructor.js]
+features: [Reflect.construct, Promise.prototype.finally, arrow-function]
+---*/
+
+assert.sameValue(
+ isConstructor(Promise.prototype.finally),
+ false,
+ 'isConstructor(Promise.prototype.finally) must return false'
+);
+
+assert.throws(TypeError, () => {
+ let p = new Promise(() => {}); new p.finally();
+}, '`let p = new Promise(() => {}); new p.finally()` throws TypeError');
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/prop-desc.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/prop-desc.js
new file mode 100644
index 0000000000..47d2f64fdd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/prop-desc.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: Promise.prototype.finally property descriptor
+esid: sec-promise.prototype.finally
+info: |
+ Every other data property described in clauses 18 through 26 and in Annex
+ B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+includes: [propertyHelper.js]
+features: [Promise.prototype.finally]
+---*/
+
+assert.sameValue(typeof Promise.prototype.finally, 'function');
+
+verifyNotEnumerable(Promise.prototype, 'finally');
+verifyWritable(Promise.prototype, 'finally');
+verifyConfigurable(Promise.prototype, 'finally');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-PromiseResolve.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-PromiseResolve.js
new file mode 100644
index 0000000000..ecdbbdd164
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-PromiseResolve.js
@@ -0,0 +1,57 @@
+// |reftest| async
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-catchfinallyfunctions
+description: >
+ PromiseResolve() avoids extra Promise capability creation.
+info: |
+ Catch Finally Functions
+
+ [...]
+ 7. Let promise be ? PromiseResolve(C, result).
+ 8. Let thrower be equivalent to a function that throws reason.
+ 9. Return ? Invoke(promise, "then", « thrower »).
+
+ PromiseResolve ( C, x )
+
+ 1. Assert: Type(C) is Object.
+ 2. If IsPromise(x) is true, then
+ a. Let xConstructor be ? Get(x, "constructor").
+ b. If SameValue(xConstructor, C) is true, return x.
+features: [Promise.prototype.finally]
+flags: [async]
+---*/
+
+class MyPromise extends Promise {}
+
+var mp1Value = {};
+var mp1 = MyPromise.reject(mp1Value);
+var mp2 = MyPromise.reject(42);
+
+var thenCalls = [];
+var then = Promise.prototype.then;
+Promise.prototype.then = function(resolve, reject) {
+ thenCalls.push({promise: this, resolve, reject});
+ return then.call(this, resolve, reject);
+};
+
+mp1.finally(() => mp2).then(value => {
+ throw new Test262Error("Expected the promise to be rejected, got resolved with " + value);
+}, () => {
+ assert.sameValue(thenCalls.length, 5);
+
+ var mp2Calls = thenCalls.filter(c => c.promise === mp2);
+ assert.sameValue(mp2Calls.length, 1);
+ assert.sameValue(mp2Calls[0].reject, undefined);
+
+ var thrown = false;
+ try {
+ mp2Calls[0].resolve();
+ } catch (error) {
+ thrown = true;
+ assert.sameValue(error, mp1Value);
+ }
+
+ assert(thrown, "Expected resolve() to throw, but it didn't");
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-argument.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-argument.js
new file mode 100644
index 0000000000..4d183bf248
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls-argument.js
@@ -0,0 +1,69 @@
+// |reftest| async
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-catchfinallyfunctions
+description: >
+ thrower is anonymous built-in function with length of 1 that throws reason.
+info: |
+ Catch Finally Functions
+
+ ...
+ 8. Let thrower be equivalent to a function that throws reason.
+ 9. Return ? Invoke(promise, "then", « thrower »).
+
+ The "length" property of a Catch Finally function is 1.
+features: [Promise.prototype.finally, Reflect.construct, class, arrow-function]
+includes: [isConstructor.js]
+flags: [async]
+---*/
+
+class MyError extends Error {}
+
+var myError = new MyError();
+Promise.reject(myError)
+ .finally(function() {})
+ .then(function(value) {
+ $DONE('Expected promise to be rejected, got fulfilled with ' + value);
+ }, function(reason) {
+ if (reason === myError) {
+ $DONE();
+ } else {
+ $DONE(reason);
+ }
+ });
+
+var calls = 0;
+var expected = [
+ { length: 0, name: '' },
+ { length: 1, name: '' }
+];
+
+var then = Promise.prototype.then;
+Promise.prototype.then = function(resolve, reject) {
+
+ assert.sameValue(
+ resolve.length,
+ expected[calls].length,
+ 'The value of resolve.length is expected to equal the value of expected[calls].length'
+ );
+ assert.sameValue(
+ resolve.name,
+ expected[calls].name,
+ 'The value of resolve.name is expected to equal the value of expected[calls].name'
+ );
+ if (calls === 0) {
+ assert.throws(MyError, resolve, '`resolve()` throws `MyError`');
+ assert.sameValue(arguments.length, 1, '`then` invoked with one argument');
+ } else {
+ assert.sameValue(isConstructor(reject), false, 'isConstructor(reject) must return false');
+ assert.throws(TypeError, () => {
+ new reject();
+ }, '`new reject()` throws TypeError');
+ assert.sameValue(arguments.length, 2, '`then` invoked with two arguments');
+ }
+
+ calls += 1;
+
+ return then.call(this, resolve, reject);
+};
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls.js
new file mode 100644
index 0000000000..2d4dd9caaf
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejected-observable-then-calls.js
@@ -0,0 +1,40 @@
+// |reftest| async
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: finally observably calls .then
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+flags: [async]
+includes: [promiseHelper.js]
+---*/
+var sequence = [];
+var noReason = {};
+var no = Promise.reject(noReason);
+no.then = function() {
+ sequence.push(1);
+ return Promise.prototype.then.apply(this, arguments);
+};
+
+var yesValue = {};
+var yes = Promise.resolve(yesValue);
+yes.then = function() {
+ sequence.push(4);
+ return Promise.prototype.then.apply(this, arguments);
+};
+
+no.catch(function(e) {
+ sequence.push(2);
+ assert.sameValue(e, noReason);
+ throw e;
+}).finally(function() {
+ sequence.push(3);
+ return yes;
+}).catch(function(e) {
+ sequence.push(5);
+ assert.sameValue(e, noReason);
+}).then(function() {
+ assert.sameValue(sequence.length, 5);
+ checkSequence(sequence, "All expected callbacks called in correct order");
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-no-fulfill.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-no-fulfill.js
new file mode 100644
index 0000000000..3903e7778b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-no-fulfill.js
@@ -0,0 +1,30 @@
+// |reftest| async
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: finally on a rejected promise can not convert to a fulfillment
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+flags: [async]
+includes: [promiseHelper.js]
+---*/
+var sequence = [];
+var original = {};
+var replacement = {};
+
+var p = Promise.reject(original);
+
+p.finally(function() {
+ sequence.push(1);
+ assert.sameValue(arguments.length, 0, 'onFinally receives zero args');
+ return replacement;
+}).then(function() {
+ throw new Test262Error('promise is rejected pre-finally; onFulfill should not be called');
+}).catch(function(reason) {
+ sequence.push(2);
+ assert.sameValue(reason, original, 'onFinally can not override the rejection value by returning');
+}).then(function() {
+ assert.sameValue(sequence.length, 2);
+ checkSequence(sequence, "All expected callbacks called in correct order");
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-override-with-throw.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-override-with-throw.js
new file mode 100644
index 0000000000..66b6a468b3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/rejection-reason-override-with-throw.js
@@ -0,0 +1,30 @@
+// |reftest| async
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: finally on a rejected promise can override the rejection reason
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+flags: [async]
+includes: [promiseHelper.js]
+---*/
+var sequence = [];
+var original = {};
+var thrown = {};
+
+var p = Promise.reject(original);
+
+p.finally(function() {
+ sequence.push(1);
+ assert.sameValue(arguments.length, 0, 'onFinally receives zero args');
+ throw thrown;
+}).then(function() {
+ throw new Test262Error('promise is rejected; onFulfill should not be called');
+}).catch(function(reason) {
+ sequence.push(2);
+ assert.sameValue(reason, thrown, 'onFinally can override the rejection reason by throwing');
+}).then(function() {
+ assert.sameValue(sequence.length, 2);
+ checkSequence(sequence, "All expected callbacks called in correct order");
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/resolution-value-no-override.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolution-value-no-override.js
new file mode 100644
index 0000000000..4951119385
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolution-value-no-override.js
@@ -0,0 +1,26 @@
+// |reftest| async
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: finally on a fulfilled promise can not override the resolution value
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+flags: [async]
+includes: [promiseHelper.js]
+---*/
+var sequence = [];
+var obj = {};
+var p = Promise.resolve(obj);
+
+p.finally(function() {
+ sequence.push(1);
+ assert.sameValue(arguments.length, 0, 'onFinally receives zero args');
+ return {};
+}).then(function(x) {
+ sequence.push(2);
+ assert.sameValue(x, obj, 'onFinally can not override the resolution value');
+}).then(function() {
+ assert.sameValue(sequence.length, 2);
+ checkSequence(sequence, "All expected callbacks called in correct order");
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-PromiseResolve.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-PromiseResolve.js
new file mode 100644
index 0000000000..137448ae6f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-PromiseResolve.js
@@ -0,0 +1,46 @@
+// |reftest| async
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-thenfinallyfunctions
+description: >
+ PromiseResolve() avoids extra Promise capability creation.
+info: |
+ Then Finally Functions
+
+ [...]
+ 7. Let promise be ? PromiseResolve(C, result).
+ 8. Let valueThunk be equivalent to a function that returns value.
+ 9. Return ? Invoke(promise, "then", « valueThunk »).
+
+ PromiseResolve ( C, x )
+
+ 1. Assert: Type(C) is Object.
+ 2. If IsPromise(x) is true, then
+ a. Let xConstructor be ? Get(x, "constructor").
+ b. If SameValue(xConstructor, C) is true, return x.
+features: [Promise.prototype.finally]
+flags: [async]
+---*/
+
+class MyPromise extends Promise {}
+
+var mp1Value = {};
+var mp1 = MyPromise.resolve(mp1Value);
+var mp2 = MyPromise.resolve(42);
+
+var thenCalls = [];
+var then = Promise.prototype.then;
+Promise.prototype.then = function(resolve, reject) {
+ thenCalls.push({promise: this, resolve, reject});
+ return then.call(this, resolve, reject);
+};
+
+mp1.finally(() => mp2).then(() => {
+ assert.sameValue(thenCalls.length, 5);
+
+ var mp2Calls = thenCalls.filter(c => c.promise === mp2);
+ assert.sameValue(mp2Calls.length, 1);
+ assert.sameValue(mp2Calls[0].reject, undefined);
+ assert.sameValue(mp2Calls[0].resolve(), mp1Value);
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-argument.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-argument.js
new file mode 100644
index 0000000000..ab7eedb192
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls-argument.js
@@ -0,0 +1,55 @@
+// |reftest| async
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-thenfinallyfunctions
+description: >
+ valueThunk is anonymous built-in function with length of 1 that returns value.
+info: |
+ Then Finally Functions
+
+ ...
+ 8. Let valueThunk be equivalent to a function that returns value.
+ 9. Return ? Invoke(promise, "then", « valueThunk »).
+
+ The "length" property of a Then Finally function is 1.
+features: [Promise.prototype.finally, Reflect.construct, arrow-function]
+includes: [isConstructor.js]
+flags: [async]
+---*/
+
+var value = {};
+
+Promise.resolve(value)
+ .finally(function() {})
+ .then(() => $DONE(), $DONE);
+
+var calls = 0;
+var expected = [
+ { length: 0, name: '' },
+ { length: 1, name: '' }
+];
+
+var then = Promise.prototype.then;
+Promise.prototype.then = function(resolve) {
+ assert.sameValue(isConstructor(resolve), false, 'isConstructor(resolve) must return false');
+ assert.throws(TypeError, () => {
+ new resolve();
+ }, '`new resolve()` throws TypeError');
+
+ assert.sameValue(
+ resolve.length,
+ expected[calls].length,
+ 'The value of resolve.length is expected to equal the value of expected[calls].length'
+ );
+ assert.sameValue(
+ resolve.name,
+ expected[calls].name,
+ 'The value of resolve.name is expected to equal the value of expected[calls].name'
+ );
+ if (calls === 0) {
+ assert.sameValue(resolve(), value, 'resolve() must return the value of value');
+ }
+ calls += 1;
+ return then.call(this, resolve);
+};
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls.js
new file mode 100644
index 0000000000..4f2341bfb0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/resolved-observable-then-calls.js
@@ -0,0 +1,40 @@
+// |reftest| async
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: finally observably calls .then
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+flags: [async]
+includes: [promiseHelper.js]
+---*/
+var sequence = [];
+var yesValue = {};
+var yes = Promise.resolve(yesValue);
+yes.then = function() {
+ sequence.push(1);
+ return Promise.prototype.then.apply(this, arguments);
+};
+
+var noReason = {};
+var no = Promise.reject(noReason);
+no.then = function() {
+ sequence.push(4);
+ return Promise.prototype.then.apply(this, arguments);
+};
+
+yes.then(function(x) {
+ sequence.push(2);
+ assert.sameValue(x, yesValue);
+ return x;
+}).finally(function() {
+ sequence.push(3);
+ return no;
+}).catch(function(e) {
+ sequence.push(5);
+ assert.sameValue(e, noReason);
+}).then(function() {
+ assert.sameValue(sequence.length, 5);
+ checkSequence(sequence, "All expected callbacks called in correct order");
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/shell.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/shell.js
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/species-constructor.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/species-constructor.js
new file mode 100644
index 0000000000..00c1127836
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/species-constructor.js
@@ -0,0 +1,25 @@
+// |reftest| async
+// Copyright (C) 2017 V8. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Sathya Gunasekaran
+description: finally calls the SpeciesConstructor and creates the right amount of promises
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+flags: [async]
+---*/
+
+
+var count = 0;
+class FooPromise extends Promise {
+ constructor(resolve, reject) {
+ count++;
+ return super(resolve, reject);
+ }
+}
+
+new FooPromise(r => r())
+ .finally(() => {})
+ .then(() => {
+ assert.sameValue(count, 7, "7 new promises were created");
+ }).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-reject-count.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-reject-count.js
new file mode 100644
index 0000000000..6bf6504a22
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-reject-count.js
@@ -0,0 +1,24 @@
+// |reftest| async
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: Promise subclass finally on rejected creates the proper number of subclassed promises
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+flags: [async]
+---*/
+
+var count = 0;
+class FooPromise extends Promise {
+ constructor(resolve, reject) {
+ count++;
+ return super(resolve, reject);
+ }
+}
+
+FooPromise.reject().finally(() => {}).then(value => {
+ throw new Test262Error("Expected Promise to be rejected, got: resolved with " + value);
+}, () => {
+ assert.sameValue(count, 7);
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-resolve-count.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-resolve-count.js
new file mode 100644
index 0000000000..6af753fa66
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-resolve-count.js
@@ -0,0 +1,22 @@
+// |reftest| async
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: Promise subclass finally on resolved creates the proper number of subclassed promises
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+flags: [async]
+---*/
+
+var count = 0;
+class FooPromise extends Promise {
+ constructor(resolve, reject) {
+ count++;
+ return super(resolve, reject);
+ }
+}
+
+FooPromise.resolve().finally(() => {}).then(() => {
+ assert.sameValue(count, 7);
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-reject-count.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-reject-count.js
new file mode 100644
index 0000000000..9e9995fc91
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-reject-count.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: finally on rejected Promise calls the SpeciesConstructor
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+---*/
+
+class FooPromise extends Promise {
+ static get[Symbol.species]() {
+ return Promise;
+ }
+}
+
+var p = Promise.reject().finally(() => FooPromise.reject());
+
+assert.sameValue(p instanceof Promise, true);
+assert.sameValue(p instanceof FooPromise, false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-resolve-count.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-resolve-count.js
new file mode 100644
index 0000000000..e5049b7349
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/subclass-species-constructor-resolve-count.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: finally on resolved Promise calls the SpeciesConstructor
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+---*/
+
+class FooPromise extends Promise {
+ static get[Symbol.species]() {
+ return Promise;
+ }
+}
+
+var p = Promise.resolve().finally(() => FooPromise.resolve());
+
+assert.sameValue(p instanceof Promise, true);
+assert.sameValue(p instanceof FooPromise, false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-non-object.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-non-object.js
new file mode 100644
index 0000000000..8c9ec2e7bd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-non-object.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: >
+ Promise.prototype.finally called with a non-object-coercible `this` value
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+---*/
+
+assert.sameValue(typeof Promise.prototype.finally, 'function');
+
+assert.throws(TypeError, function() {
+ Promise.prototype.finally.call(undefined);
+}, 'undefined');
+
+assert.throws(TypeError, function() {
+ Promise.prototype.finally.call(null);
+}, 'null');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-proxy.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-proxy.js
new file mode 100644
index 0000000000..15ca9b1d7c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-proxy.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: >
+ Promise.prototype.finally called with a non-branded Promise does not throw
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+---*/
+
+var called = false;
+var p = new Proxy(Promise.resolve(), {});
+var oldThen = Promise.prototype.then;
+Promise.prototype.then = () => {
+ called = true;
+};
+Promise.prototype.finally.call(p);
+assert.sameValue(called, true);
+Promise.prototype.then = oldThen;
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-not-callable.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-not-callable.js
new file mode 100644
index 0000000000..ad5c687d6b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-not-callable.js
@@ -0,0 +1,56 @@
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: >
+ Promise.prototype.finally called with a `this` value that does not define a
+ callable `then` property
+esid: sec-promise.prototype.finally
+features: [Symbol, Promise.prototype.finally]
+---*/
+assert.sameValue(typeof Promise.prototype.finally, 'function');
+
+var symbol = Symbol();
+
+var thrower = function() {
+ throw new Test262Error('this should never happen');
+};
+
+var p = new Promise(function() {});
+
+p.then = undefined;
+assert.throws(TypeError, function() {
+ Promise.prototype.finally.call(p, thrower);
+}, 'undefined');
+
+p.then = null;
+assert.throws(TypeError, function() {
+ Promise.prototype.finally.call(p, thrower);
+}, 'null');
+
+p.then = 1;
+assert.throws(TypeError, function() {
+ Promise.prototype.finally.call(p, thrower);
+}, 'number');
+
+p.then = '';
+assert.throws(TypeError, function() {
+ Promise.prototype.finally.call(p, thrower);
+}, 'string');
+
+p.then = true;
+assert.throws(TypeError, function() {
+ Promise.prototype.finally.call(p, thrower);
+}, 'boolean');
+
+p.then = symbol;
+assert.throws(TypeError, function() {
+ Promise.prototype.finally.call(p, thrower);
+}, 'symbol');
+
+p.then = {};
+assert.throws(TypeError, function() {
+ Promise.prototype.finally.call(p, thrower);
+}, 'ordinary object');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-poisoned.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-poisoned.js
new file mode 100644
index 0000000000..44e4173989
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-poisoned.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: >
+ Promise.prototype.finally called with a `this` value whose `then` property is
+ an accessor property that returns an abrupt completion
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+---*/
+
+var poisonedThen = Object.defineProperty(new Promise(function() {}), 'then', {
+ get: function() {
+ throw new Test262Error();
+ }
+});
+
+assert.throws(Test262Error, function() {
+ Promise.prototype.finally.call(poisonedThen);
+});
+
+assert.throws(Test262Error, function() {
+ poisonedThen.finally();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-throws.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-throws.js
new file mode 100644
index 0000000000..536ed24171
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-then-throws.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2017 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+author: Jordan Harband
+description: >
+ Promise.prototype.finally called with a `this` value that defines a `then`
+ method which returns an abrupt completion.
+esid: sec-promise.prototype.finally
+features: [Promise.prototype.finally]
+---*/
+
+var thrower = new Promise(function() {});
+thrower.then = function() {
+ throw new Test262Error();
+};
+
+assert.throws(Test262Error, function() {
+ Promise.prototype.finally.call(thrower);
+});
+
+assert.throws(Test262Error, function() {
+ thrower.finally();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-thenable.js
new file mode 100644
index 0000000000..dccb5be50c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/finally/this-value-thenable.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-promise.prototype.finally
+description: >
+ Promise.prototype.finally invoked on thenable returns result of "then" call.
+features: [Promise.prototype.finally]
+---*/
+
+var thenResult = {};
+var Thenable = function() {};
+Thenable.prototype.then = function() { return thenResult; };
+
+assert.sameValue(
+ Promise.prototype.finally.call(new Thenable()),
+ thenResult
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/no-promise-state.js b/js/src/tests/test262/built-ins/Promise/prototype/no-promise-state.js
new file mode 100644
index 0000000000..096249ac1d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/no-promise-state.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-properties-of-the-promise-prototype-object
+description: Promise.prototype does not have a [[PromiseState]] internal slot
+info: |
+ The Promise prototype object is the intrinsic object %PromisePrototype%. The
+ value of the [[Prototype]] internal slot of the Promise prototype object is
+ the intrinsic object %ObjectPrototype%. The Promise prototype object is an
+ ordinary object. It does not have a [[PromiseState]] internal slot or any of
+ the other internal slots of Promise instances.
+
+ 25.4.5.3 Promise.prototype.then
+
+ 1. Let promise be the this value.
+ 2. If IsPromise(promise) is false, throw a TypeError exception.
+
+ 25.4.1.6 IsPromise
+
+ 1. If Type(x) is not Object, return false.
+ 2. If x does not have a [[PromiseState]] internal slot, return false.
+---*/
+
+assert.throws(TypeError, function() {
+ Promise.prototype.then.call(Promise.prototype, function() {}, function() {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Promise/prototype/prop-desc.js
new file mode 100644
index 0000000000..b369a731ad
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/prop-desc.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-promise.prototype
+description: Property descriptor of 'prototype' property
+info: |
+ This property has the attributes { [[Writable]]: false, [[Enumerable]]:
+ false, [[Configurable]]: false }.
+includes: [propertyHelper.js]
+---*/
+
+verifyNotEnumerable(Promise, 'prototype');
+verifyNotWritable(Promise, 'prototype');
+verifyNotConfigurable(Promise, 'prototype');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/proto.js b/js/src/tests/test262/built-ins/Promise/prototype/proto.js
new file mode 100644
index 0000000000..d0fb702c39
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/proto.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-properties-of-the-promise-prototype-object
+description: Promise.prototype [[Prototype]] is %ObjectPrototype%
+info: |
+ The Promise prototype object is the intrinsic object %PromisePrototype%. The
+ value of the [[Prototype]] internal slot of the Promise prototype object is
+ the intrinsic object %ObjectPrototype%. The Promise prototype object is an
+ ordinary object. It does not have a [[PromiseState]] internal slot or any of
+ the other internal slots of Promise instances.
+---*/
+
+assert.sameValue(Object.getPrototypeOf(Promise.prototype), Object.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/shell.js b/js/src/tests/test262/built-ins/Promise/prototype/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/shell.js
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A1.1_T1.js
new file mode 100644
index 0000000000..30133bb896
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A1.1_T1.js
@@ -0,0 +1,42 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Misc sequencing tests
+ inspired by https://github.com/getify/native-promise-only/issues/34#issuecomment-54282002
+es6id: S25.4.2.1_A3.2_T2
+author: Sam Mikes
+description: Promise onResolved functions are called in predictable sequence
+includes: [promiseHelper.js]
+flags: [async]
+---*/
+
+var sequence = [];
+
+var p = new Promise(function(resolve, reject) {
+ sequence.push(1);
+ resolve("");
+});
+
+p.then(function() {
+ sequence.push(3);
+}).then(function() {
+ sequence.push(5);
+}).then(function() {
+ sequence.push(7);
+});
+
+p.then(function() {
+ sequence.push(4);
+}).then(function() {
+ sequence.push(6);
+}).then(function() {
+ sequence.push(8);
+}).then(function() {
+ assert.sameValue(sequence.length, 8);
+ checkSequence(sequence, "Sequence should be as expected");
+}).then($DONE, $DONE);
+
+sequence.push(2);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T1.js
new file mode 100644
index 0000000000..2b504506bb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T1.js
@@ -0,0 +1,37 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Misc sequencing tests
+ inspired by https://github.com/promises-aplus/promises-tests/issues/61
+ Case "T1"
+es6id: S25.4.4_A2.1_T1
+author: Sam Mikes
+description: Promise onResolved functions are called in predictable sequence
+includes: [promiseHelper.js]
+flags: [async]
+---*/
+
+var resolveP1, rejectP2, sequence = [];
+
+(new Promise(function(resolve, reject) {
+ resolveP1 = resolve;
+})).then(function(msg) {
+ sequence.push(msg);
+}).then(function() {
+ assert.sameValue(sequence.length, 3);
+checkSequence(sequence, "Expected 1,2,3");
+}).then($DONE, $DONE);
+
+(new Promise(function(resolve, reject) {
+ rejectP2 = reject;
+})).catch(function(msg) {
+ sequence.push(msg);
+});
+
+rejectP2(2);
+resolveP1(3);
+
+sequence.push(1);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T2.js
new file mode 100644
index 0000000000..c689e07f99
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T2.js
@@ -0,0 +1,41 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Misc sequencing tests
+ inspired by https://github.com/promises-aplus/promises-tests/issues/61
+ Case "T2a"
+es6id: S25.4.4_A2.1_T2
+author: Sam Mikes
+description: Promise onResolved functions are called in predictable sequence
+includes: [promiseHelper.js]
+flags: [async]
+---*/
+
+var resolveP1, rejectP2, p1, p2,
+ sequence = [];
+
+p1 = new Promise(function(resolve, reject) {
+ resolveP1 = resolve;
+});
+p2 = new Promise(function(resolve, reject) {
+ rejectP2 = reject;
+});
+
+rejectP2(3);
+resolveP1(2);
+
+p1.then(function(msg) {
+ sequence.push(msg);
+});
+
+p2.catch(function(msg) {
+ sequence.push(msg);
+}).then(function() {
+ assert.sameValue(sequence.length, 3);
+ checkSequence(sequence, "Expected 1,2,3");
+}).then($DONE, $DONE);
+
+sequence.push(1);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T3.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T3.js
new file mode 100644
index 0000000000..dc1f0d7233
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.4_A2.1_T3.js
@@ -0,0 +1,43 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Misc sequencing tests
+ inspired by https://github.com/promises-aplus/promises-tests/issues/61
+ Case "T2b"
+es6id: S25.4.4_A2.1_T3
+author: Sam Mikes
+description: Promise onResolved functions are called in predictable sequence
+includes: [promiseHelper.js]
+flags: [async]
+---*/
+
+var resolveP1, rejectP2, p1, p2,
+ sequence = [];
+
+p1 = new Promise(function(resolve, reject) {
+ resolveP1 = resolve;
+});
+p2 = new Promise(function(resolve, reject) {
+ rejectP2 = reject;
+});
+
+rejectP2(3);
+resolveP1(2);
+
+Promise.resolve().then(function() {
+ p1.then(function(msg) {
+ sequence.push(msg);
+ });
+
+ p2.catch(function(msg) {
+ sequence.push(msg);
+ }).then(function() {
+ assert.sameValue(sequence.length, 3);
+ checkSequence(sequence, "Expected 1,2,3");
+ }).then($DONE, $DONE);
+});
+
+sequence.push(1);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js
new file mode 100644
index 0000000000..959bc284dc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T1.js
@@ -0,0 +1,16 @@
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Promise.prototype.then is a function of two arguments
+es6id: S25.4.5.3_A1.1_T1
+author: Sam Mikes
+description: Promise.prototype.then is a function of two arguments
+---*/
+assert(
+ !!(Promise.prototype.then instanceof Function),
+ 'The value of !!(Promise.prototype.then instanceof Function) is expected to be true'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js
new file mode 100644
index 0000000000..c89023e083
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A1.1_T2.js
@@ -0,0 +1,17 @@
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Promise.prototype.then is a function of two arguments
+es6id: S25.4.5.3_A1.1_T2
+author: Sam Mikes
+description: Promise.prototype.then is a function of two arguments
+---*/
+
+var p = new Promise(function() {});
+
+assert(!!(p.then instanceof Function), 'The value of !!(p.then instanceof Function) is expected to be true');
+assert.sameValue(p.then.length, 2, 'The value of p.then.length is expected to be 2');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T1.js
new file mode 100644
index 0000000000..a4e20bae96
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T1.js
@@ -0,0 +1,18 @@
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Promise.prototype.then expects a constructor conforming to Promise as 'this'
+es6id: S25.4.5.3_A2.1_T1
+author: Sam Mikes
+description: Promise.prototype.then throw if 'this' is non-Object
+---*/
+
+var p = new Promise(function() {});
+
+assert.throws(TypeError, function() {
+ p.then.call(3, function() {}, function() {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T2.js
new file mode 100644
index 0000000000..4a982b5675
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A2.1_T2.js
@@ -0,0 +1,20 @@
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Promise.prototype.then expects a Promise as 'this'
+es6id: S25.4.5.3_A2.1_T2
+author: Sam Mikes
+description: Promise.prototype.then throw if 'this' is non-Promise Object
+---*/
+
+function ZeroArgConstructor() {}
+
+var z = new ZeroArgConstructor();
+
+assert.throws(TypeError, function() {
+ Promise.then.call(z, function() {}, function() {});
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T1.js
new file mode 100644
index 0000000000..8fc66ab964
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T1.js
@@ -0,0 +1,21 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ PerformPromiseThen
+ Ref 25.4.5.3.1
+es6id: S25.4.5.3_A4.1_T1
+author: Sam Mikes
+description: Promise.prototype.then accepts 'undefined' as arg1, arg2
+flags: [async]
+---*/
+
+var arg = {};
+var p = Promise.resolve(arg);
+
+p.then(undefined, undefined)
+ .then(function(result) {
+ assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg');
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T2.js
new file mode 100644
index 0000000000..3aeca23d95
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.1_T2.js
@@ -0,0 +1,22 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ PerformPromiseThen
+ Ref 25.4.5.3.1
+es6id: S25.4.5.3_A4.1_T2
+author: Sam Mikes
+description: Promise.prototype.then accepts 'undefined' as arg1, arg2
+flags: [async]
+---*/
+
+var arg = {};
+var p = Promise.reject(arg);
+
+p.then(undefined, undefined).then(function() {
+ throw new Test262Error("Should not be called -- promise was rejected.");
+}, function(result) {
+ assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg');
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T1.js
new file mode 100644
index 0000000000..5b1ac21b27
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T1.js
@@ -0,0 +1,21 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ PerformPromiseThen
+ Ref 25.4.5.3.1
+es6id: S25.4.5.3_A4.2_T1
+author: Sam Mikes
+description: Promise.prototype.then treats non-callable arg1, arg2 as undefined
+flags: [async]
+---*/
+
+var arg = {};
+var p = Promise.resolve(arg);
+
+p.then(3, 5)
+ .then(function(result) {
+ assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg');
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T2.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T2.js
new file mode 100644
index 0000000000..5efe836020
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A4.2_T2.js
@@ -0,0 +1,22 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ PerformPromiseThen
+ Ref 25.4.5.3.1
+es6id: S25.4.5.3_A4.2_T2
+author: Sam Mikes
+description: Promise.prototype.then treats non-callable arg1, arg2 as undefined
+flags: [async]
+---*/
+
+var arg = {};
+var p = Promise.reject(arg);
+
+p.then(3, 5).then(function() {
+ throw new Test262Error("Should not be called -- promise was rejected.");
+}, function(result) {
+ assert.sameValue(result, arg, 'The value of result is expected to equal the value of arg');
+}).then($DONE, $DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.1_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.1_T1.js
new file mode 100644
index 0000000000..2f0b062fae
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.1_T1.js
@@ -0,0 +1,43 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ PerformPromiseThen
+ Ref 25.4.5.3.1
+es6id: S25.4.5.3_A5.1_T1
+author: Sam Mikes
+description: Promise.prototype.then enqueues handler if pending
+includes: [promiseHelper.js]
+flags: [async]
+---*/
+
+var sequence = [],
+ pResolve,
+ p = new Promise(function(resolve, reject) {
+ pResolve = resolve;
+ });
+
+sequence.push(1);
+
+p.then(function() {
+ sequence.push(3);
+ assert.sameValue(sequence.length, 3);
+ checkSequence(sequence, "Should be second");
+}).catch($DONE);
+
+Promise.resolve().then(function() {
+ // enqueue another then-handler
+ p.then(function() {
+ sequence.push(4);
+ assert.sameValue(sequence.length, 4);
+ checkSequence(sequence, "Should be third");
+ }).then($DONE, $DONE);
+
+ sequence.push(2);
+ assert.sameValue(sequence.length, 2);
+ checkSequence(sequence, "Should be first");
+
+ pResolve();
+}).catch($DONE);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.2_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.2_T1.js
new file mode 100644
index 0000000000..6e09de73a1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.2_T1.js
@@ -0,0 +1,45 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ PerformPromiseThen
+ Ref 25.4.5.3.1
+es6id: S25.4.5.3_A5.2_T1
+author: Sam Mikes
+description: Promise.prototype.then immediately queues handler if fulfilled
+includes: [promiseHelper.js]
+flags: [async]
+---*/
+
+var sequence = [],
+ pResolve,
+ p = new Promise(function(resolve, reject) {
+ pResolve = resolve;
+ });
+
+sequence.push(1);
+
+pResolve();
+
+p.then(function() {
+ sequence.push(3);
+ assert.sameValue(sequence.length, 3);
+checkSequence(sequence, "Should be first");
+}).catch($DONE);
+
+Promise.resolve().then(function() {
+ // enqueue another then-handler
+ p.then(function() {
+ sequence.push(5);
+ assert.sameValue(sequence.length, 5);
+checkSequence(sequence, "Should be third");
+ }).then($DONE, $DONE);
+
+ sequence.push(4);
+ assert.sameValue(sequence.length, 4);
+checkSequence(sequence, "Should be second");
+}).catch($DONE);
+
+sequence.push(2);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.3_T1.js b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.3_T1.js
new file mode 100644
index 0000000000..87a2b2271b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/S25.4.5.3_A5.3_T1.js
@@ -0,0 +1,49 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ PerformPromiseThen
+ Ref 25.4.5.3.1
+es6id: S25.4.5.3_A5.3_T1
+author: Sam Mikes
+description: Promise.prototype.then immediately queues handler if rejected
+includes: [promiseHelper.js]
+flags: [async]
+---*/
+
+var sequence = [],
+ pReject,
+ p = new Promise(function(resolve, reject) {
+ pReject = reject;
+ });
+
+sequence.push(1);
+
+pReject();
+
+p.then(function() {
+ throw new Test262Error("Should not be called -- Promise rejected.");
+}, function() {
+ sequence.push(3);
+ assert.sameValue(sequence.length, 3, 'The value of sequence.length is expected to be 3');
+ checkSequence(sequence, "Should be first");
+}).catch($DONE);
+
+Promise.resolve().then(function() {
+ // enqueue another then-handler
+ p.then(function() {
+ throw new Test262Error("Should not be called (2) -- Promise rejected.");
+ }, function() {
+ sequence.push(5);
+ assert.sameValue(sequence.length, 5, 'The value of sequence.length is expected to be 5');
+ checkSequence(sequence, "Should be third");
+ }).then($DONE, $DONE);
+
+ sequence.push(4);
+ assert.sameValue(sequence.length, 4, 'The value of sequence.length is expected to be 4');
+ checkSequence(sequence, "Should be second");
+}).catch($DONE);
+
+sequence.push(2);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/browser.js b/js/src/tests/test262/built-ins/Promise/prototype/then/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/browser.js
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-called-twice.js b/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-called-twice.js
new file mode 100644
index 0000000000..de6cea8025
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-called-twice.js
@@ -0,0 +1,99 @@
+// Copyright (C) 2015 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 25.4.5.3
+description: >
+ Throws a TypeError if capabilities executor already called with non-undefined values.
+info: |
+ Promise.prototype.then ( onFulfilled , onRejected )
+
+ ...
+ 5. Let promiseCapability be NewPromiseCapability(C).
+ 6. ReturnIfAbrupt(promiseCapability).
+ ...
+
+ 25.4.1.5.1 GetCapabilitiesExecutor Functions
+ ...
+ 3. If promiseCapability.[[Resolve]] is not undefined, throw a TypeError exception.
+ 4. If promiseCapability.[[Reject]] is not undefined, throw a TypeError exception.
+ 5. Set promiseCapability.[[Resolve]] to resolve.
+ 6. Set promiseCapability.[[Reject]] to reject.
+ ...
+features: [class]
+---*/
+
+var constructorFunction;
+
+var promise = new class extends Promise {
+ constructor(executor) {
+ if (constructorFunction) {
+ constructorFunction(executor);
+ return {};
+ }
+ return super(executor);
+ }
+}(function() {});
+
+var checkPoint = "";
+constructorFunction = function(executor) {
+ checkPoint += "a";
+ executor();
+ checkPoint += "b";
+ executor(function() {}, function() {});
+ checkPoint += "c";
+};
+promise.then();
+assert.sameValue(checkPoint, "abc", "executor initially called with no arguments");
+
+var checkPoint = "";
+constructorFunction = function(executor) {
+ checkPoint += "a";
+ executor(undefined, undefined);
+ checkPoint += "b";
+ executor(function() {}, function() {});
+ checkPoint += "c";
+};
+promise.then();
+assert.sameValue(checkPoint, "abc", "executor initially called with (undefined, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+ constructorFunction = function(executor) {
+ checkPoint += "a";
+ executor(undefined, function() {});
+ checkPoint += "b";
+ executor(function() {}, function() {});
+ checkPoint += "c";
+ };
+ promise.then();
+}, "executor initially called with (undefined, function)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (undefined, function)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+ constructorFunction = function(executor) {
+ checkPoint += "a";
+ executor(function() {}, undefined);
+ checkPoint += "b";
+ executor(function() {}, function() {});
+ checkPoint += "c";
+ };
+ promise.then();
+}, "executor initially called with (function, undefined)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (function, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+ constructorFunction = function(executor) {
+ checkPoint += "a";
+ executor("invalid value", 123);
+ checkPoint += "b";
+ executor(function() {}, function() {});
+ checkPoint += "c";
+ };
+ promise.then();
+}, "executor initially called with (String, Number)");
+assert.sameValue(checkPoint, "ab", "executor initially called with (String, Number)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-not-callable.js
new file mode 100644
index 0000000000..ed3dee89ae
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/capability-executor-not-callable.js
@@ -0,0 +1,104 @@
+// Copyright (C) 2015 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 25.4.5.3
+description: >
+ Throws a TypeError if either resolve or reject capability is not callable.
+info: |
+ Promise.prototype.then ( onFulfilled , onRejected )
+
+ ...
+ 5. Let promiseCapability be NewPromiseCapability(C).
+ 6. ReturnIfAbrupt(promiseCapability).
+ ...
+
+ 25.4.1.5 NewPromiseCapability ( C )
+ ...
+ 4. Let executor be a new built-in function object as defined in GetCapabilitiesExecutor Functions (25.4.1.5.1).
+ 5. Set the [[Capability]] internal slot of executor to promiseCapability.
+ 6. Let promise be Construct(C, «executor»).
+ 7. ReturnIfAbrupt(promise).
+ 8. If IsCallable(promiseCapability.[[Resolve]]) is false, throw a TypeError exception.
+ 9. If IsCallable(promiseCapability.[[Reject]]) is false, throw a TypeError exception.
+ ...
+features: [class]
+---*/
+
+var constructorFunction;
+
+var promise = new class extends Promise {
+ constructor(executor) {
+ if (constructorFunction) {
+ constructorFunction(executor);
+ return {};
+ }
+ return super(executor);
+ }
+}(function() {});
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+ constructorFunction = function(executor) {
+ checkPoint += "a";
+ };
+ promise.then();
+}, "executor not called at all");
+assert.sameValue(checkPoint, "a", "executor not called at all");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+ constructorFunction = function(executor) {
+ checkPoint += "a";
+ executor();
+ checkPoint += "b";
+ };
+ promise.then();
+}, "executor called with no arguments");
+assert.sameValue(checkPoint, "ab", "executor called with no arguments");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+ constructorFunction = function(executor) {
+ checkPoint += "a";
+ executor(undefined, undefined);
+ checkPoint += "b";
+ };
+ promise.then();
+}, "executor called with (undefined, undefined)");
+assert.sameValue(checkPoint, "ab", "executor called with (undefined, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+ constructorFunction = function(executor) {
+ checkPoint += "a";
+ executor(undefined, function() {});
+ checkPoint += "b";
+ };
+ promise.then();
+}, "executor called with (undefined, function)");
+assert.sameValue(checkPoint, "ab", "executor called with (undefined, function)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+ constructorFunction = function(executor) {
+ checkPoint += "a";
+ executor(function() {}, undefined);
+ checkPoint += "b";
+ };
+ promise.then();
+}, "executor called with (function, undefined)");
+assert.sameValue(checkPoint, "ab", "executor called with (function, undefined)");
+
+var checkPoint = "";
+assert.throws(TypeError, function() {
+ constructorFunction = function(executor) {
+ checkPoint += "a";
+ executor(123, "invalid value");
+ checkPoint += "b";
+ };
+ promise.then();
+}, "executor called with (Number, String)");
+assert.sameValue(checkPoint, "ab", "executor called with (Number, String)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/context-check-on-entry.js b/js/src/tests/test262/built-ins/Promise/prototype/then/context-check-on-entry.js
new file mode 100644
index 0000000000..794407fa72
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/context-check-on-entry.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2015 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 25.4.5.3
+description: >
+ Throws a TypeError if `this` is not a Promise object.
+info: |
+ Promise.prototype.then ( onFulfilled , onRejected )
+
+ 1. Let promise be the this value.
+ 2. If IsPromise(promise) is false, throw a TypeError exception.
+ ...
+---*/
+
+var object = {
+ get constructor() {
+ throw new Test262Error("get constructor called");
+ }
+};
+
+assert.throws(TypeError, function() {
+ Promise.prototype.then.call(object);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-access-count.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-access-count.js
new file mode 100644
index 0000000000..9c54c46ac4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-access-count.js
@@ -0,0 +1,52 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.3
+description: The instance's `constructor` property is accessed exactly once
+info: |
+ 1. Let promise be the this value.
+ 2. If IsPromise(promise) is false, throw a TypeError exception.
+ 3. Let C be SpeciesConstructor(promise, %Promise%).
+ 4. ReturnIfAbrupt(C).
+ 5. Let resultCapability be NewPromiseCapability(C).
+ 6. ReturnIfAbrupt(resultCapability).
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 7.3.20 SpeciesConstructor ( O, defaultConstructor )
+
+ 1. Assert: Type(O) is Object.
+ 2. Let C be Get(O, "constructor").
+ 3. ReturnIfAbrupt(C).
+ 4. If C is undefined, return defaultConstructor.
+ 5. If Type(C) is not Object, throw a TypeError exception.
+ 6. Let S be Get(C, @@species).
+ 7. ReturnIfAbrupt(S).
+ 8. If S is either undefined or null, return defaultConstructor.
+ 9. If IsConstructor(S) is true, return S.
+ 10. Throw a TypeError exception.
+flags: [async]
+---*/
+
+var callCount = 0;
+var prms = new Promise(function(resolve) {
+ resolve();
+});
+Object.defineProperty(prms, 'constructor', {
+ get: function() {
+ callCount += 1;
+ return Promise;
+ }
+});
+
+prms.then(function() {
+ if (callCount !== 1) {
+ $DONE('Expected constructor access count: 1. Actual: ' + callCount);
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-custom.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-custom.js
new file mode 100644
index 0000000000..0ad80c7513
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-custom.js
@@ -0,0 +1,51 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.3
+description: The constructor defined by Symbol.species takes precedence
+info: |
+ 1. Let promise be the this value.
+ 2. If IsPromise(promise) is false, throw a TypeError exception.
+ 3. Let C be SpeciesConstructor(promise, %Promise%).
+ 4. ReturnIfAbrupt(C).
+ 5. Let resultCapability be NewPromiseCapability(C).
+features: [Symbol.species, class]
+---*/
+
+var callCount = 0;
+var thisValue, firstArg, argLength, getCapabilitiesExecutor;
+var executor = function() {};
+var p1 = new Promise(function() {});
+var SpeciesConstructor = class extends Promise {
+ constructor(a) {
+ super(a);
+ callCount += 1;
+ thisValue = this;
+ getCapabilitiesExecutor = a;
+ argLength = arguments.length;
+ }
+};
+var p2;
+
+p1.constructor = function() {};
+p1.constructor[Symbol.species] = SpeciesConstructor;
+
+p2 = p1.then();
+
+assert.sameValue(callCount, 1, 'The constructor is invoked exactly once');
+assert(thisValue instanceof SpeciesConstructor);
+assert.sameValue(
+ argLength, 1, 'The constructor is invoked with a single argument'
+);
+assert.sameValue(typeof getCapabilitiesExecutor, 'function');
+assert.sameValue(
+ getCapabilitiesExecutor.length,
+ 2,
+ 'ES6 25.4.1.5.1: The length property of a GetCapabilitiesExecutor function is 2.'
+);
+assert(
+ p2 instanceof SpeciesConstructor,
+ 'The returned object is an instance of the constructor'
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-null.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-null.js
new file mode 100644
index 0000000000..a0b6df2a9e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-null.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.3
+description: >
+ A TypeError is thrown when the `this` value has a non-object `constructor` property
+info: |
+ 1. Let promise be the this value.
+ 2. If IsPromise(promise) is false, throw a TypeError exception.
+ 3. Let C be SpeciesConstructor(promise, %Promise%).
+ 4. ReturnIfAbrupt(C).
+ 5. Let resultCapability be NewPromiseCapability(C).
+---*/
+
+var p = new Promise(function() {});
+p.constructor = null;
+
+assert.throws(TypeError, function() {
+ p.then();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-poisoned.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-poisoned.js
new file mode 100644
index 0000000000..c0bb06362d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-poisoned.js
@@ -0,0 +1,29 @@
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Promise.prototype.then throws TypeError if Get(promise, "constructor") throws
+ Ref 25.4.5.3 step 4 ReturnIfAbrupt(C)
+es6id: S25.4.5.3_A3.1_T1
+author: Sam Mikes
+description: Promise.prototype.then throws if Get(promise, "constructor") throws
+---*/
+
+var p = Promise.resolve("foo");
+
+Object.defineProperty(p, "constructor", {
+ get: function() {
+ throw new Test262Error();
+ }
+});
+
+assert.throws(Test262Error, function() {
+ p.then(function() {
+ throw new Test262Error("Should never be called.");
+ }, function() {
+ throw new Test262Error("Should never be called.");
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-throws.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-throws.js
new file mode 100644
index 0000000000..d54621103e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-throws.js
@@ -0,0 +1,45 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ `Promise.prototype.then` invoked on a constructor value that throws an
+ error
+es6id: 25.4.5.3
+info: |
+ 1. Let promise be the this value.
+ [...]
+ 3. Let C be SpeciesConstructor(promise, %Promise%).
+ [...]
+ 5. Let resultCapability be NewPromiseCapability(C).
+ 6. ReturnIfAbrupt(resultCapability).
+
+ 25.4.1.5 NewPromiseCapability
+ [...]
+ 6. Let promise be Construct(C, «executor»).
+ 7. ReturnIfAbrupt(promise).
+ features: [Symbol.species]
+---*/
+
+var BadCtor = function() {
+ throw new Test262Error();
+};
+var originalSpecies = Object.getOwnPropertyDescriptor(Promise, Symbol.species);
+
+Object.defineProperty(Promise, Symbol.species, {
+ value: BadCtor
+});
+
+try {
+ var p = new Promise(function(resolve) {
+ resolve();
+ });
+
+ assert.throws(Test262Error, function() {
+ p.then();
+ });
+} finally {
+ Object.defineProperty(Promise, Symbol.species, originalSpecies);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-undef.js b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-undef.js
new file mode 100644
index 0000000000..513f9d6cb6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/ctor-undef.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.3
+description: >
+ The Promise built-in is used when the `this` value has no `constructor` property
+info: |
+ 1. Let promise be the this value.
+ 2. If IsPromise(promise) is false, throw a TypeError exception.
+ 3. Let C be SpeciesConstructor(promise, %Promise%).
+ 4. ReturnIfAbrupt(C).
+ 5. Let resultCapability be NewPromiseCapability(C).
+---*/
+
+var p1 = new Promise(function() {});
+delete p1.constructor;
+
+var p2 = p1.then();
+
+assert(p2 instanceof Promise);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/deferred-is-resolved-value.js b/js/src/tests/test262/built-ins/Promise/prototype/then/deferred-is-resolved-value.js
new file mode 100644
index 0000000000..fd2f6f1cf5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/deferred-is-resolved-value.js
@@ -0,0 +1,68 @@
+// |reftest| async
+// Copyright (C) 2015 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 25.4.5.3
+description: >
+ Promise reaction jobs do not check for cyclic resolutions.
+info: |
+ Promise.prototype.then ( onFulfilled , onRejected )
+
+ ...
+ 5. Let resultCapability be NewPromiseCapability(C).
+ 6. ReturnIfAbrupt(resultCapability).
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen ( promise, onFulfilled, onRejected, resultCapability )
+ ...
+ 3. If IsCallable(onFulfilled) is false, then
+ a. Let onFulfilled be "Identity".
+ 4. If IsCallable(onRejected) is false, then
+ a. Let onRejected be "Thrower".
+ 5. Let fulfillReaction be the PromiseReaction { [[Capabilities]]: resultCapability, [[Handler]]: onFulfilled }.
+ 6. Let rejectReaction be the PromiseReaction { [[Capabilities]]: resultCapability, [[Handler]]: onRejected}.
+ ...
+ 8. Else if the value of promise's [[PromiseState]] internal slot is "fulfilled",
+ a. Let value be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, value»).
+ ...
+
+ 25.4.2.1 PromiseReactionJob ( reaction, argument )
+ ...
+ 4. If handler is "Identity", let handlerResult be NormalCompletion(argument).
+ ...
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined, «handlerResult.[[value]]»).
+ 9. NextJob Completion(status).
+features: [class]
+flags: [async]
+---*/
+
+var createBadPromise = false;
+var object = {};
+
+class P extends Promise {
+ constructor(executor) {
+ if (createBadPromise) {
+ executor(
+ function(v) {
+ assert.sameValue(v, object);
+ $DONE();
+ },
+ function(e) {
+ $DONE(e);
+ }
+ );
+ return object;
+ }
+ return super(executor);
+ }
+}
+
+var p = P.resolve(object);
+
+createBadPromise = true;
+var q = p.then();
+createBadPromise = false;
+
+assert.sameValue(q, object, "then() returns object");
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/length.js b/js/src/tests/test262/built-ins/Promise/prototype/then/length.js
new file mode 100644
index 0000000000..1e865b0460
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/length.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.3
+description: Promise.prototype.then `length` property
+info: |
+ ES6 Section 17:
+ Every built-in Function object, including constructors, has a length
+ property whose value is an integer. Unless otherwise specified, this value
+ is equal to the largest number of named arguments shown in the subclause
+ headings for the function description, including optional parameters.
+
+ [...]
+
+ Unless otherwise specified, the length property of a built-in Function
+ object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+ [[Configurable]]: true }.
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(Promise.prototype.then.length, 2);
+
+verifyNotEnumerable(Promise.prototype.then, 'length');
+verifyNotWritable(Promise.prototype.then, 'length');
+verifyConfigurable(Promise.prototype.then, 'length');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/name.js b/js/src/tests/test262/built-ins/Promise/prototype/then/name.js
new file mode 100644
index 0000000000..b1c97f9956
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/name.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.3
+description: Promise.prototype.then `name` property
+info: |
+ ES6 Section 17:
+
+ Every built-in Function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value is a
+ String. Unless otherwise specified, this value is the name that is given to
+ the function in this specification.
+
+ [...]
+
+ Unless otherwise specified, the name property of a built-in Function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(Promise.prototype.then.name, 'then');
+
+verifyNotEnumerable(Promise.prototype.then, 'name');
+verifyNotWritable(Promise.prototype.then, 'name');
+verifyConfigurable(Promise.prototype.then, 'name');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/prototype/then/not-a-constructor.js
new file mode 100644
index 0000000000..d943772f86
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/not-a-constructor.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-ecmascript-standard-built-in-objects
+description: >
+ Promise.prototype.then does not implement [[Construct]], is not new-able
+info: |
+ ECMAScript Function Objects
+
+ Built-in function objects that are not identified as constructors do not
+ implement the [[Construct]] internal method unless otherwise specified in
+ the description of a particular function.
+
+ sec-evaluatenew
+
+ ...
+ 7. If IsConstructor(constructor) is false, throw a TypeError exception.
+ ...
+includes: [isConstructor.js]
+features: [Reflect.construct, arrow-function]
+---*/
+
+assert.sameValue(
+ isConstructor(Promise.prototype.then),
+ false,
+ 'isConstructor(Promise.prototype.then) must return false'
+);
+
+assert.throws(TypeError, () => {
+ let p = new Promise(() => {}); new p.then();
+}, '`let p = new Promise(() => {}); new p.then()` throws TypeError');
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-fulfilled.js b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-fulfilled.js
new file mode 100644
index 0000000000..89d5e2de5f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-fulfilled.js
@@ -0,0 +1,36 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.3
+description: PerformPromiseThen on a fulfilled promise
+info: |
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+
+ [...]
+ 8. Else if the value of promise's [[PromiseState]] internal slot is
+ "fulfilled",
+ a. Let value be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+ «fulfillReaction, value»).
+ [...]
+flags: [async]
+---*/
+
+var value = {};
+var p = new Promise(function(resolve) {
+ resolve(value);
+});
+
+p.then(function(x) {
+ if (x !== value) {
+ $DONE('The `onFulfilled` handler should be invoked with the promise result.');
+ return;
+ }
+ $DONE();
+}, function() {
+ $DONE('The `onRejected` handler should not be invoked.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-fulfulled.js b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-fulfulled.js
new file mode 100644
index 0000000000..93204370cd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-fulfulled.js
@@ -0,0 +1,39 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.3
+description: PerformPromiseThen on a pending promise that is later fulfilled
+info: |
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ a. Append fulfillReaction as the last element of the List that is the
+ value of promise's [[PromiseFulfillReactions]] internal slot.
+ b. Append rejectReaction as the last element of the List that is the
+ value of promise's [[PromiseRejectReactions]] internal slot.
+ [...]
+flags: [async]
+---*/
+
+var value = {};
+var resolve;
+var p = new Promise(function(_resolve) {
+ resolve = _resolve;
+});
+
+p.then(function(x) {
+ if (x !== value) {
+ $DONE('The `onFulfilled` handler should be invoked with the promise result.');
+ return;
+ }
+ $DONE();
+}, function() {
+ $DONE('The `onRejected` handler should not be invoked.');
+});
+
+resolve(value);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-rejected.js b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-rejected.js
new file mode 100644
index 0000000000..b65b5596ce
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-pending-rejected.js
@@ -0,0 +1,39 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.3
+description: PerformPromiseThen on a pending promise that is later rejected
+info: |
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ a. Append fulfillReaction as the last element of the List that is the
+ value of promise's [[PromiseFulfillReactions]] internal slot.
+ b. Append rejectReaction as the last element of the List that is the
+ value of promise's [[PromiseRejectReactions]] internal slot.
+ [...]
+flags: [async]
+---*/
+
+var value = {};
+var reject;
+var p = new Promise(function(_, _reject) {
+ reject = _reject;
+});
+
+p.then(function() {
+ $DONE('The `onFulfilled` handler should not be invoked.');
+}, function(x) {
+ if (x !== value) {
+ $DONE('The `onRejected` handler should be invoked with the promise result.');
+ return;
+ }
+ $DONE();
+});
+
+reject(value);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-rejected.js b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-rejected.js
new file mode 100644
index 0000000000..4b74b5f3cb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/prfm-rejected.js
@@ -0,0 +1,36 @@
+// |reftest| async
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.3
+description: PerformPromiseThen on a rejected promise
+info: |
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+
+ [...]
+ 9. Else if the value of promise's [[PromiseState]] internal slot is
+ "rejected",
+ a. Let reason be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+ «rejectReaction, reason»).
+ [...]
+flags: [async]
+---*/
+
+var value = {};
+var p = new Promise(function(_, reject) {
+ reject(value);
+});
+
+p.then(function() {
+ $DONE('The `onFulfilled` handler should not be invoked.');
+}, function(x) {
+ if (x !== value) {
+ $DONE('The `onRejected` handler should be invoked with the promise result.');
+ return;
+ }
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/prop-desc.js b/js/src/tests/test262/built-ins/Promise/prototype/then/prop-desc.js
new file mode 100644
index 0000000000..75e58c3117
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/prop-desc.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 25.4.5.1
+description: Promise.prototype.then property descriptor
+info: |
+ Every other data property described in clauses 18 through 26 and in Annex
+ B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(typeof Promise.prototype.then, 'function');
+
+verifyNotEnumerable(Promise.prototype, 'then');
+verifyWritable(Promise.prototype, 'then');
+verifyConfigurable(Promise.prototype, 'then');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-fulfilled.js b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-fulfilled.js
new file mode 100644
index 0000000000..7795f1bb2a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-fulfilled.js
@@ -0,0 +1,49 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Rejecting from a pending promise that is later fulfilled
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ a. Append fulfillReaction as the last element of the List that is the
+ value of promise's [[PromiseFulfillReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.1 Promise Reject Functions
+ [...]
+ 6. Return RejectPromise(promise, reason).
+flags: [async]
+---*/
+
+var resolve;
+var thenable = new Promise(function(_resolve) {
+ resolve = _resolve;
+});
+var p1 = new Promise(function(resolve) {
+ resolve();
+});
+var p2;
+
+p2 = p1.then(function() {
+ throw thenable;
+});
+
+p2.then(function() {
+ $DONE('The promise should not be fulfilled.');
+}, function(x) {
+ if (x !== thenable) {
+ $DONE('The promise should be rejected with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+});
+
+resolve();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-rejected.js b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-rejected.js
new file mode 100644
index 0000000000..72c27c684c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-pending-rejected.js
@@ -0,0 +1,50 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Rejecting from a pending promise that is later rejected
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ [...]
+ b. Append rejectReaction as the last element of the List that is the
+ value of promise's [[PromiseRejectReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.1 Promise Reject Functions
+ [...]
+ 6. Return RejectPromise(promise, reason).
+flags: [async]
+---*/
+
+var reject;
+var thenable = new Promise(function(resolve) {
+ resolve();
+});
+var p1 = new Promise(function(_, _reject) {
+ reject = _reject;
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ throw thenable;
+});
+
+p2.then(function() {
+ $DONE('The promise should not be fulfilled.');
+}, function(x) {
+ if (x !== thenable) {
+ $DONE('The promise should be rejected with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+});
+
+reject();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-fulfilled.js b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-fulfilled.js
new file mode 100644
index 0000000000..56dbd6fff3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-fulfilled.js
@@ -0,0 +1,54 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Rejecting from a fulfilled promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 8. Else if the value of promise's [[PromiseState]] internal slot is
+ "fulfilled",
+ a. Let value be the value of promise's [[PromiseResult]] internal slot.
+ b. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction,
+ value»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 7. If handlerResult is an abrupt completion, then
+ a. Let status be Call(promiseCapability.[[Reject]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.1 Promise Reject Functions
+ [...]
+ 6. Return RejectPromise(promise, reason).
+flags: [async]
+---*/
+
+var thenable = new Promise(function(resolve) {
+ resolve();
+});
+var p1 = new Promise(function(resolve) {
+ resolve();
+});
+var p2;
+
+p2 = p1.then(function() {
+ throw thenable;
+});
+
+p2.then(function() {
+ $DONE('The promise should not be fulfilled.');
+}, function(x) {
+ if (x !== thenable) {
+ $DONE('The promise should be rejected with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-rejected.js b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-rejected.js
new file mode 100644
index 0000000000..0f87c6bb01
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/reject-settled-rejected.js
@@ -0,0 +1,54 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Rejecting from a rejected promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 9. Else if the value of promise's [[PromiseState]] internal slot is
+ "rejected",
+ a. Let reason be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+ «rejectReaction, reason»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 7. If handlerResult is an abrupt completion, then
+ a. Let status be Call(promiseCapability.[[Reject]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.1 Promise Reject Functions
+ [...]
+ 6. Return RejectPromise(promise, reason).
+flags: [async]
+---*/
+
+var thenable = new Promise(function(resolve) {
+ resolve();
+});
+var p1 = new Promise(function(_, reject) {
+ reject();
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ throw thenable;
+});
+
+p2.then(function() {
+ $DONE('The promise should not be fulfilled.');
+}, function(x) {
+ if (x !== thenable) {
+ $DONE('The promise should be rejected with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-obj.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-obj.js
new file mode 100644
index 0000000000..fd6602988b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-obj.js
@@ -0,0 +1,46 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a non-object value from a pending promise that is later fulfilled
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ a. Append fulfillReaction as the last element of the List that is the
+ value of promise's [[PromiseFulfillReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ 7. If Type(resolution) is not Object, then
+ a. Return FulfillPromise(promise, resolution).
+flags: [async]
+---*/
+
+var resolve;
+var p1 = new Promise(function(_resolve) {
+ resolve = _resolve;
+});
+var p2;
+
+p2 = p1.then(function() {
+ return 23;
+});
+
+p2.then(function(value) {
+ if (value !== 23) {
+ $DONE('The promise should be fulfilled with the provided value.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
+
+resolve();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-thenable.js
new file mode 100644
index 0000000000..e71b639f39
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-non-thenable.js
@@ -0,0 +1,54 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a non-thenable object value from a pending promise that is later fulfilled
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ a. Append fulfillReaction as the last element of the List that is the
+ value of promise's [[PromiseFulfillReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ a. Return FulfillPromise(promise, resolution).
+flags: [async]
+---*/
+
+var nonThenable = {
+ then: null
+};
+var resolve;
+var p1 = new Promise(function(_resolve) {
+ resolve = _resolve;
+});
+var p2;
+
+p2 = p1.then(function() {
+ return nonThenable;
+});
+
+p2.then(function(value) {
+ if (value !== nonThenable) {
+ $DONE('The promise should be fulfilled with the provided value.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
+
+resolve();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-poisoned-then.js
new file mode 100644
index 0000000000..88c3cd57a5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-poisoned-then.js
@@ -0,0 +1,54 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with an object with a "poisoned" `then` property from a pending promise that is later fulfilled
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ a. Append fulfillReaction as the last element of the List that is the
+ value of promise's [[PromiseFulfillReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ a. Return RejectPromise(promise, then.[[value]]).
+flags: [async]
+---*/
+
+var value = {};
+var resolve;
+var poisonedThen = Object.defineProperty({}, 'then', {
+ get: function() {
+ throw value;
+ }
+});
+var p1 = new Promise(function(_resolve) {
+ resolve = _resolve;
+});
+var p2;
+
+p2 = p1.then(function() {
+ return poisonedThen;
+});
+
+p2.then(function(x) {
+ $DONE('The promise should not be fulfilled.');
+}, function(x) {
+ if (x !== value) {
+ $DONE('The promise should be rejected with the thrown exception.');
+ return;
+ }
+
+ $DONE();
+});
+
+resolve();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-prms-cstm-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-prms-cstm-then.js
new file mode 100644
index 0000000000..147ce71f22
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-prms-cstm-then.js
@@ -0,0 +1,61 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a resolved Promise instance whose `then` method has been overridden from a pending promise that is later fulfilled
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ a. Append fulfillReaction as the last element of the List that is the
+ value of promise's [[PromiseFulfillReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ [...]
+ 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob,
+ «promise, resolution, thenAction»)
+flags: [async]
+---*/
+
+var value = {};
+var resolve;
+var thenable = new Promise(function(resolve) {
+ resolve();
+});
+var p1 = new Promise(function(_resolve) {
+ resolve = _resolve;
+});
+var p2;
+
+thenable.then = function(resolve) {
+ resolve(value);
+};
+
+p2 = p1.then(function() {
+ return thenable;
+});
+
+p2.then(function(x) {
+ if (x !== value) {
+ $DONE('The promise should be fulfilled with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
+
+resolve();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-self.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-self.js
new file mode 100644
index 0000000000..1191706a68
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-self.js
@@ -0,0 +1,53 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a reference to the promise itself from a pending promise that is later fulfilled
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ a. Append fulfillReaction as the last element of the List that is the
+ value of promise's [[PromiseFulfillReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 6. If SameValue(resolution, promise) is true, then
+ a. Let selfResolutionError be a newly created TypeError object.
+ b. Return RejectPromise(promise, selfResolutionError).
+flags: [async]
+---*/
+
+var resolve;
+var p1 = new Promise(function(_resolve) {
+ resolve = _resolve;
+});
+var p2;
+
+p2 = p1.then(function() {
+ return p2;
+});
+
+p2.then(function() {
+ $DONE('The promise should not be fulfilled.');
+}, function(reason) {
+ if (!reason) {
+ $DONE('The promise should be rejected with a value.');
+ return;
+ }
+
+ if (reason.constructor !== TypeError) {
+ $DONE('The promise should be rejected with a TypeError instance.');
+ return;
+ }
+
+ $DONE();
+});
+
+resolve();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-thenable.js
new file mode 100644
index 0000000000..52ad8d2366
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-fulfilled-thenable.js
@@ -0,0 +1,57 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a thenable object value from a pending promise that is later fulfilled
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ a. Append fulfillReaction as the last element of the List that is the
+ value of promise's [[PromiseFulfillReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ [...]
+ 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob,
+ «promise, resolution, thenAction»)
+flags: [async]
+---*/
+
+var value = {};
+var resolve;
+var thenable = new Promise(function(resolve) {
+ resolve(value);
+});
+var p1 = new Promise(function(_resolve) {
+ resolve = _resolve;
+});
+var p2;
+
+p2 = p1.then(function() {
+ return thenable;
+});
+
+p2.then(function(x) {
+ if (x !== value) {
+ $DONE('The promise should be fulfilled with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
+
+resolve();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-obj.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-obj.js
new file mode 100644
index 0000000000..1480ad1f5f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-obj.js
@@ -0,0 +1,47 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a non-object value from a pending promise that is later rejected
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ [...]
+ b. Append rejectReaction as the last element of the List that is the
+ value of promise's [[PromiseRejectReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ 7. If Type(resolution) is not Object, then
+ a. Return FulfillPromise(promise, resolution).
+flags: [async]
+---*/
+
+var reject;
+var p1 = new Promise(function(_, _reject) {
+ reject = _reject;
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ return 23;
+});
+
+p2.then(function(value) {
+ if (value !== 23) {
+ $DONE('The promise should be fulfilled with the provided value.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
+
+reject();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-thenable.js
new file mode 100644
index 0000000000..19764d8de7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-non-thenable.js
@@ -0,0 +1,55 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a non-thenable object value from a pending promise that is later rejected
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ [...]
+ b. Append rejectReaction as the last element of the List that is the
+ value of promise's [[PromiseRejectReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ a. Return FulfillPromise(promise, resolution).
+flags: [async]
+---*/
+
+var nonThenable = {
+ then: null
+};
+var reject;
+var p1 = new Promise(function(_, _reject) {
+ reject = _reject;
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ return nonThenable;
+});
+
+p2.then(function(value) {
+ if (value !== nonThenable) {
+ $DONE('The promise should be fulfilled with the provided value.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
+
+reject();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-poisoned-then.js
new file mode 100644
index 0000000000..542c6e7ead
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-poisoned-then.js
@@ -0,0 +1,55 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with an object with a "poisoned" `then` property from a pending promise that is later rejected
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ [...]
+ b. Append rejectReaction as the last element of the List that is the
+ value of promise's [[PromiseRejectReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ a. Return RejectPromise(promise, then.[[value]]).
+flags: [async]
+---*/
+
+var value = {};
+var reject;
+var poisonedThen = Object.defineProperty({}, 'then', {
+ get: function() {
+ throw value;
+ }
+});
+var p1 = new Promise(function(_, _reject) {
+ reject = _reject;
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ return poisonedThen;
+});
+
+p2.then(function(x) {
+ $DONE('The promise should not be fulfilled.');
+}, function(x) {
+ if (x !== value) {
+ $DONE('The promise should be rejected with the thrown exception.');
+ return;
+ }
+
+ $DONE();
+});
+
+reject();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-prms-cstm-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-prms-cstm-then.js
new file mode 100644
index 0000000000..4a3fbc1674
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-prms-cstm-then.js
@@ -0,0 +1,62 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a resolved Promise instance whose `then` method has been overridden from a pending promise that is later rejected
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ [...]
+ b. Append rejectReaction as the last element of the List that is the
+ value of promise's [[PromiseRejectReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ [...]
+ 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob,
+ «promise, resolution, thenAction»)
+flags: [async]
+---*/
+
+var value = {};
+var reject;
+var thenable = new Promise(function(resolve) {
+ resolve();
+});
+var p1 = new Promise(function(_, _reject) {
+ reject = _reject;
+});
+var p2;
+
+thenable.then = function(resolve) {
+ resolve(value);
+};
+
+p2 = p1.then(function() {}, function() {
+ return thenable;
+});
+
+p2.then(function(x) {
+ if (x !== value) {
+ $DONE('The promise should be fulfilled with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
+
+reject();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-self.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-self.js
new file mode 100644
index 0000000000..7a31dc46bc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-self.js
@@ -0,0 +1,54 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a reference to the promise itself from a pending promise that is later rejected
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ [...]
+ b. Append rejectReaction as the last element of the List that is the
+ value of promise's [[PromiseRejectReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 6. If SameValue(resolution, promise) is true, then
+ a. Let selfResolutionError be a newly created TypeError object.
+ b. Return RejectPromise(promise, selfResolutionError).
+flags: [async]
+---*/
+
+var reject;
+var p1 = new Promise(function(_, _reject) {
+ reject = _reject;
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ return p2;
+});
+
+p2.then(function() {
+ $DONE('The promise should not be fulfilled.');
+}, function(reason) {
+ if (!reason) {
+ $DONE('The promise should be rejected with a value.');
+ return;
+ }
+
+ if (reason.constructor !== TypeError) {
+ $DONE('The promise should be rejected with a TypeError instance.');
+ return;
+ }
+
+ $DONE();
+});
+
+reject();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-thenable.js
new file mode 100644
index 0000000000..775bb1f79f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-pending-rejected-thenable.js
@@ -0,0 +1,58 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a thenable object value from a pending promise that is later rejected
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 7. If the value of promise's [[PromiseState]] internal slot is "pending",
+ [...]
+ b. Append rejectReaction as the last element of the List that is the
+ value of promise's [[PromiseRejectReactions]] internal slot.
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ [...]
+ 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob,
+ «promise, resolution, thenAction»)
+flags: [async]
+---*/
+
+var value = {};
+var reject;
+var thenable = new Promise(function(resolve) {
+ resolve(value);
+});
+var p1 = new Promise(function(_, _reject) {
+ reject = _reject;
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ return thenable;
+});
+
+p2.then(function(x) {
+ if (x !== value) {
+ $DONE('The promise should be fulfilled with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
+
+reject();
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-obj.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-obj.js
new file mode 100644
index 0000000000..5f6494fa3a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-obj.js
@@ -0,0 +1,50 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a non-object value from a fulfilled promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 8. Else if the value of promise's [[PromiseState]] internal slot is
+ "fulfilled",
+ a. Let value be the value of promise's [[PromiseResult]] internal slot.
+ b. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction,
+ value»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ 7. If Type(resolution) is not Object, then
+ a. Return FulfillPromise(promise, resolution).
+flags: [async]
+---*/
+
+var p1 = new Promise(function(resolve) {
+ resolve();
+});
+var p2;
+
+p2 = p1.then(function() {
+ return 23;
+});
+
+p2.then(function(value) {
+ if (value !== 23) {
+ $DONE('The promise should be fulfilled with the provided value.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-thenable.js
new file mode 100644
index 0000000000..3ca031489f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-non-thenable.js
@@ -0,0 +1,58 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a non-thenable object value from a fulfilled promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 8. Else if the value of promise's [[PromiseState]] internal slot is
+ "fulfilled",
+ a. Let value be the value of promise's [[PromiseResult]] internal slot.
+ b. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction,
+ value»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ a. Return FulfillPromise(promise, resolution).
+flags: [async]
+---*/
+
+var nonThenable = {
+ then: null
+};
+var p1 = new Promise(function(resolve) {
+ resolve();
+});
+var p2;
+
+p2 = p1.then(function() {
+ return nonThenable;
+});
+
+p2.then(function(value) {
+ if (value !== nonThenable) {
+ $DONE('The promise should be fulfilled with the provided value.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-poisoned-then.js
new file mode 100644
index 0000000000..ab5ee4a727
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-poisoned-then.js
@@ -0,0 +1,58 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with an object with a "poisoned" `then` property from a fulfilled promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 8. Else if the value of promise's [[PromiseState]] internal slot is
+ "fulfilled",
+ a. Let value be the value of promise's [[PromiseResult]] internal slot.
+ b. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction,
+ value»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ a. Return RejectPromise(promise, then.[[value]]).
+flags: [async]
+---*/
+
+var value = {};
+var poisonedThen = Object.defineProperty({}, 'then', {
+ get: function() {
+ throw value;
+ }
+});
+var p1 = new Promise(function(resolve) {
+ resolve();
+});
+var p2;
+
+p2 = p1.then(function() {
+ return poisonedThen;
+});
+
+p2.then(function(x) {
+ $DONE('The promise should not be fulfilled.');
+}, function(x) {
+ if (x !== value) {
+ $DONE('The promise should be rejected with the thrown exception.');
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-prms-cstm-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-prms-cstm-then.js
new file mode 100644
index 0000000000..5594511e34
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-prms-cstm-then.js
@@ -0,0 +1,65 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a resolved Promise instance whose `then` method has been overridden from a fulfilled promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 8. Else if the value of promise's [[PromiseState]] internal slot is
+ "fulfilled",
+ a. Let value be the value of promise's [[PromiseResult]] internal slot.
+ b. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction,
+ value»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ [...]
+ 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob,
+ «promise, resolution, thenAction»)
+flags: [async]
+---*/
+
+var value = {};
+var thenable = new Promise(function(resolve) {
+ resolve();
+});
+var p1 = new Promise(function(resolve) {
+ resolve();
+});
+var p2;
+
+thenable.then = function(resolve) {
+ resolve(value);
+};
+
+p2 = p1.then(function() {
+ return thenable;
+});
+
+p2.then(function(x) {
+ if (x !== value) {
+ $DONE('The promise should be fulfilled with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-self.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-self.js
new file mode 100644
index 0000000000..89c4f064b8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-self.js
@@ -0,0 +1,57 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a reference to the promise itself from a fulfilled promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 8. Else if the value of promise's [[PromiseState]] internal slot is
+ "fulfilled",
+ a. Let value be the value of promise's [[PromiseResult]] internal slot.
+ b. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction,
+ value»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 6. If SameValue(resolution, promise) is true, then
+ a. Let selfResolutionError be a newly created TypeError object.
+ b. Return RejectPromise(promise, selfResolutionError).
+flags: [async]
+---*/
+
+var p1 = new Promise(function(resolve) {
+ resolve();
+});
+var p2;
+
+p2 = p1.then(function() {
+ return p2;
+});
+
+p2.then(function() {
+ $DONE('The promise should not be fulfilled.');
+}, function(reason) {
+ if (!reason) {
+ $DONE('The promise should be rejected with a value.');
+ return;
+ }
+
+ if (reason.constructor !== TypeError) {
+ $DONE('The promise should be rejected with a TypeError instance.');
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-thenable.js
new file mode 100644
index 0000000000..f978984c36
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-fulfilled-thenable.js
@@ -0,0 +1,61 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a thenable object value from a fulfilled promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 8. Else if the value of promise's [[PromiseState]] internal slot is
+ "fulfilled",
+ a. Let value be the value of promise's [[PromiseResult]] internal slot.
+ b. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction,
+ value»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ [...]
+ 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob,
+ «promise, resolution, thenAction»)
+flags: [async]
+---*/
+
+var value = {};
+var thenable = new Promise(function(resolve) {
+ resolve(value);
+});
+var p1 = new Promise(function(resolve) {
+ resolve();
+});
+var p2;
+
+p2 = p1.then(function() {
+ return thenable;
+});
+
+p2.then(function(x) {
+ if (x !== value) {
+ $DONE('The promise should be fulfilled with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-obj.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-obj.js
new file mode 100644
index 0000000000..1d39308386
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-obj.js
@@ -0,0 +1,50 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a non-object value from a rejected promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 9. Else if the value of promise's [[PromiseState]] internal slot is
+ "rejected",
+ a. Let reason be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+ «rejectReaction, reason»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ 7. If Type(resolution) is not Object, then
+ a. Return FulfillPromise(promise, resolution).
+flags: [async]
+---*/
+
+var p1 = new Promise(function(_, reject) {
+ reject();
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ return 23;
+});
+
+p2.then(function(value) {
+ if (value !== 23) {
+ $DONE('The promise should be fulfilled with the provided value.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-thenable.js
new file mode 100644
index 0000000000..eae6797f1a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-non-thenable.js
@@ -0,0 +1,58 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a non-thenable object value from a rejected promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 9. Else if the value of promise's [[PromiseState]] internal slot is
+ "rejected",
+ a. Let reason be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+ «rejectReaction, reason»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ a. Return FulfillPromise(promise, resolution).
+flags: [async]
+---*/
+
+var nonThenable = {
+ then: null
+};
+var p1 = new Promise(function(_, reject) {
+ reject();
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ return nonThenable;
+});
+
+p2.then(function(value) {
+ if (value !== nonThenable) {
+ $DONE('The promise should be fulfilled with the provided value.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-poisoned-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-poisoned-then.js
new file mode 100644
index 0000000000..2f33c820bb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-poisoned-then.js
@@ -0,0 +1,58 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with an object with a "poisoned" `then` property from a rejected promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 9. Else if the value of promise's [[PromiseState]] internal slot is
+ "rejected",
+ a. Let reason be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+ «rejectReaction, reason»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ a. Return RejectPromise(promise, then.[[value]]).
+flags: [async]
+---*/
+
+var value = {};
+var poisonedThen = Object.defineProperty({}, 'then', {
+ get: function() {
+ throw value;
+ }
+});
+var p1 = new Promise(function(_, reject) {
+ reject();
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ return poisonedThen;
+});
+
+p2.then(function(x) {
+ $DONE('The promise should not be fulfilled.');
+}, function(x) {
+ if (x !== value) {
+ $DONE('The promise should be rejected with the thrown exception.');
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-prms-cstm-then.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-prms-cstm-then.js
new file mode 100644
index 0000000000..303a5315b0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-prms-cstm-then.js
@@ -0,0 +1,65 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a resolved Promise instance whose `then` method has been overridden from a rejected promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 9. Else if the value of promise's [[PromiseState]] internal slot is
+ "rejected",
+ a. Let reason be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+ «rejectReaction, reason»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ [...]
+ 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob,
+ «promise, resolution, thenAction»)
+flags: [async]
+---*/
+
+var value = {};
+var thenable = new Promise(function(resolve) {
+ resolve();
+});
+var p1 = new Promise(function(_, reject) {
+ reject();
+});
+var p2;
+
+thenable.then = function(resolve) {
+ resolve(value);
+};
+
+p2 = p1.then(function() {}, function() {
+ return thenable;
+});
+
+p2.then(function(x) {
+ if (x !== value) {
+ $DONE('The promise should be fulfilled with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-self.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-self.js
new file mode 100644
index 0000000000..a585ca9b2e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-self.js
@@ -0,0 +1,57 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a reference to the promise itself from a rejected promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 9. Else if the value of promise's [[PromiseState]] internal slot is
+ "rejected",
+ a. Let reason be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+ «rejectReaction, reason»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 6. If SameValue(resolution, promise) is true, then
+ a. Let selfResolutionError be a newly created TypeError object.
+ b. Return RejectPromise(promise, selfResolutionError).
+flags: [async]
+---*/
+
+var p1 = new Promise(function(_, reject) {
+ reject();
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ return p2;
+});
+
+p2.then(function() {
+ $DONE('The promise should not be fulfilled.');
+}, function(reason) {
+ if (!reason) {
+ $DONE('The promise should be rejected with a value.');
+ return;
+ }
+
+ if (reason.constructor !== TypeError) {
+ $DONE('The promise should be rejected with a TypeError instance.');
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-thenable.js b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-thenable.js
new file mode 100644
index 0000000000..827ff855f6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/resolve-settled-rejected-thenable.js
@@ -0,0 +1,61 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Resolving with a thenable object value from a rejected promise
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 9. Else if the value of promise's [[PromiseState]] internal slot is
+ "rejected",
+ a. Let reason be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+ «rejectReaction, reason»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ [...]
+
+ 25.4.1.3.2 Promise Resolve Functions
+ [...]
+ 8. Let then be Get(resolution, "then").
+ 9. If then is an abrupt completion, then
+ [...]
+ 10. Let thenAction be then.[[value]].
+ 11. If IsCallable(thenAction) is false, then
+ [...]
+ 12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob,
+ «promise, resolution, thenAction»)
+flags: [async]
+---*/
+
+var value = {};
+var thenable = new Promise(function(resolve) {
+ resolve(value);
+});
+var p1 = new Promise(function(_, reject) {
+ reject();
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ return thenable;
+});
+
+p2.then(function(x) {
+ if (x !== value) {
+ $DONE('The promise should be fulfilled with the resolution value of the provided promise.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-nonstrict.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-nonstrict.js
new file mode 100644
index 0000000000..61fd431b65
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-nonstrict.js
@@ -0,0 +1,38 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ [...]
+ 6. Else, let handlerResult be Call(handler, undefined, «argument»).
+es6id: S25.4.2.1_A3.1_T1
+author: Sam Mikes
+description: >
+ "fulfilled" handler invoked correctly outside of strict mode
+flags: [async, noStrict]
+---*/
+
+var expectedThis = this,
+ obj = {};
+
+var p = Promise.resolve(obj).then(function(arg) {
+ if (this !== expectedThis) {
+ $DONE("'this' must be global object, got " + this);
+ return;
+ }
+
+ if (arg !== obj) {
+ $DONE("Expected promise to be fulfilled by obj, actually " + arg);
+ return;
+ }
+
+ if (arguments.length !== 1) {
+ $DONE('Expected handler function to be called with exactly 1 argument.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-strict-strict.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-strict-strict.js
new file mode 100644
index 0000000000..3c0ab9a54d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-invoke-strict-strict.js
@@ -0,0 +1,39 @@
+// |reftest| async
+'use strict';
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ [...]
+ 6. Else, let handlerResult be Call(handler, undefined, «argument»).
+es6id: S25.4.2.1_A3.1_T2
+author: Sam Mikes
+description: >
+ "fulfilled" handler invoked correctly in strict mode
+flags: [async, onlyStrict]
+---*/
+
+var expectedThis = undefined,
+ obj = {};
+
+var p = Promise.resolve(obj).then(function(arg) {
+ if (this !== expectedThis) {
+ $DONE("'this' must be undefined, got " + this);
+ return;
+ }
+
+ if (arg !== obj) {
+ $DONE("Expected promise to be fulfilled by obj, actually " + arg);
+ return;
+ }
+
+ if (arguments.length !== 1) {
+ $DONE('Expected handler function to be called with exactly 1 argument.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next-abrupt.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next-abrupt.js
new file mode 100644
index 0000000000..ec9ab0172b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next-abrupt.js
@@ -0,0 +1,46 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Abrupt completions should not preclude additional jobs
+es6id: 25.4.2.1
+info: |
+ [...]
+ 7. If handlerResult is an abrupt completion, then
+ a. Let status be Call(promiseCapability.[[Reject]], undefined,
+ «handlerResult.[[value]]»).
+ b. NextJob Completion(status).
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ 9. NextJob Completion(status).
+flags: [async]
+---*/
+
+var promise = new Promise(function(resolve) {
+ resolve();
+});
+var fulfilledCallCount = 0;
+var rejectedCallCount = 0;
+
+promise.then(function() {
+ fulfilledCallCount += 1;
+ throw new Error();
+}, function() {
+ rejectedCallCount += 1;
+});
+
+promise.then(function() {
+ if (fulfilledCallCount !== 1) {
+ $DONE('Expected "onFulfilled" handler to be invoked exactly once.');
+ return;
+ }
+
+ if (rejectedCallCount !== 0) {
+ $DONE('Expected "onRejected" handler to not be invoked.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('This promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next.js
new file mode 100644
index 0000000000..13fb4ca62f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next.js
@@ -0,0 +1,54 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: All queued jobs should be executed in series
+es6id: 25.4.2.1
+info: |
+ [...]
+ 7. If handlerResult is an abrupt completion, then
+ a. Let status be Call(promiseCapability.[[Reject]], undefined,
+ «handlerResult.[[value]]»).
+ b. NextJob Completion(status).
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ 9. NextJob Completion(status).
+flags: [async]
+---*/
+
+var promise = new Promise(function(resolve) {
+ resolve();
+});
+var log = '';
+
+promise.then(function() {
+ log += 'a';
+}, function() {
+ log += 'A';
+});
+
+promise.then(function() {
+ log += 'b';
+}, function() {
+ log += 'B';
+});
+
+promise.then(function() {
+ log += 'c';
+}, function() {
+ log += 'C';
+});
+
+promise.then(function() {
+ if (log !== 'abc') {
+ $DONE(
+ 'Expected each "onFulfilled" handler to be invoked exactly once in series. ' +
+ 'Expected: abc. Actual: ' + log
+ );
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('This promise should not be rejected.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-abrupt.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-abrupt.js
new file mode 100644
index 0000000000..a394847ce9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-abrupt.js
@@ -0,0 +1,51 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: An abrupt completion should trigger promise rejection
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 8. Else if the value of promise's [[PromiseState]] internal slot is
+ "fulfilled",
+ a. Let value be the value of promise's [[PromiseResult]] internal slot.
+ b. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction,
+ value»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 7. If handlerResult is an abrupt completion, then
+ a. Let status be Call(promiseCapability.[[Reject]], undefined,
+ «handlerResult.[[value]]»).
+ b. NextJob Completion(status).
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ 9. NextJob Completion(status).
+flags: [async]
+---*/
+
+var value = {};
+var p1 = new Promise(function(resolve) {
+ resolve();
+});
+var p2;
+
+p2 = p1.then(function() {
+ throw value;
+}, function() {});
+
+p2.then(function() {
+ $DONE('The `onFulfilled` handler should not be invoked.');
+}, function(x) {
+ if (x !== value) {
+ $DONE('The `onRejected` handler should be invoked with the promise result.');
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-normal.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-normal.js
new file mode 100644
index 0000000000..5acd838f06
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-normal.js
@@ -0,0 +1,51 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: A normal completion should trigger promise fulfillment
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 8. Else if the value of promise's [[PromiseState]] internal slot is
+ "fulfilled",
+ a. Let value be the value of promise's [[PromiseResult]] internal slot.
+ b. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction,
+ value»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 7. If handlerResult is an abrupt completion, then
+ a. Let status be Call(promiseCapability.[[Reject]], undefined,
+ «handlerResult.[[value]]»).
+ b. NextJob Completion(status).
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ 9. NextJob Completion(status).
+flags: [async]
+---*/
+
+var value = {};
+var p1 = new Promise(function(resolve) {
+ resolve();
+});
+var p2;
+
+p2 = p1.then(function() {
+ return value;
+}, function() {});
+
+p2.then(function(x) {
+ if (x !== value) {
+ $DONE('The `onFulfilled` handler should be invoked with the promise result.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The `onRejected` handler should not be invoked.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-identity.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-identity.js
new file mode 100644
index 0000000000..d559176177
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-identity.js
@@ -0,0 +1,25 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Promise reaction jobs have predictable environment
+es6id: S25.4.2.1_A1.1_T1
+author: Sam Mikes
+description: argument passes through "Identity"
+flags: [async]
+---*/
+
+var obj = {};
+
+var p = Promise.resolve(obj).then( /*Identity, Thrower*/ )
+ .then(function(arg) {
+ if (arg !== obj) {
+ $DONE("Expected promise to be fulfilled with obj, actually " + arg);
+ return;
+ }
+ $DONE();
+ }, function() {
+ $DONE('The promise should not be rejected.');
+ });
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-nonstrict.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-nonstrict.js
new file mode 100644
index 0000000000..0b548a01f5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-nonstrict.js
@@ -0,0 +1,38 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ [...]
+ 6. Else, let handlerResult be Call(handler, undefined, «argument»).
+es6id: S25.4.2.1_A3.2_T1
+author: Sam Mikes
+description: >
+ "rejected" handler invoked correctly outside of strict mode
+flags: [async, noStrict]
+---*/
+
+var expectedThis = this,
+ obj = {};
+
+var p = Promise.reject(obj).then(function() {
+ $DONE("Unexpected fulfillment; expected rejection.");
+}, function(arg) {
+ if (this !== expectedThis) {
+ $DONE("'this' must be global object, got " + this);
+ return;
+ }
+
+ if (arg !== obj) {
+ $DONE("Expected promise to be rejected with obj, actually " + arg);
+ return;
+ }
+
+ if (arguments.length !== 1) {
+ $DONE('Expected handler function to be called with exactly 1 argument.');
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-strict-strict.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-strict-strict.js
new file mode 100644
index 0000000000..09f0954c0d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-invoke-strict-strict.js
@@ -0,0 +1,39 @@
+// |reftest| async
+'use strict';
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ [...]
+ 6. Else, let handlerResult be Call(handler, undefined, «argument»).
+es6id: S25.4.2.1_A3.2_T2
+author: Sam Mikes
+description: >
+ "rejected" handler invoked correctly in strict mode
+flags: [async, onlyStrict]
+---*/
+
+var expectedThis = undefined,
+ obj = {};
+
+var p = Promise.reject(obj).then(function() {
+ $DONE("Unexpected fulfillment; expected rejection.");
+}, function(arg) {
+ if (this !== expectedThis) {
+ $DONE("'this' must be undefined, got " + this);
+ return;
+ }
+
+ if (arg !== obj) {
+ $DONE("Expected promise to be rejected with obj, actually " + arg);
+ return;
+ }
+
+ if (arguments.length !== 1) {
+ $DONE('Expected handler function to be called with exactly 1 argument.');
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next-abrupt.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next-abrupt.js
new file mode 100644
index 0000000000..681f4fabc1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next-abrupt.js
@@ -0,0 +1,46 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Abrupt completions should not preclude additional jobs
+es6id: 25.4.2.1
+info: |
+ [...]
+ 7. If handlerResult is an abrupt completion, then
+ a. Let status be Call(promiseCapability.[[Reject]], undefined,
+ «handlerResult.[[value]]»).
+ b. NextJob Completion(status).
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ 9. NextJob Completion(status).
+flags: [async]
+---*/
+
+var promise = new Promise(function(_, reject) {
+ reject();
+});
+var fulfilledCallCount = 0;
+var rejectedCallCount = 0;
+
+promise.then(function() {
+ fulfilledCallCount += 1;
+}, function() {
+ rejectedCallCount += 1;
+ throw new Error();
+});
+
+promise.then(function() {
+ $DONE('This promise should not be fulfilled.');
+}, function() {
+ if (fulfilledCallCount !== 0) {
+ $DONE('Expected "onFulfilled" handler to not be invoked.');
+ return;
+ }
+
+ if (rejectedCallCount !== 1) {
+ $DONE('Expected "onRejected" handler to be invoked exactly once.');
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next.js
new file mode 100644
index 0000000000..d88d3e1a48
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-next.js
@@ -0,0 +1,54 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: All queued jobs should be executed in series
+es6id: 25.4.2.1
+info: |
+ [...]
+ 7. If handlerResult is an abrupt completion, then
+ a. Let status be Call(promiseCapability.[[Reject]], undefined,
+ «handlerResult.[[value]]»).
+ b. NextJob Completion(status).
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ 9. NextJob Completion(status).
+flags: [async]
+---*/
+
+var promise = new Promise(function(_, reject) {
+ reject();
+});
+var log = '';
+
+promise.then(function() {
+ log += 'A';
+}, function() {
+ log += 'a';
+});
+
+promise.then(function() {
+ log += 'B';
+}, function() {
+ log += 'b';
+});
+
+promise.then(function() {
+ log += 'C';
+}, function() {
+ log += 'c';
+});
+
+promise.then(function() {
+ $DONE('This promise should not be fulfilled.');
+}, function() {
+ if (log !== 'abc') {
+ $DONE(
+ 'Expected each "onFulfilled" handler to be invoked exactly once in series. ' +
+ 'Expected: abc. Actual: ' + log
+ );
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-abrupt.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-abrupt.js
new file mode 100644
index 0000000000..8b89456853
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-abrupt.js
@@ -0,0 +1,51 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: An abrupt completion should trigger promise rejection
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 9. Else if the value of promise's [[PromiseState]] internal slot is
+ "rejected",
+ a. Let reason be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+ «rejectReaction, reason»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 7. If handlerResult is an abrupt completion, then
+ a. Let status be Call(promiseCapability.[[Reject]], undefined,
+ «handlerResult.[[value]]»).
+ b. NextJob Completion(status).
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ 9. NextJob Completion(status).
+flags: [async]
+---*/
+
+var value = {};
+var p1 = new Promise(function(_, reject) {
+ reject();
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ throw value;
+});
+
+p2.then(function() {
+ $DONE('The `onFulfilled` handler should not be invoked.');
+}, function(x) {
+ if (x !== value) {
+ $DONE('The `onRejected` handler should be invoked with the promise result.');
+ return;
+ }
+
+ $DONE();
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-normal.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-normal.js
new file mode 100644
index 0000000000..d29489baa8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-rejected-return-normal.js
@@ -0,0 +1,51 @@
+// |reftest| async
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: A normal completion should trigger promise fulfillment
+es6id: 25.4.5.3
+info: |
+ [...]
+ 7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+ resultCapability).
+
+ 25.4.5.3.1 PerformPromiseThen
+ [...]
+ 9. Else if the value of promise's [[PromiseState]] internal slot is
+ "rejected",
+ a. Let reason be the value of promise's [[PromiseResult]] internal slot.
+ b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+ «rejectReaction, reason»).
+
+ 25.4.2.1 PromiseReactionJob
+ [...]
+ 7. If handlerResult is an abrupt completion, then
+ a. Let status be Call(promiseCapability.[[Reject]], undefined,
+ «handlerResult.[[value]]»).
+ b. NextJob Completion(status).
+ 8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+ «handlerResult.[[value]]»).
+ 9. NextJob Completion(status).
+flags: [async]
+---*/
+
+var value = {};
+var p1 = new Promise(function(_, reject) {
+ reject();
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+ return value;
+});
+
+p2.then(function(x) {
+ if (x !== value) {
+ $DONE('The `onFulfilled` handler should be invoked with the promise result.');
+ return;
+ }
+
+ $DONE();
+}, function() {
+ $DONE('The `onRejected` handler should not be invoked.');
+});
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-thrower.js b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-thrower.js
new file mode 100644
index 0000000000..6961da914e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/rxn-handler-thrower.js
@@ -0,0 +1,25 @@
+// |reftest| async
+// Copyright 2014 Cubane Canada, Inc. All rights reserved.
+// See LICENSE for details.
+
+/*---
+info: |
+ Promise reaction jobs have predictable environment
+es6id: S25.4.2.1_A2.1_T1
+author: Sam Mikes
+description: argument thrown through "Thrower"
+flags: [async]
+---*/
+
+var obj = {};
+
+var p = Promise.reject(obj).then( /*Identity, Thrower*/ )
+ .then(function() {
+ $DONE("Unexpected fulfillment - promise should reject.");
+ }, function(arg) {
+ if (arg !== obj) {
+ $DONE("Expected reject reason to be obj, actually " + arg);
+ return;
+ }
+ $DONE();
+ });
diff --git a/js/src/tests/test262/built-ins/Promise/prototype/then/shell.js b/js/src/tests/test262/built-ins/Promise/prototype/then/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Promise/prototype/then/shell.js