162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Copyright 2017 the V8 project authors. All rights reserved. 262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// found in the LICENSE file. 462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/builtins/builtins-async.h" 662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/builtins/builtins-utils.h" 762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/builtins/builtins.h" 862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/code-factory.h" 962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/code-stub-assembler.h" 1062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/frames-inl.h" 1162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace v8 { 1362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace internal { 1462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace { 1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Describe fields of Context associated with the AsyncIterator unwrap closure. 1862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass ValueUnwrapContext { 1962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch public: 2062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch enum Fields { kDoneSlot = Context::MIN_CONTEXT_SLOTS, kLength }; 2162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}; 2262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler { 2462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch public: 2562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch explicit AsyncFromSyncBuiltinsAssembler(CodeAssemblerState* state) 2662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : AsyncBuiltinsAssembler(state) {} 2762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void ThrowIfNotAsyncFromSyncIterator(Node* const context, Node* const object, 2962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_exception, 3062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable* var_exception, 3162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* method_name); 3262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 3362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch typedef std::function<void(Node* const context, Node* const promise, 3462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_exception)> 3562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UndefinedMethodHandler; 3662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void Generate_AsyncFromSyncIteratorMethod( 3762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const context, Node* const iterator, Node* const sent_value, 3862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<Name> method_name, UndefinedMethodHandler&& if_method_undefined, 3962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* operation_name, 4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label::Type reject_label_type = Label::kDeferred, 4162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const initial_exception_value = nullptr); 4262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 4362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* AllocateAsyncIteratorValueUnwrapContext(Node* native_context, 4462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* done); 4562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 4662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Load "value" and "done" from an iterator result object. If an exception 4762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // is thrown at any point, jumps to te `if_exception` label with exception 4862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // stored in `var_exception`. 4962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // 5062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Returns a Pair of Nodes, whose first element is the value of the "value" 5162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // property, and whose second element is the value of the "done" property, 5262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // converted to a Boolean if needed. 5362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch std::pair<Node*, Node*> LoadIteratorResult(Node* const context, 5462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const native_context, 5562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const iter_result, 5662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_exception, 5762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable* var_exception); 5862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 5962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* CreateUnwrapClosure(Node* const native_context, Node* const done); 6062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}; 6162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 6262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid AsyncFromSyncBuiltinsAssembler::ThrowIfNotAsyncFromSyncIterator( 6362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const context, Node* const object, Label* if_exception, 6462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable* var_exception, const char* method_name) { 6562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label if_receiverisincompatible(this, Label::kDeferred), done(this); 6662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 6762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(TaggedIsSmi(object), &if_receiverisincompatible); 6862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(HasInstanceType(object, JS_ASYNC_FROM_SYNC_ITERATOR_TYPE), &done, 6962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_receiverisincompatible); 7062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 7162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_receiverisincompatible); 7262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 7362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // If Type(O) is not Object, or if O does not have a [[SyncIterator]] 7462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // internal slot, then 7562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 7662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Let badIteratorError be a new TypeError exception. 7762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const error = 7862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MakeTypeError(MessageTemplate::kIncompatibleMethodReceiver, context, 7962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CStringConstant(method_name), object); 8062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 8162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Perform ! Call(promiseCapability.[[Reject]], undefined, 8262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // « badIteratorError »). 8362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_exception->Bind(error); 8462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(if_exception); 8562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 8662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 8762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&done); 8862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 8962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 9062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod( 9162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const context, Node* const iterator, Node* const sent_value, 9262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<Name> method_name, UndefinedMethodHandler&& if_method_undefined, 9362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const char* operation_name, Label::Type reject_label_type, 9462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const initial_exception_value) { 9562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const native_context = LoadNativeContext(context); 9662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const promise = AllocateAndInitJSPromise(context); 9762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 9862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_exception(this, MachineRepresentation::kTagged, 9962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch initial_exception_value == nullptr 10062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ? UndefinedConstant() 10162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : initial_exception_value); 10262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label reject_promise(this, reject_label_type); 10362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 10462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ThrowIfNotAsyncFromSyncIterator(context, iterator, &reject_promise, 10562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &var_exception, operation_name); 10662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 10762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const sync_iterator = 10862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadObjectField(iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset); 10962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 11062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const method = GetProperty(context, sync_iterator, method_name); 11162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 11262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (if_method_undefined) { 11362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label if_isnotundefined(this); 11462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 11562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsUndefined(method), &if_isnotundefined); 11662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if_method_undefined(native_context, promise, &reject_promise); 11762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 11862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_isnotundefined); 11962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 12062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 12162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const iter_result = CallJS(CodeFactory::Call(isolate()), context, 12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch method, sync_iterator, sent_value); 12362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfException(iter_result, &reject_promise, &var_exception); 12462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 12562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* value; 12662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* done; 12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch std::tie(value, done) = LoadIteratorResult( 12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch context, native_context, iter_result, &reject_promise, &var_exception); 12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const wrapper = AllocateAndInitJSPromise(context); 13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Perform ! Call(valueWrapperCapability.[[Resolve]], undefined, « 13262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // throwValue »). 13362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch InternalResolvePromise(context, wrapper, value); 13462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 13562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Let onFulfilled be a new built-in function object as defined in 13662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Async Iterator Value Unwrap Functions. 13762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Set onFulfilled.[[Done]] to throwDone. 13862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const on_fulfilled = CreateUnwrapClosure(native_context, done); 13962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 14062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Perform ! PerformPromiseThen(valueWrapperCapability.[[Promise]], 14162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // onFulfilled, undefined, promiseCapability). 14262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const undefined = UndefinedConstant(); 14362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch InternalPerformPromiseThen(context, wrapper, on_fulfilled, undefined, promise, 14462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch undefined, undefined); 14562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Return(promise); 14662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 14762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&reject_promise); 14862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 14962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const exception = var_exception.value(); 15062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch InternalPromiseReject(context, promise, exception, TrueConstant()); 15162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 15262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Return(promise); 15362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 15462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 15562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 15662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstd::pair<Node*, Node*> AsyncFromSyncBuiltinsAssembler::LoadIteratorResult( 15762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const context, Node* const native_context, Node* const iter_result, 15862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_exception, Variable* var_exception) { 15962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label if_fastpath(this), if_slowpath(this), merge(this), to_boolean(this), 16062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch done(this), if_notanobject(this, Label::kDeferred); 16162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(TaggedIsSmi(iter_result), &if_notanobject); 16262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 16362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const iter_result_map = LoadMap(iter_result); 16462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfNot(IsJSReceiverMap(iter_result_map), &if_notanobject); 16562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 16662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const fast_iter_result_map = 16762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX); 16862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 16962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_value(this, MachineRepresentation::kTagged); 17062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Variable var_done(this, MachineRepresentation::kTagged); 17162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(WordEqual(iter_result_map, fast_iter_result_map), &if_fastpath, 17262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &if_slowpath); 17362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 17462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_fastpath); 17562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 17662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_value.Bind( 17762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LoadObjectField(iter_result, JSIteratorResult::kValueOffset)); 17862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_done.Bind(LoadObjectField(iter_result, JSIteratorResult::kDoneOffset)); 17962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&merge); 18062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 18162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 18262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_slowpath); 18362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 18462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Let nextValue be IteratorValue(nextResult). 18562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // IfAbruptRejectPromise(nextValue, promiseCapability). 18662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const value = 18762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GetProperty(context, iter_result, factory()->value_string()); 18862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfException(value, if_exception, var_exception); 18962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 19062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Let nextDone be IteratorComplete(nextResult). 19162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // IfAbruptRejectPromise(nextDone, promiseCapability). 19262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const done = 19362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GetProperty(context, iter_result, factory()->done_string()); 19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIfException(done, if_exception, var_exception); 19562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 19662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_value.Bind(value); 19762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_done.Bind(done); 19862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&merge); 19962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 20062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 20162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&if_notanobject); 20262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 20362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Sync iterator result is not an object --- Produce a TypeError and jump 20462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // to the `if_exception` path. 20562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const error = MakeTypeError( 20662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MessageTemplate::kIteratorResultNotAnObject, context, iter_result); 20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_exception->Bind(error); 20862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(if_exception); 20962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 21062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 21162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&merge); 21262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Ensure `iterResult.done` is a Boolean. 21362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(TaggedIsSmi(var_done.value()), &to_boolean); 21462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Branch(IsBoolean(var_done.value()), &done, &to_boolean); 21562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 21662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&to_boolean); 21762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 21862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const result = 21962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallStub(CodeFactory::ToBoolean(isolate()), context, var_done.value()); 22062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch var_done.Bind(result); 22162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(&done); 22262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 22362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 22462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(&done); 22562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return std::make_pair(var_value.value(), var_done.value()); 22662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 22762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 22862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* AsyncFromSyncBuiltinsAssembler::CreateUnwrapClosure(Node* native_context, 22962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* done) { 23062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const map = LoadContextElement( 23162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); 23262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const on_fulfilled_shared = LoadContextElement( 23362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch native_context, Context::ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN); 23462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, 23562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HasInstanceType(on_fulfilled_shared, SHARED_FUNCTION_INFO_TYPE)); 23662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const closure_context = 23762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AllocateAsyncIteratorValueUnwrapContext(native_context, done); 23862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return AllocateFunctionWithMapAndContext(map, on_fulfilled_shared, 23962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch closure_context); 24062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 24162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 24262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* AsyncFromSyncBuiltinsAssembler::AllocateAsyncIteratorValueUnwrapContext( 24362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* native_context, Node* done) { 24462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, IsNativeContext(native_context)); 24562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, IsBoolean(done)); 24662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 24762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const context = 24862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CreatePromiseContext(native_context, ValueUnwrapContext::kLength); 24962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch StoreContextElementNoWriteBarrier(context, ValueUnwrapContext::kDoneSlot, 25062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch done); 25162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return context; 25262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 25362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} // namespace 25462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 25562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// https://tc39.github.io/proposal-async-iteration/ 25662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Section #sec-%asyncfromsynciteratorprototype%.next 25762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) { 25862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const iterator = Parameter(0); 25962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const value = Parameter(1); 26062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const context = Parameter(4); 26162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 26262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Generate_AsyncFromSyncIteratorMethod( 26362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch context, iterator, value, factory()->next_string(), 26462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UndefinedMethodHandler(), "[Async-from-Sync Iterator].prototype.next"); 26562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 26662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 26762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// https://tc39.github.io/proposal-async-iteration/ 26862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Section #sec-%asyncfromsynciteratorprototype%.return 26962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(AsyncFromSyncIteratorPrototypeReturn, 27062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AsyncFromSyncBuiltinsAssembler) { 27162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const iterator = Parameter(0); 27262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const value = Parameter(1); 27362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const context = Parameter(4); 27462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 27562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_return_undefined = [=](Node* const native_context, 27662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const promise, Label* if_exception) { 27762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // If return is undefined, then 27862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Let iterResult be ! CreateIterResultObject(value, true) 27962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const iter_result = 28062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallStub(CodeFactory::CreateIterResultObject(isolate()), context, value, 28162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TrueConstant()); 28262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 28362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Perform ! Call(promiseCapability.[[Resolve]], undefined, « iterResult »). 28462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // IfAbruptRejectPromise(nextDone, promiseCapability). 28562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Return promiseCapability.[[Promise]]. 28662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch PromiseFulfill(context, promise, iter_result, v8::Promise::kFulfilled); 28762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Return(promise); 28862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }; 28962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 29062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Generate_AsyncFromSyncIteratorMethod( 29162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch context, iterator, value, factory()->return_string(), if_return_undefined, 29262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "[Async-from-Sync Iterator].prototype.return"); 29362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 29462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 29562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// https://tc39.github.io/proposal-async-iteration/ 29662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Section #sec-%asyncfromsynciteratorprototype%.throw 29762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(AsyncFromSyncIteratorPrototypeThrow, 29862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AsyncFromSyncBuiltinsAssembler) { 29962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const iterator = Parameter(0); 30062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const reason = Parameter(1); 30162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const context = Parameter(4); 30262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 30362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto if_throw_undefined = [=](Node* const native_context, Node* const promise, 30462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label* if_exception) { Goto(if_exception); }; 30562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 30662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Generate_AsyncFromSyncIteratorMethod( 30762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch context, iterator, reason, factory()->throw_string(), if_throw_undefined, 30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "[Async-from-Sync Iterator].prototype.throw", Label::kNonDeferred, 30962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch reason); 31062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 31162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 31262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(AsyncIteratorValueUnwrap, AsyncFromSyncBuiltinsAssembler) { 31362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const value = Parameter(1); 31462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const context = Parameter(4); 31562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 31662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const done = LoadContextElement(context, ValueUnwrapContext::kDoneSlot); 31762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CSA_ASSERT(this, IsBoolean(done)); 31862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 31962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Node* const unwrapped_value = CallStub( 32062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeFactory::CreateIterResultObject(isolate()), context, value, done); 32162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 32262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Return(unwrapped_value); 32362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 32462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 32562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} // namespace internal 32662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} // namespace v8 327