14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/jobs/micro_job_queue.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/global_env.h" 194514f5e3Sopenharmony_ci#include "ecmascript/jobs/pending_job.h" 204514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value-inl.h" 214514f5e3Sopenharmony_ci#include "ecmascript/object_factory.h" 224514f5e3Sopenharmony_ci#include "ecmascript/tagged_queue.h" 234514f5e3Sopenharmony_ci 244514f5e3Sopenharmony_cinamespace panda::ecmascript::job { 254514f5e3Sopenharmony_ciuint32_t MicroJobQueue::GetPromiseQueueSize(JSThread *thread, JSHandle<MicroJobQueue> jobQueue) 264514f5e3Sopenharmony_ci{ 274514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 284514f5e3Sopenharmony_ci JSHandle<TaggedQueue> promiseQueue(thread, jobQueue->GetPromiseJobQueue()); 294514f5e3Sopenharmony_ci return promiseQueue->Size(); 304514f5e3Sopenharmony_ci} 314514f5e3Sopenharmony_ci 324514f5e3Sopenharmony_civoid MicroJobQueue::EnqueueJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueue, QueueType queueType, 334514f5e3Sopenharmony_ci const JSHandle<JSFunction> &job, const JSHandle<TaggedArray> &argv) 344514f5e3Sopenharmony_ci{ 354514f5e3Sopenharmony_ci // 1. Assert: Type(queueName) is String and its value is the name of a Job Queue recognized by this implementation. 364514f5e3Sopenharmony_ci // 2. Assert: job is the name of a Job. 374514f5e3Sopenharmony_ci // 3. Assert: arguments is a List that has the same number of elements as the number of parameters required by job. 384514f5e3Sopenharmony_ci // 4. Let callerContext be the running execution context. 394514f5e3Sopenharmony_ci // 5. Let callerRealm be callerContext’s Realm. 404514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 414514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 424514f5e3Sopenharmony_ci JSHandle<PendingJob> pendingJob(factory->NewPendingJob(job, argv)); 434514f5e3Sopenharmony_ci ENQUEUE_JOB_HITRACE(pendingJob, queueType); 444514f5e3Sopenharmony_ci ENQUEUE_JOB_TRACE(thread, pendingJob); 454514f5e3Sopenharmony_ci 464514f5e3Sopenharmony_ci if (queueType == QueueType::QUEUE_PROMISE) { 474514f5e3Sopenharmony_ci JSHandle<TaggedQueue> promiseQueue(thread, jobQueue->GetPromiseJobQueue()); 484514f5e3Sopenharmony_ci TaggedQueue *newPromiseQueue = TaggedQueue::Push(thread, promiseQueue, JSHandle<JSTaggedValue>(pendingJob)); 494514f5e3Sopenharmony_ci jobQueue->SetPromiseJobQueue(thread, JSTaggedValue(newPromiseQueue)); 504514f5e3Sopenharmony_ci LOG_ECMA(VERBOSE) << "EnqueueJob length: " << newPromiseQueue->Size(); 514514f5e3Sopenharmony_ci } else if (queueType == QueueType::QUEUE_SCRIPT) { 524514f5e3Sopenharmony_ci JSHandle<TaggedQueue> scriptQueue(thread, jobQueue->GetScriptJobQueue()); 534514f5e3Sopenharmony_ci TaggedQueue *newScriptQueue = TaggedQueue::Push(thread, scriptQueue, JSHandle<JSTaggedValue>(pendingJob)); 544514f5e3Sopenharmony_ci jobQueue->SetScriptJobQueue(thread, JSTaggedValue(newScriptQueue)); 554514f5e3Sopenharmony_ci } 564514f5e3Sopenharmony_ci} 574514f5e3Sopenharmony_ci 584514f5e3Sopenharmony_civoid MicroJobQueue::ExecutePendingJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueue) 594514f5e3Sopenharmony_ci{ 604514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 614514f5e3Sopenharmony_ci JSMutableHandle<TaggedQueue> promiseQueue(thread, jobQueue->GetPromiseJobQueue()); 624514f5e3Sopenharmony_ci JSMutableHandle<PendingJob> pendingJob(thread, JSTaggedValue::Undefined()); 634514f5e3Sopenharmony_ci while (!promiseQueue->Empty()) { 644514f5e3Sopenharmony_ci LOG_ECMA(VERBOSE) << "ExecutePendingJob length: " << promiseQueue->Size(); 654514f5e3Sopenharmony_ci pendingJob.Update(promiseQueue->Pop(thread)); 664514f5e3Sopenharmony_ci PendingJob::ExecutePendingJob(pendingJob, thread); 674514f5e3Sopenharmony_ci if (!thread->IsInConcurrentScope()) { 684514f5e3Sopenharmony_ci thread->SetTaskInfo(reinterpret_cast<uintptr_t>(nullptr)); 694514f5e3Sopenharmony_ci } 704514f5e3Sopenharmony_ci if (thread->HasPendingException()) { 714514f5e3Sopenharmony_ci return; 724514f5e3Sopenharmony_ci } 734514f5e3Sopenharmony_ci if (thread->HasTerminated()) { 744514f5e3Sopenharmony_ci JSHandle<TaggedQueue> emptyQueue(thread->GlobalConstants()->GetHandledEmptyTaggedQueue()); 754514f5e3Sopenharmony_ci jobQueue->SetPromiseJobQueue(thread, emptyQueue); 764514f5e3Sopenharmony_ci return; 774514f5e3Sopenharmony_ci } 784514f5e3Sopenharmony_ci promiseQueue.Update(jobQueue->GetPromiseJobQueue()); 794514f5e3Sopenharmony_ci } 804514f5e3Sopenharmony_ci 814514f5e3Sopenharmony_ci JSHandle<TaggedQueue> scriptQueue(thread, jobQueue->GetScriptJobQueue()); 824514f5e3Sopenharmony_ci while (!scriptQueue->Empty()) { 834514f5e3Sopenharmony_ci pendingJob.Update(scriptQueue->Pop(thread)); 844514f5e3Sopenharmony_ci PendingJob::ExecutePendingJob(pendingJob, thread); 854514f5e3Sopenharmony_ci if (thread->HasPendingException()) { 864514f5e3Sopenharmony_ci return; 874514f5e3Sopenharmony_ci } 884514f5e3Sopenharmony_ci } 894514f5e3Sopenharmony_ci} 904514f5e3Sopenharmony_ci} // namespace panda::ecmascript::job 91