Merge pull request #461 from jugglinmike/improve-promise-coverage-then

Improve Promise coverage: Promise.prototype.then
This commit is contained in:
Gorkem Yakin 2016-01-13 16:49:17 -08:00
commit 8e76f6ca62
31 changed files with 662 additions and 298 deletions

View File

@ -1,24 +0,0 @@
// Copyright 2014 Cubane Canada, Inc. All rights reserved.
// See LICENSE for details.
/*---
info: >
Promise reaction jobs have predictable environment
es6id: S25.4.2.1_A3.1_T1
author: Sam Mikes
description: Promise.onFulfilled gets undefined as 'this'
flags: [noStrict]
includes: [fnGlobalObject.js]
---*/
var expectedThis = fnGlobalObject(),
obj = {};
var p = Promise.resolve(obj).then(function(arg) {
if (this !== expectedThis) {
$ERROR("'this' must be global object, got " + this);
}
if (arg !== obj) {
$ERROR("Expected promise to be fulfilled by obj, actually " + arg);
}
}).then($DONE, $DONE);

View File

@ -1,23 +0,0 @@
// Copyright 2014 Cubane Canada, Inc. All rights reserved.
// See LICENSE for details.
/*---
info: >
Promise reaction jobs have predictable environment
es6id: S25.4.2.1_A3.1_T2
author: Sam Mikes
description: Promise.onFulfilled gets undefined as 'this'
flags: [onlyStrict]
---*/
var expectedThis = undefined,
obj = {};
var p = Promise.resolve(obj).then(function(arg) {
if (this !== expectedThis) {
$ERROR("'this' must be undefined, got " + this);
}
if (arg !== obj) {
$ERROR("Expected promise to be fulfilled by obj, actually " + arg);
}
}).then($DONE, $DONE);

View File

@ -1,29 +0,0 @@
// Copyright 2014 Cubane Canada, Inc. All rights reserved.
// See LICENSE for details.
/*---
info: >
Promise reaction jobs have predictable environment
'this' is global object in sloppy mode,
undefined in strict mode
es6id: S25.4.2.1_A3.2_T1
author: Sam Mikes
description: onRejected gets default 'this'
flags: [noStrict]
includes: [fnGlobalObject.js]
---*/
var expectedThis = fnGlobalObject(),
obj = {};
var p = Promise.reject(obj).then(function () {
$ERROR("Unexpected fulfillment; expected rejection.");
}, function(arg) {
if (this !== expectedThis) {
$ERROR("'this' must be global object, got " + this);
}
if (arg !== obj) {
$ERROR("Expected promise to be rejected with obj, actually " + arg);
}
}).then($DONE, $DONE);

View File

@ -1,28 +0,0 @@
// Copyright 2014 Cubane Canada, Inc. All rights reserved.
// See LICENSE for details.
/*---
info: >
Promise reaction jobs have predictable environment
'this' is global object in sloppy mode,
undefined in strict mode
es6id: S25.4.2.1_A3.2_T2
author: Sam Mikes
description: onRejected gets default 'this'
flags: [onlyStrict]
---*/
var expectedThis = undefined,
obj = {};
var p = Promise.reject(obj).then(function () {
$ERROR("Unexpected fulfillment; expected rejection.");
}, function(arg) {
if (this !== expectedThis) {
$ERROR("'this' must be undefined, got " + this);
}
if (arg !== obj) {
$ERROR("Expected promise to be rejected with obj, actually " + arg);
}
}).then($DONE, $DONE);

View File

@ -1,46 +0,0 @@
// 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: >
Access error for the `then` property of the object returned from the "on fulfilled" handler
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»).
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]]).
---*/
var poisonedThen = {};
var error = new Test262Error();
Object.defineProperty(poisonedThen, 'then', {
get: function() {
throw error;
}
});
var p = new Promise(function(r) { r(); });
p.then(function() {
return poisonedThen;
}).then(function() {
$DONE('The promise should not be fulfilled');
}, function(reason) {
assert.sameValue(reason, error);
$DONE();
});

View File

@ -1,41 +0,0 @@
// 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 return value of the `onFulfilled` method is a "thenable" object
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»).
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).
---*/
var promise1 = new Promise(function(resolve) {
resolve();
});
var promise2 = promise1.then(function() {
return promise2;
});
promise2.then(function() {
$DONE('This promise should not be resolved');
}, function(reason) {
assert.sameValue(reason.constructor, TypeError);
$DONE();
});

View File

@ -1,57 +0,0 @@
// 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 `onFulfilled` method throws an error
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»).
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]]).
10. Let thenAction be then.[[value]].
11. If IsCallable(thenAction) is false, then
a. Return FulfillPromise(promise, resolution).
12. Perform EnqueueJob ("PromiseJobs", PromiseResolveThenableJob, «promise,
resolution, thenAction»)
13. Return undefined.
25.4.2.2 PromiseResolveThenableJob
2. Let thenCallResult be Call(then, thenable,
«resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»).
3. If thenCallResult is an abrupt completion,
a. Let status be Call(resolvingFunctions.[[Reject]], undefined,
«thenCallResult.[[value]]»).
b. NextJob Completion(status).
---*/
var error = new Test262Error();
var promiseFulfilled = false;
var promiseRejected = false;
var promise = new Promise(function(resolve) {
resolve();
});
promise.then(function() {
throw error;
}).then(function() {
$DONE('This promise should not be fulfilled');
}, function(reason) {
assert.sameValue(reason, error);
$DONE();
});

View File

@ -1,33 +0,0 @@
// 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 return value of the `onRejected` method
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»).
---*/
var returnVal = {};
var promise = new Promise(function(_, reject) {
reject();
});
promise.then(null, function() {
return returnVal;
}).then(function(result) {
assert.sameValue(result, returnVal);
$DONE();
}, function() {
$DONE('The promise should not be rejected');
});

View File

@ -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.
/*---
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»).
[...]
---*/
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.');
});

View File

@ -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.
/*---
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.
[...]
---*/
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);

View File

@ -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.
/*---
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.
[...]
---*/
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);

View File

@ -2,7 +2,7 @@
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 25.4.5.3
description: The `onRejected` method throws an error
description: PerformPromiseThen on a rejected promise
info: >
7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
resultCapability).
@ -15,19 +15,18 @@ info: >
a. Let reason be the value of promise's [[PromiseResult]] internal slot.
b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
«rejectReaction, reason»).
[...]
---*/
var error = new Test262Error();
var promise = new Promise(function(_, reject) {
reject();
});
promise.then(null, function() {
throw error;
}).then(function(result) {
$DONE('This promise should not be fulfilled');
}, function(reason) {
assert.sameValue(reason, error);
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();
});

View File

@ -0,0 +1,38 @@
// 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: [noStrict]
includes: [fnGlobalObject.js]
---*/
var expectedThis = fnGlobalObject(),
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.');
});

View File

@ -0,0 +1,37 @@
// 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: [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.');
});

View File

@ -0,0 +1,44 @@
// 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).
---*/
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.');
});

View File

@ -0,0 +1,52 @@
// 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).
---*/
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.');
});

View File

@ -0,0 +1,49 @@
// 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).
---*/
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();
});

View File

@ -0,0 +1,49 @@
// 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).
---*/
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.');
});

View File

@ -14,6 +14,10 @@ var obj = {};
var p = Promise.resolve(obj).then(/*Identity, Thrower*/)
.then(function (arg) {
if (arg !== obj) {
$ERROR("Expected promise to be fulfilled with obj, actually " + arg);
$DONE("Expected promise to be fulfilled with obj, actually " + arg);
return;
}
}).then($DONE, $DONE);
$DONE();
}, function() {
$DONE('The promise should not be rejected.');
});

View File

@ -0,0 +1,38 @@
// 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: [noStrict]
includes: [fnGlobalObject.js]
---*/
var expectedThis = fnGlobalObject(),
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();
});

View File

@ -0,0 +1,37 @@
// 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: [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();
});

View File

@ -0,0 +1,44 @@
// 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).
---*/
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();
});

View File

@ -0,0 +1,52 @@
// 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).
---*/
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();
});

View File

@ -0,0 +1,49 @@
// 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).
---*/
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();
});

View File

@ -0,0 +1,49 @@
// 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).
---*/
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.');
});

View File

@ -13,9 +13,11 @@ var obj = {};
var p = Promise.reject(obj).then(/*Identity, Thrower*/)
.then(function () {
$ERROR("Unexpected fulfillment - promise should reject.");
$DONE("Unexpected fulfillment - promise should reject.");
}, function (arg) {
if (arg !== obj) {
$ERROR("Expected reject reason to be obj, actually " + arg);
$DONE("Expected reject reason to be obj, actually " + arg);
return;
}
}).then($DONE, $DONE);
$DONE();
});