Commit 7826bfa7 authored by littledan's avatar littledan Committed by Commit bot

[promise] Async/await edge case spec compliance fix

- Don't read .constructor when returning a Promise from an async function.
  Instead, call out to the internals of Promise.resolve directly.
  This is done by adding back in an "optimization" from an earlier form of
  the async/await code written by Caitlin Potter.
- Async functions always return a new Promise with a distinct identity,
  even if they simply return another Promise.

R=caitp@igalia.com
BUG=v8:4483

Review-Url: https://codereview.chromium.org/2219623002
Cr-Commit-Position: refs/heads/master@{#38404}
parent 3f936a5b
......@@ -13,17 +13,17 @@
var AsyncFunctionNext;
var AsyncFunctionThrow;
var IsPromise;
var GlobalPromise;
var NewPromiseCapability;
var PerformPromiseThen;
var PromiseCastResolved;
utils.Import(function(from) {
AsyncFunctionNext = from.AsyncFunctionNext;
AsyncFunctionThrow = from.AsyncFunctionThrow;
IsPromise = from.IsPromise;
GlobalPromise = from.GlobalPromise;
NewPromiseCapability = from.NewPromiseCapability;
PromiseCastResolved = from.PromiseCastResolved;
PerformPromiseThen = from.PerformPromiseThen;
});
......@@ -34,14 +34,7 @@ function AsyncFunctionAwait(generator, value) {
// value => AsyncFunctionNext(value),
// error => AsyncFunctionThrow(error)
// );
var promise;
if (IsPromise(value)) {
promise = value;
} else {
var promiseCapability = NewPromiseCapability(GlobalPromise);
%_Call(promiseCapability.resolve, UNDEFINED, value);
promise = promiseCapability.promise;
}
var promise = PromiseCastResolved(value);
var onFulfilled =
(sentValue) => %_Call(AsyncFunctionNext, generator, sentValue);
......
......@@ -191,7 +191,6 @@ function PostNatives(utils) {
"IntlParseDate",
"IntlParseNumber",
"IsNaN",
"IsPromise",
"MakeError",
"MakeRangeError",
"MakeTypeError",
......@@ -206,8 +205,7 @@ function PostNatives(utils) {
"PromiseChain",
"PromiseDefer",
"PromiseAccept",
"PromiseCreateRejected",
"PromiseCreateResolved",
"PromiseCastResolved",
"PromiseThen",
"RegExpSubclassExecJS",
"RegExpSubclassMatch",
......
......@@ -386,8 +386,20 @@ function PromiseCreateRejected(r) {
return %_Call(PromiseReject, GlobalPromise, r);
}
function PromiseCreateResolved(x) {
return %_Call(PromiseResolve, GlobalPromise, x);
function PromiseCreateResolved(value) {
var promise = PromiseInit(new GlobalPromise(promiseRawSymbol));
var resolveResult = ResolvePromise(promise, value);
return promise;
}
function PromiseCastResolved(value) {
if (IsPromise(value)) {
return value;
} else {
var promise = PromiseInit(new GlobalPromise(promiseRawSymbol));
var resolveResult = ResolvePromise(promise, value);
return promise;
}
}
function PerformPromiseThen(promise, onResolve, onReject, resultCapability) {
......@@ -629,14 +641,11 @@ utils.InstallFunctions(extrasUtils, 0, [
fn => %FunctionRemovePrototype(fn));
utils.Export(function(to) {
to.IsPromise = IsPromise;
to.PromiseChain = PromiseChain;
to.PromiseDefer = PromiseDefer;
to.PromiseAccept = PromiseAccept;
to.PromiseCreateRejected = PromiseCreateRejected;
to.PromiseCreateResolved = PromiseCreateResolved;
to.PromiseCastResolved = PromiseCastResolved;
to.PromiseThen = PromiseThen;
to.GlobalPromise = GlobalPromise;
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-async-await --allow-natives-syntax
'use strict';
var resolved = Promise.resolve();
var count = 0;
Object.defineProperty(Promise.prototype, 'constructor',
{ get() { count++; return Promise; } })
async function foo() {
await resolved;
return resolved;
}
async function bar() {
throw 1;
}
foo();
bar();
%RunMicrotasks();
assertEquals(0, count);
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-async-await
var resolved = Promise.resolve();
assertTrue((async() => resolved)() !== resolved);
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