/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ecmascript/js_async_from_sync_iterator.h" #include "ecmascript/base/builtins_base.h" #include "ecmascript/builtins/builtins_promise.h" #include "ecmascript/builtins/builtins_promise_handler.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/global_env.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/js_iterator.h" #include "ecmascript/js_promise.h" #include "ecmascript/js_function.h" #include "ecmascript/object_factory.h" #include "libpandabase/macros.h" namespace panda::ecmascript { JSHandle JSAsyncFromSyncIterator::CreateAsyncFromSyncIterator(JSThread *thread, JSHandle &syncIteratorRecord) { // 1.Let asyncIterator be ! OrdinaryObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIteratorRecord]] »). JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle IterFunc(env->GetAsyncFromSyncIterator()); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle asyncIterator(factory->NewJSObjectByConstructor(IterFunc)); // 2.Set asyncIterator.[[SyncIteratorRecord]] to syncIteratorRecord. asyncIterator->SetSyncIteratorRecord(thread, syncIteratorRecord); // 3.Let nextMethod be ! Get(asyncIterator, "next"). JSHandle nextStr = thread->GlobalConstants()->GetHandledNextString(); JSHandle tmpAsyncIterator(thread, asyncIterator.GetTaggedValue()); JSHandle nextMethod = JSTaggedValue::GetProperty(thread, tmpAsyncIterator, nextStr).GetValue(); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); // 4.Let iteratorRecord be the Record {[[Iterator]]: asyncIterator, [[NextMethod]]: nextMethod, [[Done]]: false}. JSHandle iteratorRecord = factory->NewAsyncIteratorRecord(tmpAsyncIterator, nextMethod, false); return JSHandle(thread, iteratorRecord->GetIterator()); } JSTaggedValue JSAsyncFromSyncIterator::AsyncFromSyncIteratorContinuation(JSThread *thread, JSHandle &result, JSHandle &promiseCapability) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); // 1.Let done be IteratorComplete(result). bool done = JSIterator::IteratorComplete(thread, result); // 2.IfAbruptRejectPromise(done, promiseCapability). JSHandle tmpDone(thread, JSTaggedValue(done)); RETURN_REJECT_PROMISE_IF_ABRUPT(thread, tmpDone, promiseCapability); // 3.Let value be IteratorValue(result). JSHandle value = JSIterator::IteratorValue(thread, result); // 4.IfAbruptRejectPromise(value, promiseCapability). RETURN_REJECT_PROMISE_IF_ABRUPT(thread, value, promiseCapability); // 5.Let valueWrapper be PromiseResolve(%Promise%, value). // 6.IfAbruptRejectPromise(valueWrapper, promiseCapability). // 7.Let steps be the algorithm steps defined in Async-from-Sync Iterator Value Unwrap Functions. // 8.Let length be the number of non-optional parameters of the function definition // in Async-from-Sync Iterator Value Unwrap Functions. JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle valueWrapper = builtins::BuiltinsPromiseHandler::PromiseResolve(thread, JSHandle::Cast(env->GetPromiseFunction()), value); RETURN_REJECT_PROMISE_IF_ABRUPT(thread, valueWrapper, promiseCapability); JSHandle promise = JSHandle::Cast(valueWrapper); // 9.Let onFulfilled be ! CreateBuiltinFunction(steps, length, "", « [[Done]] »). JSHandle onFulfilled = factory->NewJSAsyncFromSyncIterUnwarpFunction(); // 10.Set onFulfilled.[[Done]] to done. onFulfilled->SetDone(thread, JSTaggedValue(done)); // 11.Perform ! PerformPromiseThen(valueWrapper, onFulfilled, undefined, promiseCapability). JSHandle onFulRejected(thread, JSTaggedValue::Undefined()); builtins::BuiltinsPromise::PerformPromiseThen(thread, JSHandle::Cast(promise), JSHandle::Cast(onFulfilled), onFulRejected, promiseCapability); // 12.Return promiseCapability.[[Promise]]. return promiseCapability->GetPromise(); } JSTaggedValue JSAsyncFromSyncIterator::AsyncFromSyncIterUnwarpFunction(EcmaRuntimeCallInfo *argv) { // 1. Let F be the active function object. JSThread *thread = argv->GetThread(); JSHandle unwarpFunction = JSHandle::Cast((base::BuiltinsBase::GetConstructor(argv))); // 2.Return ! CreateIterResultObject(value, F.[[Done]]). JSHandle value = base::BuiltinsBase::GetCallArg(argv, 0); bool done = unwarpFunction->GetDone().ToBoolean(); return JSIterator::CreateIterResultObject(thread, value, done).GetTaggedValue(); } } // namespace panda::ecmascript