Skip to content

feat(react/runtime): delay the timing of runOnMainThread()#1667

Merged
hzy merged 1 commit intolynx-family:mainfrom
Yradex:mts/run-on-mt/x
Sep 11, 2025
Merged

feat(react/runtime): delay the timing of runOnMainThread()#1667
hzy merged 1 commit intolynx-family:mainfrom
Yradex:mts/run-on-mt/x

Conversation

@Yradex
Copy link
Copy Markdown
Collaborator

@Yradex Yradex commented Sep 8, 2025

Summary by CodeRabbit

  • New Features
    • Queues main-thread tasks during render/hydration and runs them afterward for smoother, more reliable UI updates.
  • Bug Fixes
    • Prevents main-thread actions from running during initial render, avoiding null references and ensuring correct hydration behavior.
  • Compatibility
    • Plugin now supports @lynx-js/react v0.113.0 in addition to previous versions.
  • Tests
    • Reworked and expanded test coverage for main-thread task execution and hydration timing.
  • Chores
    • Added changeset entries for versioning and compatibility notes.

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 Sep 8, 2025

🦋 Changeset detected

Latest commit: cf82fa7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@lynx-js/react Minor
@lynx-js/react-rsbuild-plugin Patch
@lynx-js/react-alias-rsbuild-plugin Patch

Not sure what this means? Click here to learn what changesets are.

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 8, 2025

📝 Walkthrough

Walkthrough

Implements delayed execution for runOnMainThread during initial render/hydration, plumbing delayed tasks through patch payloads and executing them on the main thread via a new runtime API. Updates listeners, bindings, and global interfaces; adds tests reflecting new behavior; updates peer dependency range; adds changesets.

Changes

Cohort / File(s) Summary
Runtime: delayed runOnMainThread flow
packages/react/runtime/src/worklet/runOnMainThread.ts, packages/react/runtime/src/lifecycle/patch/commit.ts, packages/react/runtime/src/lifecycle/patch/updateMainThread.ts, packages/react/runtime/src/lynx/tt.ts
Adds delay queue for runOnMainThread during render/hydration; extends PatchList with optional delayedRunOnMainThreadData; plumbs delayed data into patches and executes them with controlled EOM flushing; uses isRendering/__globalSnapshotPatch gating.
Worklet runtime: main-thread task API
packages/react/worklet-runtime/src/runOnMainThread.ts, packages/react/worklet-runtime/src/listeners.ts, packages/react/worklet-runtime/src/bindings/bindings.ts, packages/react/worklet-runtime/src/global.ts, packages/react/worklet-runtime/src/workletRuntime.ts
Introduces runRunOnMainThreadTask to execute worklets on main thread and dispatch FunctionCallRet; replaces inline handling in listeners; exposes _runRunOnMainThreadTask on lynxWorkletImpl; exports binding wrapper.
Tests: runtime and worklet runtime
packages/react/runtime/__test__/worklet/runOnMainThread.test.js, packages/react/runtime/__test__/worklet/runOnMainThread.test.jsx, packages/react/worklet-runtime/__test__/runOnMainThread.test.js
Removes old JS test; adds JSX test suite covering delay during render/hydration and gating; adds worklet-runtime test for runRunOnMainThreadTask dispatch and return path.
Versioning / compatibility
.changeset/lemon-streets-watch.md, .changeset/smooth-dragons-smash.md, packages/rspeedy/plugin-react/package.json
Adds changesets (minor bump for @lynx-js/react; plugin patch + compatibility note); expands @lynx-js/react peer range to include ^0.113.0.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • hzy
  • colinaaa
  • gaoachao

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately summarizes the primary change: delaying the timing of runOnMainThread and scopes it to react/runtime using conventional-commit style. It is clear, concise, and directly reflects the core modifications in the changeset (hydration-aware delayed execution).

Poem

I queued my tasks, then nibbled hay,
Waiting for hydrate’s sunny day.
Now hops to main thread, swift and bright,
Return values tucked in tight.
Patch-list crumbs, a tidy spread—
Carrots flushed, then off to bed. 🥕🐇

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Sep 8, 2025

Codecov Report

❌ Patch coverage is 94.11765% with 3 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...ges/react/worklet-runtime/src/bindings/bindings.ts 0.00% 2 Missing ⚠️
packages/react/worklet-runtime/src/listeners.ts 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@relativeci
Copy link
Copy Markdown

relativeci Bot commented Sep 8, 2025

React Example

#5093 Bundle Size — 238.9KiB (+0.29%).

cf82fa7(current) vs 69b3ae0 main#5090(baseline)

Bundle metrics  Change 2 changes
                 Current
#5093
     Baseline
#5090
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 38.81% 0%
No change  Chunks 0 0
No change  Assets 4 4
No change  Modules 163 163
No change  Duplicate Modules 67 67
Change  Duplicate Code 46.79%(-0.19%) 46.88%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#5093
     Baseline
#5090
No change  IMG 145.76KiB 145.76KiB
Regression  Other 93.14KiB (+0.75%) 92.45KiB

Bundle analysis reportBranch Yradex:mts/run-on-mt/xProject dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented Sep 8, 2025

Web Explorer

#5086 Bundle Size — 362.79KiB (0%).

cf82fa7(current) vs 69b3ae0 main#5083(baseline)

Bundle metrics  Change 2 changes
                 Current
#5086
     Baseline
#5083
No change  Initial JS 145.21KiB 145.21KiB
No change  Initial CSS 31.89KiB 31.89KiB
No change  Cache Invalidation 0% 0%
No change  Chunks 8 8
No change  Assets 8 8
Change  Modules 220(+0.92%) 218
No change  Duplicate Modules 16 16
Change  Duplicate Code 3.33%(-0.3%) 3.34%
No change  Packages 4 4
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#5086
     Baseline
#5083
No change  JS 236.88KiB 236.88KiB
No change  Other 94.02KiB 94.02KiB
No change  CSS 31.89KiB 31.89KiB

Bundle analysis reportBranch Yradex:mts/run-on-mt/xProject dashboard


Generated by RelativeCIDocumentationReport issue

@Yradex Yradex marked this pull request as ready for review September 8, 2025 09:21
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Sep 8, 2025

CodSpeed Performance Report

Merging #1667 will not alter performance

Comparing Yradex:mts/run-on-mt/x (cf82fa7) with main (69b3ae0)

Summary

✅ 53 untouched benchmarks

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: 4

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/lifecycle/patch/commit.ts (1)

140-145: Don’t drop queued main-thread tasks when there’s no snapshot patch.

If runOnMainThread is called during render but diff yields no snapshotPatch, the early return skips sending delayed tasks, potentially stalling them indefinitely.

Apply this diff to gate the early return on an empty delayed queue:

-      if (!snapshotPatch && workletRefInitValuePatch.length === 0) {
+      if (!snapshotPatch && workletRefInitValuePatch.length === 0 && delayedRunOnMainThreadData.length === 0) {
         // before hydration, skip patch
         applyQueuedRefs();
         originalPreactCommit?.(vnode, commitQueue);
         return;
       }

Add a follow-up test to cover “no snapshot patch but delayed tasks exist”.

🧹 Nitpick comments (11)
.changeset/lemon-streets-watch.md (1)

5-9: Clarify behavior change and minimum SDK in notes.

Add an explicit note that this requires Lynx SDK >= 2.14 and that initial-render calls are deferred (queued and drained post-hydration), plus a brief migration note.

Apply this diff:

 fix: Delay execution of `runOnMainThread()` during initial render

 When called during the initial render, `runOnMainThread()` would execute before the `main-thread:ref` was hydrated, causing it to be incorrectly set to null.

-This change delays the function's execution to ensure the ref is available and correctly assigned.
+This change delays the function's execution to ensure the ref is available and correctly assigned.
+
+Notes:
+- Requires Lynx SDK >= 2.14.
+- Calls made during initial render are queued and executed after hydration completes; ordering is preserved.
+- Introduces an internal main-thread runner (_runRunOnMainThreadTask) used by the runtime to drain queued tasks.
packages/react/runtime/__test__/worklet/runOnMainThread.test.jsx (3)

79-97: Avoid brittle inline snapshot for event payload; assert structure instead.

Inline-snapshot hardcodes resolveId=1 and the full JSON string, which is fragile. Parse and assert shape.

-    expect(lynx.getCoreContext().dispatchEvent.mock.calls).toMatchInlineSnapshot(`
-      [
-        [
-          {
-            "data": "{"worklet":{"_wkltId":"835d:450ef:2"},"params":[1,["args"]],"resolveId":1}",
-            "type": "Lynx.Worklet.runWorkletCtx",
-          },
-        ],
-      ]
-    `);
+    const evt = lynx.getCoreContext().dispatchEvent.mock.calls[0][0];
+    expect(evt.type).toBe(WorkletEvents.runWorkletCtx);
+    const payload = JSON.parse(evt.data);
+    expect(payload.worklet).toEqual(worklet);
+    expect(payload.params).toEqual([1, ['args']]);
+    expect(typeof payload.resolveId).toBe('number');

138-222: Prefer intent-focused assertions over full MTFQueue snapshots.

The long inline snapshot couples the test to internal shapes. Assert API order (and select critical fields) to reduce churn.

-    {
-      expect(MTFQueue).toMatchInlineSnapshot(`
-        [
-          { "api": "runWorklet", ... },
-          { "api": "setShouldFlush", "value": false },
-          { "api": "_runRunOnMainThreadTask", "args": [], "worklet": "MTF_during_render" },
-          { "api": "_runRunOnMainThreadTask", "args": [], "worklet": "MTF_after_render" },
-          { "api": "setShouldFlush", "value": true },
-          { "api": "__FlushElementTree" },
-        ]
-      `);
-      expect(lynx.getCoreContext().dispatchEvent.mock.calls).toMatchInlineSnapshot(`[]`);
-    }
+    {
+      expect(MTFQueue.map(i => i.api)).toEqual([
+        'runWorklet',
+        'setShouldFlush',
+        '_runRunOnMainThreadTask',
+        '_runRunOnMainThreadTask',
+        'setShouldFlush',
+        '__FlushElementTree',
+      ]);
+      expect(MTFQueue[0].worklet?._wkltId).toBe('MTRef'); // ensure ref hydration happened
+      expect(lynx.getCoreContext().dispatchEvent).not.toHaveBeenCalled();
+    }

224-322: Apply the same snapshot simplification for update-phase test.

Mirror the compact order assertions; strengthens the signal while avoiding brittle structure comparisons.

-    {
-      expect(MTFQueue).toMatchInlineSnapshot(`
-        [
-          { "api": "runWorklet", ... },
-          { "api": "setShouldFlush", "value": false },
-          { "api": "_runRunOnMainThreadTask", "args": [], "worklet": "MTF_during_render" },
-          { "api": "setShouldFlush", "value": true },
-          { "api": "__FlushElementTree" },
-        ]
-      `);
-      expect(lynx.getCoreContext().dispatchEvent.mock.calls).toMatchInlineSnapshot(`[]`);
-    }
+    {
+      expect(MTFQueue.map(i => i.api)).toEqual([
+        'runWorklet',
+        'setShouldFlush',
+        '_runRunOnMainThreadTask',
+        'setShouldFlush',
+        '__FlushElementTree',
+      ]);
+      expect(MTFQueue[0].worklet?._wkltId).toBe('MTRef');
+      expect(lynx.getCoreContext().dispatchEvent).not.toHaveBeenCalled();
+    }
packages/react/worklet-runtime/src/workletRuntime.ts (1)

15-24: Minor naming nit: consider runMainThreadTask.

runRunOnMainThreadTask is a mouthful; runMainThreadTask communicates intent without repetition. Renaming is optional and can be deferred.

packages/react/runtime/src/lynx/tt.ts (1)

118-126: Avoid duplicated “drain delayed data into patch” logic across files.

Both tt.ts and commit.ts implement the same drain-and-attach flow. Consider a small helper in ../worklet/runOnMainThread.ts, e.g., drainDelayedMainThreadDataInto(patchList), to centralize behavior and future-proof ordering.

packages/react/worklet-runtime/__test__/runOnMainThread.test.js (2)

22-24: Tighten teardown to avoid cross-test leakage.

Also reset globals created by initWorklet/registration to keep tests hermetic.

Apply this diff:

 afterEach(() => {
   delete globalThis.lynxWorkletImpl;
+  delete globalThis.lynx;
+  delete globalThis.runWorklet;
+  delete globalThis.registerWorklet;
 });

34-45: Consider adding an error-path assertion.

runRunOnMainThreadTask always dispatches a FunctionCallRet even on throw. Add a test with a throwing worklet to lock current semantics (until TODO is addressed).

packages/react/runtime/src/lifecycle/patch/commit.ts (1)

186-209: Payload size note.

Including delayedRunOnMainThreadData in the JSON payload can grow frames; if needed later, consider sending only worklet ids and minimal params.

packages/react/worklet-runtime/src/bindings/bindings.ts (1)

82-83: Minor naming nit.

runRunOnMainThreadTask reads a bit repetitive; runTaskOnMainThread would be shorter. Non-blocking.

packages/react/worklet-runtime/src/runOnMainThread.ts (1)

7-21: Always-dispatch pattern is pragmatic; consider explicit error channel.

Currently errors result in returnValue being undefined but still “resolve”. When you tackle the TODO, emit an error field or a separate reject event to allow background to reject the promise.

Example (shape-only, adjust types/consumers before landing):

 export function runRunOnMainThreadTask(task: Worklet, params: ClosureValueType[], resolveId: number): void {
-  let returnValue;
+  let returnValue, error: unknown = undefined;
   try {
     returnValue = runWorklet(task, params);
+  } catch (e) {
+    error = e instanceof Error ? { message: e.message, name: e.name } : String(e);
   } finally {
     lynx.getJSContext().dispatchEvent({
       type: WorkletEvents.FunctionCallRet,
       data: JSON.stringify({
         resolveId,
-        returnValue,
+        returnValue,
+        error,
       } as RunWorkletCtxRetData),
     });
   }
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d7c5da3 and af63eb6.

📒 Files selected for processing (13)
  • .changeset/lemon-streets-watch.md (1 hunks)
  • packages/react/runtime/__test__/worklet/runOnMainThread.test.js (0 hunks)
  • packages/react/runtime/__test__/worklet/runOnMainThread.test.jsx (1 hunks)
  • packages/react/runtime/src/lifecycle/patch/commit.ts (4 hunks)
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts (4 hunks)
  • packages/react/runtime/src/lynx/tt.ts (2 hunks)
  • packages/react/runtime/src/worklet/runOnMainThread.ts (2 hunks)
  • packages/react/worklet-runtime/__test__/runOnMainThread.test.js (1 hunks)
  • packages/react/worklet-runtime/src/bindings/bindings.ts (1 hunks)
  • packages/react/worklet-runtime/src/global.ts (1 hunks)
  • packages/react/worklet-runtime/src/listeners.ts (2 hunks)
  • packages/react/worklet-runtime/src/runOnMainThread.ts (1 hunks)
  • packages/react/worklet-runtime/src/workletRuntime.ts (2 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/runtime/test/worklet/runOnMainThread.test.js
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-12T16:09:32.413Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1497
File: packages/react/transform/tests/__swc_snapshots__/src/swc_plugin_snapshot/mod.rs/basic_full_static.js:9-10
Timestamp: 2025-08-12T16:09:32.413Z
Learning: In the Lynx stack, functions prefixed with `__` that are called in transformed code may be injected globally by the Lynx Engine at runtime rather than exported from the React runtime package. For example, `__CreateFrame` is injected globally by the Lynx Engine, not exported from lynx-js/react.

Applied to files:

  • packages/react/worklet-runtime/src/global.ts
🧬 Code graph analysis (11)
packages/react/worklet-runtime/src/global.ts (1)
packages/react/worklet-runtime/src/bindings/types.ts (2)
  • Worklet (41-52)
  • ClosureValueType (28-39)
packages/react/worklet-runtime/src/bindings/bindings.ts (2)
packages/react/worklet-runtime/src/runOnMainThread.ts (1)
  • runRunOnMainThreadTask (7-21)
packages/react/worklet-runtime/src/bindings/types.ts (2)
  • Worklet (41-52)
  • ClosureValueType (28-39)
packages/react/runtime/src/lifecycle/patch/commit.ts (1)
packages/react/runtime/src/worklet/runOnMainThread.ts (2)
  • delayedRunOnMainThreadData (13-13)
  • takeDelayedRunOnMainThreadData (15-19)
packages/react/worklet-runtime/src/runOnMainThread.ts (1)
packages/react/worklet-runtime/src/bindings/types.ts (2)
  • Worklet (41-52)
  • ClosureValueType (28-39)
packages/react/runtime/__test__/worklet/runOnMainThread.test.jsx (6)
packages/react/runtime/src/worklet/functionality.ts (1)
  • clearConfigCacheForTesting (29-29)
packages/react/runtime/__test__/utils/envManager.ts (1)
  • globalEnvManager (86-86)
packages/react/runtime/src/lifecycle/patch/commit.ts (1)
  • replaceCommitHook (246-246)
packages/react/runtime/src/worklet/destroy.ts (1)
  • destroyWorklet (9-16)
packages/react/runtime/src/lifecycle/patch/snapshotPatch.ts (1)
  • initGlobalSnapshotPatch (65-67)
packages/react/runtime/src/worklet/runOnMainThread.ts (1)
  • runOnMainThread (39-66)
packages/react/worklet-runtime/__test__/runOnMainThread.test.js (2)
packages/react/worklet-runtime/src/workletRuntime.ts (1)
  • initWorklet (171-171)
packages/react/worklet-runtime/src/runOnMainThread.ts (1)
  • runRunOnMainThreadTask (7-21)
packages/react/worklet-runtime/src/workletRuntime.ts (2)
packages/react/worklet-runtime/src/bindings/bindings.ts (1)
  • runRunOnMainThreadTask (82-82)
packages/react/worklet-runtime/src/runOnMainThread.ts (1)
  • runRunOnMainThreadTask (7-21)
packages/react/runtime/src/lynx/tt.ts (1)
packages/react/runtime/src/worklet/runOnMainThread.ts (2)
  • delayedRunOnMainThreadData (13-13)
  • takeDelayedRunOnMainThreadData (15-19)
packages/react/runtime/src/worklet/runOnMainThread.ts (5)
packages/react/worklet-runtime/src/bindings/index.ts (2)
  • RunWorkletCtxData (12-12)
  • WorkletEvents (12-12)
packages/react/worklet-runtime/src/bindings/events.ts (2)
  • RunWorkletCtxData (29-29)
  • WorkletEvents (29-29)
packages/react/worklet-runtime/src/bindings/types.ts (1)
  • Worklet (41-52)
packages/react/runtime/src/lifecycle/patch/snapshotPatch.ts (1)
  • __globalSnapshotPatch (53-53)
packages/react/runtime/src/lifecycle/isRendering.ts (1)
  • isRendering (10-10)
packages/react/worklet-runtime/src/listeners.ts (2)
packages/react/worklet-runtime/src/runOnMainThread.ts (1)
  • runRunOnMainThreadTask (7-21)
packages/react/worklet-runtime/src/bindings/types.ts (1)
  • ClosureValueType (28-39)
packages/react/runtime/src/lifecycle/patch/updateMainThread.ts (3)
packages/react/runtime/src/worklet/functionality.ts (1)
  • isMtsEnabled (29-29)
packages/react/worklet-runtime/src/runOnMainThread.ts (1)
  • runRunOnMainThreadTask (7-21)
packages/react/worklet-runtime/src/bindings/types.ts (1)
  • ClosureValueType (28-39)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: benchmark / nodejs-benchmark
🔇 Additional comments (19)
packages/react/runtime/__test__/worklet/runOnMainThread.test.jsx (3)

116-124: LGTM: main-thread guard.

The error branch and message are precise and match the runtime checks.


126-136: LGTM: SDK gating.

Version check and error path are covered; beforeEach resets the SDK version back to 2.14.


142-146: No import required—renderPage is injected globally by the test harness via injectCalledByNative.

packages/react/worklet-runtime/src/workletRuntime.ts (2)

11-11: Good: explicit import for the main-thread runner.

Brings the runner into the runtime module for controlled exposure.


15-24: Type already includes _runRunOnMainThreadTask. The LynxWorkletImpl definition in packages/react/worklet-runtime/src/global.ts already declares this property, so no additional typing updates are needed.

packages/react/runtime/src/lynx/tt.ts (2)

25-25: Import looks correct; live-binding check is safe.

Using the live import to peek queue length before draining is fine here.


124-126: Good: piggyback delayed runOnMainThread data onto the hydration patch.

This guarantees queued tasks are flushed right after firstScreen commit.

packages/react/worklet-runtime/__test__/runOnMainThread.test.js (1)

9-20: Test bootstrapping is minimal and clear.

initWorklet + JSContext dispatch spy is sufficient for this unit.

packages/react/runtime/src/lifecycle/patch/commit.ts (2)

24-25: Type import aligns with new PatchList field.

No issues with the public surface expansion here.


66-70: Verify native/Lepus patch parser compatibility
Ensure the native (Lepus) patch payload parser either ignores the new delayedRunOnMainThreadData field or has been updated to consume it to avoid rollout mismatches.

packages/react/worklet-runtime/src/bindings/bindings.ts (1)

66-74: Binding is correct and safely optional-chained.

The pass-through to global impl is clean.

packages/react/worklet-runtime/src/global.ts (1)

21-21: Global surface addition looks good.

Signature matches the binding and runtime implementation.

packages/react/runtime/src/worklet/runOnMainThread.ts (3)

13-19: Queue drain API is clear and side-effect-free.

takeDelayedRunOnMainThreadData() resets the queue predictably.


50-59: Delay condition is correct.

Queuing when __globalSnapshotPatch is undefined or during render avoids pre-hydration dispatch issues.


60-63: Verify worklet payload and JSON-safe params

  • Confirm runRunOnMainThreadTask only relies on worklet._wkltId (not the full object)
  • Document or pre-normalize params so JSON.stringify can’t fail (only JSON-serializable values or IDs/handles)
packages/react/runtime/src/lifecycle/patch/updateMainThread.ts (2)

5-10: Imports look correct and scoped to bindings/features added in this PR.

No issues.

Also applies to: 20-20


45-45: resolveId is correctly typed as number end-to-end. Verified that RunWorkletCtxData.resolveId is declared as a number in the worklet-runtime bindings and is preserved through JSON.stringify/JSON.parse in the patch update (no string coercion). No local casting is necessary.

packages/react/worklet-runtime/src/listeners.ts (2)

5-7: Imports update aligns with the new delegation path.

Looks good.


16-18: resolveId type and payload are correct: RunWorkletCtxData.resolveId is declared as number and the dispatchEvent call sends it via JSON.stringify(data), so it’s parsed back as a numeric value.

Comment thread .changeset/lemon-streets-watch.md
Comment thread packages/react/runtime/src/lifecycle/patch/commit.ts
Comment thread packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
Comment thread packages/react/worklet-runtime/src/listeners.ts
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: 0

🧹 Nitpick comments (2)
packages/react/worklet-runtime/__test__/runOnMainThread.test.js (2)

36-45: Avoid brittle inline snapshot; assert fields directly.

Inline snapshots here are fragile (string escaping of JSON can drift). Prefer explicit assertions on type and decoded payload.

Apply this diff:

-    expect(globalThis.lynx.getJSContext().dispatchEvent.mock.calls).toMatchInlineSnapshot(`
-      [
-        [
-          {
-            "data": "{"resolveId":10,"returnValue":"ret"}",
-            "type": "Lynx.Worklet.FunctionCallRet",
-          },
-        ],
-      ]
-    `);
+    const calls = globalThis.lynx.getJSContext().dispatchEvent.mock.calls;
+    expect(calls).toHaveLength(1);
+    expect(calls[0][0].type).toBe('Lynx.Worklet.FunctionCallRet');
+    expect(JSON.parse(calls[0][0].data)).toEqual({ resolveId: 10, returnValue: 'ret' });

22-24: Tidy up globals between tests.

Clean up lynx and SystemInfo as well to avoid hidden cross-test coupling.

Apply this diff:

 afterEach(() => {
   delete globalThis.lynxWorkletImpl;
+  delete globalThis.lynx;
+  delete globalThis.SystemInfo;
 });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af63eb6 and 8b42f4c.

📒 Files selected for processing (16)
  • .changeset/lemon-streets-watch.md (1 hunks)
  • .changeset/smooth-dragons-smash.md (1 hunks)
  • packages/react/runtime/__test__/worklet/runOnMainThread.test.js (0 hunks)
  • packages/react/runtime/__test__/worklet/runOnMainThread.test.jsx (1 hunks)
  • packages/react/runtime/src/lifecycle/patch/commit.ts (4 hunks)
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts (4 hunks)
  • packages/react/runtime/src/lynx/tt.ts (2 hunks)
  • packages/react/runtime/src/worklet/runOnMainThread.ts (2 hunks)
  • packages/react/worklet-runtime/__test__/runOnMainThread.test.js (1 hunks)
  • packages/react/worklet-runtime/src/bindings/bindings.ts (1 hunks)
  • packages/react/worklet-runtime/src/global.ts (1 hunks)
  • packages/react/worklet-runtime/src/listeners.ts (2 hunks)
  • packages/react/worklet-runtime/src/runOnMainThread.ts (1 hunks)
  • packages/react/worklet-runtime/src/workletRuntime.ts (2 hunks)
  • packages/rspeedy/plugin-react/package.json (1 hunks)
  • packages/webpack/react-webpack-plugin/package.json (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/runtime/test/worklet/runOnMainThread.test.js
✅ Files skipped from review due to trivial changes (1)
  • .changeset/smooth-dragons-smash.md
🚧 Files skipped from review as they are similar to previous changes (10)
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
  • .changeset/lemon-streets-watch.md
  • packages/react/worklet-runtime/src/bindings/bindings.ts
  • packages/react/runtime/src/worklet/runOnMainThread.ts
  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/worklet-runtime/src/workletRuntime.ts
  • packages/react/worklet-runtime/src/listeners.ts
  • packages/react/runtime/src/lifecycle/patch/commit.ts
  • packages/react/worklet-runtime/src/runOnMainThread.ts
  • packages/react/runtime/test/worklet/runOnMainThread.test.jsx
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • packages/rspeedy/plugin-react/package.json
  • packages/webpack/react-webpack-plugin/package.json
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • packages/rspeedy/plugin-react/package.json
  • packages/webpack/react-webpack-plugin/package.json
📚 Learning: 2025-08-13T11:36:12.075Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1523
File: vitest.config.ts:52-72
Timestamp: 2025-08-13T11:36:12.075Z
Learning: The lynx-stack project requires Node.js >=22 as specified in package.json engines, so Node.js compatibility fallbacks for features introduced before v22 are unnecessary.

Applied to files:

  • packages/rspeedy/plugin-react/package.json
  • packages/webpack/react-webpack-plugin/package.json
📚 Learning: 2025-08-20T04:56:36.011Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1566
File: package.json:53-53
Timestamp: 2025-08-20T04:56:36.011Z
Learning: In lynx-stack, Node.js v24 is the preferred/default version for development (established in PR #1557), but Node.js v22 compatibility is maintained specifically for external CI systems like rspack-ecosystem-ci. The engines.node specification uses "^22 || ^24" to support both versions while keeping v24 as the primary target.

Applied to files:

  • packages/webpack/react-webpack-plugin/package.json
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
PR: lynx-family/lynx-stack#1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • packages/webpack/react-webpack-plugin/package.json
📚 Learning: 2025-08-14T12:54:51.143Z
Learnt from: upupming
PR: lynx-family/lynx-stack#1370
File: .changeset/brave-melons-add.md:1-7
Timestamp: 2025-08-14T12:54:51.143Z
Learning: In the lynx-family/lynx-stack repository, packages use 0.x.x versioning where minor version bumps indicate breaking changes (not major bumps), following pre-1.0 semantic versioning conventions.

Applied to files:

  • packages/webpack/react-webpack-plugin/package.json
📚 Learning: 2025-08-11T05:59:28.530Z
Learnt from: upupming
PR: lynx-family/lynx-stack#1305
File: packages/react/testing-library/src/plugins/vitest.ts:4-6
Timestamp: 2025-08-11T05:59:28.530Z
Learning: In the lynx-family/lynx-stack repository, the `packages/react/testing-library` package does not have `vite` as a direct dependency. It relies on `vitest` being available from the monorepo root and accesses Vite types through re-exports from `vitest/node`. Direct imports from `vite` should not be suggested for this package.

Applied to files:

  • packages/webpack/react-webpack-plugin/package.json
🧬 Code graph analysis (2)
packages/react/worklet-runtime/src/global.ts (1)
packages/react/worklet-runtime/src/bindings/types.ts (2)
  • Worklet (41-52)
  • ClosureValueType (28-39)
packages/react/worklet-runtime/__test__/runOnMainThread.test.js (1)
packages/react/worklet-runtime/src/runOnMainThread.ts (1)
  • runRunOnMainThreadTask (7-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: test-rust / Test (Ubuntu)
  • GitHub Check: code-style-check
  • GitHub Check: CodeQL Analyze (javascript-typescript)
  • GitHub Check: CodeQL Analyze (actions)
🔇 Additional comments (3)
packages/webpack/react-webpack-plugin/package.json (1)

56-56: Peer range bump to ^0.113.0 looks correct.

Matches the repo-wide move to support @lynx-js/react v0.113.x. No further action needed here.

packages/rspeedy/plugin-react/package.json (1)

67-67: Peer range bump to ^0.113.0 is consistent.

Aligned with other packages in this PR. Good to go.

packages/react/worklet-runtime/src/global.ts (1)

21-21: LGTM: add _runRunOnMainThreadTask to global API.

Signature matches bindings/types and the new runtime wiring. No issues spotted.

@Yradex Yradex requested a review from hzy September 8, 2025 09:55
colinaaa
colinaaa previously approved these changes Sep 8, 2025
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: 0

♻️ Duplicate comments (1)
packages/react/worklet-runtime/src/listeners.ts (1)

15-18: Guard the listener with try/catch and validate payload before invoking the task.

Uncaught errors from JSON.parse or runRunOnMainThreadTask will bubble and can destabilize the JSContext listener. Validate resolveId/worklet/params and report errors instead of throwing.

     (event: Event) => {
-      const data = JSON.parse(event.data as string) as RunWorkletCtxData;
-      runRunOnMainThreadTask(data.worklet, data.params as ClosureValueType[], data.resolveId);
+      try {
+        const raw = JSON.parse(event.data as string);
+        if (!raw || typeof raw.resolveId !== 'number' || !raw.worklet) {
+          throw new Error('Invalid RunWorkletCtxData payload');
+        }
+        const data = raw as RunWorkletCtxData;
+        runRunOnMainThreadTask(
+          data.worklet,
+          (data.params ?? []) as ClosureValueType[],
+          data.resolveId,
+        );
+      } catch (e) {
+        lynx.reportError(e as Error);
+      }
     },
🧹 Nitpick comments (1)
packages/react/worklet-runtime/src/listeners.ts (1)

21-24: Validate ReleaseWorkletRef payload before removing.

Defensive check avoids accidental deletions on malformed events.

-    (event: Event) => {
-      removeValueFromWorkletRefMap((event.data as ReleaseWorkletRefData).id);
-    },
+    (event: Event) => {
+      const id = (event.data as ReleaseWorkletRefData)?.id;
+      if (typeof id !== 'number') {
+        lynx.reportError(new Error('Invalid ReleaseWorkletRefData payload'));
+        return;
+      }
+      removeValueFromWorkletRefMap(id);
+    },
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8b42f4c and cf82fa7.

📒 Files selected for processing (15)
  • .changeset/lemon-streets-watch.md (1 hunks)
  • .changeset/smooth-dragons-smash.md (1 hunks)
  • packages/react/runtime/__test__/worklet/runOnMainThread.test.js (0 hunks)
  • packages/react/runtime/__test__/worklet/runOnMainThread.test.jsx (1 hunks)
  • packages/react/runtime/src/lifecycle/patch/commit.ts (4 hunks)
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts (4 hunks)
  • packages/react/runtime/src/lynx/tt.ts (2 hunks)
  • packages/react/runtime/src/worklet/runOnMainThread.ts (2 hunks)
  • packages/react/worklet-runtime/__test__/runOnMainThread.test.js (1 hunks)
  • packages/react/worklet-runtime/src/bindings/bindings.ts (1 hunks)
  • packages/react/worklet-runtime/src/global.ts (1 hunks)
  • packages/react/worklet-runtime/src/listeners.ts (2 hunks)
  • packages/react/worklet-runtime/src/runOnMainThread.ts (1 hunks)
  • packages/react/worklet-runtime/src/workletRuntime.ts (2 hunks)
  • packages/rspeedy/plugin-react/package.json (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/react/runtime/test/worklet/runOnMainThread.test.js
✅ Files skipped from review due to trivial changes (1)
  • .changeset/smooth-dragons-smash.md
🚧 Files skipped from review as they are similar to previous changes (12)
  • packages/react/worklet-runtime/src/global.ts
  • packages/react/worklet-runtime/src/workletRuntime.ts
  • packages/react/worklet-runtime/src/bindings/bindings.ts
  • packages/rspeedy/plugin-react/package.json
  • packages/react/runtime/src/lynx/tt.ts
  • packages/react/runtime/test/worklet/runOnMainThread.test.jsx
  • packages/react/runtime/src/worklet/runOnMainThread.ts
  • .changeset/lemon-streets-watch.md
  • packages/react/runtime/src/lifecycle/patch/commit.ts
  • packages/react/runtime/src/lifecycle/patch/updateMainThread.ts
  • packages/react/worklet-runtime/test/runOnMainThread.test.js
  • packages/react/worklet-runtime/src/runOnMainThread.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/react/worklet-runtime/src/listeners.ts (2)
packages/react/worklet-runtime/src/runOnMainThread.ts (1)
  • runRunOnMainThreadTask (7-21)
packages/react/worklet-runtime/src/bindings/types.ts (1)
  • ClosureValueType (28-39)
🔇 Additional comments (2)
packages/react/worklet-runtime/src/listeners.ts (2)

5-8: Imports update looks correct.

Switch to runRunOnMainThreadTask and dropping RunWorkletCtxRetData aligns with delegated return dispatch.


11-19: Sanity-check: only one FunctionCallRet dispatcher remains

Found a single FunctionCallRet dispatch in packages/react/worklet-runtime/src/runOnMainThread.ts; listeners route WorkletEvents.runWorkletCtx → runRunOnMainThreadTask (packages/react/worklet-runtime/src/listeners.ts) and packages/react/runtime/src/worklet/runOnMainThread.ts emits runWorkletCtx — no other FunctionCallRet dispatchers found.

@Yradex Yradex requested a review from colinaaa September 11, 2025 12:23
@hzy hzy merged commit e1cdec2 into lynx-family:main Sep 11, 2025
83 of 85 checks passed
@Yradex Yradex deleted the mts/run-on-mt/x branch September 12, 2025 03:39
colinaaa pushed a commit that referenced this pull request Sep 15, 2025
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @lynx-js/react@0.113.0

### Minor Changes

- fix: Delay execution of `runOnMainThread()` during initial render
([#1667](#1667))

When called during the initial render, `runOnMainThread()` would execute
before the `main-thread:ref` was hydrated, causing it to be incorrectly
set to null.

This change delays the function's execution to ensure the ref is
available and correctly assigned.

### Patch Changes

- Fix "TypeError: cannot read property '0' of undefined" in deferred
list-item scenarios.
([#1692](#1692))

Deferred `componentAtIndex` causes nodes that quickly appear/disappear
to be enqueued without `__elements`. Update `signMap` before
`__FlushElementTree` to resolve the issue.

- Keep the same `<page/>` element when calling `rerender` in testing
library. ([#1656](#1656))

- Bump `swc_core` to `39.0.3`.
([#1721](#1721))

## @lynx-js/tailwind-preset@0.3.0

### Minor Changes

- Added `group-*`, `peer-*`, and `parent-*` modifiers (ancestor,
sibling, and direct-parent scopes) for `uiVariants` plugin.
([#1741](#1741))

Fixed prefix handling in prefixed projects — `ui-*` state markers are
not prefixed, while scope markers (`.group`/`.peer`) honor
`config('prefix')`.

**BREAKING**: Removed slash-based naming modifiers on self
(non-standard); slash modifiers remain supported for scoped markers
(e.g. `group/menu`, `peer/tab`).

Bumped peer dependency to `tailwindcss@^3.4.0` (required for use of
internal features).

## @lynx-js/react-webpack-plugin@0.7.0

### Minor Changes

- Remove `@lynx-js/react` from peerDependencies.
([#1711](#1711))

- Add a new required option `workletRuntimePath`.
([#1711](#1711))

## @lynx-js/rspeedy@0.11.2

### Patch Changes

- Support `server.proxy`.
([#1745](#1745))

- Support `command` and `env` parameters in the function exported by
`lynx.config.js`.
([#1669](#1669))

    ```js
    import { defineConfig } from "@lynx-js/rspeedy";

    export default defineConfig(({ command, env }) => {
      const isBuild = command === "build";
      const isTest = env === "test";

      return {
        output: {
          minify: !isTest,
        },
        performance: {
          buildCache: isBuild,
        },
      };
    });
    ```

- Support `resolve.dedupe`.
([#1671](#1671))

This is useful when having multiple duplicated packages in the bundle:

    ```js
    import { defineConfig } from "@lynx-js/rspeedy";

    export default defineConfig({
      resolve: {
        dedupe: ["tslib"],
      },
    });
    ```

- Support `resolve.aliasStrategy` for controlling priority between
`tsconfig.json` paths and `resolve.alias`
([#1722](#1722))

    ```js
    import { defineConfig } from "@lynx-js/rspeedy";

    export default defineConfig({
      resolve: {
        alias: {
          "@": "./src",
        },
// 'prefer-tsconfig' (default): tsconfig.json paths take priority
        // 'prefer-alias': resolve.alias takes priority
        aliasStrategy: "prefer-alias",
      },
    });
    ```

- Bump Rsbuild v1.5.4 with Rspack v1.5.2.
([#1644](#1644))

- Updated dependencies
\[[`d7c5da3`](d7c5da3)]:
    -   @lynx-js/chunk-loading-webpack-plugin@0.3.3
    -   @lynx-js/cache-events-webpack-plugin@0.0.2

## @lynx-js/react-rsbuild-plugin@0.10.14

### Patch Changes

- Fix using wrong version of `@lynx-js/react/worklet-runtime`.
([#1711](#1711))

- Be compat with `@lynx-js/react` v0.113.0
([#1667](#1667))

- Disable `builtin:lightningcss-loader` for `environments.web`.
([#1732](#1732))

- Updated dependencies
\[[`5ad38e6`](5ad38e6),
[`69b3ae0`](69b3ae0),
[`69b3ae0`](69b3ae0),
[`c2f90bd`](c2f90bd)]:
    -   @lynx-js/template-webpack-plugin@0.8.6
    -   @lynx-js/react-webpack-plugin@0.7.0
    -   @lynx-js/react-alias-rsbuild-plugin@0.10.14
    -   @lynx-js/css-extract-webpack-plugin@0.6.2
    -   @lynx-js/use-sync-external-store@1.5.0
    -   @lynx-js/react-refresh-webpack-plugin@0.3.4

## @lynx-js/react-alias-rsbuild-plugin@0.10.14

### Patch Changes

- Allow customization of the react$ alias.
([#1653](#1653))

    ```js
    import { defineConfig } from "@lynx-js/rspeedy";

    export default defineConfig({
      resolve: {
        alias: {
          react$: "@lynx-js/react/compat",
        },
      },
    });
    ```

## @lynx-js/web-constants@0.16.1

### Patch Changes

- feat: supports lazy bundle. (This feature requires `@lynx-js/lynx-core
>= 0.1.3`)
([#1235](#1235))

-   Updated dependencies \[]:
    -   @lynx-js/web-worker-rpc@0.16.1

## @lynx-js/web-core@0.16.1

### Patch Changes

- refactor: improve chunk loading
([#1703](#1703))

- feat: supports lazy bundle. (This feature requires `@lynx-js/lynx-core
>= 0.1.3`)
([#1235](#1235))

- Updated dependencies
\[[`608f375`](608f375)]:
    -   @lynx-js/web-mainthread-apis@0.16.1
    -   @lynx-js/web-worker-runtime@0.16.1
    -   @lynx-js/web-constants@0.16.1
    -   @lynx-js/web-worker-rpc@0.16.1

## @lynx-js/web-core-server@0.16.1

### Patch Changes

- refactor: improve chunk loading
([#1703](#1703))

- feat: supports lazy bundle. (This feature requires `@lynx-js/lynx-core
>= 0.1.3`)
([#1235](#1235))

## @lynx-js/web-elements@0.8.6

### Patch Changes

- fix: 1. svg use image tag to render, to differentiate background-image
styles ([#1668](#1668))

    1.  use blob instead of raw data-uri

    > Not using data-uri(data:image/svg+xml;utf8,${props.content})
    > since it has follow limitations:
    >
    > &lt; and > must be encoded to %3C and %3E.
    > Double quotes must be converted to single quotes.
> Colors must use a non-hex format because # will not work inside
data-uri.
    > See: <https://codepen.io/zvuc/pen/BWNLJL>
> Instead, we use modern Blob API to create SVG URL that have the same
support

- Updated dependencies
\[[`d618304`](d618304),
[`1d97fce`](1d97fce)]:
    -   @lynx-js/web-elements-template@0.8.6

## @lynx-js/web-elements-template@0.8.6

### Patch Changes

- x-overlay-ng prevent page scroll when visible
([#1499](#1499))

- fix: 1. svg use image tag to render, to differentiate background-image
styles ([#1668](#1668))

    1.  use blob instead of raw data-uri

    > Not using data-uri(data:image/svg+xml;utf8,${props.content})
    > since it has follow limitations:
    >
    > &lt; and > must be encoded to %3C and %3E.
    > Double quotes must be converted to single quotes.
> Colors must use a non-hex format because # will not work inside
data-uri.
    > See: <https://codepen.io/zvuc/pen/BWNLJL>
> Instead, we use modern Blob API to create SVG URL that have the same
support

## @lynx-js/web-mainthread-apis@0.16.1

### Patch Changes

- feat: supports lazy bundle. (This feature requires `@lynx-js/lynx-core
>= 0.1.3`)
([#1235](#1235))

- Updated dependencies
\[[`608f375`](608f375)]:
    -   @lynx-js/web-constants@0.16.1
    -   @lynx-js/web-style-transformer@0.16.1

## @lynx-js/web-worker-runtime@0.16.1

### Patch Changes

- feat: supports lazy bundle. (This feature requires `@lynx-js/lynx-core
>= 0.1.3`)
([#1235](#1235))

- Updated dependencies
\[[`608f375`](608f375)]:
    -   @lynx-js/web-mainthread-apis@0.16.1
    -   @lynx-js/web-constants@0.16.1
    -   @lynx-js/web-worker-rpc@0.16.1

## @lynx-js/chunk-loading-webpack-plugin@0.3.3

### Patch Changes

- Fix unmet peer dependency "@rspack/core@'^1.3.10".
([#1660](#1660))

## @lynx-js/template-webpack-plugin@0.8.6

### Patch Changes

- fix: add appType field for lazy bundle for web
([#1738](#1738))

## create-rspeedy@0.11.2



## upgrade-rspeedy@0.11.2



## @lynx-js/web-style-transformer@0.16.1



## @lynx-js/web-worker-rpc@0.16.1

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

3 participants