onejs-react 0.1.6 → 0.1.7
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/package.json +1 -1
- package/src/host-config.ts +35 -5
package/package.json
CHANGED
package/src/host-config.ts
CHANGED
|
@@ -12,6 +12,13 @@ declare function clearTimeout(id: number): void;
|
|
|
12
12
|
|
|
13
13
|
declare const console: { log: (...args: unknown[]) => void; error: (...args: unknown[]) => void };
|
|
14
14
|
|
|
15
|
+
// Native delegate callback helpers (from QuickJSBootstrap __csHelpers)
|
|
16
|
+
declare const __csHelpers: {
|
|
17
|
+
createDelegateCallback(fn: Function): number;
|
|
18
|
+
freeDelegateCallback(handle: number): void;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
|
|
15
22
|
// Priority constants from react-reconciler/constants
|
|
16
23
|
// These match React's internal lane priorities
|
|
17
24
|
const DiscreteEventPriority = 2;
|
|
@@ -149,6 +156,8 @@ export interface Instance {
|
|
|
149
156
|
hasMixedContent?: boolean;
|
|
150
157
|
// For vector drawing: track the current generateVisualContent callback
|
|
151
158
|
visualContentCallback?: GenerateVisualContentCallback;
|
|
159
|
+
// Native callback handle for the above (used to free slot on replacement)
|
|
160
|
+
visualContentCallbackHandle?: number;
|
|
152
161
|
}
|
|
153
162
|
|
|
154
163
|
export type TextInstance = Instance; // For Label elements with text content
|
|
@@ -435,6 +444,15 @@ function untrackParent(child: CSObject) {
|
|
|
435
444
|
}
|
|
436
445
|
}
|
|
437
446
|
|
|
447
|
+
// Free native callback handles tracked on an instance (prevents callback table leak)
|
|
448
|
+
function cleanupCallbackHandles(instance: Instance) {
|
|
449
|
+
if (instance.visualContentCallbackHandle !== undefined) {
|
|
450
|
+
__csHelpers.freeDelegateCallback(instance.visualContentCallbackHandle);
|
|
451
|
+
instance.visualContentCallbackHandle = undefined;
|
|
452
|
+
instance.visualContentCallback = undefined;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
438
456
|
// Apply event handlers
|
|
439
457
|
function applyEvents(instance: Instance, props: BaseProps) {
|
|
440
458
|
for (const [propName, eventType] of Object.entries(EVENT_PROPS)) {
|
|
@@ -468,17 +486,27 @@ function applyVisualContentCallback(instance: Instance, props: BaseProps) {
|
|
|
468
486
|
if (callback !== existingCallback) {
|
|
469
487
|
const element = instance.element as unknown as { generateVisualContent: GenerateVisualContentCallback | null };
|
|
470
488
|
|
|
471
|
-
//
|
|
489
|
+
// Free old native callback handle to prevent callback table leak
|
|
472
490
|
if (existingCallback) {
|
|
473
|
-
// Clear the delegate via C# interop
|
|
474
491
|
element.generateVisualContent = null;
|
|
492
|
+
if (instance.visualContentCallbackHandle !== undefined) {
|
|
493
|
+
__csHelpers.freeDelegateCallback(instance.visualContentCallbackHandle);
|
|
494
|
+
}
|
|
495
|
+
instance.visualContentCallbackHandle = undefined;
|
|
475
496
|
}
|
|
476
497
|
|
|
477
498
|
// Add new callback if provided
|
|
478
499
|
if (callback) {
|
|
479
|
-
//
|
|
480
|
-
|
|
481
|
-
|
|
500
|
+
// Register with argument wrapping and track the handle for cleanup
|
|
501
|
+
const handle = __csHelpers.createDelegateCallback(callback);
|
|
502
|
+
if (handle >= 0) {
|
|
503
|
+
instance.visualContentCallbackHandle = handle;
|
|
504
|
+
// Pass pre-resolved handle directly — bypasses __resolveValue's auto-registration
|
|
505
|
+
element.generateVisualContent = { __csCallbackHandle: handle } as any;
|
|
506
|
+
} else {
|
|
507
|
+
// WebGL path: no native callback table
|
|
508
|
+
element.generateVisualContent = callback;
|
|
509
|
+
}
|
|
482
510
|
instance.visualContentCallback = callback;
|
|
483
511
|
} else {
|
|
484
512
|
instance.visualContentCallback = undefined;
|
|
@@ -947,6 +975,7 @@ export const hostConfig = {
|
|
|
947
975
|
removeMergedTextChild(parentInstance, child);
|
|
948
976
|
} else {
|
|
949
977
|
__eventAPI.removeAllEventListeners(child.element);
|
|
978
|
+
cleanupCallbackHandles(child);
|
|
950
979
|
parentInstance.element.Remove(child.element);
|
|
951
980
|
}
|
|
952
981
|
untrackParent(child.element);
|
|
@@ -954,6 +983,7 @@ export const hostConfig = {
|
|
|
954
983
|
|
|
955
984
|
removeChildFromContainer(container: Container, child: Instance) {
|
|
956
985
|
__eventAPI.removeAllEventListeners(child.element);
|
|
986
|
+
cleanupCallbackHandles(child);
|
|
957
987
|
container.Remove(child.element);
|
|
958
988
|
untrackParent(child.element);
|
|
959
989
|
},
|