Commit e4af5cdb authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

[promise] Make Promise.reject match spec, and validate promise capabilities

Correctly validate promise capabilities in NewPromiseCapabilities() and in
GetCapabilitiesExtractor(). Also explicitly follows Promise.race step 2 and
similar cases in the spec, rather than passing tests asserting these steps
are taken in NewPromiseCapability

Also changes Promise.reject to match specification.

Fixes the following test262 tests:

- built-ins/Promise/all/capability-executor-called-twice.js
- built-ins/Promise/all/capability-executor-not-callable.js
- built-ins/Promise/prototype/then/capability-executor-called-twice.js
- built-ins/Promise/prototype/then/capability-executor-not-callable.js
- built-ins/Promise/reject/capability-executor-called-twice.js
- built-ins/Promise/reject/capability-executor-not-callable.js
- built-ins/Promise/resolve/capability-executor-called-twice.js
- built-ins/Promise/resolve/capability-executor-not-callable.js
- built-ins/Promise/race/capability-executor-called-twice.js
- built-ins/Promise/race/capability-executor-not-callable.js
- built-ins/Promise/reject/S25.4.4.4_A3.1_T1.js
- built-ins/Promise/race/S25.4.4.3_A3.1_T2.js

Per v8:3641, mjsunit/es6/debug-promises/throw-with-undefined-reject.js becomes invalid. The exception is thrown before the chain handler is ever invoked, and is caught externally by d8's own handler --- thus evading the uncaught exception event.

BUG=v8:4633, v8:4631, v8:4243, v8:3641
LOG=N
R=littledan@chromium.org, cbruni@chromium.org

Review URL: https://codereview.chromium.org/1531073004

Cr-Commit-Position: refs/heads/master@{#33128}
parent 8d6899c8
......@@ -227,15 +227,22 @@ function NewPromiseCapability(C) {
resolve: callbacks.resolve,
reject: callbacks.reject
};
} else {
var result = {promise: UNDEFINED, resolve: UNDEFINED, reject: UNDEFINED };
result.promise = new C(function(resolve, reject) {
// TODO(littledan): Check for resolve and reject being not undefined
result.resolve = resolve;
result.reject = reject;
});
return result;
}
var result = {promise: UNDEFINED, resolve: UNDEFINED, reject: UNDEFINED };
result.promise = new C(function(resolve, reject) {
if (!IS_UNDEFINED(result.resolve) || !IS_UNDEFINED(result.reject))
throw MakeTypeError(kPromiseExecutorAlreadyInvoked);
result.resolve = resolve;
result.reject = reject;
});
if (!IS_CALLABLE(result.resolve))
throw MakeTypeError(kCalledNonCallable, "promiseCapability.[[Resolve]]");
if (!IS_CALLABLE(result.reject))
throw MakeTypeError(kCalledNonCallable, "promiseCapability.[[Reject]]");
return result;
}
function PromiseDeferred() {
......@@ -250,17 +257,18 @@ function PromiseRejected(r) {
if (!IS_RECEIVER(this)) {
throw MakeTypeError(kCalledOnNonObject, PromiseRejected);
}
var promise;
if (this === GlobalPromise) {
// Optimized case, avoid extra closure.
promise = PromiseCreateAndSet(-1, r);
var promise = PromiseCreateAndSet(-1, r);
// The debug event for this would always be an uncaught promise reject,
// which is usually simply noise. Do not trigger that debug event.
%PromiseRejectEvent(promise, r, false);
return promise;
} else {
promise = new this(function(resolve, reject) { reject(r) });
var promiseCapability = NewPromiseCapability(this);
%_Call(promiseCapability.reject, UNDEFINED, r);
return promiseCapability.promise;
}
return promise;
}
// Multi-unwrapped chaining with thenable coercion.
......@@ -359,6 +367,10 @@ function PromiseAll(iterable) {
}
function PromiseRace(iterable) {
if (!IS_RECEIVER(this)) {
throw MakeTypeError(kCalledOnNonObject, PromiseRace);
}
var deferred = NewPromiseCapability(this);
try {
for (var value of iterable) {
......
......@@ -180,6 +180,8 @@ class CallSite {
T(OrdinaryFunctionCalledAsConstructor, \
"Function object that's not a constructor was created with new") \
T(PromiseCyclic, "Chaining cycle detected for promise %") \
T(PromiseExecutorAlreadyInvoked, \
"Promise executor has already been invoked with non-undefined arguments") \
T(PropertyDescObject, "Property description must be an object: %") \
T(PropertyNotFunction, \
"'%' returned for property '%' of object '%' is not a function") \
......
......@@ -54,6 +54,7 @@
'es6/debug-promises/reject-with-throw-in-reject': [FAIL],
'es6/debug-promises/reject-with-undefined-reject': [FAIL],
'es6/debug-promises/reject-with-invalid-reject': [FAIL],
'es6/debug-promises/throw-with-undefined-reject': [FAIL],
##############################################################################
# TurboFan compiler failures.
......
......@@ -122,15 +122,6 @@
'built-ins/WeakMap/iterator-items-are-not-object-close-iterator': [FAIL],
'built-ins/WeakSet/iterator-close-after-add-failure': [FAIL],
# https://code.google.com/p/v8/issues/detail?id=4243
'built-ins/Promise/race/S25.4.4.3_A3.1_T2': [FAIL],
'built-ins/Promise/reject/S25.4.4.4_A3.1_T1': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=4631
'built-ins/Promise/resolve/capability-executor-called-twice': [FAIL],
'built-ins/Promise/reject/capability-executor-called-twice': [FAIL],
'built-ins/Promise/race/capability-executor-called-twice': [FAIL],
# https://code.google.com/p/v8/issues/detail?id=4119
'built-ins/RegExp/call_with_non_regexp_same_constructor': [FAIL],
'built-ins/RegExp/from-regexp-like-short-circuit': [FAIL],
......@@ -423,10 +414,7 @@
'built-ins/Promise/all/same-reject-function': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=4633
'built-ins/Promise/resolve/capability-executor-not-callable': [FAIL],
'built-ins/Promise/reject/capability-executor-not-callable': [FAIL],
'built-ins/Promise/prototype/then/deferred-is-resolved-value': [SKIP],
'built-ins/Promise/race/capability-executor-not-callable': [FAIL],
'built-ins/Promise/prototype/then/context-check-on-entry': [FAIL],
'built-ins/Promise/exception-after-resolve-in-executor': [FAIL],
'built-ins/Promise/reject-function-name': [FAIL],
......@@ -435,15 +423,11 @@
'built-ins/Promise/resolve-function-nonconstructor': [FAIL],
'built-ins/Promise/all/call-resolve-element-after-return': [FAIL],
'built-ins/Promise/all/call-resolve-element': [FAIL],
'built-ins/Promise/all/capability-executor-called-twice': [FAIL],
'built-ins/Promise/all/call-resolve-element-items': [FAIL],
'built-ins/Promise/all/resolve-before-loop-exit-from-same': [FAIL],
'built-ins/Promise/all/resolve-element-function-name': [FAIL],
'built-ins/Promise/all/resolve-element-function-nonconstructor': [FAIL],
'built-ins/Promise/prototype/then/capability-executor-called-twice': [FAIL],
'built-ins/Promise/prototype/then/capability-executor-not-callable': [FAIL],
'built-ins/Promise/exception-after-resolve-in-thenable-job': [FAIL],
'built-ins/Promise/all/capability-executor-not-callable': [FAIL],
'built-ins/Promise/all/resolve-before-loop-exit': [FAIL],
'built-ins/Promise/executor-function-name': [FAIL],
'built-ins/Promise/executor-function-nonconstructor': [FAIL],
......@@ -616,6 +600,8 @@
'built-ins/GeneratorPrototype/*': [SKIP],
'built-ins/Map/*': [SKIP],
'built-ins/MapIteratorPrototype/*': [SKIP],
'built-ins/Promise/prototype/then/capability-executor-called-twice': [SKIP],
'built-ins/Promise/prototype/then/capability-executor-not-callable': [SKIP],
'built-ins/Proxy/has/*': [SKIP],
'built-ins/Reflect/enumerate/*': [SKIP],
'built-ins/Set/*': [SKIP],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment