!7228 NAPI Optimization - ResolveReject Defer

Merge pull request !7228 from yaoyuan/napi_defer
This commit is contained in:
openharmony_ci 2024-05-05 13:59:45 +00:00 committed by Gitee
commit 2d507b7009
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
5 changed files with 91 additions and 5 deletions

View File

@ -93,7 +93,9 @@ void MicroJobQueue::EnqueueJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueu
void MicroJobQueue::ExecutePendingJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueue)
{
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "MicroJobQueue::ExecutePendingJob");
if (thread->GetEcmaVM()->GetJSOptions().EnableMicroJobTrace()) {
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "MicroJobQueue::ExecutePendingJob");
}
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSMutableHandle<TaggedQueue> promiseQueue(thread, jobQueue->GetPromiseJobQueue());
JSMutableHandle<PendingJob> pendingJob(thread, JSTaggedValue::Undefined());

View File

@ -70,9 +70,9 @@ JSTaggedValue JSPromise::FulfillPromise(JSThread *thread, const JSHandle<JSPromi
// 3. Set the value of promise's [[PromiseResult]] internal slot to value.
promise->SetPromiseResult(thread, value);
// 4. Set the value of promise's [[PromiseFulfillReactions]] internal slot to undefined.
promise->SetPromiseFulfillReactions(thread, globalConst->GetHandledUndefined());
promise->SetPromiseFulfillReactions(thread, globalConst->GetHandledUndefined(), SKIP_BARRIER);
// 5. Set the value of promise's [[PromiseRejectReactions]] internal slot to undefined.
promise->SetPromiseRejectReactions(thread, globalConst->GetHandledUndefined());
promise->SetPromiseRejectReactions(thread, globalConst->GetHandledUndefined(), SKIP_BARRIER);
// 6. Set the value of promise's [[PromiseState]] internal slot to "fulfilled".
promise->SetPromiseState(PromiseState::FULFILLED);
// 7. Return TriggerPromiseReactions(reactions, reason).
@ -147,9 +147,9 @@ JSTaggedValue JSPromise::RejectPromise(JSThread *thread, const JSHandle<JSPromis
// 3. Set the value of promise's [[PromiseResult]] internal slot to reason.
promise->SetPromiseResult(thread, reason);
// 4. Set the value of promise's [[PromiseFulfillReactions]] internal slot to undefined.
promise->SetPromiseFulfillReactions(thread, globalConst->GetHandledUndefined());
promise->SetPromiseFulfillReactions(thread, globalConst->GetHandledUndefined(), SKIP_BARRIER);
// 5. Set the value of promise's [[PromiseRejectReactions]] internal slot to undefined.
promise->SetPromiseRejectReactions(thread, globalConst->GetHandledUndefined());
promise->SetPromiseRejectReactions(thread, globalConst->GetHandledUndefined(), SKIP_BARRIER);
// 6. Set the value of promise's [[PromiseState]] internal slot to "rejected".
promise->SetPromiseState(PromiseState::REJECTED);
// 7. When a promise is rejected without any handlers, it is called with its operation argument set to "reject".

View File

@ -1189,7 +1189,9 @@ public:
class ECMA_PUBLIC_API PromiseCapabilityRef : public ObjectRef {
public:
static Local<PromiseCapabilityRef> New(const EcmaVM *vm);
bool Resolve(const EcmaVM *vm, uintptr_t value);
bool Resolve(const EcmaVM *vm, Local<JSValueRef> value);
bool Reject(const EcmaVM *vm, uintptr_t reason);
bool Reject(const EcmaVM *vm, Local<JSValueRef> reason);
Local<PromiseRef> GetPromise(const EcmaVM *vm);
};

View File

@ -1266,6 +1266,30 @@ Local<PromiseRef> PromiseCapabilityRef::GetPromise(const EcmaVM *vm)
return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, capacity->GetPromise()));
}
bool PromiseCapabilityRef::Resolve(const EcmaVM *vm, uintptr_t value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
const GlobalEnvConstants *constants = thread->GlobalConstants();
JSHandle<JSTaggedValue> arg(value);
JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(capacity, FATAL);
JSHandle<JSTaggedValue> resolve(thread, capacity->GetResolve());
JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, resolve, undefined, undefined, 1);
RETURN_VALUE_IF_ABRUPT(thread, false);
info->SetCallArg(arg.GetTaggedValue());
JSFunction::Call(info);
RETURN_VALUE_IF_ABRUPT(thread, false);
thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
RETURN_VALUE_IF_ABRUPT(thread, false);
vm->GetHeap()->ClearKeptObjects();
return true;
}
bool PromiseCapabilityRef::Resolve(const EcmaVM *vm, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
@ -1290,6 +1314,31 @@ bool PromiseCapabilityRef::Resolve(const EcmaVM *vm, Local<JSValueRef> value)
return true;
}
bool PromiseCapabilityRef::Reject(const EcmaVM *vm, uintptr_t reason)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
const GlobalEnvConstants *constants = thread->GlobalConstants();
JSHandle<JSTaggedValue> arg(reason);
JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(capacity, FATAL);
JSHandle<JSTaggedValue> reject(thread, capacity->GetReject());
JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefined, undefined, 1);
RETURN_VALUE_IF_ABRUPT(thread, false);
info->SetCallArg(arg.GetTaggedValue());
JSFunction::Call(info);
RETURN_VALUE_IF_ABRUPT(thread, false);
thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
RETURN_VALUE_IF_ABRUPT(thread, false);
vm->GetHeap()->ClearKeptObjects();
return true;
}
bool PromiseCapabilityRef::Reject(const EcmaVM *vm, Local<JSValueRef> reason)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);

View File

@ -625,6 +625,23 @@ HWTEST_F_L0(JSNApiTests, PromiseCatch)
vm_->GetJSThread()->GetCurrentEcmaContext()->ExecutePromisePendingJob();
}
HWTEST_F_L0(JSNApiTests, PromiseCatchUintPtr)
{
LocalScope scope(vm_);
Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
Local<PromiseRef> promise = capability->GetPromise(vm_);
Local<FunctionRef> reject = FunctionRef::New(vm_, RejectCallback);
Local<PromiseRef> catchPromise = promise->Catch(vm_, reject);
ASSERT_TRUE(promise->IsPromise());
ASSERT_TRUE(catchPromise->IsPromise());
Local<StringRef> reason = StringRef::NewFromUtf8(vm_, "Reject");
ASSERT_TRUE(capability->Reject(vm_, reinterpret_cast<uintptr_t>(*reason)));
vm_->GetJSThread()->GetCurrentEcmaContext()->ExecutePromisePendingJob();
}
/*
* @tc.number: ffi_interface_api_013
* @tc.name: CheckResolve_New_Reject
@ -667,6 +684,22 @@ HWTEST_F_L0(JSNApiTests, PromiseThen)
vm_->GetJSThread()->GetCurrentEcmaContext()->ExecutePromisePendingJob();
}
HWTEST_F_L0(JSNApiTests, PromiseThenUintPtr)
{
LocalScope scope(vm_);
Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
Local<PromiseRef> promise = capability->GetPromise(vm_);
Local<FunctionRef> resolve = FunctionRef::New(vm_, ResolvedCallback);
Local<FunctionRef> reject = FunctionRef::New(vm_, RejectCallback);
Local<PromiseRef> thenPromise = promise->Then(vm_, resolve, reject);
ASSERT_TRUE(promise->IsPromise());
ASSERT_TRUE(thenPromise->IsPromise());
Local<StringRef> value = NumberRef::New(vm_, 300.3); // 300.3 : test case of input
ASSERT_TRUE(capability->Resolve(vm_, reinterpret_cast<uintptr_t>(*value)));
vm_->GetJSThread()->GetCurrentEcmaContext()->ExecutePromisePendingJob();
}
/**
* @tc.number: ffi_interface_api_014