From eae27fa0c7a6fa12804bb1c6a5972fd2e0556643 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 19 Nov 2024 17:44:16 +0300 Subject: [PATCH 1/2] Add VSyncAwait missings --- .../src/generated/arkoala_api_generated.h | 18 +++++--- .../native/src/generated/bridge_custom.cc | 42 +++++++++++++++---- .../native/src/generated/dummy_impl.cc | 18 +++++++- arkoala/framework/src/Application.ts | 21 ++-------- .../framework/src/generated/NativeModule.ts | 9 ++-- .../src/generated/NativeModuleEmpty.ts | 8 +++- interop/src/cpp/common-interop.cc | 21 +++++----- 7 files changed, 86 insertions(+), 51 deletions(-) diff --git a/arkoala/framework/native/src/generated/arkoala_api_generated.h b/arkoala/framework/native/src/generated/arkoala_api_generated.h index 737b21d42..45c05713c 100644 --- a/arkoala/framework/native/src/generated/arkoala_api_generated.h +++ b/arkoala/framework/native/src/generated/arkoala_api_generated.h @@ -27,7 +27,7 @@ #define GENERATED_ARKUI_NODE_API_VERSION GENERATED_ARKUI_FULL_API_VERSION #define GENERATED_ARKUI_BASIC_NODE_API_VERSION 1 -#define GENERATED_ARKUI_EXTENDED_NODE_API_VERSION 7 +#define GENERATED_ARKUI_EXTENDED_NODE_API_VERSION 8 #define GENERATED_ARKUI_NODE_GRAPHICS_API_VERSION 5 #define GENERATED_ARKUI_NODE_MODIFIERS_API_VERSION 6 #define GENERIC_SERVICE_API_VERSION 1 @@ -86,6 +86,13 @@ struct _Ark_Node; typedef struct _Ark_Node* Ark_NodeHandle; struct _Ark_Canvas; typedef struct _Ark_Canvas* Ark_CanvasHandle; +typedef struct Ark_Deferred { + void* handler; + void* context; + void (*resolve)(struct Ark_Deferred* thiz, uint8_t* data, int32_t length); + void (*reject)(struct Ark_Deferred* thiz, const char* message); + void (*release)(struct Ark_Deferred* thiz); +} Ark_Deferred; enum Ark_APINodeFlags { GENERATED_CUSTOM_NONE = 0, @@ -20396,6 +20403,8 @@ typedef struct GenericServiceAPI { void (*setLogger)(const ServiceLogger* logger); } GenericServiceAPI; +typedef void (*Ark_VsyncCallback)(); + typedef struct GENERATED_ArkUIExtendedNodeAPI { Ark_Int32 version; @@ -20459,11 +20468,8 @@ typedef struct GENERATED_ArkUIExtendedNodeAPI { /// Vsync support Ark_PipelineContext (*getPipelineContext)(Ark_NodeHandle node); - void (*setVsyncCallback)(Ark_VMContext vmContext, - Ark_PipelineContext pipelineContext, - Ark_Int32 callbackId); - void (*unblockVsyncWait)(Ark_VMContext vmContext, - Ark_PipelineContext pipelineContext); + void (*setVsyncCallback)(Ark_PipelineContext pipelineContext, + Ark_VsyncCallback callback); void (*setChildTotalCount)(Ark_NodeHandle node, Ark_Int32 totalCount); diff --git a/arkoala/framework/native/src/generated/bridge_custom.cc b/arkoala/framework/native/src/generated/bridge_custom.cc index affe6569d..e33d421c8 100644 --- a/arkoala/framework/native/src/generated/bridge_custom.cc +++ b/arkoala/framework/native/src/generated/bridge_custom.cc @@ -343,21 +343,45 @@ void impl_SetLazyItemIndexer(KVMContext vmContext, Ark_NativePointer nodePtr, Ar } KOALA_INTEROP_CTX_V2(SetLazyItemIndexer, Ark_NativePointer, Ark_Int32) -void impl_SetVsyncCallback(KVMContext vmContext, Ark_NativePointer pipelineContext, Ark_Int32 callbackId) +// TODO: map if multiple pipeline contexts. +static KVMDeferred* currentVsyncDeferred = nullptr; + +void vsyncCallback() { + if (currentVsyncDeferred) { + currentVsyncDeferred->resolve(currentVsyncDeferred, nullptr, 0); + currentVsyncDeferred = nullptr; + } +} + +void impl_SetVsyncCallback(Ark_NativePointer pipelineContext) { - Ark_VMContext vmContextCast = (Ark_VMContext) vmContext; Ark_PipelineContext pipelineContextCast = (Ark_PipelineContext) pipelineContext; - GetArkUIExtendedNodeAPI()->setVsyncCallback(vmContextCast, pipelineContextCast, callbackId); + GetArkUIExtendedNodeAPI()->setVsyncCallback(pipelineContextCast, vsyncCallback); } -KOALA_INTEROP_CTX_V2(SetVsyncCallback, Ark_NativePointer, Ark_Int32) +KOALA_INTEROP_V1(SetVsyncCallback, Ark_NativePointer) -void impl_UnblockVsyncWait(KVMContext vmContext, Ark_NativePointer pipelineContext) +KVMObjectHandle impl_VSyncAwait(KVMContext vmContext, Ark_NativePointer pipelineContext) { - Ark_VMContext vmContextCast = (Ark_VMContext) vmContext; - Ark_PipelineContext pipelineContextCast = (Ark_PipelineContext) pipelineContext; - GetArkUIExtendedNodeAPI()->unblockVsyncWait(vmContextCast, pipelineContextCast); + Ark_PipelineContext pipelineContextCast = (Ark_PipelineContext)pipelineContext; + KVMObjectHandle result = nullptr; + KVMDeferred* deferred = CreateDeferred(vmContext, &result); + if (currentVsyncDeferred) { + LOGE("%s", "Multiple unresolved vsync deferred"); + currentVsyncDeferred->reject(currentVsyncDeferred, "Wrong"); + } + currentVsyncDeferred = deferred; + return result; +} +KOALA_INTEROP_CTX_1(VSyncAwait, KVMObjectHandle, Ark_NativePointer) + +void impl_UnblockVsyncWait() +{ + if (currentVsyncDeferred) { + currentVsyncDeferred->resolve(currentVsyncDeferred, nullptr, 0); + currentVsyncDeferred = nullptr; + } } -KOALA_INTEROP_CTX_V1(UnblockVsyncWait, Ark_NativePointer) +KOALA_INTEROP_V0(UnblockVsyncWait) void impl_SetCustomCallback(KVMContext vmContext, Ark_NativePointer nodePtr, Ark_Int32 updaterId) { diff --git a/arkoala/framework/native/src/generated/dummy_impl.cc b/arkoala/framework/native/src/generated/dummy_impl.cc index a9977afed..eb8287b5d 100644 --- a/arkoala/framework/native/src/generated/dummy_impl.cc +++ b/arkoala/framework/native/src/generated/dummy_impl.cc @@ -769,8 +769,22 @@ void SetLazyItemIndexer(Ark_VMContext vmContext, Ark_NodeHandle nodePtr, Ark_Int Ark_PipelineContext GetPipelineContext(Ark_NodeHandle node) { return nullptr; } -void SetVsyncCallback(Ark_VMContext vmContext, Ark_PipelineContext pipelineContext, Ark_Int32 callbackId) {} -void UnblockVsyncWait(Ark_VMContext vmContext, Ark_PipelineContext pipelineContext) {} +Ark_Deferred* currentVsyncWait = nullptr; +void SetVsyncCallback(Ark_PipelineContext pipelineContext, Ark_Deferred* deferred) { + auto delayed_call = std::async(std::launch::async, [deferred] { + currentVsyncWait = deferred; + std::this_thread::sleep_for(1000ms); + if (currentVsyncWait) + deferred->resolve(currentVsyncWait, nullptr, 0); + currentVsyncWait = nullptr; + }); +} +void UnblockVsyncWait(Ark_VMContext vmContext, Ark_PipelineContext pipelineContext) { + if (currentVsyncWait) { + currentVsyncWait->reject(currentVsyncWait, "Reject vsync"); + currentVsyncWait = nullptr; + } +} void SetChildTotalCount(Ark_NodeHandle node, Ark_Int32 totalCount) {} void ShowCrash(Ark_CharPtr message) {} } diff --git a/arkoala/framework/src/Application.ts b/arkoala/framework/src/Application.ts index a086d473d..80fbd4d11 100644 --- a/arkoala/framework/src/Application.ts +++ b/arkoala/framework/src/Application.ts @@ -18,9 +18,8 @@ import { nativeModule } from "./generated/NativeModule" import { checkEvents } from "./Events" import { ArkoalaHost, ArkoalaControl, WaitFramesEvent, UIElement } from "./Declarations" import { ArkoalaControlImpl } from "./ArkoalaControl" -import { Access, withInt32Array, KInt32ArrayPtr, withString, KPointer, wrapCallback } from "@koalaui/interop" +import { withString } from "@koalaui/interop" import { PeerNode } from "./PeerNode" -import { PeerEvent, SinglePointerPeerEvent, TextInputEvent } from "./PeerEvents" import { int32 } from "@koalaui/common" import { ArkUINodeId } from "./ArkUINodeType" import { initInteropModule } from "./generated/NativeModule" @@ -178,12 +177,13 @@ async function eventLoopRun( } const pipelineContext = getNativePipelineContext(root!.value as PeerNode) - const waitVsyncFunc = host?.waitForVSync ?? (() => waitForVSync(pipelineContext)) + nativeModule()._SetVsyncCallback(pipelineContext) + const waitVsyncFunc = (() => nativeModule()._VSyncAwait(pipelineContext)) let unlocker = setInterval(() => { // TODO: uncomment this code to enable Koala animations. // timer.value = Date.now() if (GlobalStateManager.instance.isUpdateNeeded()) - nativeModule()._UnblockVsyncWait(pipelineContext) + nativeModule()._UnblockVsyncWait() }, 32) let exitApp = false @@ -307,19 +307,6 @@ function drawCurrentCrash(crash: Object) { withString(msg, (msgPtr) => nativeModule()._ShowCrash(msgPtr ?? "unknown error message")) } -function waitForVSync(pipelineContext: KPointer): Promise { - return new Promise((resolve, reject) => { - nativeModule()._SetVsyncCallback(pipelineContext, wrapCallback((args1: Uint8Array, length: int32) => { - const args = new Int32Array(args1.buffer) - if (args[0] != 0) - resolve() - else - reject(new Error("vsync failed")) - return 0 - })) - }) -} - function dumpTree(node: IncrementalNode, indent: number = 0) { const indentToString = (indent: number) => { let str = "" diff --git a/arkoala/framework/src/generated/NativeModule.ts b/arkoala/framework/src/generated/NativeModule.ts index 0d23a3c53..3e6ab3515 100644 --- a/arkoala/framework/src/generated/NativeModule.ts +++ b/arkoala/framework/src/generated/NativeModule.ts @@ -150,10 +150,11 @@ export interface NodeOps { _IndexerChecker(ptr0: KPointer): int32 _SetRangeUpdater(ptr0: KPointer, arg: int32): void _SetLazyItemIndexer(ptr0: KPointer, arg: int32): void - _GetPipelineContext(ptr0: KPointer): KPointer - _SetVsyncCallback(ptr0: KPointer, arg: int32): void - _UnblockVsyncWait(ptr0: KPointer): void - _SetChildTotalCount(ptr0: KPointer, arg: int32): void + _GetPipelineContext(ptr0: KPointer): KPointer + _SetVsyncCallback(ptr0: KPointer): void + _VSyncAwait(ptr0: KPointer): Promise + _UnblockVsyncWait(): void + _SetChildTotalCount(ptr0: KPointer, arg: int32): void _ShowCrash(message: string): void _CheckArkoalaGeneratedEvents(result: Uint8Array, size: int32): int32 _EmulateClickEvent(nodeId: int32, x: number, y: number): void diff --git a/arkoala/framework/src/generated/NativeModuleEmpty.ts b/arkoala/framework/src/generated/NativeModuleEmpty.ts index 71d617048..0797b8ed6 100644 --- a/arkoala/framework/src/generated/NativeModuleEmpty.ts +++ b/arkoala/framework/src/generated/NativeModuleEmpty.ts @@ -208,10 +208,14 @@ export class NativeModuleEmptyIntegrated implements NativeModuleIntegrated { console.log("_GetPipelineContext") return -1 } - _SetVsyncCallback(ptr0: KPointer, arg: int32): void { + _SetVsyncCallback(ptr0: KPointer): void { console.log("_SetVsyncCallback") } - _UnblockVsyncWait(ptr0: KPointer): void { + _VSyncAwait(ptr0: KPointer): Promise { + console.log("_VSyncAwait") + return Promise.resolve() + } + _UnblockVsyncWait(): void { console.log("_UnblockVsyncWait") } _SetChildTotalCount(ptr0: KPointer, arg: int32): void { diff --git a/interop/src/cpp/common-interop.cc b/interop/src/cpp/common-interop.cc index bb9978650..d020c1caf 100644 --- a/interop/src/cpp/common-interop.cc +++ b/interop/src/cpp/common-interop.cc @@ -304,13 +304,15 @@ int32_t callCallback(KVMContext context, int32_t methodId, uint8_t* argsData, in void resolveDeferred(KVMDeferred* deferred, uint8_t* argsData, int32_t argsLength) { #ifdef KOALA_NAPI - napi_call_threadsafe_function((napi_threadsafe_function)deferred->handler, deferred, napi_tsfn_nonblocking); + napi_acquire_threadsafe_function((napi_threadsafe_function)deferred->handler); + auto status = napi_call_threadsafe_function((napi_threadsafe_function)deferred->handler, deferred, napi_tsfn_nonblocking); + if (status != napi_ok) LOGE("cannot call thread-safe function; status=%d", status); + napi_release_threadsafe_function((napi_threadsafe_function)deferred->handler, napi_tsfn_release); #endif } void rejectDeferred(KVMDeferred* deferred, const char* message) { #ifdef KOALA_NAPI - // TODO: implement me! napi_release_threadsafe_function((napi_threadsafe_function)deferred->handler, napi_tsfn_abort); deferred->release(deferred); #endif @@ -318,11 +320,10 @@ void rejectDeferred(KVMDeferred* deferred, const char* message) { #ifdef KOALA_NAPI void resolveDeferredImpl(napi_env env, napi_value js_callback, KVMDeferred* deferred, void* data) { - napi_status status; - napi_value undefined; - status = napi_get_undefined(env, &undefined); - napi_resolve_deferred(env, (napi_deferred)deferred->context, undefined); - napi_release_threadsafe_function((napi_threadsafe_function)deferred->handler, napi_tsfn_abort); + napi_value undefined = nullptr; + napi_get_undefined(env, &undefined); + auto status = napi_resolve_deferred(env, (napi_deferred)deferred->context, undefined); + if (status != napi_ok) LOGE("cannot resolve deferred; status=%d", status); deferred->release(deferred); } #endif @@ -336,7 +337,6 @@ KVMDeferred* CreateDeferred(KVMContext vmContext, KVMObjectHandle* promiseHandle deferred->release = releaseDeferred; deferred->resolve = resolveDeferred; deferred->reject = rejectDeferred; - KVMObjectHandle result = nullptr; #ifdef KOALA_NAPI // TODO: move to interop! napi_env env = (napi_env)vmContext; @@ -345,7 +345,7 @@ KVMDeferred* CreateDeferred(KVMContext vmContext, KVMObjectHandle* promiseHandle napi_value resourceName; napi_create_string_utf8(env, "Async", 5, &resourceName); auto status = napi_create_promise(env, (napi_deferred*)&deferred->context, &promise); - if (status != napi_ok) fprintf(stderr, "cannot make a promise; %d\n", status); + if (status != napi_ok) LOGE("cannot make a promise; status=%d", status); status = napi_create_threadsafe_function(env, nullptr, nullptr, @@ -357,8 +357,7 @@ KVMDeferred* CreateDeferred(KVMContext vmContext, KVMObjectHandle* promiseHandle deferred, (napi_threadsafe_function_call_js)resolveDeferredImpl, (napi_threadsafe_function*)&deferred->handler); - if (status != napi_ok) fprintf(stderr, "cannot make threadsafe function; %d\n", status); - napi_acquire_threadsafe_function((napi_threadsafe_function)deferred->handler); + if (status != napi_ok) LOGE("cannot make threadsafe function; status=%d", status); *promiseHandle = (KVMObjectHandle)promise; #endif return deferred; -- Gitee From b379221b377adb3826c4b8e9d09a8aadf8496d05 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 20 Nov 2024 20:32:01 +0300 Subject: [PATCH 2/2] Add @memo to CustomComponent in index-full.d.ts --- arkoala/arkui/types/index-full.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arkoala/arkui/types/index-full.d.ts b/arkoala/arkui/types/index-full.d.ts index 8a4cab50c..917024816 100644 --- a/arkoala/arkui/types/index-full.d.ts +++ b/arkoala/arkui/types/index-full.d.ts @@ -1865,6 +1865,7 @@ declare type Blender<> = any; declare type ComponentContent<> = any; declare type Theme<> = any; declare class CustomComponent extends CommonAttribute { + /** @memo */ build(): void; aboutToAppear?(): void; aboutToDisappear?(): void; @@ -1880,6 +1881,7 @@ declare class CustomComponent extends CommonAttribute { onFormRecycle?(): string; onFormRecover?(statusData: string): void; onBackPress?(): boolean; + /** @memo */ pageTransition?(): void; getUIContext(): UIContext; getUniqueId(): number; -- Gitee