@depup/react-native-worklets 0.11.3-depup.0 → 0.12.1-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Common/cpp/worklets/AnimationFrameQueue/AnimationFrameBatchinator.cpp +6 -3
- package/Common/cpp/worklets/Compat/StableApi.cpp +4 -0
- package/Common/cpp/worklets/Compat/StableApi.h +3 -1
- package/Common/cpp/worklets/NativeModules/JSIWorkletsModuleProxy.cpp +26 -43
- package/Common/cpp/worklets/RunLoop/AsyncQueueImpl.cpp +32 -0
- package/Common/cpp/worklets/RunLoop/EventLoop.cpp +16 -7
- package/Common/cpp/worklets/RunLoop/EventLoop.h +4 -2
- package/Common/cpp/worklets/SharedItems/MemoryManager.cpp +2 -2
- package/Common/cpp/worklets/SharedItems/Serializable.h +14 -16
- package/Common/cpp/worklets/Tools/UIScheduler.cpp +10 -0
- package/Common/cpp/worklets/Tools/UIScheduler.h +3 -0
- package/Common/cpp/worklets/Tools/WorkletsJSIUtils.h +23 -0
- package/Common/cpp/worklets/WorkletRuntime/RuntimeManager.cpp +7 -4
- package/Common/cpp/worklets/WorkletRuntime/RuntimeManager.h +2 -1
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp +60 -88
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h +335 -122
- package/README.md +2 -2
- package/android/build.gradle.kts +20 -6
- package/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp +10 -8
- package/android/src/main/cpp/worklets/android/JScriptBufferWrapper.cpp +2 -11
- package/android/src/main/cpp/worklets/android/JScriptBufferWrapper.h +1 -4
- package/android/src/main/java/com/swmansion/worklets/AndroidUIScheduler.kt +3 -0
- package/android/src/main/java/com/swmansion/worklets/ScriptBufferWrapper.kt +87 -43
- package/android/src/networking/com/swmansion/worklets/WorkletsModule.kt +25 -9
- package/android/src/no-networking/com/swmansion/worklets/WorkletsModule.kt +25 -9
- package/apple/worklets/apple/IOSUIScheduler.h +3 -0
- package/apple/worklets/apple/IOSUIScheduler.mm +6 -1
- package/apple/worklets/apple/ScriptLoader.h +11 -0
- package/apple/worklets/apple/ScriptLoader.mm +124 -0
- package/apple/worklets/apple/WorkletsModule.h +1 -16
- package/apple/worklets/apple/WorkletsModule.mm +4 -16
- package/changes.json +1 -1
- package/compatibility.json +4 -1
- package/lib/module/WorkletsModule/NativeWorklets.native.js +2 -2
- package/lib/module/WorkletsModule/NativeWorklets.native.js.map +1 -1
- package/lib/module/debug/jsVersion.js +1 -1
- package/lib/module/memory/serializable.native.js +59 -21
- package/lib/module/memory/serializable.native.js.map +1 -1
- package/lib/module/mock.js +58 -17
- package/lib/module/mock.js.map +1 -1
- package/lib/module/runLoop/uiRuntime/requestAnimationFrame.js +1 -2
- package/lib/module/runLoop/uiRuntime/requestAnimationFrame.js.map +1 -1
- package/lib/module/runLoop/workletRuntime/taskQueue.js +0 -1
- package/lib/module/runLoop/workletRuntime/taskQueue.js.map +1 -1
- package/lib/module/runtimes.native.js +7 -8
- package/lib/module/runtimes.native.js.map +1 -1
- package/lib/module/threads.js +35 -24
- package/lib/module/threads.js.map +1 -1
- package/lib/typescript/WorkletsModule/NativeWorklets.native.d.ts.map +1 -1
- package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts +1 -1
- package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts.map +1 -1
- package/lib/typescript/debug/jsVersion.d.ts +1 -1
- package/lib/typescript/memory/serializable.native.d.ts.map +1 -1
- package/lib/typescript/runLoop/uiRuntime/requestAnimationFrame.d.ts.map +1 -1
- package/lib/typescript/runLoop/workletRuntime/taskQueue.d.ts.map +1 -1
- package/lib/typescript/runtimes.native.d.ts.map +1 -1
- package/lib/typescript/specs/NativeWorkletsModule.d.ts +1 -1
- package/lib/typescript/threads.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +38 -8
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +14 -15
- package/plugin/index.js +1625 -1572
- package/src/WorkletsModule/NativeWorklets.native.ts +4 -2
- package/src/WorkletsModule/workletsModuleProxy.ts +2 -1
- package/src/debug/jsVersion.ts +1 -1
- package/src/memory/serializable.native.ts +103 -36
- package/src/mock.ts +85 -23
- package/src/runLoop/uiRuntime/requestAnimationFrame.ts +1 -2
- package/src/runLoop/workletRuntime/taskQueue.ts +0 -1
- package/src/runtimes.native.ts +12 -8
- package/src/threads.ts +38 -26
- package/src/types.ts +42 -8
- package/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp +0 -95
- package/Common/cpp/worklets/Registries/EventHandlerRegistry.h +0 -44
- package/Common/cpp/worklets/Tools/WorkletEventHandler.cpp +0 -34
- package/Common/cpp/worklets/Tools/WorkletEventHandler.h +0 -44
- package/jest/pluginTestUtils.ts +0 -16
|
@@ -270,14 +270,16 @@ See https://docs.swmansion.com/react-native-worklets/docs/guides/troubleshooting
|
|
|
270
270
|
initializer: SerializableRef<() => void>,
|
|
271
271
|
useDefaultQueue: boolean,
|
|
272
272
|
customQueue: object | undefined,
|
|
273
|
-
enableEventLoop: boolean
|
|
273
|
+
enableEventLoop: boolean,
|
|
274
|
+
enableLocking: boolean
|
|
274
275
|
) {
|
|
275
276
|
return this.#workletsModuleProxy.createWorkletRuntime(
|
|
276
277
|
name,
|
|
277
278
|
initializer,
|
|
278
279
|
useDefaultQueue,
|
|
279
280
|
customQueue,
|
|
280
|
-
enableEventLoop
|
|
281
|
+
enableEventLoop,
|
|
282
|
+
enableLocking
|
|
281
283
|
);
|
|
282
284
|
}
|
|
283
285
|
|
|
@@ -160,7 +160,8 @@ export interface WorkletsModuleProxy {
|
|
|
160
160
|
initializer: SerializableRef<() => void>,
|
|
161
161
|
useDefaultQueue: boolean,
|
|
162
162
|
customQueue: object | undefined,
|
|
163
|
-
enableEventLoop: boolean
|
|
163
|
+
enableEventLoop: boolean,
|
|
164
|
+
enableLocking: boolean
|
|
164
165
|
): WorkletRuntime;
|
|
165
166
|
|
|
166
167
|
scheduleOnRuntime<TValue>(
|
package/src/debug/jsVersion.ts
CHANGED
|
@@ -89,6 +89,21 @@ const DETECT_CYCLIC_OBJECT_DEPTH_THRESHOLD = 30;
|
|
|
89
89
|
// We use it to check if later on the function reenters with the same object
|
|
90
90
|
let processedObjectAtThresholdDepth: unknown;
|
|
91
91
|
|
|
92
|
+
const serializationPathStack: string[] = [];
|
|
93
|
+
|
|
94
|
+
function withPathSegment<TValue>(segment: string, serialize: () => TValue) {
|
|
95
|
+
serializationPathStack.push(segment);
|
|
96
|
+
try {
|
|
97
|
+
return serialize();
|
|
98
|
+
} finally {
|
|
99
|
+
serializationPathStack.pop();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function formatSerializationPath(): string {
|
|
104
|
+
return serializationPathStack.join('');
|
|
105
|
+
}
|
|
106
|
+
|
|
92
107
|
export function createSerializable<TValue>(
|
|
93
108
|
value: TValue,
|
|
94
109
|
shouldPersistRemote = false,
|
|
@@ -211,6 +226,17 @@ export function createSerializable<TValue>(
|
|
|
211
226
|
}
|
|
212
227
|
}
|
|
213
228
|
|
|
229
|
+
if (__DEV__) {
|
|
230
|
+
const constructorName =
|
|
231
|
+
(value as { constructor?: { name?: string } })?.constructor?.name ||
|
|
232
|
+
'unknown';
|
|
233
|
+
const path = formatSerializationPath();
|
|
234
|
+
const location = path ? ` It was located at \`${path}\`.` : '';
|
|
235
|
+
console.warn(
|
|
236
|
+
`[Worklets] Cannot copy value of type \`${constructorName}\`.${location}`
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
214
240
|
return cloneUndefined() as SerializableRef<TValue>;
|
|
215
241
|
}
|
|
216
242
|
|
|
@@ -356,11 +382,17 @@ function cloneObjectProperties<T extends object>(
|
|
|
356
382
|
if (key === '__initData' && clonedProps.__initData !== undefined) {
|
|
357
383
|
continue;
|
|
358
384
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
385
|
+
if (__DEV__) {
|
|
386
|
+
clonedProps[key] = withPathSegment(`[${JSON.stringify(key)}]`, () =>
|
|
387
|
+
createSerializable(element, shouldPersistRemote, depth + 1)
|
|
388
|
+
);
|
|
389
|
+
} else {
|
|
390
|
+
clonedProps[key] = createSerializable(
|
|
391
|
+
element,
|
|
392
|
+
shouldPersistRemote,
|
|
393
|
+
depth + 1
|
|
394
|
+
);
|
|
395
|
+
}
|
|
364
396
|
}
|
|
365
397
|
return clonedProps;
|
|
366
398
|
}
|
|
@@ -383,8 +415,12 @@ function cloneArray<T extends unknown[]>(
|
|
|
383
415
|
shouldPersistRemote: boolean,
|
|
384
416
|
depth: number
|
|
385
417
|
): SerializableRef<T> {
|
|
386
|
-
const clonedElements = value.map((element) =>
|
|
387
|
-
|
|
418
|
+
const clonedElements = value.map((element, index) =>
|
|
419
|
+
__DEV__
|
|
420
|
+
? withPathSegment(`[${index}]`, () =>
|
|
421
|
+
createSerializable(element, shouldPersistRemote, depth + 1)
|
|
422
|
+
)
|
|
423
|
+
: createSerializable(element, shouldPersistRemote, depth + 1)
|
|
388
424
|
);
|
|
389
425
|
const clone = WorkletsModule.createSerializableArray(
|
|
390
426
|
clonedElements,
|
|
@@ -452,33 +488,39 @@ function cloneWorklet<TValue extends WorkletFunction>(
|
|
|
452
488
|
// seems more elegant to handle it this way.
|
|
453
489
|
delete (value as WorkletFunction).__stackDetails;
|
|
454
490
|
}
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
491
|
+
const buildClone = (): SerializableRef<TValue> => {
|
|
492
|
+
const clonedProps: Record<string, unknown> = cloneObjectProperties(
|
|
493
|
+
value,
|
|
494
|
+
shouldPersistRemote,
|
|
495
|
+
depth
|
|
496
|
+
);
|
|
497
|
+
// to save on transferring static __initData field of worklet structure
|
|
498
|
+
// we request serializable value to persist its UI counterpart. This means
|
|
499
|
+
// that the __initData field that contains long strings representing the
|
|
500
|
+
// worklet code, source map, and location, will always be
|
|
501
|
+
// serialized/deserialized once.
|
|
502
|
+
clonedProps.__initData = __DEV__
|
|
503
|
+
? withPathSegment('["__initData"]', () =>
|
|
504
|
+
createSerializable(value.__initData, true, depth + 1)
|
|
505
|
+
)
|
|
506
|
+
: createSerializable(value.__initData, true, depth + 1);
|
|
507
|
+
|
|
508
|
+
const clone = WorkletsModule.createSerializableWorklet(
|
|
509
|
+
clonedProps,
|
|
510
|
+
// TODO: Check after refactor if we can remove shouldPersistRemote parameter (imho it's redundant here since worklets are always persistent)
|
|
511
|
+
// retain all worklets
|
|
512
|
+
true
|
|
513
|
+
) as SerializableRef<TValue>;
|
|
514
|
+
serializableMappingCache.set(value, clone);
|
|
515
|
+
serializableMappingCache.set(clone);
|
|
470
516
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
// retain all worklets
|
|
475
|
-
true
|
|
476
|
-
) as SerializableRef<TValue>;
|
|
477
|
-
serializableMappingCache.set(value, clone);
|
|
478
|
-
serializableMappingCache.set(clone);
|
|
517
|
+
freezeObjectInDev(value);
|
|
518
|
+
return clone;
|
|
519
|
+
};
|
|
479
520
|
|
|
480
|
-
|
|
481
|
-
|
|
521
|
+
return __DEV__
|
|
522
|
+
? withPathSegment(`<worklet ${value.name || 'anonymous'}>`, buildClone)
|
|
523
|
+
: buildClone();
|
|
482
524
|
}
|
|
483
525
|
|
|
484
526
|
/**
|
|
@@ -541,9 +583,22 @@ function cloneMap(
|
|
|
541
583
|
): SerializableRef<Map<unknown, unknown>> {
|
|
542
584
|
const clonedKeys: unknown[] = [];
|
|
543
585
|
const clonedValues: unknown[] = [];
|
|
586
|
+
let index = 0;
|
|
544
587
|
for (const [key, element] of value.entries()) {
|
|
545
|
-
|
|
546
|
-
|
|
588
|
+
if (__DEV__) {
|
|
589
|
+
clonedKeys.push(
|
|
590
|
+
withPathSegment(`.keys()[${index}]`, () => createSerializable(key))
|
|
591
|
+
);
|
|
592
|
+
clonedValues.push(
|
|
593
|
+
withPathSegment(`.values()[${index}]`, () =>
|
|
594
|
+
createSerializable(element)
|
|
595
|
+
)
|
|
596
|
+
);
|
|
597
|
+
index++;
|
|
598
|
+
} else {
|
|
599
|
+
clonedKeys.push(createSerializable(key));
|
|
600
|
+
clonedValues.push(createSerializable(element));
|
|
601
|
+
}
|
|
547
602
|
}
|
|
548
603
|
const clone = WorkletsModule.createSerializableMap(clonedKeys, clonedValues);
|
|
549
604
|
serializableMappingCache.set(value, clone);
|
|
@@ -555,8 +610,18 @@ function cloneMap(
|
|
|
555
610
|
|
|
556
611
|
function cloneSet(value: Set<unknown>): SerializableRef<Set<unknown>> {
|
|
557
612
|
const clonedElements: unknown[] = [];
|
|
613
|
+
let index = 0;
|
|
558
614
|
for (const element of value) {
|
|
559
|
-
|
|
615
|
+
if (__DEV__) {
|
|
616
|
+
clonedElements.push(
|
|
617
|
+
withPathSegment(`.values()[${index}]`, () =>
|
|
618
|
+
createSerializable(element)
|
|
619
|
+
)
|
|
620
|
+
);
|
|
621
|
+
index++;
|
|
622
|
+
} else {
|
|
623
|
+
clonedElements.push(createSerializable(element));
|
|
624
|
+
}
|
|
560
625
|
}
|
|
561
626
|
const clone = WorkletsModule.createSerializableSet(clonedElements);
|
|
562
627
|
serializableMappingCache.set(value, clone);
|
|
@@ -638,7 +703,9 @@ function cloneCustom<TValue extends object, TPacked = unknown>(
|
|
|
638
703
|
typeId: number
|
|
639
704
|
): SerializableRef<TValue> {
|
|
640
705
|
const packedData = pack(data);
|
|
641
|
-
const serialized =
|
|
706
|
+
const serialized = __DEV__
|
|
707
|
+
? withPathSegment('.pack()', () => createSerializable(packedData))
|
|
708
|
+
: createSerializable(packedData);
|
|
642
709
|
|
|
643
710
|
return WorkletsModule.createCustomSerializable(
|
|
644
711
|
serialized,
|
package/src/mock.ts
CHANGED
|
@@ -6,6 +6,8 @@ import { isWorkletFunction } from './workletFunction';
|
|
|
6
6
|
|
|
7
7
|
const NOOP = () => {};
|
|
8
8
|
const NOOP_FACTORY = () => NOOP;
|
|
9
|
+
const UI_RUNTIME_HOLDER = {};
|
|
10
|
+
const UI_SCHEDULER_HOLDER = {};
|
|
9
11
|
const ID = <TValue>(value: TValue) => value;
|
|
10
12
|
const IMMEDIATE_CALLBACK_INVOCATION = <TCallback>(callback: () => TCallback) =>
|
|
11
13
|
callback();
|
|
@@ -23,32 +25,50 @@ globalThis._getAnimationTimestamp = () => performance.now();
|
|
|
23
25
|
globalThis.requestAnimationFrame = mockedRequestAnimationFrame;
|
|
24
26
|
|
|
25
27
|
const WorkletAPI = {
|
|
28
|
+
callMicrotasks: NOOP,
|
|
29
|
+
createSerializable: ID,
|
|
30
|
+
createShareable<TValue>(_hostRuntimeId: number, initial: TValue) {
|
|
31
|
+
let value = initial;
|
|
32
|
+
const set = (next: TValue | ((prev: TValue) => TValue)) => {
|
|
33
|
+
value =
|
|
34
|
+
typeof next === 'function'
|
|
35
|
+
? (next as (prev: TValue) => TValue)(value)
|
|
36
|
+
: next;
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
isHost: false,
|
|
40
|
+
__shareableRef: true,
|
|
41
|
+
getAsync: () => Promise.resolve(value),
|
|
42
|
+
getSync: () => value,
|
|
43
|
+
setAsync: set,
|
|
44
|
+
setSync: set,
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
createSynchronizable: ID,
|
|
48
|
+
createWorkletRuntime: NOOP_FACTORY,
|
|
49
|
+
executeOnUIRuntimeSync: ID,
|
|
50
|
+
getDynamicFeatureFlag: () => false,
|
|
51
|
+
getRuntimeKind: () => RuntimeKind.ReactNative,
|
|
52
|
+
getStaticFeatureFlag: () => false,
|
|
53
|
+
getUIRuntimeHolder: () => UI_RUNTIME_HOLDER,
|
|
54
|
+
getUISchedulerHolder: () => UI_SCHEDULER_HOLDER,
|
|
55
|
+
isBundleModeEnabled: () => false,
|
|
56
|
+
isRNRuntime: () => true,
|
|
57
|
+
isSerializableRef: ID,
|
|
58
|
+
isShareable: (value: unknown) =>
|
|
59
|
+
typeof value === 'object' &&
|
|
60
|
+
value !== null &&
|
|
61
|
+
!!(value as Record<string, unknown>).__shareableRef,
|
|
26
62
|
isShareableRef: () => true,
|
|
63
|
+
isSynchronizable: () => false,
|
|
64
|
+
isUIRuntime: () => false, // maybe it should be true?
|
|
65
|
+
isWorkerRuntime: () => false,
|
|
66
|
+
isWorkletFunction: isWorkletFunction,
|
|
67
|
+
isWorkletRuntime: () => false,
|
|
27
68
|
makeShareable: ID,
|
|
28
69
|
makeShareableCloneOnUIRecursive: ID,
|
|
29
70
|
makeShareableCloneRecursive: ID,
|
|
30
|
-
|
|
31
|
-
getStaticFeatureFlag: () => false,
|
|
32
|
-
setDynamicFeatureFlag: NOOP,
|
|
33
|
-
isSynchronizable: () => false,
|
|
34
|
-
getRuntimeKind: () => RuntimeKind.ReactNative,
|
|
35
|
-
RuntimeKind: RuntimeKind,
|
|
36
|
-
createWorkletRuntime: NOOP_FACTORY,
|
|
37
|
-
runOnRuntime: ID,
|
|
38
|
-
runOnRuntimeAsync<Args extends unknown[], ReturnValue>(
|
|
39
|
-
_workletRuntime: unknown,
|
|
40
|
-
worklet: (...args: Args) => ReturnValue,
|
|
41
|
-
...args: Args
|
|
42
|
-
): Promise<ReturnValue> {
|
|
43
|
-
return WorkletAPI.runOnUIAsync(worklet, ...args);
|
|
44
|
-
},
|
|
45
|
-
scheduleOnRuntime: IMMEDIATE_CALLBACK_INVOCATION,
|
|
46
|
-
createSerializable: ID,
|
|
47
|
-
isSerializableRef: ID,
|
|
48
|
-
serializableMappingCache: new Map(),
|
|
49
|
-
createSynchronizable: ID,
|
|
50
|
-
callMicrotasks: NOOP,
|
|
51
|
-
executeOnUIRuntimeSync: ID,
|
|
71
|
+
registerCustomSerializable: NOOP,
|
|
52
72
|
runOnJS<Args extends unknown[], ReturnValue>(
|
|
53
73
|
fun: (...args: Args) => ReturnValue
|
|
54
74
|
): (...args: Args) => void {
|
|
@@ -59,6 +79,35 @@ const WorkletAPI = {
|
|
|
59
79
|
: (fun as () => ReturnValue)
|
|
60
80
|
);
|
|
61
81
|
},
|
|
82
|
+
runOnRuntime: ID,
|
|
83
|
+
runOnRuntimeAsync<Args extends unknown[], ReturnValue>(
|
|
84
|
+
_workletRuntime: unknown,
|
|
85
|
+
worklet: (...args: Args) => ReturnValue,
|
|
86
|
+
...args: Args
|
|
87
|
+
): Promise<ReturnValue> {
|
|
88
|
+
return WorkletAPI.runOnUIAsync(worklet, ...args);
|
|
89
|
+
},
|
|
90
|
+
runOnRuntimeAsyncWithId<Args extends unknown[], ReturnValue>(
|
|
91
|
+
_runtimeId: number,
|
|
92
|
+
worklet: (...args: Args) => ReturnValue,
|
|
93
|
+
...args: Args
|
|
94
|
+
): Promise<ReturnValue> {
|
|
95
|
+
return WorkletAPI.runOnUIAsync(worklet, ...args);
|
|
96
|
+
},
|
|
97
|
+
runOnRuntimeSync<Args extends unknown[], ReturnValue>(
|
|
98
|
+
_workletRuntime: unknown,
|
|
99
|
+
worklet: (...args: Args) => ReturnValue,
|
|
100
|
+
...args: Args
|
|
101
|
+
): ReturnValue {
|
|
102
|
+
return worklet(...args);
|
|
103
|
+
},
|
|
104
|
+
runOnRuntimeSyncWithId<Args extends unknown[], ReturnValue>(
|
|
105
|
+
_runtimeId: number,
|
|
106
|
+
worklet: (...args: Args) => ReturnValue,
|
|
107
|
+
...args: Args
|
|
108
|
+
): ReturnValue {
|
|
109
|
+
return worklet(...args);
|
|
110
|
+
},
|
|
62
111
|
runOnUI<Args extends unknown[], ReturnValue>(
|
|
63
112
|
worklet: (...args: Args) => ReturnValue
|
|
64
113
|
): (...args: Args) => void {
|
|
@@ -89,19 +138,32 @@ const WorkletAPI = {
|
|
|
89
138
|
});
|
|
90
139
|
},
|
|
91
140
|
runOnUISync: IMMEDIATE_CALLBACK_INVOCATION,
|
|
141
|
+
RuntimeKind: RuntimeKind,
|
|
92
142
|
scheduleOnRN<Args extends unknown[], ReturnValue>(
|
|
93
143
|
fun: (...args: Args) => ReturnValue,
|
|
94
144
|
...args: Args
|
|
95
145
|
): void {
|
|
96
146
|
WorkletAPI.runOnJS(fun)(...args);
|
|
97
147
|
},
|
|
148
|
+
scheduleOnRuntime: IMMEDIATE_CALLBACK_INVOCATION,
|
|
149
|
+
scheduleOnRuntimeWithId<Args extends unknown[], ReturnValue>(
|
|
150
|
+
_runtimeId: number,
|
|
151
|
+
worklet: (...args: Args) => ReturnValue,
|
|
152
|
+
...args: Args
|
|
153
|
+
): void {
|
|
154
|
+
WorkletAPI.scheduleOnUI(worklet, ...args);
|
|
155
|
+
},
|
|
98
156
|
scheduleOnUI<Args extends unknown[], ReturnValue>(
|
|
99
157
|
worklet: (...args: Args) => ReturnValue,
|
|
100
158
|
...args: Args
|
|
101
159
|
): void {
|
|
102
160
|
WorkletAPI.runOnUI(worklet)(...args);
|
|
103
161
|
},
|
|
104
|
-
|
|
162
|
+
serializableMappingCache: new Map(),
|
|
163
|
+
setDynamicFeatureFlag: NOOP,
|
|
164
|
+
shareableMappingCache: new Map(),
|
|
165
|
+
toggleSlowAnimationsOnUIRuntime: () => false,
|
|
166
|
+
UIRuntimeId: RuntimeKind.UI,
|
|
105
167
|
WorkletsModule: {},
|
|
106
168
|
};
|
|
107
169
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
export function setupRequestAnimationFrame() {
|
|
4
4
|
'worklet';
|
|
5
|
-
const callMicrotasks = globalThis.__callMicrotasks;
|
|
6
5
|
|
|
7
6
|
let queuedCallbacks: ((timestamp: number) => void)[] = [];
|
|
8
7
|
let queuedCallbacksBegin = 0;
|
|
@@ -28,7 +27,7 @@ export function setupRequestAnimationFrame() {
|
|
|
28
27
|
|
|
29
28
|
flushedCallbacksBegin = flushedCallbacksEnd;
|
|
30
29
|
|
|
31
|
-
|
|
30
|
+
globalThis.__callMicrotasks();
|
|
32
31
|
|
|
33
32
|
const finalizers = queuedFinalizers;
|
|
34
33
|
queuedFinalizers = [];
|
package/src/runtimes.native.ts
CHANGED
|
@@ -81,6 +81,7 @@ export function createWorkletRuntime(
|
|
|
81
81
|
let queue: 'default' | object | null = 'default';
|
|
82
82
|
let animationQueuePollingRate: number;
|
|
83
83
|
let enableEventLoop = true;
|
|
84
|
+
let enableLocking = true;
|
|
84
85
|
if (typeof nameOrConfig === 'string') {
|
|
85
86
|
name = nameOrConfig;
|
|
86
87
|
initializerFn = initializer;
|
|
@@ -96,7 +97,15 @@ export function createWorkletRuntime(
|
|
|
96
97
|
animationQueuePollingRate = Math.round(
|
|
97
98
|
nameOrConfig?.animationQueuePollingRate ?? 16
|
|
98
99
|
);
|
|
99
|
-
|
|
100
|
+
enableLocking = nameOrConfig?.enableLocking ?? true;
|
|
101
|
+
if (__DEV__ && !enableLocking && nameOrConfig?.enableEventLoop) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
'[Worklets] The Event Loop cannot be enabled on a runtime with locking disabled.'
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
enableEventLoop = enableLocking
|
|
107
|
+
? (nameOrConfig?.enableEventLoop ?? true)
|
|
108
|
+
: false;
|
|
100
109
|
}
|
|
101
110
|
|
|
102
111
|
const useDefaultQueue = queue === 'default';
|
|
@@ -126,7 +135,8 @@ export function createWorkletRuntime(
|
|
|
126
135
|
}),
|
|
127
136
|
useDefaultQueue,
|
|
128
137
|
customQueue,
|
|
129
|
-
enableEventLoop
|
|
138
|
+
enableEventLoop,
|
|
139
|
+
enableLocking
|
|
130
140
|
);
|
|
131
141
|
}
|
|
132
142
|
|
|
@@ -172,7 +182,6 @@ export function scheduleOnRuntime<Args extends unknown[], ReturnValue>(
|
|
|
172
182
|
createSerializable(() => {
|
|
173
183
|
'worklet';
|
|
174
184
|
worklet(...args);
|
|
175
|
-
globalThis.__callMicrotasks?.();
|
|
176
185
|
}),
|
|
177
186
|
SHOULD_CAPTURE_SCHEDULE_STACK ? new Error().stack : undefined
|
|
178
187
|
);
|
|
@@ -196,7 +205,6 @@ if (!isBundleModeEnabled()) {
|
|
|
196
205
|
globalThis.__serializer(() => {
|
|
197
206
|
'worklet';
|
|
198
207
|
worklet(...args);
|
|
199
|
-
globalThis.__callMicrotasks?.();
|
|
200
208
|
})
|
|
201
209
|
);
|
|
202
210
|
}
|
|
@@ -250,7 +258,6 @@ export function scheduleOnRuntimeWithId<Args extends unknown[], ReturnValue>(
|
|
|
250
258
|
createSerializable(() => {
|
|
251
259
|
'worklet';
|
|
252
260
|
worklet(...args);
|
|
253
|
-
globalThis.__callMicrotasks?.();
|
|
254
261
|
}),
|
|
255
262
|
SHOULD_CAPTURE_SCHEDULE_STACK ? new Error().stack : undefined
|
|
256
263
|
);
|
|
@@ -274,7 +281,6 @@ if (!isBundleModeEnabled()) {
|
|
|
274
281
|
globalThis.__serializer(() => {
|
|
275
282
|
'worklet';
|
|
276
283
|
worklet(...args);
|
|
277
|
-
globalThis.__callMicrotasks?.();
|
|
278
284
|
})
|
|
279
285
|
);
|
|
280
286
|
}
|
|
@@ -470,7 +476,6 @@ export function runOnRuntimeAsync<Args extends unknown[], ReturnValue>(
|
|
|
470
476
|
serializedError
|
|
471
477
|
);
|
|
472
478
|
}
|
|
473
|
-
globalThis.__callMicrotasks?.();
|
|
474
479
|
}),
|
|
475
480
|
scheduleStack
|
|
476
481
|
);
|
|
@@ -545,7 +550,6 @@ export function runOnRuntimeAsyncWithId<Args extends unknown[], ReturnValue>(
|
|
|
545
550
|
serializedError
|
|
546
551
|
);
|
|
547
552
|
}
|
|
548
|
-
globalThis.__callMicrotasks?.();
|
|
549
553
|
}),
|
|
550
554
|
scheduleStack
|
|
551
555
|
);
|
package/src/threads.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
import { IS_JEST } from './platformChecker';
|
|
4
|
-
import { mockedRequestAnimationFrame } from './runLoop/uiRuntime/mockedRequestAnimationFrame';
|
|
5
4
|
|
|
6
5
|
export function scheduleOnUI<Args extends unknown[], ReturnValue>(
|
|
7
6
|
worklet: (...args: Args) => ReturnValue,
|
|
@@ -58,8 +57,8 @@ export function runOnUIAsync<Args extends unknown[], ReturnValue>(
|
|
|
58
57
|
worklet: (...args: Args) => ReturnValue,
|
|
59
58
|
...args: Args
|
|
60
59
|
): Promise<ReturnValue> {
|
|
61
|
-
return new Promise<ReturnValue>((resolve) => {
|
|
62
|
-
enqueueUI(worklet, args, resolve);
|
|
60
|
+
return new Promise<ReturnValue>((resolve, reject) => {
|
|
61
|
+
enqueueUI(worklet, args, resolve, reject);
|
|
63
62
|
});
|
|
64
63
|
}
|
|
65
64
|
|
|
@@ -67,6 +66,7 @@ type UIJob<Args extends unknown[] = unknown[], ReturnValue = unknown> = [
|
|
|
67
66
|
worklet: (...args: Args) => ReturnValue,
|
|
68
67
|
args: Args,
|
|
69
68
|
resolve?: (value: ReturnValue) => void,
|
|
69
|
+
reject?: (reason?: unknown) => void,
|
|
70
70
|
];
|
|
71
71
|
|
|
72
72
|
let runOnUIQueue: UIJob[] = [];
|
|
@@ -74,37 +74,49 @@ let runOnUIQueue: UIJob[] = [];
|
|
|
74
74
|
function enqueueUI<Args extends unknown[], ReturnValue>(
|
|
75
75
|
worklet: (...args: Args) => ReturnValue,
|
|
76
76
|
args: Args,
|
|
77
|
-
resolve?: (value: ReturnValue) => void
|
|
77
|
+
resolve?: (value: ReturnValue) => void,
|
|
78
|
+
reject?: (reason?: unknown) => void
|
|
78
79
|
): void {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
});
|
|
84
|
-
} else {
|
|
85
|
-
const job = [worklet, args, resolve];
|
|
86
|
-
runOnUIQueue.push(job as UIJob);
|
|
87
|
-
if (runOnUIQueue.length === 1) {
|
|
80
|
+
const job = [worklet, args, resolve, reject];
|
|
81
|
+
runOnUIQueue.push(job as UIJob);
|
|
82
|
+
if (runOnUIQueue.length === 1) {
|
|
83
|
+
if (IS_JEST) {
|
|
88
84
|
flushUIQueue();
|
|
85
|
+
} else {
|
|
86
|
+
queueMicrotask(flushUIQueue);
|
|
89
87
|
}
|
|
90
88
|
}
|
|
91
89
|
}
|
|
92
90
|
|
|
91
|
+
let offset = 0;
|
|
92
|
+
|
|
93
93
|
function flushUIQueue(): void {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
const queue = runOnUIQueue;
|
|
95
|
+
runOnUIQueue = [];
|
|
96
|
+
requestAnimationFrame(() => {
|
|
97
|
+
offset = 0;
|
|
98
|
+
while (queue.length > offset) {
|
|
99
|
+
try {
|
|
100
|
+
drainUIQueue(queue);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
const [, , , jobReject] = queue[offset - 1];
|
|
103
|
+
if (jobReject) {
|
|
104
|
+
jobReject(e);
|
|
105
|
+
} else {
|
|
106
|
+
console.error(e);
|
|
102
107
|
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
105
110
|
});
|
|
106
111
|
}
|
|
107
112
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
function drainUIQueue(queue: UIJob[]): void {
|
|
114
|
+
while (queue.length > offset) {
|
|
115
|
+
const [workletFunction, workletArgs, jobResolve] = queue[offset];
|
|
116
|
+
offset++;
|
|
117
|
+
const result = workletFunction(...workletArgs);
|
|
118
|
+
if (jobResolve) {
|
|
119
|
+
jobResolve(result);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -121,18 +121,52 @@ type WorkletRuntimeConfigBase = {
|
|
|
121
121
|
* by requestAnimationFrame. If not specified, it defaults to 16 ms.
|
|
122
122
|
*/
|
|
123
123
|
animationQueuePollingRate?: number;
|
|
124
|
-
/**
|
|
125
|
-
* Determines whether to enable the default Event Loop or not. The Event Loop
|
|
126
|
-
* provides implementations for `setTimeout`, `setImmediate`, `setInterval`,
|
|
127
|
-
* `requestAnimationFrame`, `queueMicrotask`, `clearTimeout`, `clearInterval`,
|
|
128
|
-
* `clearImmediate`, and `cancelAnimationFrame` methods. If not specified, it
|
|
129
|
-
* defaults to `true`.
|
|
130
|
-
*/
|
|
131
|
-
enableEventLoop?: boolean;
|
|
132
124
|
};
|
|
133
125
|
|
|
134
126
|
/** Configuration object for creating a worklet runtime. */
|
|
135
127
|
export type WorkletRuntimeConfig = WorkletRuntimeConfigBase &
|
|
128
|
+
(
|
|
129
|
+
| {
|
|
130
|
+
/**
|
|
131
|
+
* Determines whether to enable the default Event Loop, which provides
|
|
132
|
+
* `setTimeout`, `setInterval`, `requestAnimationFrame` and other
|
|
133
|
+
* scheduling APIs. If not specified, it defaults to `true`. Cannot be
|
|
134
|
+
* enabled when {@link enableLocking} is set to `false`.
|
|
135
|
+
*/
|
|
136
|
+
enableEventLoop?: boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Determines whether access to the underlying JS runtime is
|
|
139
|
+
* synchronized with a mutex around every JSI operation. If not
|
|
140
|
+
* specified, it defaults to `true`. Can be disabled only together
|
|
141
|
+
* with the Event Loop.
|
|
142
|
+
*
|
|
143
|
+
* Runtime without locking doesn't receive HMR updates
|
|
144
|
+
* and new Custom Serializable registrations.
|
|
145
|
+
*
|
|
146
|
+
* Disable only when you can guarantee thread safety of all access to the runtime.
|
|
147
|
+
*/
|
|
148
|
+
enableLocking?: true;
|
|
149
|
+
}
|
|
150
|
+
| {
|
|
151
|
+
/**
|
|
152
|
+
* The Event Loop cannot be enabled on a runtime with
|
|
153
|
+
* {@link enableLocking} set to `false`.
|
|
154
|
+
*/
|
|
155
|
+
enableEventLoop?: false;
|
|
156
|
+
/**
|
|
157
|
+
* Determines whether access to the underlying JS runtime is
|
|
158
|
+
* synchronized with a mutex around every JSI operation. If not
|
|
159
|
+
* specified, it defaults to `true`. Can be disabled only together
|
|
160
|
+
* with the Event Loop.
|
|
161
|
+
*
|
|
162
|
+
* Runtime without locking doesn't receive HMR updates
|
|
163
|
+
* and new Custom Serializable registrations.
|
|
164
|
+
*
|
|
165
|
+
* Disable only when you can guarantee thread safety of all access to the runtime.
|
|
166
|
+
*/
|
|
167
|
+
enableLocking: false;
|
|
168
|
+
}
|
|
169
|
+
) &
|
|
136
170
|
(
|
|
137
171
|
| {
|
|
138
172
|
/**
|