Skip to content

feat(react): support ET typed page update flow#2694

Open
Yradex wants to merge 5 commits into
lynx-family:mainfrom
Yradex:wt/pick-5645-75fc-20260522
Open

feat(react): support ET typed page update flow#2694
Yradex wants to merge 5 commits into
lynx-family:mainfrom
Yradex:wt/pick-5645-75fc-20260522

Conversation

@Yradex
Copy link
Copy Markdown
Collaborator

@Yradex Yradex commented May 22, 2026

Summary by CodeRabbit

  • New Features

    • Added reload versioning system to track template refresh cycles.
    • Introduced typed element template support for improved page rendering control.
    • Added page data reset capability for updatePage operations.
  • Tests

    • Extended test coverage for element template lifecycle, reload behavior, and page data updates.

Review Change Stack

Overview

Element Template now owns the page/update lifecycle through typed ET primitives instead of relying on legacy page append semantics. This change aligns the typed element protocol, page root handling, immediate updatePage, and reloadTemplate flow so main-thread create, background hydrate, and later update events all use the same ET handle and reload-version boundaries.

Key Points

  • Adds a createTypedElement update command so the main thread can create typed native nodes through __CreateTypedElementTemplate(type, attributes, slots, uid, options).
  • Replaces legacy ET page handling with a typed page container created as __CreateTypedElementTemplate("page", null, null, "0", null), then inserts or removes React roots through page slot 0.
  • Implements immediate ET updatePage and reloadTemplate support by sharing initData merge/reset logic, rebuilding main/background ET state on reload, and resetting template/event/runtime state at the reload boundary.
  • Carries reloadVersion through hydrate and update commit payloads so stale events from before a reload are ignored while the previous array-shaped hydrate payload remains accepted.

Runtime Contract

The update stream can now carry typed creates:

[
  ElementTemplateUpdateOps.createTypedElement,
  handleId,
  type,
  attributes,
  elementSlots,
  options,
]

elementSlots are resolved from handle ids to ElementRef[][] before native create. For options, this phase only resolves list-specific options.listChildren handle references; generic nested option refs remain deferred.

Hydrate/update payloads can now be wrapped as:

{
  instances: SerializedEtNode[],
  reloadVersion?: number,
}

The background listener still accepts the old array payload for compatibility. Serialized typed nodes are modeled in the protocol, but hydrate matching remains compiled-node only for now; typed roots are reported and dropped until typed hydrate support lands.

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).
  • Changeset added, and when a BREAKING CHANGE occurs, it needs to be clearly marked (or not required).

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 22, 2026

⚠️ No Changeset found

Latest commit: 2f20f3c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

📝 Walkthrough

Walkthrough

This PR implements typed element template support with reload versioning and hydration lifecycle management. It introduces core helpers (applyUpdatePageData, reload version tracking), extends the element-template protocol with runtime options and typed element opcodes, creates a typed page root model with insertion APIs, adds createTypedElement patch processing with handle/option resolution, implements main-thread and background reload orchestration, updates hydration listeners to gate by reload version, and refactors mock templates and test fixtures throughout to reflect new typed page and insertion operations.

Changes

Typed Element Template Reload & Hydration Lifecycle

Layer / File(s) Summary
Reload version module and tests
packages/react/runtime/src/core/reload-version.ts, packages/react/runtime/__test__/core/reload-version.test.ts
Module exports getReloadVersion() and increaseReloadVersion() via direct export function declarations; test suite verifies monotonic increment behavior across calls.
Page data initialization and merging helper
packages/react/runtime/src/core/lynx-page-data.ts, packages/react/runtime/__test__/core/lynx-page-data.test.ts
New applyUpdatePageData() optionally resets lynx.__initData, validates non-null non-empty objects, and merges via Object.assign; test suite covers reset semantics, init creation, and no-op cases for invalid inputs.
Protocol types, opcodes, and serialization models
packages/react/runtime/src/element-template/protocol/opcodes.ts, packages/react/runtime/src/element-template/protocol/types.ts
Adds createTypedElement opcode (value 5); introduces RuntimeOptionValue, RuntimeOptions, RuntimeAttributeSlotValue, serialized node variants (SerializedCompiledNode, SerializedTypedNode, SerializedEtNode); adds ElementTemplateHydrateCommitContext with optional reloadVersion; updates ElementTemplateUpdateCommand and serialization types.
Global element-template API type declarations
packages/react/runtime/src/element-template/types.d.ts
Updates __CreateElementTemplate, __CreateTypedElementTemplate signatures to accept `options?: RuntimeOptions
Debug ALog formatting for typed element opcodes
packages/react/runtime/src/element-template/debug/alog.ts
Extends FormattedElementTemplateUpdateCommand union with createTypedElement variant; formatElementTemplateUpdateCommands switch decodes and emits typed-element commands from stream.
Debug wrapper for __CreateTypedElementTemplate
packages/react/runtime/src/element-template/debug/elementPAPICall.ts
Adds __CreateTypedElementTemplate to PAPI wrapper list; records returned element template refs in elementTemplateMap using args[3] as suffix.
Page creation and root management helpers
packages/react/runtime/src/element-template/runtime/page/page.ts
__page retyped to ElementRef; new createElementTemplatePage() creates typed page template via __CreateTypedElementTemplate; setupPage() accepts/stores ElementRef; insertRootIntoPage() and removeRootFromPage() manage root slot insertion/removal.
Page helper unit tests
packages/react/runtime/__test__/element-template/runtime/page/page.test.ts
Stubs global runtime functions, verifies createElementTemplatePage() returns typed page, asserts __CreateTypedElementTemplate calls with expected arguments, and verifies insert/remove helper routing to global functions with correct parameters.
Template handle native ref cleanup
packages/react/runtime/src/element-template/runtime/template/handle.ts
destroyElementTemplateId() calls deleteElementTemplateNativeRef(id) to perform native cleanup.
Main-thread root ref lifecycle tracking
packages/react/runtime/src/element-template/runtime/render/render-main-thread.ts
Introduces module-level mainThreadRootRefs with resetMainThreadRootRefs() and removeMainThreadRootRefs() helpers; roots inserted via insertRootIntoPage and stored; hydrate dispatch sends ElementTemplateHydrateCommitContext containing instances array and reloadVersion.
Main-thread render tests with reload version assertions
packages/react/runtime/__test__/element-template/runtime/render/render-main-thread.test.ts, packages/react/runtime/__test__/element-template/runtime/render/render-main-thread.contract.test.ts
Tests cast page as ElementRef, assert __InsertNodeToElementTemplate insertion calls for each root, and verify hydrate dispatch payload structure (data.instances array, data.reloadVersion number).
Typed element opcode handling in patch processor
packages/react/runtime/src/element-template/runtime/patch.ts
applyElementTemplateUpdateCommands extended with createTypedElement case; parses type, attributes, element slots, options; validates handleId in __DEV__; resolveRuntimeOptions converts listChildren.__etHandleRef entries to resolved ElementRefs; typed templates created via __CreateTypedElementTemplate and registered.
Patch listener reload version gating
packages/react/runtime/src/element-template/native/patch-listener.ts
Imports getReloadVersion; adds early-return guard in patch handler to skip updates when payload.reloadVersion is a number less than current getReloadVersion().
Typed element patch and update timing tests
packages/react/runtime/__test__/element-template/runtime/patch/element-template-patch.test.tsx, packages/react/runtime/__test__/element-template/runtime/patch/update-timing.test.ts
Covers typed element creation with slot/option handle resolution, registry updates, error reporting on unresolved handles, typed slot attribute updates, and reload version filtering for patch updates.
Main-thread and background reload implementations
packages/react/runtime/src/element-template/native/reload.ts
Exports reloadMainThread(data, options) and reloadBackground(updateData). Both increment reload version, merge/apply data, clear templates, re-render; main-thread flushes element tree; background re-initializes document/hydration; optional profiling with try/finally cleanup.
Main-thread API hook wiring for reload and updatePage
packages/react/runtime/src/element-template/native/main-thread-api.ts
renderPage creates element-template page, resets root refs, renders; updatePage gates on timing, supports reloadTemplate option routing to reloadMainThread, otherwise applies page data and flushes element tree.
Background reload native injection
packages/react/runtime/src/element-template/native/index.ts
Imports reloadBackground and assigns to lynxCoreInject.tt.onAppReload during background initialization.
Reload orchestration tests
packages/react/runtime/__test__/element-template/native/reload.test.ts
Comprehensive main-thread and background reload tests verify version increment, data update, template cleanup, rendering/serialization, hydrate dispatch with reload version, flushing, and optional profiling.
Main-thread API behavior tests for renderPage and updatePage
packages/react/runtime/__test__/element-template/native/main-thread-api.test.ts
Refactored tests with hoisted mock page state verify updatePage data merging, flush-only behavior, resetPageData semantics, empty/non-object handling, reloadTemplate routing, and non-immediate timing gate.
Hydrate payload extraction helper and utilities
packages/react/runtime/__test__/element-template/test-utils/debug/hydratePayload.ts, packages/react/runtime/__test__/element-template/test-utils/debug/compiledHydrationScenario.ts, packages/react/runtime/__test__/element-template/test-utils/debug/updateRunner.ts, plus fixture files
New extractSerializedHydrateInstances helper normalizes unknown input to array of SerializedElementTemplate; used across utilities and fixtures to simplify hydrate event handlers and payload extraction.
Background hydration listener reload version gating and typed node validation
packages/react/runtime/src/element-template/background/hydration-listener.ts
Listener handles array or ElementTemplateHydrateCommitContext payloads; adds reloadVersion gate (ignores older versions); validates each node has templateKey property; dispatched update includes reloadVersion.
Hydration listener tests with reload version and typed node validation
packages/react/runtime/__test__/element-template/runtime/hydration/hydration-listener.test.ts
Tests ignore stale hydrate payloads, reject typed roots before typed support with error reporting, assert reloadVersion in dispatched updates.
Background commit hook with reload version dispatch
packages/react/runtime/src/element-template/background/commit-hook.ts, packages/react/runtime/__test__/element-template/runtime/background/commit-hook.test.ts
Commit hook adds reloadVersion: getReloadVersion() to update payload; tests assert presence alongside ops and flushOptions.
Background reload instance lifecycle tests
packages/react/runtime/__test__/element-template/runtime/background/reload.test.ts
Tests initialize background runtime, trigger reload, dispatch hydrate event with serialized instance and reload version, validate instance manager state changes.
Snapshot lifecycle reload version and import updates
packages/react/runtime/src/snapshot/lifecycle/patch/commit.ts, packages/react/runtime/src/snapshot/lifecycle/patch/updateMainThread.ts, packages/react/runtime/src/snapshot/lifecycle/reload.ts, packages/react/runtime/src/snapshot/lynx/calledByNative.ts
Snapshot lifecycle modules import getReloadVersion/increaseReloadVersion from core; reloadMainThread adds explicit data !== null check; updatePage uses applyUpdatePageData helper.
Mock native PAPI typed element template creation
packages/react/runtime/__test__/element-template/test-utils/mock/mockNativePapi.ts
Adds mockCreateTypedElementTemplate; removes isUnknownArrayForMock and page/append stubs; updates MockNativePapi interface and stub exports.
Compiled template node model with typed element fields and mutations
packages/react/runtime/__test__/element-template/test-utils/mock/mockNativePapi/templateTree.ts
Extends CompiledTemplateNode with __typedElementType, __attributeSlots, __elementSlots; adds element-slot operation helpers; updates mutation functions to branch on typed vs. compiled elements.
Serialization refactor for typed and compiled nodes with opcode formatting
packages/react/runtime/__test__/element-template/test-utils/mock/mockNativePapi/templateTree.ts
Adds serialized node types for runtime options and typed/compiled variants; serializeTemplateNode/Instance handle both node kinds; formatUpdateCommands supports createTypedElement opcode.
Mock template tree tests for typed serialization and insertion
packages/react/runtime/__test__/element-template/test-utils/mock/mockNativePapi/templateTree.test.ts
Tests verify typed node serialization shape and moving typed children between element slots without duplication.
Native wiring tests for reload injection
packages/react/runtime/__test__/element-template/native/index.test.ts
Unmocks/mocks reload module, defines reloadBackground mock, and asserts lynxCoreInject.tt.onAppReload wiring in background initialization.
PAPI fixture outputs with typed page template
Multiple papi.txt files in fixture render directories
Fixtures add __CreateTypedElementTemplate entry for page; replace __AppendElement with __InsertNodeToElementTemplate into <page /> at index 0.
Opcode-into-template fixture cases with insert operations
Multiple case.ts and native-log.txt files in opcode-into-element-template fixtures
Fixture cases switch from __AppendElement to __InsertNodeToElementTemplate for placing nodes at slot 0.
Native log fixtures with typed page and insert operations
Multiple native-log.txt files in element-template fixtures
Native log fixtures record __CreateTypedElementTemplate for page and replace __AppendElement with __InsertNodeToElementTemplate across rendering scenarios.
Shared fixture setup with page type and template creation
packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/_shared.ts
Sets RootNode type discriminant to 'page' (from 'root'); initializes roots via __CreateTypedElementTemplate('page', ...).
Update runner test and utility with typed element formatting
packages/react/runtime/__test__/element-template/test-utils/debug/updateRunner.test.tsx, packages/react/runtime/__test__/element-template/test-utils/debug/updateRunner.ts
Update runner adds createTypedElement opcode in test stream and formatting; extends FormattedUpdateEntry union; uses hydrate payload extraction.
Debug ALog test with typed element command
packages/react/runtime/__test__/element-template/debug/alog.test.ts, packages/react/runtime/__test__/element-template/debug/elementPAPICall.test.ts
ALog test includes createTypedElement opcode and subsequent setAttribute; PAPI call test mocks typed create and asserts formatted output and profiling calls.
Snapshot lifecycle tests for updatePage initData
packages/react/runtime/__test__/snapshot/lifecycle/updateData.test.jsx
Tests validate updatePage resets or retains lynx.__initData based on resetPageData and input payload shape.
Render fixture runner with attribute plan clearing and root initialization
packages/react/runtime/__test__/element-template/test-utils/debug/renderFixtureRunner.ts
Fixture runner clears attribute-slot plans, makes children optional on RootNode, initializes via __CreateTypedElementTemplate, inserts roots, and tolerates optional children in serialization.
Sparse element slot fixture with typed page and insertion
packages/react/runtime/__test__/element-template/fixtures/render/sparse-element-slot/papi.txt
Fixture adds __CreateTypedElementTemplate for page, fixes array-wrapped null, and uses __InsertNodeToElementTemplate for node placement.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • lynx-family/lynx-stack#2550: Modifies the element-template ALog/debug formatter to support and emit formatted update commands, including support for new opcodes.
  • lynx-family/lynx-stack#2633: Updates Element Template ALOG instrumentation to log and wrap typed element template creation calls like __CreateTypedElementTemplate.
  • lynx-family/lynx-stack#2652: Updates element-template mock fixture test assertions for template serialization and node slot operations in similar test infrastructure areas.

Suggested reviewers

  • HuJean
  • hzy
  • gaoachao
  • upupming

🐰 A version counter hops in so swift,
New typed pages rise—old patterns shift!
Hydration listens with reload-versioned care,
While roots dance in and out with surgical flair.
Templates serialized, slots rearranged,
The element template world has changed! 🌟

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/react/runtime/src/element-template/background/hydration-listener.ts`:
- Around line 40-49: Ensure hydrate payloads and instance items are validated
before property access: when treating data as
ElementTemplateHydrateCommitContext in the block around getReloadVersion(),
first check that payload is non-null and typeof payload === 'object' (and that
'reloadVersion' in payload) before reading payload.reloadVersion and assigning
payload.instances to instances; likewise, when iterating over instances (the
code paths around checks like 'templateKey' in before), guard each item to be
non-null and an object and confirm the expected keys exist before using 'in' or
accessing properties. Update the checks around variable names data, payload,
instances, and any loop variable (e.g., before) to bail out or skip malformed
entries to avoid runtime throws.

In `@packages/react/runtime/src/element-template/native/reload.ts`:
- Line 60: The assignment unconditionally merges an unknown updateData into
lynx.__initData which can introduce non-object keys; before calling
Object.assign in reload.ts (the line setting lynx.__initData = Object.assign({},
lynx.__initData, updateData)), validate that updateData is a plain object (e.g.,
typeof updateData === 'object' && updateData !== null &&
!Array.isArray(updateData') or use an isPlainObject helper) and only merge when
that check passes; if updateData fails the guard, skip the merge (or log/ignore
the payload) so lynx.__initData cannot be polluted with non-object values.
- Around line 29-31: reloadMainThread currently ignores reset/merge semantics
and always mutates lynx.__initData via Object.assign; update the block that
checks typeof data to honor options.resetPageData: if options.resetPageData is
true (and data is object/non-null), replace lynx.__initData with a shallow clone
of data (e.g., lynx.__initData = { ...data }) to wipe stale keys, otherwise
preserve current behavior and merge with Object.assign(lynx.__initData, data);
keep the existing isEmptyObject check and ensure behavior aligns with
reloadTemplate's expectations.

In `@packages/react/runtime/src/element-template/runtime/patch.ts`:
- Around line 193-199: The loop building resolvedListChildren reads
(listChildren[index]!).__etHandleRef directly and can throw for
null/undefined/malformed entries; before calling resolveHandle, validate the
entry from listChildren (e.g., ensure it is non-null/undefined and has a
__etHandleRef property), and if it fails validation, skip it (or report/log) and
continue so patch processing doesn’t abort; update the loop around
resolveHandle/`options.listChildren[${index}]` to perform this guard and only
call resolveHandle when the entry shape is valid.
- Around line 76-99: The createTypedElement case
(ElementTemplateUpdateOps.createTypedElement) is missing the DEV-mode validation
for handleId that createTemplate includes; add the same DEV-only checks for
invalid or duplicate handle IDs (using the handleId and elementTemplateRegistry
symbols) before calling __CreateTypedElementTemplate and skip/continue if
validation fails so we don't overwrite existing registry entries during
debugging.

In
`@packages/react/runtime/src/element-template/runtime/render/render-main-thread.ts`:
- Around line 48-53: The loop that calls insertRootIntoPage can throw before
mainThreadRootRefs is set, causing already-inserted roots to be untracked;
initialize mainThreadRootRefs = [] before iterating over rootRefs, and as you
successfully call insertRootIntoPage for each rootRef push that rootRef into
mainThreadRootRefs (or call a helper like trackMainThreadRoot) so the inserted
roots are recorded incrementally; ensure any thrown error is rethrown after
updating mainThreadRootRefs so cleanup routines that rely on mainThreadRootRefs
can remove the partially-inserted roots.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1f2bee66-ef1c-4f0f-80b9-94a57fd5463d

📥 Commits

Reviewing files that changed from the base of the PR and between 1851187 and cb6a0bf.

📒 Files selected for processing (72)
  • packages/react/runtime/__test__/core/lynx-page-data.test.ts
  • packages/react/runtime/__test__/core/reload-version.test.ts
  • packages/react/runtime/__test__/element-template/debug/alog.test.ts
  • packages/react/runtime/__test__/element-template/debug/elementPAPICall.test.ts
  • packages/react/runtime/__test__/element-template/fixtures/hydrate/background-hydrate/_shared.tsx
  • packages/react/runtime/__test__/element-template/fixtures/hydrate/hydration-data/_shared.tsx
  • packages/react/runtime/__test__/element-template/fixtures/page/render-page/native-log.txt
  • packages/react/runtime/__test__/element-template/fixtures/patch/_shared.tsx
  • packages/react/runtime/__test__/element-template/fixtures/render/child-siblings/papi.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/component-slot-content/papi.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/component/papi.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/mapped-view-children/papi.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/mixed-children/papi.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/multiple-text/papi.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/nested-templates/papi.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/_shared.ts
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/appends-root-text-via-append-element/case.ts
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/appends-root-text-via-append-element/native-log.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/creates-template-from-attrs-and-slot-text/case.ts
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/creates-template-from-attrs-and-slot-text/native-log.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/handles-multiple-template-children-in-the-same-slot/case.ts
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/handles-multiple-template-children-in-the-same-slot/native-log.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/handles-multiple-text-nodes-in-the-same-slot/case.ts
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/handles-multiple-text-nodes-in-the-same-slot/native-log.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/ignores-non-attrs-opcode-payloads/case.ts
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/ignores-non-attrs-opcode-payloads/native-log.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/inserts-nested-templates-into-parent-slots/case.ts
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/inserts-nested-templates-into-parent-slots/native-log.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/keeps-slot-children-separated-and-ordered/case.ts
  • packages/react/runtime/__test__/element-template/fixtures/render/opcodes-into-element-template/keeps-slot-children-separated-and-ordered/native-log.txt
  • packages/react/runtime/__test__/element-template/fixtures/render/react-example/papi.txt
  • packages/react/runtime/__test__/element-template/native/index.test.ts
  • packages/react/runtime/__test__/element-template/native/main-thread-api.test.ts
  • packages/react/runtime/__test__/element-template/native/reload.test.ts
  • packages/react/runtime/__test__/element-template/runtime/background/commit-hook.test.ts
  • packages/react/runtime/__test__/element-template/runtime/background/reload.test.ts
  • packages/react/runtime/__test__/element-template/runtime/hydration/hydration-listener.test.ts
  • packages/react/runtime/__test__/element-template/runtime/page/page.test.ts
  • packages/react/runtime/__test__/element-template/runtime/patch/element-template-patch.test.tsx
  • packages/react/runtime/__test__/element-template/runtime/patch/update-timing.test.ts
  • packages/react/runtime/__test__/element-template/runtime/render/render-main-thread.contract.test.ts
  • packages/react/runtime/__test__/element-template/runtime/render/render-main-thread.test.ts
  • packages/react/runtime/__test__/element-template/test-utils/debug/compiledHydrationScenario.ts
  • packages/react/runtime/__test__/element-template/test-utils/debug/hydratePayload.ts
  • packages/react/runtime/__test__/element-template/test-utils/debug/renderFixtureRunner.ts
  • packages/react/runtime/__test__/element-template/test-utils/debug/updateRunner.test.tsx
  • packages/react/runtime/__test__/element-template/test-utils/debug/updateRunner.ts
  • packages/react/runtime/__test__/element-template/test-utils/mock/mockNativePapi.ts
  • packages/react/runtime/__test__/element-template/test-utils/mock/mockNativePapi/templateTree.test.ts
  • packages/react/runtime/__test__/element-template/test-utils/mock/mockNativePapi/templateTree.ts
  • packages/react/runtime/__test__/snapshot/lifecycle/updateData.test.jsx
  • packages/react/runtime/src/core/lynx-page-data.ts
  • packages/react/runtime/src/core/reload-version.ts
  • packages/react/runtime/src/element-template/background/commit-hook.ts
  • packages/react/runtime/src/element-template/background/hydration-listener.ts
  • packages/react/runtime/src/element-template/debug/alog.ts
  • packages/react/runtime/src/element-template/debug/elementPAPICall.ts
  • packages/react/runtime/src/element-template/native/index.ts
  • packages/react/runtime/src/element-template/native/main-thread-api.ts
  • packages/react/runtime/src/element-template/native/patch-listener.ts
  • packages/react/runtime/src/element-template/native/reload.ts
  • packages/react/runtime/src/element-template/protocol/opcodes.ts
  • packages/react/runtime/src/element-template/protocol/types.ts
  • packages/react/runtime/src/element-template/runtime/page/page.ts
  • packages/react/runtime/src/element-template/runtime/patch.ts
  • packages/react/runtime/src/element-template/runtime/render/render-main-thread.ts
  • packages/react/runtime/src/element-template/runtime/template/handle.ts
  • packages/react/runtime/src/element-template/types.d.ts
  • packages/react/runtime/src/snapshot/lifecycle/patch/commit.ts
  • packages/react/runtime/src/snapshot/lifecycle/patch/updateMainThread.ts
  • packages/react/runtime/src/snapshot/lifecycle/reload.ts
  • packages/react/runtime/src/snapshot/lynx/calledByNative.ts
💤 Files with no reviewable changes (1)
  • packages/react/runtime/src/element-template/runtime/template/handle.ts

Comment thread packages/react/runtime/src/element-template/native/reload.ts Outdated
Comment thread packages/react/runtime/src/element-template/native/reload.ts Outdated
Comment thread packages/react/runtime/src/element-template/runtime/patch.ts
Comment thread packages/react/runtime/src/element-template/runtime/patch.ts
@codecov
Copy link
Copy Markdown

codecov Bot commented May 22, 2026

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 22, 2026

Merging this PR will not alter performance

✅ 81 untouched benchmarks
⏩ 26 skipped benchmarks1


Comparing Yradex:wt/pick-5645-75fc-20260522 (2f20f3c) with main (2d64575)2

Open in CodSpeed

Footnotes

  1. 26 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (1851187) during the generation of this report, so 2d64575 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 22, 2026

React Example with Element Template

#867 Bundle Size — 203.8KiB (+0.81%).

2f20f3c(current) vs 60bdcd4 main#858(baseline)

Bundle metrics  Change 4 changes Regression 1 regression
                 Current
#867
     Baseline
#858
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 27.9% 0%
No change  Chunks 0 0
No change  Assets 4 4
Change  Modules 121(+21%) 100
Regression  Duplicate Modules 49(+63.33%) 30
Change  Duplicate Code 45.28%(+15.45%) 39.22%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#867
     Baseline
#858
No change  IMG 145.76KiB 145.76KiB
Regression  Other 58.04KiB (+2.9%) 56.41KiB

Bundle analysis reportBranch Yradex:wt/pick-5645-75fc-2026052...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 22, 2026

React External

#1715 Bundle Size — 698.11KiB (+0.01%).

2f20f3c(current) vs 60bdcd4 main#1707(baseline)

Bundle metrics  Change 1 change
                 Current
#1715
     Baseline
#1707
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 41.23% 0%
No change  Chunks 0 0
No change  Assets 3 3
No change  Modules 17 17
No change  Duplicate Modules 5 5
No change  Duplicate Code 8.59% 8.59%
No change  Packages 0 0
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#1715
     Baseline
#1707
Regression  Other 698.11KiB (+0.01%) 698.01KiB

Bundle analysis reportBranch Yradex:wt/pick-5645-75fc-2026052...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 22, 2026

Web Explorer

#10174 Bundle Size — 903.53KiB (0%).

2f20f3c(current) vs 60bdcd4 main#10165(baseline)

Bundle metrics  Change 2 changes
                 Current
#10174
     Baseline
#10165
No change  Initial JS 45.06KiB 45.06KiB
No change  Initial CSS 2.22KiB 2.22KiB
No change  Cache Invalidation 0% 0%
No change  Chunks 9 9
No change  Assets 11 11
Change  Modules 231(+0.87%) 229
No change  Duplicate Modules 11 11
Change  Duplicate Code 27.12%(-0.04%) 27.13%
No change  Packages 10 10
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#10174
     Baseline
#10165
No change  JS 499.15KiB 499.15KiB
No change  Other 402.16KiB 402.16KiB
No change  CSS 2.22KiB 2.22KiB

Bundle analysis reportBranch Yradex:wt/pick-5645-75fc-2026052...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 22, 2026

React MTF Example

#1732 Bundle Size — 208.77KiB (~+0.01%).

2f20f3c(current) vs 60bdcd4 main#1723(baseline)

Bundle metrics  Change 3 changes
                 Current
#1732
     Baseline
#1723
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 46.72% 0%
No change  Chunks 0 0
No change  Assets 3 3
Change  Modules 196(+0.51%) 195
No change  Duplicate Modules 77 77
Change  Duplicate Code 44.15%(-0.05%) 44.17%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#1732
     Baseline
#1723
No change  IMG 111.23KiB 111.23KiB
Regression  Other 97.54KiB (+0.02%) 97.52KiB

Bundle analysis reportBranch Yradex:wt/pick-5645-75fc-2026052...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 22, 2026

React Example

#8598 Bundle Size — 237.82KiB (~+0.01%).

2f20f3c(current) vs 60bdcd4 main#8589(baseline)

Bundle metrics  Change 3 changes
                 Current
#8598
     Baseline
#8589
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 38.71% 0%
No change  Chunks 0 0
No change  Assets 4 4
Change  Modules 201(+0.5%) 200
No change  Duplicate Modules 80 80
Change  Duplicate Code 44.66%(-0.04%) 44.68%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#8598
     Baseline
#8589
No change  IMG 145.76KiB 145.76KiB
Regression  Other 92.07KiB (+0.02%) 92.05KiB

Bundle analysis reportBranch Yradex:wt/pick-5645-75fc-2026052...Project dashboard


Generated by RelativeCIDocumentationReport issue

@Yradex Yradex marked this pull request as ready for review May 22, 2026 09:10
@Yradex Yradex requested review from HuJean and hzy as code owners May 22, 2026 09:10
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/react/runtime/src/element-template/runtime/patch.ts (1)

76-93: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject malformed typed-create payload shapes before calling native.

createTemplate rejects bad top-level payload shapes in DEV, but createTypedElement still accepts them. For example, a non-array elementSlots becomes null in resolveElementSlots(), and a primitive/non-object options is passed through unchanged by resolveRuntimeOptions(). That hides protocol bugs and can hand invalid data to __CreateTypedElementTemplate across the native boundary.

Suggested fix
       case ElementTemplateUpdateOps.createTypedElement: {
         const handleId = stream[i++] as number;
         const type = stream[i++] as string;
         const attributes = stream[i++] as TypedElementAttributesCommand | null | undefined;
         const elementSlots = stream[i++] as number[][] | null | undefined;
         const options = stream[i++] as RuntimeOptionsCommand | null | undefined;
 
         if (__DEV__) {
-          const createError = validateCreateHandleId(handleId);
+          const createError = validateCreateTypedElementPayload(handleId, elementSlots, options);
           if (createError) {
             lynx.reportError(createError);
             continue;
           }
         }
@@
 function validateCreateHandleId(handleId: number): Error | null {
   if (!isValidHandleId(handleId)) {
     return new Error(`ElementTemplate update has invalid handleId ${String(handleId)}.`);
   }
   if (elementTemplateRegistry.get(handleId)) {
     return new Error(`ElementTemplate update received duplicate handleId ${handleId}.`);
   }
   return null;
 }
 
+function validateCreateTypedElementPayload(
+  handleId: number,
+  elementSlots: number[][] | null | undefined,
+  options: RuntimeOptionsCommand | null | undefined,
+): Error | null {
+  const handleError = validateCreateHandleId(handleId);
+  if (handleError) {
+    return handleError;
+  }
+  if (elementSlots != null && !Array.isArray(elementSlots)) {
+    return new Error(
+      'ElementTemplate update typed create elementSlots must be an array, null, or undefined.',
+    );
+  }
+  if (options != null && (typeof options !== 'object' || Array.isArray(options))) {
+    return new Error(
+      'ElementTemplate update typed create options must be an object, null, or undefined.',
+    );
+  }
+  if (
+    options != null
+    && 'listChildren' in options
+    && options.listChildren != null
+    && !Array.isArray(options.listChildren)
+  ) {
+    return new Error(
+      'ElementTemplate update options.listChildren must be an array, null, or undefined.',
+    );
+  }
+  return null;
+}
+
 function validateCreateTemplatePayload(
   handleId: number,
   attributeSlots: SerializableValue[] | null | undefined,
   elementSlots: number[][] | null | undefined,
 ): Error | null {

Also applies to: 189-199

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/react/runtime/src/element-template/runtime/patch.ts` around lines 76
- 93, The createTypedElement handler (case
ElementTemplateUpdateOps.createTypedElement) currently passes malformed
elementSlots and options to native; add explicit runtime-shape checks before
calling native: after validateCreateHandleId and before
resolveElementSlots/resolveRuntimeOptions, verify elementSlots is either
null/undefined or an array and options is either null/undefined or an object,
and if not call lynx.reportError with a descriptive message and continue to skip
the native call; apply the same guards to the other createTypedElement-like
branch around lines 189-199 so __CreateTypedElementTemplate never receives
primitive/non-array payloads.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/react/runtime/src/element-template/runtime/patch.ts`:
- Around line 76-93: The createTypedElement handler (case
ElementTemplateUpdateOps.createTypedElement) currently passes malformed
elementSlots and options to native; add explicit runtime-shape checks before
calling native: after validateCreateHandleId and before
resolveElementSlots/resolveRuntimeOptions, verify elementSlots is either
null/undefined or an array and options is either null/undefined or an object,
and if not call lynx.reportError with a descriptive message and continue to skip
the native call; apply the same guards to the other createTypedElement-like
branch around lines 189-199 so __CreateTypedElementTemplate never receives
primitive/non-array payloads.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 67b95089-63b5-4d04-a0fb-54a8c07dd1fe

📥 Commits

Reviewing files that changed from the base of the PR and between cb6a0bf and 2f20f3c.

📒 Files selected for processing (6)
  • packages/react/runtime/__test__/element-template/fixtures/render/sparse-element-slot/papi.txt
  • packages/react/runtime/__test__/element-template/native/reload.test.ts
  • packages/react/runtime/__test__/element-template/runtime/patch/element-template-patch.test.tsx
  • packages/react/runtime/__test__/element-template/test-utils/debug/renderFixtureRunner.ts
  • packages/react/runtime/src/element-template/native/reload.ts
  • packages/react/runtime/src/element-template/runtime/patch.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant