Skip to content
Snippets Groups Projects
Commit 8e76f6ca authored by Gorkem Yakin's avatar Gorkem Yakin
Browse files

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

Improve Promise coverage: Promise.prototype.then
parents c9764dc5 a5bf1948
No related branches found
No related tags found
No related merge requests found
Showing
with 507 additions and 71 deletions
// 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();
});
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// 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 return value of the `onFulfilled` method is a "thenable" object
description: PerformPromiseThen on a fulfilled promise
info: >
7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
resultCapability).
......@@ -15,27 +15,18 @@ info: >
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();
});
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.');
});
// 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);
// 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);
......@@ -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();
});
......@@ -3,10 +3,12 @@
/*---
info: >
Promise reaction jobs have predictable environment
[...]
6. Else, let handlerResult be Call(handler, undefined, «argument»).
es6id: S25.4.2.1_A3.1_T1
author: Sam Mikes
description: Promise.onFulfilled gets undefined as 'this'
description: >
"fulfilled" handler invoked correctly outside of strict mode
flags: [noStrict]
includes: [fnGlobalObject.js]
---*/
......@@ -16,9 +18,21 @@ var expectedThis = fnGlobalObject(),
var p = Promise.resolve(obj).then(function(arg) {
if (this !== expectedThis) {
$ERROR("'this' must be global object, got " + this);
$DONE("'this' must be global object, got " + this);
return;
}
if (arg !== obj) {
$ERROR("Expected promise to be fulfilled by obj, actually " + arg);
$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;
}
}).then($DONE, $DONE);
$DONE();
}, function() {
$DONE('The promise should not be rejected.');
});
......@@ -3,10 +3,12 @@
/*---
info: >
Promise reaction jobs have predictable environment
[...]
6. Else, let handlerResult be Call(handler, undefined, «argument»).
es6id: S25.4.2.1_A3.1_T2
author: Sam Mikes
description: Promise.onFulfilled gets undefined as 'this'
description: >
"fulfilled" handler invoked correctly in strict mode
flags: [onlyStrict]
---*/
......@@ -15,9 +17,21 @@ var expectedThis = undefined,
var p = Promise.resolve(obj).then(function(arg) {
if (this !== expectedThis) {
$ERROR("'this' must be undefined, got " + this);
$DONE("'this' must be undefined, got " + this);
return;
}
if (arg !== obj) {
$ERROR("Expected promise to be fulfilled by obj, actually " + arg);
$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;
}
}).then($DONE, $DONE);
$DONE();
}, function() {
$DONE('The promise should not be rejected.');
});
// 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.');
});
// 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.');
});
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// 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
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
b. EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction,
value»).
25.4.2.1 PromiseReactionJob
[...]
8. Let then be Get(resolution, "then").
9. If then is an abrupt completion, then
a. Return RejectPromise(promise, then.[[value]]).
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 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();
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();
});
// 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.');
});
......@@ -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.');
});
......@@ -3,12 +3,12 @@
/*---
info: >
Promise reaction jobs have predictable environment
'this' is global object in sloppy mode,
undefined in strict mode
[...]
6. Else, let handlerResult be Call(handler, undefined, «argument»).
es6id: S25.4.2.1_A3.2_T1
author: Sam Mikes
description: onRejected gets default 'this'
description: >
"rejected" handler invoked correctly outside of strict mode
flags: [noStrict]
includes: [fnGlobalObject.js]
---*/
......@@ -17,13 +17,22 @@ var expectedThis = fnGlobalObject(),
obj = {};
var p = Promise.reject(obj).then(function () {
$ERROR("Unexpected fulfillment; expected rejection.");
$DONE("Unexpected fulfillment; expected rejection.");
}, function(arg) {
if (this !== expectedThis) {
$ERROR("'this' must be global object, got " + this);
$DONE("'this' must be global object, got " + this);
return;
}
if (arg !== obj) {
$ERROR("Expected promise to be rejected with obj, actually " + arg);
$DONE("Expected promise to be rejected with obj, actually " + arg);
return;
}
}).then($DONE, $DONE);
if (arguments.length !== 1) {
$DONE('Expected handler function to be called with exactly 1 argument.');
return;
}
$DONE();
});
......@@ -3,12 +3,12 @@
/*---
info: >
Promise reaction jobs have predictable environment
'this' is global object in sloppy mode,
undefined in strict mode
[...]
6. Else, let handlerResult be Call(handler, undefined, «argument»).
es6id: S25.4.2.1_A3.2_T2
author: Sam Mikes
description: onRejected gets default 'this'
description: >
"rejected" handler invoked correctly in strict mode
flags: [onlyStrict]
---*/
......@@ -16,13 +16,22 @@ var expectedThis = undefined,
obj = {};
var p = Promise.reject(obj).then(function () {
$ERROR("Unexpected fulfillment; expected rejection.");
$DONE("Unexpected fulfillment; expected rejection.");
}, function(arg) {
if (this !== expectedThis) {
$ERROR("'this' must be undefined, got " + this);
$DONE("'this' must be undefined, got " + this);
return;
}
if (arg !== obj) {
$ERROR("Expected promise to be rejected with obj, actually " + arg);
$DONE("Expected promise to be rejected with obj, actually " + arg);
return;
}
}).then($DONE, $DONE);
if (arguments.length !== 1) {
$DONE('Expected handler function to be called with exactly 1 argument.');
return;
}
$DONE();
});
// 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();
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment