Skip to content
41 changes: 11 additions & 30 deletions packages/react/runtime/src/lynx/tt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
const tt = lynxCoreInject.tt;
tt.OnLifecycleEvent = onLifecycleEvent;
tt.publishEvent = delayedPublishEvent;
tt.publicComponentEvent = delayedPublicComponentEvent;
tt.publicComponentEvent = (_componentId, handlerName, data) => tt.publishEvent(handlerName, data);
tt.callDestroyLifetimeFun = () => {
removeCtxNotFoundEventListener();
destroyWorklet();
Expand All @@ -51,10 +51,9 @@
}

function onLifecycleEvent([type, data]: [LifecycleConstant, unknown]) {
const hasRootRendered = CHILDREN in __root;
// never called `render(<App/>, __root)`
// happens if user call `root.render()` async
if (!hasRootRendered) {
if (!(CHILDREN in __root)) {
delayLifecycleEvent(type, data);
return;
}
Expand Down Expand Up @@ -130,23 +129,15 @@

// TODO: It seems `delayedEvents` and `delayedLifecycleEvents` should be merged into one array to ensure the proper order of events.
flushDelayedLifecycleEvents();
if (delayedEvents) {
delayedEvents.forEach((args) => {
const [handlerName, data] = args;
// eslint-disable-next-line prefer-const
let [idStr, ...rest] = handlerName.split(':');
while (jsReadyEventIdSwap[idStr!]) idStr = jsReadyEventIdSwap[idStr!]?.toString();
try {
publishEvent([idStr, ...rest].join(':'), data);
} catch (e) {
lynx.reportError(e as Error);
}
});
delayedEvents.length = 0;
for (const [handlerName, data] of delayedEvents) {

Check failure on line 132 in packages/react/runtime/src/lynx/tt.ts

View workflow job for this annotation

GitHub Actions / code-style-check

'delayedEvents' is possibly 'undefined'.

Check failure on line 132 in packages/react/runtime/src/lynx/tt.ts

View workflow job for this annotation

GitHub Actions / build / Build (Ubuntu)

'delayedEvents' is possibly 'undefined'.

Check failure on line 132 in packages/react/runtime/src/lynx/tt.ts

View workflow job for this annotation

GitHub Actions / build / Build (Windows)

'delayedEvents' is possibly 'undefined'.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Guard delayed event replay against empty queue

When firstScreen runs without any pre-hydration events, delayedEvents is still undefined (it is lazily initialized in delayEvents.ts), so iterating it here throws a TypeError. That exception is caught by onLifecycleEvent, which stops the rest of firstScreen processing before patch commit and leaves hydration incomplete. This makes startup fail in flows where no delayed events were queued.

Useful? React with 👍 / 👎.

// eslint-disable-next-line prefer-const
let [idStr, ...rest] = handlerName.split(':');
while (jsReadyEventIdSwap[idStr!]) idStr = jsReadyEventIdSwap[idStr!]?.toString();
publishEvent([idStr, ...rest].join(':'), data);
}
delayedEvents.length = 0;

Check failure on line 138 in packages/react/runtime/src/lynx/tt.ts

View workflow job for this annotation

GitHub Actions / code-style-check

'delayedEvents' is possibly 'undefined'.

Check failure on line 138 in packages/react/runtime/src/lynx/tt.ts

View workflow job for this annotation

GitHub Actions / build / Build (Ubuntu)

'delayedEvents' is possibly 'undefined'.

Check failure on line 138 in packages/react/runtime/src/lynx/tt.ts

View workflow job for this annotation

GitHub Actions / build / Build (Windows)

'delayedEvents' is possibly 'undefined'.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

lynxCoreInject.tt.publishEvent = publishEvent;
lynxCoreInject.tt.publicComponentEvent = publicComponentEvent;

// console.debug("********** After hydration:");
// printSnapshotInstance(__root as BackgroundSnapshotInstance);
Expand Down Expand Up @@ -193,12 +184,10 @@
// avoid stackoverflow
if (flushingDelayedLifecycleEvents) return;
flushingDelayedLifecycleEvents = true;
if (delayedLifecycleEvents) {
delayedLifecycleEvents.forEach((e) => {
onLifecycleEvent(e);
});
delayedLifecycleEvents.length = 0;
for (const e of delayedLifecycleEvents) {
onLifecycleEvent(e);
}
delayedLifecycleEvents.length = 0;
flushingDelayedLifecycleEvents = false;
}

Expand Down Expand Up @@ -254,14 +243,6 @@
}
}

function publicComponentEvent(_componentId: string, handlerName: string, data: EventDataType) {
publishEvent(handlerName, data);
}

function delayedPublicComponentEvent(_componentId: string, handlerName: string, data: EventDataType) {
delayedPublishEvent(handlerName, data);
}

function updateGlobalProps(newData: Record<string, any>): void {
Object.assign(lynx.__globalProps, newData);

Expand Down
Loading