Forward the absence of the argument on AsyncFromSyncIterator prototype methods
https://github.com/tc39/ecma262/pull/1776 is a normative change that reached consensus in the November 2019 TC39. It changes %AsyncFromSyncIteratorPrototype% methods to forward the absence of arguments to the underlying sync iterator. This is observable via `arguments.length` inside the underlying sync iterator. For example, .next is changed to, roughly: ``` %AsyncFromSyncIteratorPrototype%.next = function(value) { let res; if (arguments.length < 1) { res = [[SyncIteratorRecord]].[[Iterator]].next(); } else { res = [[SyncIteratorRecord]].[[Iterator]].next(value); } // ... }; ``` Bug: v8:10395 Change-Id: Ib8127d08cd78b8d502e6510241f3f13fbbaba5c7 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2247041 Reviewed-by: Marja Hölttä <marja@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Commit-Queue: Shu-yu Guo <syg@chromium.org> Cr-Commit-Position: refs/heads/master@{#68398}
This commit is contained in:
parent
401513217a
commit
44a655c8af
@ -16,6 +16,10 @@ namespace internal {
|
||||
namespace {
|
||||
class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
|
||||
public:
|
||||
// The 'next' and 'return' take an optional value parameter, and the 'throw'
|
||||
// method take an optional reason parameter.
|
||||
static const int kValueOrReasonArg = 0;
|
||||
|
||||
explicit AsyncFromSyncBuiltinsAssembler(compiler::CodeAssemblerState* state)
|
||||
: AsyncBuiltinsAssembler(state) {}
|
||||
|
||||
@ -31,8 +35,8 @@ class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
|
||||
using SyncIteratorNodeGenerator =
|
||||
std::function<TNode<Object>(TNode<JSReceiver>)>;
|
||||
void Generate_AsyncFromSyncIteratorMethod(
|
||||
const TNode<Context> context, const TNode<Object> iterator,
|
||||
const TNode<Object> sent_value,
|
||||
CodeStubArguments* args, const TNode<Context> context,
|
||||
const TNode<Object> iterator, const TNode<Object> sent_value,
|
||||
const SyncIteratorNodeGenerator& get_method,
|
||||
const UndefinedMethodHandler& if_method_undefined,
|
||||
const char* operation_name,
|
||||
@ -40,9 +44,9 @@ class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
|
||||
base::Optional<TNode<Object>> initial_exception_value = base::nullopt);
|
||||
|
||||
void Generate_AsyncFromSyncIteratorMethod(
|
||||
const TNode<Context> context, const TNode<Object> iterator,
|
||||
const TNode<Object> sent_value, Handle<String> name,
|
||||
const UndefinedMethodHandler& if_method_undefined,
|
||||
CodeStubArguments* args, const TNode<Context> context,
|
||||
const TNode<Object> iterator, const TNode<Object> sent_value,
|
||||
Handle<String> name, const UndefinedMethodHandler& if_method_undefined,
|
||||
const char* operation_name,
|
||||
Label::Type reject_label_type = Label::kDeferred,
|
||||
base::Optional<TNode<Object>> initial_exception_value = base::nullopt) {
|
||||
@ -50,7 +54,7 @@ class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
|
||||
return GetProperty(context, sync_iterator, name);
|
||||
};
|
||||
return Generate_AsyncFromSyncIteratorMethod(
|
||||
context, iterator, sent_value, get_method, if_method_undefined,
|
||||
args, context, iterator, sent_value, get_method, if_method_undefined,
|
||||
operation_name, reject_label_type, initial_exception_value);
|
||||
}
|
||||
|
||||
@ -97,8 +101,9 @@ void AsyncFromSyncBuiltinsAssembler::ThrowIfNotAsyncFromSyncIterator(
|
||||
}
|
||||
|
||||
void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
|
||||
const TNode<Context> context, const TNode<Object> iterator,
|
||||
const TNode<Object> sent_value, const SyncIteratorNodeGenerator& get_method,
|
||||
CodeStubArguments* args, const TNode<Context> context,
|
||||
const TNode<Object> iterator, const TNode<Object> sent_value,
|
||||
const SyncIteratorNodeGenerator& get_method,
|
||||
const UndefinedMethodHandler& if_method_undefined,
|
||||
const char* operation_name, Label::Type reject_label_type,
|
||||
base::Optional<TNode<Object>> initial_exception_value) {
|
||||
@ -128,16 +133,31 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
|
||||
BIND(&if_isnotundefined);
|
||||
}
|
||||
|
||||
TNode<Object> iter_result;
|
||||
TVARIABLE(Object, iter_result);
|
||||
{
|
||||
Label has_sent_value(this), no_sent_value(this), merge(this);
|
||||
ScopedExceptionHandler handler(this, &reject_promise, &var_exception);
|
||||
iter_result = Call(context, method, sync_iterator, sent_value);
|
||||
Branch(
|
||||
IntPtrGreaterThan(args->GetLength(), IntPtrConstant(kValueOrReasonArg)),
|
||||
&has_sent_value, &no_sent_value);
|
||||
BIND(&has_sent_value);
|
||||
{
|
||||
iter_result = Call(context, method, sync_iterator, sent_value);
|
||||
Goto(&merge);
|
||||
}
|
||||
BIND(&no_sent_value);
|
||||
{
|
||||
iter_result = Call(context, method, sync_iterator);
|
||||
Goto(&merge);
|
||||
}
|
||||
BIND(&merge);
|
||||
}
|
||||
|
||||
TNode<Object> value;
|
||||
TNode<Oddball> done;
|
||||
std::tie(value, done) = LoadIteratorResult(
|
||||
context, native_context, iter_result, &reject_promise, &var_exception);
|
||||
std::tie(value, done) =
|
||||
LoadIteratorResult(context, native_context, iter_result.value(),
|
||||
&reject_promise, &var_exception);
|
||||
|
||||
const TNode<JSFunction> promise_fun =
|
||||
CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX));
|
||||
@ -160,15 +180,16 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
|
||||
|
||||
// Perform ! PerformPromiseThen(valueWrapper,
|
||||
// onFulfilled, undefined, promiseCapability).
|
||||
Return(CallBuiltin(Builtins::kPerformPromiseThen, context, value_wrapper,
|
||||
on_fulfilled, UndefinedConstant(), promise));
|
||||
args->PopAndReturn(CallBuiltin(Builtins::kPerformPromiseThen, context,
|
||||
value_wrapper, on_fulfilled,
|
||||
UndefinedConstant(), promise));
|
||||
|
||||
BIND(&reject_promise);
|
||||
{
|
||||
const TNode<Object> exception = var_exception.value();
|
||||
CallBuiltin(Builtins::kRejectPromise, context, promise, exception,
|
||||
TrueConstant());
|
||||
Return(promise);
|
||||
args->PopAndReturn(promise);
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,8 +273,12 @@ AsyncFromSyncBuiltinsAssembler::LoadIteratorResult(
|
||||
// https://tc39.github.io/proposal-async-iteration/
|
||||
// Section #sec-%asyncfromsynciteratorprototype%.next
|
||||
TF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) {
|
||||
const TNode<Object> iterator = CAST(Parameter(Descriptor::kReceiver));
|
||||
const TNode<Object> value = CAST(Parameter(Descriptor::kValue));
|
||||
TNode<IntPtrT> argc = ChangeInt32ToIntPtr(
|
||||
UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)));
|
||||
CodeStubArguments args(this, argc);
|
||||
|
||||
const TNode<Object> iterator = args.GetReceiver();
|
||||
const TNode<Object> value = args.GetOptionalArgumentValue(kValueOrReasonArg);
|
||||
const TNode<Context> context = CAST(Parameter(Descriptor::kContext));
|
||||
|
||||
auto get_method = [=](const TNode<JSReceiver> unused) {
|
||||
@ -261,7 +286,7 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) {
|
||||
JSAsyncFromSyncIterator::kNextOffset);
|
||||
};
|
||||
Generate_AsyncFromSyncIteratorMethod(
|
||||
context, iterator, value, get_method, UndefinedMethodHandler(),
|
||||
&args, context, iterator, value, get_method, UndefinedMethodHandler(),
|
||||
"[Async-from-Sync Iterator].prototype.next");
|
||||
}
|
||||
|
||||
@ -269,11 +294,16 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) {
|
||||
// Section #sec-%asyncfromsynciteratorprototype%.return
|
||||
TF_BUILTIN(AsyncFromSyncIteratorPrototypeReturn,
|
||||
AsyncFromSyncBuiltinsAssembler) {
|
||||
const TNode<Object> iterator = CAST(Parameter(Descriptor::kReceiver));
|
||||
const TNode<Object> value = CAST(Parameter(Descriptor::kValue));
|
||||
TNode<IntPtrT> argc = ChangeInt32ToIntPtr(
|
||||
UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)));
|
||||
CodeStubArguments args(this, argc);
|
||||
|
||||
const TNode<Object> iterator = args.GetReceiver();
|
||||
const TNode<Object> value = args.GetOptionalArgumentValue(kValueOrReasonArg);
|
||||
const TNode<Context> context = CAST(Parameter(Descriptor::kContext));
|
||||
|
||||
auto if_return_undefined = [=](const TNode<NativeContext> native_context,
|
||||
auto if_return_undefined = [=, &args](
|
||||
const TNode<NativeContext> native_context,
|
||||
const TNode<JSPromise> promise,
|
||||
Label* if_exception) {
|
||||
// If return is undefined, then
|
||||
@ -285,20 +315,24 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeReturn,
|
||||
// IfAbruptRejectPromise(nextDone, promiseCapability).
|
||||
// Return promiseCapability.[[Promise]].
|
||||
CallBuiltin(Builtins::kResolvePromise, context, promise, iter_result);
|
||||
Return(promise);
|
||||
args.PopAndReturn(promise);
|
||||
};
|
||||
|
||||
Generate_AsyncFromSyncIteratorMethod(
|
||||
context, iterator, value, factory()->return_string(), if_return_undefined,
|
||||
"[Async-from-Sync Iterator].prototype.return");
|
||||
&args, context, iterator, value, factory()->return_string(),
|
||||
if_return_undefined, "[Async-from-Sync Iterator].prototype.return");
|
||||
}
|
||||
|
||||
// https://tc39.github.io/proposal-async-iteration/
|
||||
// Section #sec-%asyncfromsynciteratorprototype%.throw
|
||||
TF_BUILTIN(AsyncFromSyncIteratorPrototypeThrow,
|
||||
AsyncFromSyncBuiltinsAssembler) {
|
||||
const TNode<Object> iterator = CAST(Parameter(Descriptor::kReceiver));
|
||||
const TNode<Object> reason = CAST(Parameter(Descriptor::kReason));
|
||||
TNode<IntPtrT> argc = ChangeInt32ToIntPtr(
|
||||
UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)));
|
||||
CodeStubArguments args(this, argc);
|
||||
|
||||
const TNode<Object> iterator = args.GetReceiver();
|
||||
const TNode<Object> reason = args.GetOptionalArgumentValue(kValueOrReasonArg);
|
||||
const TNode<Context> context = CAST(Parameter(Descriptor::kContext));
|
||||
|
||||
auto if_throw_undefined = [=](const TNode<NativeContext> native_context,
|
||||
@ -306,9 +340,9 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeThrow,
|
||||
Label* if_exception) { Goto(if_exception); };
|
||||
|
||||
Generate_AsyncFromSyncIteratorMethod(
|
||||
context, iterator, reason, factory()->throw_string(), if_throw_undefined,
|
||||
"[Async-from-Sync Iterator].prototype.throw", Label::kNonDeferred,
|
||||
reason);
|
||||
&args, context, iterator, reason, factory()->throw_string(),
|
||||
if_throw_undefined, "[Async-from-Sync Iterator].prototype.throw",
|
||||
Label::kNonDeferred, reason);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -877,11 +877,11 @@ namespace internal {
|
||||
/* %AsyncFromSyncIteratorPrototype% */ \
|
||||
/* See tc39.github.io/proposal-async-iteration/ */ \
|
||||
/* #sec-%asyncfromsynciteratorprototype%-object) */ \
|
||||
TFJ(AsyncFromSyncIteratorPrototypeNext, 1, kReceiver, kValue) \
|
||||
TFJ(AsyncFromSyncIteratorPrototypeNext, kDontAdaptArgumentsSentinel) \
|
||||
/* #sec-%asyncfromsynciteratorprototype%.throw */ \
|
||||
TFJ(AsyncFromSyncIteratorPrototypeThrow, 1, kReceiver, kReason) \
|
||||
TFJ(AsyncFromSyncIteratorPrototypeThrow, kDontAdaptArgumentsSentinel) \
|
||||
/* #sec-%asyncfromsynciteratorprototype%.return */ \
|
||||
TFJ(AsyncFromSyncIteratorPrototypeReturn, 1, kReceiver, kValue) \
|
||||
TFJ(AsyncFromSyncIteratorPrototypeReturn, kDontAdaptArgumentsSentinel) \
|
||||
/* #sec-async-iterator-value-unwrap-functions */ \
|
||||
TFJ(AsyncIteratorValueUnwrap, 1, kReceiver, kValue) \
|
||||
\
|
||||
|
@ -918,13 +918,14 @@ void Genesis::CreateAsyncIteratorMaps(Handle<JSFunction> empty) {
|
||||
Handle<JSObject> async_from_sync_iterator_prototype = factory()->NewJSObject(
|
||||
isolate()->object_function(), AllocationType::kOld);
|
||||
SimpleInstallFunction(isolate(), async_from_sync_iterator_prototype, "next",
|
||||
Builtins::kAsyncFromSyncIteratorPrototypeNext, 1, true);
|
||||
Builtins::kAsyncFromSyncIteratorPrototypeNext, 1,
|
||||
false);
|
||||
SimpleInstallFunction(isolate(), async_from_sync_iterator_prototype, "return",
|
||||
Builtins::kAsyncFromSyncIteratorPrototypeReturn, 1,
|
||||
true);
|
||||
false);
|
||||
SimpleInstallFunction(isolate(), async_from_sync_iterator_prototype, "throw",
|
||||
Builtins::kAsyncFromSyncIteratorPrototypeThrow, 1,
|
||||
true);
|
||||
false);
|
||||
|
||||
InstallToStringTag(isolate(), async_from_sync_iterator_prototype,
|
||||
"Async-from-Sync Iterator");
|
||||
|
@ -535,8 +535,6 @@
|
||||
'built-ins/RegExp/prototype/Symbol.replace/fn-invoke-args-empty-result': [FAIL],
|
||||
|
||||
# https://bugs.chromium.org/p/v8/issues/detail?id=10395
|
||||
'built-ins/AsyncFromSyncIteratorPrototype/next/absent-value-not-passed': [FAIL],
|
||||
'built-ins/AsyncFromSyncIteratorPrototype/return/absent-value-not-passed': [FAIL],
|
||||
'built-ins/AsyncFromSyncIteratorPrototype/return/return-null': [FAIL],
|
||||
'built-ins/AsyncFromSyncIteratorPrototype/throw/throw-null': [FAIL],
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user