// Copyright 2026 The Lynx Authors. All rights reserved. // Licensed under the Apache License Version 2.0 that can be found in the // LICENSE file in the root directory of this source tree. import { onFunctionCall } from './return-value.js'; import { isSdkVersionGt } from '../../utils.js'; import { WorkletEvents } from '../../worklet-runtime/bindings/events.js'; import type { RunWorkletCtxData } from '../../worklet-runtime/bindings/events.js'; import type { Worklet } from '../../worklet-runtime/bindings/types.js'; import { registerBackgroundFunctionCtx } from '../background-function/run-on-background.js'; import { isMainThreadFunction } from '../main-thread-function.js'; import { isMtsEnabled } from '../mts-capability.js'; import { dispatchReloadScopedEvent } from '../reload-scoped-event.js'; import { isRuntimeDestroyed } from '../runtime-destroy.js'; interface RunOnMainThreadOptions { shouldDispatchRunOnMainThreadDirectly: () => boolean; } export type RunOnMainThread = R>(fn: Fn) => (...args: Parameters) => Promise; export let delayedRunOnMainThreadData: RunWorkletCtxData[] = []; export function enqueueDelayedRunOnMainThreadData(data: RunWorkletCtxData): void { delayedRunOnMainThreadData.push(data); } export function takeDelayedRunOnMainThreadData(): typeof delayedRunOnMainThreadData { const data = delayedRunOnMainThreadData; delayedRunOnMainThreadData = []; return data; } /** * @internal */ export function createRunOnMainThread( options: RunOnMainThreadOptions, ): RunOnMainThread { return R>(fn: Fn): (...args: Parameters) => Promise => { if (__LEPUS__) { throw new Error('runOnMainThread can only be used on the background thread.'); } if (!isMtsEnabled()) { throw new Error('runOnMainThread requires Lynx sdk version 2.14.'); } return async (...params: Parameters): Promise => { return new Promise((resolve) => { if (isRuntimeDestroyed()) return; const worklet = fn as unknown as Worklet; prepareMainThreadFunctionCtx(worklet); const data = { worklet, params, resolveId: onFunctionCall(resolve), } as RunWorkletCtxData; if (options.shouldDispatchRunOnMainThreadDirectly()) { dispatchRunOnMainThreadEvent(data); return; } enqueueDelayedRunOnMainThreadData(data); }); }; }; } function isRunOnBackgroundSupported(): boolean { return isSdkVersionGt(2, 15); } function prepareMainThreadFunctionCtx(worklet: unknown): void { if (isMainThreadFunction(worklet) && isRunOnBackgroundSupported()) { registerBackgroundFunctionCtx(worklet); } } function dispatchRunOnMainThreadEvent(data: RunWorkletCtxData): void { dispatchReloadScopedEvent(lynx.getCoreContext(), { type: WorkletEvents.runWorkletCtx, data }); }