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