Skip to content

feat(web): support lazy bundle with CSSOG#1770

Merged
Sherry-hue merged 2 commits intolynx-family:mainfrom
Sherry-hue:feat/lazy-bundle-cssog
Sep 19, 2025
Merged

feat(web): support lazy bundle with CSSOG#1770
Sherry-hue merged 2 commits intolynx-family:mainfrom
Sherry-hue:feat/lazy-bundle-cssog

Conversation

@Sherry-hue
Copy link
Copy Markdown
Collaborator

@Sherry-hue Sherry-hue commented Sep 17, 2025

Summary by CodeRabbit

  • New Features

    • Per-entry lazy CSS for lazy-loaded bundles when CSS-selector matching is disabled, enabling isolated styling per bundle and correct class/inline style updates.
  • Tests

    • Adds extensive tests for lazy-component styling: class swaps, inline style changes/removals, reuse, multi-level selectors, type-selector cases, and layout assertions.
  • Chores

    • Adds a changeset entry for a patch release of the web-mainthread APIs package.

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 17, 2025

🦋 Changeset detected

Latest commit: 743f06a

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

This PR includes changesets to release 7 packages
Name Type
@lynx-js/web-mainthread-apis Patch
@lynx-js/web-core-server Patch
@lynx-js/web-core Patch
@lynx-js/web-worker-runtime Patch
@lynx-js/web-constants Patch
@lynx-js/web-worker-rpc Patch
@lynx-js/web-style-transformer 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 17, 2025

📝 Walkthrough

Walkthrough

Adds per-entry (entryName) routing and lazy CSS‑OG handling to the main-thread style pipeline, updates related function signatures and call sites, removes an appendStyleElement parameter, introduces per-entry lazy CSSOG storage and update flow, adds many tests/configs for enableCSSSelector: false, and a changeset.

Changes

Cohort / File(s) Summary
Release changeset
/.changeset/shiny-toes-punch.md
Adds a patch changeset entry for @lynx-js/web-mainthread-apis describing support for lazy bundles with CSSOG (enableCSSSelector: false).
Main-thread API & runtime wiring
/packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts
Introduces per-entry routing via lynxEntryNameAttribute; updates runtime callback signatures to accept entryName (e.g., updateCssOGStyle, __SetCSSIdForCSSOG); propagates entryName to elements and CSS update calls; preserves wrapper exposure for __AddClass, __SetClasses, __SetCSSId.
API call-site change
/packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts
Removes an undefined placeholder argument from appendStyleElement calls so ssrHydrateInfo becomes the 5th parameter (previously 6th).
Style processing & lazy CSSOG
/packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts
Removes entryName from appendStyleElement signature; adds lazyCSSOGInfo per-entry map; extends internal updateCssOGStyle to accept optional entryName; adds updateLazyComponentStyle to compute/append per-entry stylesheet text and store per-entry CssOGInfo; defers sheet retrieval to update path.
React test spec updates
/packages/web-platform/web-tests/tests/react.spec.ts
Adds numerous lazy-component CSSOG tests for enableCSSSelector: false scenarios; an identical nine-test block was duplicated in the file.
Test entry modules (lazy mounts)
/packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-*/index.jsx
Adds several entry files that lazy-load component bundles via lazy(() => import(..., { with: { type: 'component' } })) and mount them.
Test component sources
/packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-*/index.jsx
Adds multiple class-based test components exercising class toggles, inline style changes, multi-level and type selector scenarios for lazy CSSOG behavior (default exports).
Test component styles
/packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-*/index.css
Adds CSS files used by the new tests (utility classes, multi-level selectors, type-selector rules).
Test configs
/packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false.config.ts, .../basic.config.ts
Adds a dedicated test config that enables enableCSSSelector: false and discovers new cases; updates base basic config to exclude these entries.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • PupilTong
  • colinaaa

Poem

A rabbit hops through stylesheet rows,
Tucks entry names where the lazy bundle goes.
Green flips yellow, classes dance in line,
Per-entry tags guide each stylesheet fine.
🐇🌿✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 "feat(web): support lazy bundle with CSSOG" accurately and concisely describes the primary change in the PR — adding CSS-OG support for lazy bundles in the web platform (matching changes to processStyleInfo, createMainThreadGlobalThis, runtime wiring, tests, and a changeset). It follows conventional commit style and is specific enough for a reviewer scanning history to understand the main intent.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent 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 c636c44 and 743f06a.

📒 Files selected for processing (1)
  • packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts
⏰ 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). (3)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / Test (Ubuntu)

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.

@Sherry-hue Sherry-hue requested a review from colinaaa September 17, 2025 09:03
@codecov
Copy link
Copy Markdown

codecov Bot commented Sep 17, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

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

Caution

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

⚠️ Outside diff range comments (2)
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (1)

61-79: Set.prototype.union is not widely available; replace with a portable union

Union/difference/intersection for Set are not guaranteed across all browsers we run tests on (notably WebKit in CI). This will throw in older engines.

-function generateImportByMap(
+function generateImportByMap(
   styleInfo: StyleInfo,
   sortedCssIds: string[],
 ): Map<string, Set<string>> {
   const cssIdToImportBy = new Map<string, Set<string>>();
   for (const cssId of sortedCssIds) {
     const currentAdjunction = styleInfo[cssId]?.imports;
     if (currentAdjunction) {
-      const currentImportBy = cssIdToImportBy.get(cssId) ?? new Set([cssId]);
+      const currentImportBy = cssIdToImportBy.get(cssId) ?? new Set([cssId]);
       for (const importCssId of currentAdjunction) {
-        const importDeps = cssIdToImportBy.get(importCssId)
-          ?? new Set([importCssId]);
-        importDeps.add(cssId);
-        cssIdToImportBy.set(importCssId, currentImportBy.union(importDeps));
+        const importDeps =
+          cssIdToImportBy.get(importCssId) ?? new Set([importCssId]);
+        importDeps.add(cssId);
+        // portable union
+        const union = new Set<string>([
+          ...currentImportBy,
+          ...importDeps,
+        ]);
+        cssIdToImportBy.set(importCssId, union);
       }
       cssIdToImportBy.set(cssId, currentImportBy);
     }
   }
   return cssIdToImportBy;
 }
packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (1)

133-139: Pass the optional entryName into updateCssOGStyle call sites

Ensure each call to callbacks.updateCssOGStyle includes the optional 4th parameter entryName (string | null) so per‑entry routing is preserved. Fix the calls in packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (around lines 574 and 602) to pass the entry's name or null.

🧹 Nitpick comments (41)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (2)

6-7: Consider using a more maintainable import path approach.

The hardcoded absolute path /dist/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.web.json could become brittle if the build output structure changes. Consider using relative paths or build-time path resolution if available in the framework.

-const importPath =
-  `/dist/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.web.json`;
+const importPath =
+  `./config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.web.json`;

21-21: Consider adding fallback UI to Suspense.

While not required for basic testing, adding a fallback prop to Suspense would provide better user experience and make the loading behavior explicit.

-    <Suspense>
+    <Suspense fallback={<div>Loading...</div>}>
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.css (1)

6-7: Document the cascade dependency to prevent accidental reordering.
A brief note helps keep .background-yellow after .background-green since the test relies on that order.

- 
+. /* NOTE: Keep .background-yellow defined after .background-green;
+   when both classes are present, later rule wins (yellow). */
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1)

9-17: Avoid allocating a new handler per render (minor).
Binding once is slightly cleaner, even in tests.

   constructor(props) {
     super(props);
     this.state = {
       flag: false,
     };
+    this.handletap = this.handletap.bind(this);
   }
@@
-        bindtap={() => {
-          this.handletap();
-        }}
+        bindtap={this.handletap}

Also applies to: 23-25

packages/web-platform/web-tests/tests/react/basic-lazy-component-fetch-only-one/index.jsx (1)

17-25: Add a stable hook for E2E assertions.

Give the container a deterministic id to make Playwright waits/assertions less brittle.

 export default function App() {
   return (
-    <view>
+    <view id="app">
       <Suspense fallback={<text id='fallback'>Loading...</text>}>
         <LazyComponent />
       </Suspense>
     </view>
   );
 }
.changeset/shiny-toes-punch.md (1)

1-6: Confirm release type and note potential breaking API shifts.

If public API shapes changed (e.g., updateCssOGStyle signature, removal of __SetCSSId), consider minor or add a BREAKING note. If those are internal/private, patch is fine. Also ensure all affected published packages are included in this changeset (private packages: no meaningful changeset needed per repo practice).

Possible edits:

 ---
-"@lynx-js/web-mainthread-apis": patch
+"@lynx-js/web-mainthread-apis": minor
 ---
 
-feat: support lazy bundle with CSSOG(`enableCSSSelector: false`).
+feat: support lazy bundle with CSSOG (enableCSSSelector: false).
+
+BREAKING CHANGE: updateCssOGStyle accepts optional entryName and __SetCSSId removed. If these are internal-only, revert to patch and drop this note.
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1)

27-27: Nit: prefer self-closing JSX in render call.

-root.render(<App></App>);
+root.render(<App />);
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1)

27-27: Nit: use self-closing JSX in render.

-root.render(<App></App>);
+root.render(<App />);
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1)

19-25: Add an explicit Suspense fallback for deterministic rendering

Providing fallback={null} avoids transient content/state differences during lazy hydration in headless runs.

Apply this diff:

   return (
-    <Suspense>
+    <Suspense fallback={null}>
       <LazyComponent />
     </Suspense>
   );
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx (1)

19-25: Add an explicit Suspense fallback for deterministic rendering

Same pattern as other lazy pages; helps stabilize E2E timing.

   return (
-    <Suspense>
+    <Suspense fallback={null}>
       <LazyComponent />
     </Suspense>
   );
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1)

19-25: Add an explicit Suspense fallback for deterministic rendering

Keeps behavior consistent across the suite and reduces flakiness.

   return (
-    <Suspense>
+    <Suspense fallback={null}>
       <LazyComponent />
     </Suspense>
   );
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (2)

19-25: Add an explicit Suspense fallback for deterministic rendering

Aligns the lazy wrappers and avoids transient UI during module fetch.

   return (
-    <Suspense>
+    <Suspense fallback={null}>
       <LazyComponent />
     </Suspense>
   );

27-27: Nit: prefer self-closing JSX

Minor consistency/readability improvement.

-root.render(<App></App>);
+root.render(<App />);
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false.config.ts (1)

21-33: Stabilize build ordering of entries

Sort the matched entries to keep deterministic output and test URLs.

-const config: Config = mergeRspeedyConfig(
+const sortedReactBasicCases = [...reactBasicCases].sort();
+
+const config: Config = mergeRspeedyConfig(
   commonConfig({
     enableCSSSelector: false,
     experimental_isLazyBundle: true,
   }),
   {
     source: {
-      entry: Object.fromEntries(reactBasicCases.map((reactBasicEntry) => {
+      entry: Object.fromEntries(sortedReactBasicCases.map((reactBasicEntry) => {
         return [path.basename(path.dirname(reactBasicEntry)), reactBasicEntry];
       })),
     },
   },
 );
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx (1)

19-25: Add an explicit Suspense fallback for deterministic rendering

Keeps lazy behavior consistent across all new pages.

   return (
-    <Suspense>
+    <Suspense fallback={null}>
       <LazyComponent />
     </Suspense>
   );
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx (1)

18-25: Handle subsequent taps: default case should return empty class

Without a default, further taps set class to undefined. Return '' to keep the attribute cleared deterministically.

   switch (this.state.stateId) {
     case 0:
       return 'background-yellow background-green';
     case 1:
       return '';
+    default:
+      return '';
   }
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1)

15-17: Bind handler once; avoid per-render closures and fragile class string concat.

  • Bind handletap in the constructor and pass it directly to bindtap to avoid allocating a new function on every render.
  • Build classes via array join to avoid trailing spaces and make toggling clearer.
   constructor(props) {
     super(props);
     this.state = {
       flag: false,
     };
+    this.handletap = this.handletap.bind(this);
   }
@@
-        class={'background-yellow '
-          + (this.state.flag ? 'background-green' : '')}
+        class={[
+          'background-yellow',
+          this.state.flag && 'background-green',
+        ].filter(Boolean).join(' ')}
@@
-        bindtap={() => {
-          this.handletap();
-        }}
+        bindtap={this.handletap}

Also applies to: 22-23, 24-26

packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx (1)

13-15: Remove unused method and simplify getInline.

  • handletap is unused.
  • getInline’s switch has only a default branch; inline it.
-  handletap() {
-    this.setState({ stateId: this.state.stateId + 1 });
-  }
   getInline() {
-    switch (this.state.stateId) {
-      default:
-        return { height: '100px', width: '100px' }; // green
-    }
+    return { height: '100px', width: '100px' };
   }

Also applies to: 16-21

packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.css (1)

1-13: Add trailing newline at EOF.

Keeps diffs cleaner and satisfies style linters.

packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.css (1)

1-14: Add trailing newline at EOF.

Minor formatting hygiene to placate linters.

packages/web-platform/web-tests/tests/react/config-lazy-component.config.ts (1)

28-31: Deterministic entry ordering.

Sort entries to avoid order flakiness across platforms/Node versions.

-      entry: Object.fromEntries(filteredCases.map((reactBasicEntry) => {
-        return [path.basename(path.dirname(reactBasicEntry)), reactBasicEntry];
-      })),
+      entry: Object.fromEntries(
+        filteredCases
+          .slice()
+          .sort((a, b) =>
+            path.basename(path.dirname(a)).localeCompare(
+              path.basename(path.dirname(b)),
+            ))
+          .map((reactBasicEntry) => [
+            path.basename(path.dirname(reactBasicEntry)),
+            reactBasicEntry,
+          ]),
+      ),
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx (1)

9-14: Drop unused state/constructor; keep the fixture minimal.

No dynamic behavior here; the state isn’t read.

-export default class Root extends Component {
-  constructor(props) {
-    super(props);
-    this.state = {
-      stateId: 0,
-    };
-  }
+export default class Root extends Component {
   render() {
     return <view id='target' class='tt' />;
   }
 }
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx (2)

21-23: Provide a Suspense fallback.

Prevents a transient blank frame during lazy load and clarifies intent.

-export default function App() {
-  return (
-    <Suspense>
+export default function App() {
+  return (
+    <Suspense fallback={null}>
       <LazyComponent />
     </Suspense>
   );
 }

6-7: Avoid hardcoding /dist if assetPrefix changes.

Not a blocker for tests, but consider deriving the URL (e.g., via a test util or env) to decouple from config.

packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1)

15-17: Make the state machine total and avoid per-render handler allocations.

  • Wrap stateId with modulo to keep it in [0,3].
  • Add default branches to getInline/getClass to guard future changes.
  • Bind the handler once and pass it directly.
   constructor(props) {
     super(props);
     this.state = {
       stateId: 0,
     };
+    this.handletap = this.handletap.bind(this);
   }
   handletap() {
-    this.setState({ stateId: this.state.stateId + 1 });
+    this.setState({ stateId: (this.state.stateId + 1) % 4 });
   }
   getInline() {
     switch (this.state.stateId) {
       case 0:
         return { height: '100px', width: '100px' }; // green
       case 1:
         return { backgroundColor: 'red', height: '100px', width: '100px' }; // red
       case 2:
         return { backgroundColor: 'red', height: '100px', width: '100px' }; // red
       case 3:
         return { height: '100px', width: '100px' }; // yellow
+      default:
+        return { height: '100px', width: '100px' };
     }
   }
   getClass() {
     switch (this.state.stateId) {
       case 0:
         return 'background-yellow background-green';
       case 1:
         return 'background-yellow background-green';
       case 2:
         return 'background-yellow';
       case 3:
         return 'background-yellow';
+      default:
+        return 'background-yellow';
     }
   }
@@
-        bindtap={() => {
-          this.handletap();
-        }}
+        bindtap={this.handletap}

Also applies to: 19-29, 30-41, 47-49

packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1)

15-17: Minor ergonomics: avoid re-creating the arrow on every render

Bind once or use a class field to reduce tiny allocations during rapid taps.

-  handletap() {
-    this.setState({ flag: !this.state.flag });
-  }
+  handletap = () => {
+    this.setState({ flag: !this.state.flag });
+  }
...
-        bindtap={() => {
-          this.handletap();
-        }}
+        bindtap={this.handletap}
packages/web-platform/web-tests/tests/react.spec.ts (4)

716-733: Skip CSSOG lazy-component tests on SSR to match other lazy tests

Earlier lazy-component tests guard with test.skip(isSSR, ...). These CSSOG cases exercise lazy routing too and will likely fail/flake under SSR.

-    test(
+    test.skip(isSSR, 'Lazy Component not support on SSR')(
       'basic-lazy-component-css-selector-false-exchange-class',

Apply the same pattern to the CSSOG tests added in this block.


733-742: Stabilize expectations: wait for style application by condition, not fixed 100ms

Use a predicate wait to reduce flakes on CI (especially Firefox/WebKit).

-        await wait(100);
-        const target = page.locator('#target');
+        const target = page.locator('#target');
+        await expect(target).toHaveCount(1);
+        await expect(target).toHaveCSS('height', '100px'); // readiness probe

Or:

-        await wait(100);
+        await page.waitForFunction(() => !!document.querySelector('#target'));

784-808: Make color assertion transitions resilient

For toggle sequences, add explicit clicks and interim waits already present, but also assert intermediate state before next action to avoid racing.

         await target.click();
-        await expect(target).toHaveCSS('background-color', 'rgb(255, 255, 0)'); // yellow
+        await expect(target).toHaveCSS('background-color', 'rgb(255, 255, 0)'); // yellow (confirmed)
         await target.click();
         await expect(target).toHaveCSS('background-color', 'rgb(0, 128, 0)'); // green

731-759: Consider asserting dimensions in at least one CSSOG case

Since CSSOG modifies selector scoping, add a single width/height check (like other suites) to detect accidental rule leakage.

Would you like me to push a small patch adding a toHaveCSS('width','100px') assertion in one test here to broaden coverage?

packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1)

15-17: Same event handler micro‑nit as sibling fixture

Use a class field or bind once for handletap.

-  handletap() {
-    this.setState({ flag: !this.state.flag });
-  }
+  handletap = () => {
+    this.setState({ flag: !this.state.flag });
+  }
...
-        bindtap={() => {
-          this.handletap();
-        }}
+        bindtap={this.handletap}
packages/web-platform/web-mainthread-apis/src/crossThreadHandlers/createQueryComponent.ts (1)

48-49: Use a shorter, stable entryName to reduce selector length and CSS text growth

Passing full url as entryName works but inflates [lynx-entry-name="..."] selectors and style text. Prefer a hashed or short identifier (e.g., template id) to keep the stylesheet compact.

-        updateLazyComponentStyle(template.styleInfo, url, template.pageConfig);
+        // e.g., use template.entryName or a short hash of url
+        const entryName = template.entryName ?? mtsRealm.hash?.(url) ?? url;
+        updateLazyComponentStyle(template.styleInfo, entryName, template.pageConfig);
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (4)

149-170: Attribute selector value construction: keep JSON quoting but guard unusual chars

Using JSON.stringify(entryName) is good. Add minimal sanitization to prevent accidental control chars breaking the CSS string (unlikely but cheap to guard).

-      suffix = `${suffix}[${lynxEntryNameAttribute}=${JSON.stringify(entryName)}]`;
+      const safe = JSON.stringify(String(entryName).replace(/[\u0000-\u001F]/g, ''));
+      suffix = `${suffix}[${lynxEntryNameAttribute}=${safe}]`;

263-271: Per‑entry OG map lifetime: memory growth risk

const lazyCSSOGInfo: Record<string, CssOGInfo> = {}; grows with each lazy entry and is never cleared. If entries are frequently loaded/unloaded, this accumulates.

  • Store per-entry info on the root DOM (WeakMap keyed by entryName) or
  • Provide a removeLazyComponentStyle(entryName) that deletes from lazyCSSOGInfo and prunes appended CSS if feasible.

284-301: Defensive check for sheet availability

cardStyleElement.sheet can be null in rare cases (e.g., disabled stylesheets). Add a guard to avoid crashes.

-    const cardStyleElementSheet =
-      (cardStyleElement as unknown as HTMLStyleElement).sheet!;
+    const sheet = (cardStyleElement as HTMLStyleElement).sheet;
+    if (!sheet) return;
...
-      const rule = cardStyleElementSheet
+      const rule = sheet
         .cssRules[lynxUniqueIdToStyleRulesIndex[uniqueId]] as CSSStyleRule;
...
-      const index = cardStyleElementSheet.insertRule(
+      const index = sheet.insertRule(

303-319: Idempotency of lazy style append

Appending textContent per entry is fine once, but repeated calls with the same entryName will duplicate rules. Consider a simple guard.

-  const updateLazyComponentStyle = (
+  const appendedEntries = new Set<string>();
+  const updateLazyComponentStyle = (
     styleInfo: StyleInfo,
     entryName: string,
     pageConfig: PageConfig,
   ) => {
+    if (appendedEntries.has(entryName)) return;
...
     lazyCSSOGInfo[entryName] = cssOGInfo;
     cardStyleElement.textContent += newStyleSheet;
+    appendedEntries.add(entryName);
   };
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (2)

22-29: Guard for unexpected state: add default class return

If handletap() is triggered twice, stateId becomes 2 and getClass() returns undefined, which may remove the class attribute and derail the test’s intent.

Apply this diff to make behavior explicit and stable:

   getClass() {
     switch (this.state.stateId) {
       case 0:
         return 'background-yellow background-green';
       case 1:
         return 'background-green background-yellow ';
+      default:
+        return 'background-yellow background-green'
     }
   }

32-39: Event handler allocation in render (non-blocking)

Creating a new arrow function in JSX each render is fine for tests, but if this pattern spreads to perf‑sensitive paths, consider a bound method to avoid churn.

packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (3)

559-581: OG add-class path is fine; consider de-duping to avoid class bloat

Repeated adds can duplicate tokens; NG path has the same behavior today. If class bloat affects OG recompute cost, de-dup here.

-  const newClassName =
-    ((element.getAttribute('class') ?? '') + ' ' + className).trim();
+  const tokens = ((element.getAttribute('class') ?? '') + ' ' + className)
+    .trim()
+    .split(/\s+/);
+  const newClassName = Array.from(new Set(tokens)).join(' ');

610-624: Apply the same routing fallback fix as AddClass

Keep routing consistent.

-  const __SetClasses: SetClassesPAPI = (
-    element,
-    classNames,
-  ) => {
-    const entryName = element.getAttribute(lynxEntryNameAttribute);
-    const isCSSOG = !(entryName
-      ? entryInfo[entryName]?.pageConfig?.enableCSSSelector
-      : pageConfig?.enableCSSSelector);
+  const __SetClasses: SetClassesPAPI = (element, classNames) => {
+    const entryName = element.getAttribute(lynxEntryNameAttribute);
+    const enableCSSSelector =
+      (entryName && entryInfo[entryName]?.pageConfig?.enableCSSSelector) ??
+      pageConfig?.enableCSSSelector;
+    const isCSSOG = !Boolean(enableCSSSelector);

667-691: Initial template classes bypass OG update

Classes from templates are applied via NG (__SetClassesForCSSNG). For OG entries, initial computed style won’t be applied unless another call triggers updateCssOGStyle (e.g., via __SetCSSId reapply). If that reapply isn’t guaranteed, first paint may be incorrect.

If safe, route through the wrapper so OG entries compute styles immediately:

-    data.class && __SetClassesForCSSNG(element, data.class.join(' '));
+    if (data.class) {
+      __SetClasses(element, data.class.join(' '));
+    }

If not safe yet, confirm there’s a subsequent call path (e.g., __SetCSSId) that re-triggers OG recomputation for these elements before first paint.

📜 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 721635d and 4daf84a.

📒 Files selected for processing (37)
  • .changeset/shiny-toes-punch.md (1 hunks)
  • packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (8 hunks)
  • packages/web-platform/web-mainthread-apis/src/crossThreadHandlers/createQueryComponent.ts (2 hunks)
  • packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts (0 hunks)
  • packages/web-platform/web-mainthread-apis/src/pureElementPAPIs.ts (0 hunks)
  • packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (3 hunks)
  • packages/web-platform/web-tests/tests/react.spec.ts (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-fetch-only-one/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false.config.ts (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component.config.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts
  • packages/web-platform/web-mainthread-apis/src/pureElementPAPIs.ts
🧰 Additional context used
📓 Path-based instructions (2)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, always generate a changeset and commit the resulting markdown file(s)

Files:

  • .changeset/shiny-toes-punch.md
packages/web-platform/web-tests/**

📄 CodeRabbit inference engine (AGENTS.md)

Place Playwright E2E tests in the web platform’s web-tests suite

Files:

  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component.config.ts
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-fetch-only-one/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false.config.ts
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx
  • packages/web-platform/web-tests/tests/react.spec.ts
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.css
🧠 Learnings (11)
📚 Learning: 2025-09-12T09:43:04.810Z
Learnt from: gaoachao
PR: lynx-family/lynx-stack#1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.810Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • .changeset/shiny-toes-punch.md
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/shiny-toes-punch.md
📚 Learning: 2025-09-12T09:43:04.810Z
Learnt from: gaoachao
PR: lynx-family/lynx-stack#1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.810Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • .changeset/shiny-toes-punch.md
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/shiny-toes-punch.md
📚 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/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-fetch-only-one/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-fetch-only-one/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false.config.ts
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false.config.ts
📚 Learning: 2025-08-13T09:20:00.936Z
Learnt from: upupming
PR: lynx-family/lynx-stack#1502
File: packages/react/testing-library/types/entry.d.ts:71-71
Timestamp: 2025-08-13T09:20:00.936Z
Learning: In lynx-js/react testing library, wrapper components must have children as a required prop because they are always called with `h(WrapperComponent, null, innerElement)` where innerElement is passed as children. The type `React.JSXElementConstructor<{ children: React.ReactNode }>` correctly requires children to be mandatory.

Applied to files:

  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx
📚 Learning: 2025-08-11T05:57:18.212Z
Learnt from: upupming
PR: lynx-family/lynx-stack#1305
File: packages/testing-library/testing-environment/src/index.ts:255-258
Timestamp: 2025-08-11T05:57:18.212Z
Learning: In the ReactLynx testing environment (`packages/testing-library/testing-environment/src/index.ts`), the dual assignment pattern `target.console.method = console.method = () => {}` is required for rstest compatibility. This is because rstest provides `console` in an IIFE (Immediately Invoked Function Expression), and both the target and global console need to have these methods defined for proper test execution.

Applied to files:

  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx
📚 Learning: 2025-08-27T08:10:09.932Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1612
File: packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/src/tsconfig.json:3-13
Timestamp: 2025-08-27T08:10:09.932Z
Learning: In the lynx-family/lynx-stack repository, Rspeedy templates use `lynx-js/rspeedy/client` types via `rspeedy-env.d.ts` instead of `vite/client` types. Rspeedy provides its own client-side environment type definitions and doesn't require direct Vite type references.

Applied to files:

  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false.config.ts
📚 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/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts
🧬 Code graph analysis (23)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (3)
  • importPath (6-7)
  • LazyComponent (8-17)
  • App (19-25)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (3)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1)
  • Root (8-31)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1)
  • Root (8-35)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1)
  • Root (8-32)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx (2)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (3)
  • importPath (6-7)
  • LazyComponent (8-17)
  • App (19-25)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
  • App (6-42)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (2)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1)
  • Root (8-33)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1)
  • Root (8-31)
packages/web-platform/web-tests/tests/react/config-lazy-component.config.ts (1)
packages/web-platform/web-tests/tests/react/commonConfig.ts (1)
  • commonConfig (10-38)
packages/web-platform/web-tests/tests/react/basic-lazy-component-fetch-only-one/index.jsx (2)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (3)
  • importPath (6-7)
  • LazyComponent (8-17)
  • App (19-25)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
  • App (6-42)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (2)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (3)
  • importPath (6-7)
  • LazyComponent (8-17)
  • App (19-25)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
  • App (6-42)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx (2)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (3)
  • importPath (6-7)
  • LazyComponent (8-17)
  • App (19-25)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
  • App (6-42)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (2)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
  • App (6-42)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx (1)
  • App (6-33)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (2)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1)
  • Root (8-33)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1)
  • Root (8-35)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (2)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (3)
  • importPath (6-7)
  • LazyComponent (8-17)
  • App (19-25)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
  • App (6-42)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (3)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1)
  • Root (8-33)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1)
  • Root (8-31)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1)
  • Root (8-32)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false.config.ts (1)
packages/web-platform/web-tests/tests/react/commonConfig.ts (1)
  • commonConfig (10-38)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (1)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
  • App (6-42)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx (1)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx (1)
  • App (6-33)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx (1)
  • App (6-33)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx (2)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1)
  • Root (8-54)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1)
  • Root (8-31)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (2)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (3)
  • importPath (6-7)
  • LazyComponent (8-17)
  • App (19-25)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
  • App (6-42)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx (1)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
  • App (6-42)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (5)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1)
  • Root (8-33)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx (1)
  • Root (8-38)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1)
  • Root (8-31)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1)
  • Root (8-35)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1)
  • Root (8-32)
packages/web-platform/web-mainthread-apis/src/crossThreadHandlers/createQueryComponent.ts (2)
packages/web-platform/web-constants/src/types/TemplateLoader.ts (1)
  • TemplateLoader (3-3)
packages/web-platform/web-constants/src/types/PageConfig.ts (1)
  • PageConfig (4-10)
packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (5)
packages/web-platform/web-constants/src/types/LynxModule.ts (1)
  • LynxTemplate (21-42)
packages/web-platform/web-constants/src/types/MainThreadGlobalThis.ts (3)
  • SetCSSIdPAPI (270-274)
  • AddClassPAPI (249-252)
  • SetClassesPAPI (254-257)
packages/web-platform/web-constants/src/constants.ts (3)
  • cssIdAttribute (7-7)
  • lynxEntryNameAttribute (13-13)
  • lynxUniqueIdAttribute (5-5)
packages/web-platform/web-mainthread-apis/src/pureElementPAPIs.ts (2)
  • __SetClasses (267-274)
  • __AddClass (307-314)
packages/web-platform/web-constants/src/types/Element.ts (1)
  • WebFiberElementImpl (51-96)
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (3)
packages/web-platform/web-constants/src/types/StyleInfo.ts (1)
  • CssOGInfo (32-36)
packages/web-platform/web-mainthread-apis/src/utils/decodeCssOG.ts (1)
  • decodeCssOG (12-31)
packages/web-platform/web-constants/src/types/PageConfig.ts (1)
  • PageConfig (4-10)
⏰ 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). (3)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: test-rust / Test (Ubuntu)

Comment thread packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts Outdated
Comment thread packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts Outdated
Comment thread packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts Outdated
@relativeci
Copy link
Copy Markdown

relativeci Bot commented Sep 17, 2025

Web Explorer

#5355 Bundle Size — 365.48KiB (+0.03%).

743f06a(current) vs db58f3c main#5350(baseline)

Bundle metrics  Change 2 changes
                 Current
#5355
     Baseline
#5350
No change  Initial JS 145.65KiB 145.65KiB
No change  Initial CSS 32KiB 32KiB
Change  Cache Invalidation 6.85% 0%
No change  Chunks 8 8
No change  Assets 8 8
Change  Modules 220(+0.92%) 218
No change  Duplicate Modules 16 16
No change  Duplicate Code 3.37% 3.37%
No change  Packages 4 4
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#5355
     Baseline
#5350
Regression  JS 239.46KiB (+0.05%) 239.34KiB
No change  Other 94.02KiB 94.02KiB
No change  CSS 32KiB 32KiB

Bundle analysis reportBranch Sherry-hue:feat/lazy-bundle-csso...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented Sep 17, 2025

React Example

#5362 Bundle Size — 237.73KiB (+0.03%).

743f06a(current) vs db58f3c main#5357(baseline)

Bundle metrics  Change 1 change
                 Current
#5362
     Baseline
#5357
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 38.67% 0%
No change  Chunks 0 0
No change  Assets 4 4
No change  Modules 165 165
No change  Duplicate Modules 67 67
No change  Duplicate Code 46.76% 46.76%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#5362
     Baseline
#5357
No change  IMG 145.76KiB 145.76KiB
Regression  Other 91.97KiB (+0.07%) 91.91KiB

Bundle analysis reportBranch Sherry-hue:feat/lazy-bundle-csso...Project dashboard


Generated by RelativeCIDocumentationReport issue

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Sep 17, 2025

CodSpeed Performance Report

Merging #1770 will improve performances by 6.92%

Comparing Sherry-hue:feat/lazy-bundle-cssog (743f06a) with main (b69a986)

🎉 Hooray! codspeed-cpp just leveled up to 1.2.0!

A heads-up, this is a breaking change and it might affect your current performance baseline a bit. But here's the exciting part - it's packed with new, cool features and promises improved result stability 🥳!
Curious about what's new? Visit our releases page to delve into all the awesome details about this new version.

Summary

⚡ 2 improvements
✅ 54 untouched

Benchmarks breakdown

Benchmark BASE HEAD Change
transform 1000 view elements 46.6 ms 43.8 ms +6.34%
basic-performance-nest-level-100 6.8 ms 6.3 ms +6.92%

@Sherry-hue Sherry-hue force-pushed the feat/lazy-bundle-cssog branch from 4daf84a to b8893bd Compare September 17, 2025 09:23
Comment thread packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts Outdated
Comment thread packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts Outdated
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/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (1)

60-76: Replace Set.prototype.union with compatible merge

Set.prototype.union isn’t widely supported in target runtimes; avoid depending on it.

Apply:

-        const importDeps = cssIdToImportBy.get(importCssId)
-          ?? new Set([importCssId]);
-        importDeps.add(cssId);
-        cssIdToImportBy.set(importCssId, currentImportBy.union(importDeps));
+        const importDeps = cssIdToImportBy.get(importCssId)
+          ?? new Set([importCssId]);
+        importDeps.add(cssId);
+        const merged = new Set<string>([...importDeps, ...currentImportBy]);
+        cssIdToImportBy.set(importCssId, merged);
♻️ Duplicate comments (2)
packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (2)

185-193: Good fallback: per-entry CSS routing now safely defaults to root pageConfig

This resolves the prior “!(undefined) → OG” pitfall.


554-565: Don’t write "null"/"undefined" cssId; correctly clear l-e-name

Setting cssId + '' yields "null"/"undefined"; entryName is never cleared when unset.

Apply:

-  for (const element of elements) {
-    element.setAttribute(cssIdAttribute, cssId + '');
-    entryName && element.setAttribute(lynxEntryNameAttribute, entryName);
+  for (const element of elements) {
+    if (cssId == null) {
+      element.removeAttribute(cssIdAttribute);
+    } else {
+      element.setAttribute(cssIdAttribute, String(cssId));
+    }
+    if (entryName == null || entryName === '') {
+      element.removeAttribute(lynxEntryNameAttribute);
+    } else {
+      element.setAttribute(lynxEntryNameAttribute, entryName);
+    }
     const cls = element.getAttribute('class');
     cls && __SetClasses(element, cls);
   }
🧹 Nitpick comments (10)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx (2)

21-23: Add a Suspense fallback to make the test deterministically waitable.
A minimal fallback (e.g., data-testid) helps Playwright await content readiness and reduces flakiness.

Apply:

-    <Suspense>
+    <Suspense fallback={<div data-testid="loading" />}>
       <LazyComponent />
     </Suspense>

27-27: Nit: self-close component tag for consistency.
No behavior change; improves consistency across test fixtures.

-root.render(<App></App>);
+root.render(<App />);
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1)

21-23: Add an explicit Suspense fallback for deterministic loading

A fallback={null} keeps markup stable and avoids incidental differences across environments.

Apply this diff:

-    <Suspense>
+    <Suspense fallback={null}>
       <LazyComponent />
     </Suspense>
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (2)

15-17: Use functional setState to avoid stale toggles.

Safer under batched updates.

-  handletap() {
-    this.setState({ flag: !this.state.flag });
-  }
+  handletap() {
+    this.setState(prev => ({ flag: !prev.flag }));
+  }

22-23: Avoid trailing space in class string.

Build classes via join for cleaner output.

-        class={'background-yellow '
-          + (this.state.flag ? 'background-green' : '')}
+        class={['background-yellow', this.state.flag && 'background-green']
+          .filter(Boolean).join(' ')}
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (3)

15-17: Use functional setState for reliable toggling.

-  handletap() {
-    this.setState({ flag: !this.state.flag });
-  }
+  handletap() {
+    this.setState(prev => ({ flag: !prev.flag }));
+  }

22-23: Build class names without string concat.

-        class={'background-yellow '
-          + (this.state.flag ? 'background-green' : '')}
+        class={['background-yellow', this.state.flag && 'background-green']
+          .filter(Boolean).join(' ')}

24-26: Minor: avoid recreating a closure on every render.

Bind once in constructor or make handletap a class field and pass the reference: bindtap={this.handletap}.

packages/web-platform/web-tests/tests/react.spec.ts (2)

716-821: Gate CSSOG lazy-component tests behind SSR skip (consistent with other lazy tests).

Existing lazy-component tests use test.skip(isSSR, ...). Do the same for this block to prevent SSR runs.

-    // lazy component with CSSOG
-    test(
+    // lazy component with CSSOG
+    test.describe('lazy component with CSSOG', () => {
+      test.skip(isSSR, 'Lazy Component not support on SSR');
+
+      test(
         'basic-lazy-component-css-selector-false-exchange-class',
         async ({ page }, { title }) => {
           await goto(page, title);
           await wait(100);
           const target = page.locator('#target');
           await expect(target).toHaveCSS('background-color', 'rgb(0, 128, 0)'); // green
           await target.click();
           await expect(target).toHaveCSS('background-color', 'rgb(255, 255, 0)'); // yellow
           await target.click();
           await expect(target).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)'); // unset
         },
       );
+    });

823-832: Duplicate/misplaced test name: appears again under “configs”.

This config-css-selector-false-type-selector test already exists in the "configs" suite (Lines 1852-1861). Remove here or rename to a “basic-lazy-component-...” case if a corresponding page exists.

-    test(
-      'config-css-selector-false-type-selector',
-      async ({ page }, { title }) => {
-        await goto(page, title);
-        await wait(100);
-        const target = page.locator('#target');
-        await expect(target).toHaveCSS('background-color', 'rgb(255, 255, 0)'); // yellow
-        await expect(target).toHaveCSS('width', '100px');
-        await expect(target).toHaveCSS('height', '100px');
-      },
-    );
📜 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 4daf84a and b8893bd.

📒 Files selected for processing (37)
  • .changeset/shiny-toes-punch.md (1 hunks)
  • packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (8 hunks)
  • packages/web-platform/web-mainthread-apis/src/crossThreadHandlers/createQueryComponent.ts (2 hunks)
  • packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts (0 hunks)
  • packages/web-platform/web-mainthread-apis/src/pureElementPAPIs.ts (0 hunks)
  • packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (3 hunks)
  • packages/web-platform/web-tests/tests/react.spec.ts (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-fetch-only-one/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false.config.ts (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component.config.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • packages/web-platform/web-mainthread-apis/src/pureElementPAPIs.ts
  • packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts
✅ Files skipped from review due to trivial changes (2)
  • .changeset/shiny-toes-punch.md
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.css
🚧 Files skipped from review as they are similar to previous changes (26)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.css
  • packages/web-platform/web-mainthread-apis/src/crossThreadHandlers/createQueryComponent.ts
  • packages/web-platform/web-tests/tests/react/config-lazy-component.config.ts
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-fetch-only-one/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false.config.ts
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx
🧰 Additional context used
📓 Path-based instructions (1)
packages/web-platform/web-tests/**

📄 CodeRabbit inference engine (AGENTS.md)

Place Playwright E2E tests in the web platform’s web-tests suite

Files:

  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx
  • packages/web-platform/web-tests/tests/react.spec.ts
🧠 Learnings (2)
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx
📚 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/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts
🧬 Code graph analysis (6)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (3)
  • importPath (6-7)
  • LazyComponent (8-17)
  • App (19-25)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (4)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1)
  • Root (8-33)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx (1)
  • Root (8-38)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1)
  • Root (8-31)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1)
  • Root (8-32)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (4)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1)
  • Root (8-54)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1)
  • Root (8-31)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1)
  • Root (8-35)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1)
  • Root (8-32)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx (1)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx (1)
  • App (6-33)
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (3)
packages/web-platform/web-constants/src/types/StyleInfo.ts (1)
  • CssOGInfo (32-36)
packages/web-platform/web-mainthread-apis/src/utils/decodeCssOG.ts (1)
  • decodeCssOG (12-31)
packages/web-platform/web-constants/src/types/PageConfig.ts (1)
  • PageConfig (4-10)
packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (5)
packages/web-platform/web-constants/src/types/LynxModule.ts (1)
  • LynxTemplate (21-42)
packages/web-platform/web-constants/src/types/Element.ts (1)
  • WebFiberElementImpl (51-96)
packages/web-platform/web-constants/src/constants.ts (3)
  • lynxEntryNameAttribute (13-13)
  • cssIdAttribute (7-7)
  • lynxUniqueIdAttribute (5-5)
packages/web-platform/web-constants/src/types/MainThreadGlobalThis.ts (3)
  • SetCSSIdPAPI (270-274)
  • AddClassPAPI (249-252)
  • SetClassesPAPI (254-257)
packages/web-platform/web-mainthread-apis/src/pureElementPAPIs.ts (2)
  • __SetClasses (267-274)
  • __AddClass (307-314)
⏰ 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). (3)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (10)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx (2)

1-1: Placement LGTM — under web-tests suite as required.
File location complies with our guideline for Playwright E2E fixtures.


6-17: ```shell
#!/bin/bash
set -euo pipefail
echo "1) Searching for occurrences of the test folder/name..."
rg -nP "basic-lazy-component-css-selector-false-multi-level-selector" packages -S -C3 || true

echo
echo "2) Show the test file if present:"
TEST_FILE="packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx"
if [ -f "$TEST_FILE" ]; then
sed -n '1,240p' "$TEST_FILE" || true
else
echo "File not found: $TEST_FILE"
fi

echo
echo "3) Search for dynamic import usages with a with: option (e.g. with: { type: ... })"
rg -nP "import\([^)]with\s:\s*\{" packages -S -C3 || true
rg -nP "with\s*:\s*\{\stype\s:" packages -S -C3 || true

echo
echo "4) Search for base/serve/mount constants or envs that would indicate non-root mounts"
rg -nP "PUBLIC_URL|PUBLIC_PATH|ASSET_PREFIX|webpack_public_path|BASE_PATH|BASE_URL|webTestsBase|mountPath|servePath|prefix|baseHref|PUBLIC_BASE|BASE_HREF" packages -i -S -C3 || true

echo
echo "5) Search for server/devServer config that might show how web-tests are mounted"
rg -nP "devServer|dev-server|webpack-dev-server|createServer|serveStatic|mount\(|mountPath|baseHref" packages -S -C3 || true

echo
echo "6) Search for 'lynx' (bundler) references"
rg -nP "lynx|Lynx" packages -i -S -C3 || true


</blockquote></details>
<details>
<summary>packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (2)</summary><blockquote>

`1-3`: **License header: looks good**

Header matches repository style.

---

`8-17`: **Lazy loader pattern aligns with existing tests**

Import attributes and structure match sibling cases.

</blockquote></details>
<details>
<summary>packages/web-platform/web-tests/tests/react.spec.ts (1)</summary><blockquote>

`716-833`: **All "basic-lazy-component-css-selector-false-*" test pages exist — no action required.**
Verified directories present under packages/web-platform/web-tests/tests/react for all listed cases.

</blockquote></details>
<details>
<summary>packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (2)</summary><blockquote>

`176-185`: **Confirm toSpliced usage in selector assembly**

Same concern as above; ensure runtime support or refactor.

See the script in the prior comment to validate baseline/polyfills.

---

`124-141`: ```shell
#!/bin/bash
# Safer, minimal checks for transpile/polyfill strategy and toSpliced usage.
echo "=== toSpliced matches (with context) ==="
rg -n --hidden -S -C2 'toSpliced\(' || true

echo
echo "=== Show file (first 300 lines) ==="
f="packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts"
if [ -f "$f" ]; then
  sed -n '1,300p' "$f" || true
else
  echo "$f not found"
fi

echo
echo "=== package.json files (list) ==="
find . -maxdepth 6 -type f -name package.json -print || true

echo
echo "=== Show package.json contents (first 200 lines each) ==="
while IFS= read -r pj; do
  echo "---- $pj ----"
  sed -n '1,200p' "$pj" || true
done < <(find . -maxdepth 6 -type f -name package.json -print) || true

echo
echo "=== .browserslistrc or browserslist files ==="
[ -f .browserslistrc ] && sed -n '1,200p' .browserslistrc || true
rg -n --hidden -S 'browserslist' || true

echo
echo "=== tsconfig.json files (show compilerOptions.target/lib if present) ==="
while IFS= read -r tc; do
  echo "---- $tc ----"
  sed -n '1,200p' "$tc" || true
done < <(find . -maxdepth 6 -type f -name tsconfig.json -print) || true

echo
echo "=== Search for polyfill / babel / preset-env / core-js / useBuiltIns ==="
rg -n --hidden -S 'core-js|useBuiltIns|@babel/preset-env|preset-env|@babel/runtime|regenerator-runtime|polyfill' || true

echo
echo "=== Search for bundlers/compilers (vite/esbuild/webpack/rollup/swc/tsup/babel) ==="
rg -n --hidden -S 'vite|esbuild|webpack|rollup|swc|tsup|parcel|babel' || true

echo
echo "=== End ==="
packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (3)

590-598: Runtime routing wrapper looks correct

Delegates to OG/NG paths based on per-entry config.


615-625: SetClasses wrapper correctly mirrors AddClass routing

Matches the OG update callback signature (with entryName).


671-676: Template classes always use NG path — confirm this is intentional

If element-templates can belong to OG-routed entries, consider using the same getCSSOGConfig-based routing here (or document why NG is correct).

Comment thread packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts Outdated
Comment thread packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts Outdated
@Sherry-hue Sherry-hue force-pushed the feat/lazy-bundle-cssog branch 3 times, most recently from 0639171 to 03ed0c3 Compare September 18, 2025 07:04
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 (3)
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (2)

317-319: Don’t mutate textContent; append a separate <style> before the runtime sheet

textContent += re-parses the stylesheet, invalidating lynxUniqueIdToStyleRulesIndex. Insert a new <style> node and keep cardStyleElement as the last sheet so runtime rules remain highest in cascade.

-    lazyCSSOGInfo[entryName] = cssOGInfo;
-    cardStyleElement.textContent += newStyleSheet;
+    lazyCSSOGInfo[entryName] = cssOGInfo;
+    const entryStyleElement = document.createElement('style') as HTMLStyleElement;
+    entryStyleElement.textContent = newStyleSheet;
+    // Ensure runtime rules in cardStyleElement stay last for specificity/cascade.
+    cardStyleElement.insertAdjacentElement('beforebegin', entryStyleElement);

286-290: Fix crash when entryName is set but lazy map not populated

decodeCssOG receives undefined when entryName exists but lazyCSSOGInfo[entryName] isn’t ready; this throws. Fall back to base cssOGInfo.

-    const newStyles = decodeCssOG(
-      newClassName,
-      (entryName ? lazyCSSOGInfo[entryName] : cssOGInfo) as any,
-      cssID,
-    );
+    const styleMap: CssOGInfo =
+      entryName && lazyCSSOGInfo[entryName]
+        ? lazyCSSOGInfo[entryName]
+        : cssOGInfo;
+    const newStyles = decodeCssOG(newClassName, styleMap, cssID);
packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (1)

546-556: Don’t serialize null/undefined cssId; also support clearing entryName

cssId + '' writes "null"/"undefined". Also, entryName && … cannot clear an existing l-e-name.

 const __SetCSSIdForCSSOG: SetCSSIdPAPI = (
   elements,
   cssId,
   entryName,
 ) => {
   for (const element of elements) {
-    element.setAttribute(cssIdAttribute, cssId + '');
-    entryName && element.setAttribute(lynxEntryNameAttribute, entryName);
+    if (cssId == null) {
+      element.removeAttribute(cssIdAttribute);
+    } else {
+      element.setAttribute(cssIdAttribute, String(cssId));
+    }
+    if (entryName == null || entryName === '') {
+      element.removeAttribute(lynxEntryNameAttribute);
+    } else {
+      element.setAttribute(lynxEntryNameAttribute, entryName);
+    }
     const cls = element.getAttribute('class');
     cls && __SetClassesForCSSOG(element, cls);
   }
 };
🧹 Nitpick comments (12)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.css (3)

6-12: Stabilize color assertions for tests.

If tests check getComputedStyle, consider using explicit RGB to avoid name→RGB normalization differences, or ensure tests assert the RGB form.

Apply if preferred:

-.background-green {
-  background-color: green;
-}
+.background-green {
+  background-color: rgb(0, 128, 0);
+}
 
-.background-yellow {
-  background-color: yellow;
-}
+.background-yellow {
+  background-color: rgb(255, 255, 0);
+}

6-12: Reduce cross-test style leakage by namespacing class names.

Optional: prefix with a test-specific slug (e.g., cssog-) and update the JSX accordingly to minimize collisions across the suite.

-.background-green {
+.cssog-background-green {
   background-color: rgb(0, 128, 0);
 }
 
-.background-yellow {
+.cssog-background-yellow {
   background-color: rgb(255, 255, 0);
 }

13-13: Ensure trailing newline at EOF.

Add a final newline to satisfy common linters/formatters.

packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (3)

13-15: Stabilize state updates and cap to 0/1 to avoid undefined classes after multiple taps

Functional setState avoids stale reads; modulo keeps states within the two supported cases.

-  handletap() {
-    this.setState({ stateId: this.state.stateId + 1 });
-  }
+  handletap = () => {
+    this.setState(s => ({ stateId: (s.stateId + 1) % 2 }));
+  }

22-29: Add defensive default and document intentional trailing space

Prevents undefined return if state ever drifts; comment preserves test intent.

   getClass() {
     switch (this.state.stateId) {
       case 0:
         return 'background-yellow background-green';
       case 1:
-        return 'background-green background-yellow ';
+        return 'background-green background-yellow '; // intentional trailing space to exercise class parsing
+      default:
+        return 'background-yellow background-green';
     }
   }

35-37: Avoid inline arrow in render to reduce churn

Since handletap is converted to a bound class field, pass it directly.

-        bindtap={() => {
-          this.handletap();
-        }}
+        bindtap={this.handletap}
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (4)

6-6: Remove unused import root.

Prevents linter noise and keeps bundles lean.

-import { Component, root } from '@lynx-js/react';
+import { Component } from '@lynx-js/react';

15-17: Use functional setState to avoid stale reads.

Safer when multiple updates are queued.

-  handletap() {
-    this.setState({ flag: !this.state.flag });
-  }
+  handletap() {
+    this.setState(prev => ({ flag: !prev.flag }));
+  }

24-26: Avoid recreating the handler in render.

Bind once in the constructor and pass the method directly.

-        bindtap={() => {
-          this.handletap();
-        }}
+        bindtap={this.handletap}

Apply in constructor:

   constructor(props) {
     super(props);
     this.state = {
       flag: false,
     };
+    this.handletap = this.handletap.bind(this);
   }

Also applies to: 9-14


22-24: Tidy class string; remove trailing space.

Template literal keeps spacing correct.

-        class={'background-yellow '
-          + (this.state.flag ? 'background-green' : '')}
+        class={`background-yellow${this.state.flag ? ' background-green' : ''}`}
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false.config.ts (1)

4-11: Avoid Node-version‑specific APIs or add fallback (fs.promises.glob, import.meta.dirname, Array.fromAsync)

These rely on Node ≥22 for fs/promises.glob and import.meta.dirname, and relatively new Array.fromAsync. If CI runs on Node 18/20, discovery will break. Prefer a backward‑compatible approach or guard with a fallback.

Apply this diff to add a safe dirname fallback and simplify the pattern to a single string (keeps fs.promises.glob but de-risks dirname and array arg):

 import { glob } from 'node:fs/promises';
 import path from 'node:path';
+import { fileURLToPath } from 'node:url';
@@
-const reactBasicCases = await Array.fromAsync(glob(
-  [
-    path.join(
-      import.meta.dirname,
-      'basic-lazy-component-css-selector-false-*',
-      '*.jsx',
-    ),
-  ],
-));
+const baseDir =
+  // Node ≥22 exposes import.meta.dirname; older nodes don't.
+  (import.meta as any).dirname ?? path.dirname(fileURLToPath(import.meta.url));
+const pattern = path.join(
+  baseDir,
+  'basic-lazy-component-css-selector-false-*',
+  '*.jsx',
+);
+const reactBasicCases = await Array.fromAsync(glob(pattern));

If CI Node <22, I can provide a tinyglobby/fast-glob variant.

packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (1)

284-286: Nit: redundant cast

cardStyleElement is already HTMLStyleElement; drop “as unknown as HTMLStyleElement”.

-    const cardStyleElementSheet =
-      (cardStyleElement as unknown as HTMLStyleElement).sheet!;
+    const cardStyleElementSheet = cardStyleElement.sheet!;
📜 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 b8893bd and 03ed0c3.

📒 Files selected for processing (34)
  • .changeset/shiny-toes-punch.md (1 hunks)
  • packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (5 hunks)
  • packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts (0 hunks)
  • packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (3 hunks)
  • packages/web-platform/web-tests/tests/react.spec.ts (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false.config.ts (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic.config.ts (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts
🚧 Files skipped from review as they are similar to previous changes (26)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.css
  • packages/web-platform/web-tests/tests/react/basic.config.ts
  • .changeset/shiny-toes-punch.md
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.css
  • packages/web-platform/web-tests/tests/react.spec.ts
🧰 Additional context used
📓 Path-based instructions (1)
packages/web-platform/web-tests/**

📄 CodeRabbit inference engine (AGENTS.md)

Place Playwright E2E tests in the web platform’s web-tests suite

Files:

  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false.config.ts
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx
🧠 Learnings (4)
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false.config.ts
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js` is a template file for scaffolding new Rspeedy projects, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false.config.ts
📚 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/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx
📚 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/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts
🧬 Code graph analysis (5)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false.config.ts (1)
packages/web-platform/web-tests/tests/react/commonConfig.ts (1)
  • commonConfig (10-38)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx (1)
  • App (6-33)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (3)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1)
  • Root (8-33)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1)
  • Root (8-31)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1)
  • Root (8-32)
packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (1)
packages/web-platform/web-constants/src/constants.ts (2)
  • cssIdAttribute (7-7)
  • lynxEntryNameAttribute (13-13)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx (1)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (3)
  • importPath (6-7)
  • LazyComponent (8-17)
  • App (19-25)
⏰ 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). (3)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (6)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.css (1)

1-5: License header: confirm consistency (year and wording).

Matches the repo style? If other files use a different year range or wording, align this header accordingly.

packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (2)

1-5: LGTM overall; fixture is in the correct web-tests suite.

Placement and structure align with the platform’s web test setup.


22-24: Confirm intent: inline style overrides CSS classes.
As written, class = 'background-yellow' + (flag ? 'background-green' : '') while inline style sets backgroundColor: flag ? 'yellow' : 'green' — computed color is green initially and yellow after tap. If the test should assert the opposite mapping, flip the class or inline-style color expressions.

packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx (1)

6-17: LGTM: lazy import wiring matches config path and component type

Import path and lazy(() => import(..., { with: { type: 'component' } })) align with the dedicated config and test pattern in this suite.

packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (2)

569-576: LGTM: propagate entryName to CSS‑OG updates

Passing the per‑element l-e-name through to updateCssOGStyle is correct and matches the lazy map logic.


585-592: LGTM: SetClasses path mirrors AddClass propagation

Symmetric propagation ensures both code paths update the right entry scope.

@Sherry-hue Sherry-hue force-pushed the feat/lazy-bundle-cssog branch from 03ed0c3 to bc64e50 Compare September 18, 2025 08:02
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 (3)
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (3)

163-170: Gate entryName scoping behind enableCSSSelector === false
Prior feedback said “don’t do this for enableCSSSelector:true”. Limit entry scoping to the CSS‑OG path to avoid unintended selector narrowing.

Apply:

-    if (entryName) {
-      suffix = `${suffix}[${lynxEntryNameAttribute}=${JSON.stringify(entryName)}]`;
-    } else {
-      suffix = `${suffix}:not([${lynxEntryNameAttribute}])`;
-    }
+    if (!pageConfig.enableCSSSelector) {
+      if (entryName) {
+        suffix = `${suffix}[${lynxEntryNameAttribute}=${JSON.stringify(entryName)}]`;
+      } else {
+        suffix = `${suffix}:not([${lynxEntryNameAttribute}])`;
+      }
+    }

286-289: Good guard against undefined lazy map
The styleMap fallback prevents crashes when lazyCSSOGInfo[entryName] is not yet populated. This addresses the earlier issue.


316-318: Stop using textContent +=; it resets the CSSOM and invalidates stored rule indices

Mutating cardStyleElement.textContent reparses the stylesheet, dropping previously insertRule-inserted rules and breaking lynxUniqueIdToStyleRulesIndex. Create a per-entry <style> element instead and track its rule indices.

Apply:

-    lazyCSSOGInfo[entryName] = cssOGInfo;
-    cardStyleElement.textContent += newStyleSheet;
+    lazyCSSOGInfo[entryName] = entryCssOGInfo;
+    const entryStyleElement = document.createElement('style') as HTMLStyleElement;
+    entryStyleElement.textContent = newStyleSheet;
+    rootDom.appendChild(entryStyleElement);
+    entryStyleElements[entryName] = entryStyleElement;
+    entryRuleIndices[entryName] = [];
🧹 Nitpick comments (15)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx (3)

6-7: Prefer a more descriptive constant name for clarity.

Use a name that conveys it’s a manifest path and update the call site.

-const importPath =
+const manifestPath =
   `/dist/config-lazy-component-css-selector-false-remove-all/index.web.json`;
@@
-    return import(
-      importPath,
+    return import(
+      manifestPath,
       {
         with: { type: 'component' },
       }
     );

Also applies to: 11-11


19-25: Add an explicit Suspense fallback to reduce E2E flakiness.

Being explicit avoids subtle differences across renderers.

-  return (
-    <Suspense>
-      <LazyComponent />
-    </Suspense>
-  );
+  return (
+    <Suspense fallback={null}>
+      <LazyComponent />
+    </Suspense>
+  );

27-27: Nit: self-close the App element for consistency.

-root.render(<App></App>);
+root.render(<App />);
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (5)

15-17: Cycle stateId modulo 4 to avoid undefined class/style after the 4th tap

Without wrap-around, Line 16 lets stateId grow beyond 0–3; both switches lack defaults, so class/style become undefined on further taps.

Apply:

-  handletap() {
-    this.setState({ stateId: this.state.stateId + 1 });
-  }
+  handletap() {
+    this.setState({ stateId: (this.state.stateId + 1) % 4 });
+  }

18-29: Add a default branch in getInline for defensive stability

Keeps element size predictable even if stateId ever escapes the expected set.

   getInline() {
     switch (this.state.stateId) {
       case 0:
         return { height: '100px', width: '100px' }; // green
       case 1:
         return { backgroundColor: 'red', height: '100px', width: '100px' }; // red
       case 2:
         return { backgroundColor: 'red', height: '100px', width: '100px' }; // red
       case 3:
         return { height: '100px', width: '100px' }; // yellow
+      default:
+        return { height: '100px', width: '100px' };
     }
   }

30-41: Add a default branch in getClass to keep a deterministic class

Prevents class from becoming undefined on unexpected states.

   getClass() {
     switch (this.state.stateId) {
       case 0:
         return 'background-yellow background-green';
       case 1:
         return 'background-yellow background-green';
       case 2:
         return 'background-yellow';
       case 3:
         return 'background-yellow';
+      default:
+        return 'background-yellow';
     }
   }

47-49: Avoid recreating the tap handler each render (optional)

Prebind once in the constructor and pass the method reference.

   constructor(props) {
     super(props);
+    this.handletap = this.handletap.bind(this);
     this.state = {
       stateId: 0,
     };
   }
-        bindtap={() => {
-          this.handletap();
-        }}
+        bindtap={this.handletap}

Also applies to: 9-14


21-27: Tighten inline comments to reflect source of background color (optional)

Clarify that the color in state 0/3 comes from CSS classes, not inline style.

-        return { height: '100px', width: '100px' }; // green
+        return { height: '100px', width: '100px' }; // green via CSS class
@@
-        return { height: '100px', width: '100px' }; // yellow
+        return { height: '100px', width: '100px' }; // yellow via CSS class
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx (3)

8-17: Minor: inline the lazy import for brevity

Functionally identical; reduces noise.

-const LazyComponent = lazy(
-  () => {
-    return import(
-      importPath,
-      {
-        with: { type: 'component' },
-      }
-    );
-  },
-);
+const LazyComponent = lazy(() =>
+  import(importPath, { with: { type: 'component' } })
+);

19-25: Be explicit about Suspense fallback to avoid UI variability

Make fallback explicit to guard against upstream defaults changing.

-  return (
-    <Suspense>
+  return (
+    <Suspense fallback={null}>
       <LazyComponent />
     </Suspense>
   );

27-27: Nit: self‑closing JSX

Stylistic consistency with other tests.

-root.render(<App></App>);
+root.render(<App />);
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (4)

284-301: Route dynamic updates to the correct stylesheet and index map (per-entry)
Currently all OG updates target the main sheet. With per-entry sheets, choose the target sheet and indices by entryName to keep indices stable and avoid cross-entry coupling.

Apply:

-    const cardStyleElementSheet =
-      (cardStyleElement as unknown as HTMLStyleElement).sheet!;
+    const targetStyleElement =
+      entryName && entryStyleElements[entryName]
+        ? entryStyleElements[entryName]
+        : cardStyleElement;
+    const targetSheet = (targetStyleElement as HTMLStyleElement).sheet!;
+    const targetRuleIndices =
+      entryName && entryRuleIndices[entryName]
+        ? entryRuleIndices[entryName]
+        : lynxUniqueIdToStyleRulesIndex;
@@
-    if (lynxUniqueIdToStyleRulesIndex[uniqueId] !== undefined) {
-      const rule = cardStyleElementSheet
-        .cssRules[lynxUniqueIdToStyleRulesIndex[uniqueId]] as CSSStyleRule;
+    if (targetRuleIndices[uniqueId] !== undefined) {
+      const rule = targetSheet.cssRules[targetRuleIndices[uniqueId]] as CSSStyleRule;
       rule.style.cssText = newStyles;
     } else {
-      const index = cardStyleElementSheet.insertRule(
+      const index = targetSheet.insertRule(
         `[${lynxUniqueIdAttribute}="${uniqueId}"]{${newStyles}}`,
-        cardStyleElementSheet.cssRules.length,
+        targetSheet.cssRules.length,
       );
-      lynxUniqueIdToStyleRulesIndex[uniqueId] = index;
+      targetRuleIndices[uniqueId] = index;
     }

263-263: Track per-entry style elements and rule indices
Required by the above routing to keep indices isolated per entry and avoid collisions.

Apply:

   const lazyCSSOGInfo: Record<string, CssOGInfo> = {};
+  const entryStyleElements: Record<string, HTMLStyleElement> = {};
+  const entryRuleIndices: Record<string, number[]> = {};

308-311: Avoid shadowing cssOGInfo; use a distinct name for entry OG info
Shadowing hurts readability and can mislead. Rename and update the assignment.

Apply:

-    const cssOGInfo: CssOGInfo = pageConfig.enableCSSSelector
+    const entryCssOGInfo: CssOGInfo = pageConfig.enableCSSSelector
       ? {}
       : genCssOGInfo(flattenedStyleInfo);
@@
-    lazyCSSOGInfo[entryName] = cssOGInfo;
+    lazyCSSOGInfo[entryName] = entryCssOGInfo;

Also applies to: 316-316


274-274: Superfluous explicit undefined
The parameter is optional; drop the explicit undefined for clarity.

Apply:

-      pageConfig,
-      undefined,
+      pageConfig,
📜 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 03ed0c3 and bc64e50.

📒 Files selected for processing (34)
  • .changeset/shiny-toes-punch.md (1 hunks)
  • packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts (5 hunks)
  • packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts (0 hunks)
  • packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (3 hunks)
  • packages/web-platform/web-tests/tests/react.spec.ts (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false.config.ts (1 hunks)
  • packages/web-platform/web-tests/tests/react/basic.config.ts (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.css (1 hunks)
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/web-platform/web-mainthread-apis/src/prepareMainThreadAPIs.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/shiny-toes-punch.md
🚧 Files skipped from review as they are similar to previous changes (28)
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-multi-level-selector/index.css
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-multi-level-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false.config.ts
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.css
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx
  • packages/web-platform/web-tests/tests/react/basic.config.ts
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx
  • packages/web-platform/web-mainthread-apis/src/createMainThreadGlobalThis.ts
  • packages/web-platform/web-tests/tests/react.spec.ts
🧰 Additional context used
📓 Path-based instructions (1)
packages/web-platform/web-tests/**

📄 CodeRabbit inference engine (AGENTS.md)

Place Playwright E2E tests in the web platform’s web-tests suite

Files:

  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx
  • packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx
🧠 Learnings (2)
📚 Learning: 2025-08-06T13:28:57.182Z
Learnt from: colinaaa
PR: lynx-family/lynx-stack#1453
File: vitest.config.ts:49-61
Timestamp: 2025-08-06T13:28:57.182Z
Learning: In the lynx-family/lynx-stack repository, the file `packages/react/testing-library/src/vitest.config.js` is source code for the testing library that gets exported for users, not a test configuration that should be included in the main vitest projects array.

Applied to files:

  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx
  • packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx
📚 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/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx
🧬 Code graph analysis (4)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx (2)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (3)
  • importPath (6-7)
  • LazyComponent (8-17)
  • App (19-25)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
  • App (6-42)
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (2)
packages/web-platform/web-constants/src/types/StyleInfo.ts (1)
  • CssOGInfo (32-36)
packages/web-platform/web-mainthread-apis/src/utils/decodeCssOG.ts (1)
  • decodeCssOG (12-31)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx (2)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-exchange-class/index.jsx (3)
  • importPath (6-7)
  • LazyComponent (8-17)
  • App (19-25)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-exchange-class/index.jsx (1)
  • App (6-42)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (5)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-css-change-same-time/index.jsx (1)
  • Root (8-33)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.jsx (1)
  • Root (8-38)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-reuse-css/index.jsx (1)
  • Root (8-31)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-css-and-style-collapsed/index.jsx (1)
  • Root (8-35)
packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-inline-style-and-reuse-css/index.jsx (1)
  • Root (8-32)
⏰ 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). (3)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / Test (Ubuntu)
🔇 Additional comments (7)
packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx (3)

4-4: Imports and Lynx React API usage look correct.

Matches sibling fixtures; no issues spotted.


1-1: No E2E spec references this fixture — add one

Search found no specs referencing packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-remove-all/index.jsx; add or update a Playwright E2E spec under packages/web-platform/web-tests/tests/ to load and exercise this fixture.


8-17: Lazy import with import attributes looks good — manifest (index.web.json) not found.

index.css is present at packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-remove-all/index.css; index.web.json is missing from that config directory. Add or verify the manifest to avoid 404s during E2E runs.

packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-inline-remove-css-remove-inline/index.jsx (1)

1-7: LGTM: correct fixture placement and scenario setup

File is in the web-tests suite and mirrors other lazy CSSOG fixtures. Import and structure align with neighboring tests.

packages/web-platform/web-tests/tests/react/basic-lazy-component-css-selector-false-type-selector/index.jsx (2)

1-4: Placement and headers look good

Correct suite location and license header; imports align with existing lazy bundle patterns.


6-7: Verify fixture/config pairing and selector under test — component & CSS present; Playwright spec missing

  • Verified: packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.jsx exports a component rendering .
  • Verified: packages/web-platform/web-tests/tests/react/config-lazy-component-css-selector-false-type-selector/index.css defines view { background-color: yellow }.
  • Missing: no Playwright spec referencing "basic-lazy-component-css-selector-false-type-selector" was found — add or point to the spec.
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (1)

69-76: Action: Ensure Set.prototype.union is available at runtime (polyfill/fallback); Array.prototype.toSpliced is broadly supported (as of Sep 18, 2025).

  • Set.prototype.union — supported in Chromium (Chrome/Edge 122+) and V8 12+ (Node 22+); Firefox may only ship it behind preview/nightly. Add a polyfill or replace the union call with explicit union logic to avoid runtime errors.
  • Array.prototype.toSpliced — widely supported in modern browsers (Chrome ≈110+, Firefox ≈115+, Safari 16+) and Node 20+; no change needed unless you must support older runtimes.

Location: packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts — lines 69–76 and 126–139.

Comment thread packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts Outdated
@Sherry-hue Sherry-hue force-pushed the feat/lazy-bundle-cssog branch from 0140622 to c636c44 Compare September 18, 2025 09:11
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: 1

Caution

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

⚠️ Outside diff range comments (1)
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (1)

279-301: Gate runtime insertRule behind pageConfig.enableCSSSelector === false

When enableCSSSelector === true cssOGInfo is {}, so decodeCssOG(...) returns an empty string and updateCssOGStyle will insert/update empty CSS rules. Call sites (createMainThreadGlobalThis.ts — __AddClassForCSSOG / __SetClassesForCSSOG) call callbacks.updateCssOGStyle unconditionally. Add an early-return in updateCssOGStyle (packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts) when pageConfig.enableCSSSelector is true, or ensure callers skip invoking it.
Also: updateLazyComponentStyle sets lazyCSSOGInfo[entryName] = genCssOGInfo(...) only when CSSOG is enabled but then unconditionally does lazyCSSOGInfo[entryName] = cssOGInfo — that override looks wrong and should be fixed.

♻️ Duplicate comments (2)
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (2)

286-289: Nice: avoids decodeCssOG crash when lazy map missing

styleMap fallback resolves the previously reported undefined deref.


306-311: Good: populate per‑entry OG map only when CSSSelector is off

Matches intent from prior feedback.

🧹 Nitpick comments (4)
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (4)

263-263: Guard against unbounded growth of per‑entry map

lazyCSSOGInfo can grow without cleanup. Add a disposal path (e.g., when an entry unmounts) to delete lazy entries and their indices to avoid memory retention.


268-275: Remove redundant double cast; passing undefined is fine

The unknown-as pattern is unnecessary here. Keep the element typed as HTMLStyleElement directly.

-    cardStyleElement = document.createElement(
-      'style',
-    ) as unknown as HTMLStyleElement;
+    cardStyleElement = document.createElement('style') as HTMLStyleElement;

284-285: Drop unnecessary cast when accessing sheet

cardStyleElement is already HTMLStyleElement.

-    const cardStyleElementSheet =
-      (cardStyleElement as unknown as HTMLStyleElement).sheet!;
+    const cardStyleElementSheet = cardStyleElement.sheet!;

317-317: Note: textContent += reparses stylesheet; indices can drift

Acknowledging team’s decision to defer optimization: reparsing can invalidate lynxUniqueIdToStyleRulesIndex for previously inserted rules. Consider separate <style> per entry (and per‑entry indices) in a follow‑up PR to fully eliminate this class of bugs.

If you want, I can open a follow‑up issue and attach a minimal prototype diff.

📜 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 bc64e50 and c636c44.

📒 Files selected for processing (1)
  • packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Sherry-hue
PR: lynx-family/lynx-stack#1770
File: packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts:316-318
Timestamp: 2025-09-18T08:12:56.778Z
Learning: In packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts, the current implementation uses cardStyleElement.textContent += for lazy component styles. While this could theoretically invalidate rule indices by reparsing the stylesheet, Sherry-hue indicated that UIDs don't repeat for the same element, making this approach acceptable for now. A future optimization to use separate style elements per entry was discussed but deferred to a separate PR to keep the current lazy bundle PR focused.
📚 Learning: 2025-09-18T08:12:56.778Z
Learnt from: Sherry-hue
PR: lynx-family/lynx-stack#1770
File: packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts:316-318
Timestamp: 2025-09-18T08:12:56.778Z
Learning: In packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts, the current implementation uses cardStyleElement.textContent += for lazy component styles. While this could theoretically invalidate rule indices by reparsing the stylesheet, Sherry-hue indicated that UIDs don't repeat for the same element, making this approach acceptable for now. A future optimization to use separate style elements per entry was discussed but deferred to a separate PR to keep the current lazy bundle PR focused.

Applied to files:

  • packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts
🧬 Code graph analysis (1)
packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts (2)
packages/web-platform/web-constants/src/types/StyleInfo.ts (1)
  • CssOGInfo (32-36)
packages/web-platform/web-mainthread-apis/src/utils/decodeCssOG.ts (1)
  • decodeCssOG (12-31)
⏰ 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). (3)
  • GitHub Check: build / Build (Ubuntu)
  • GitHub Check: build / Build (Windows)
  • GitHub Check: test-rust / Test (Ubuntu)

Comment thread packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts Outdated
…leInfo.ts

Co-authored-by: Haoyang Wang <12288479+PupilTong@users.noreply.github.com>
Signed-off-by: Sherry <37186915+Sherry-hue@users.noreply.github.com>
@Sherry-hue Sherry-hue force-pushed the feat/lazy-bundle-cssog branch from c636c44 to 743f06a Compare September 18, 2025 09:23
@Sherry-hue Sherry-hue enabled auto-merge (squash) September 18, 2025 09:46
@Sherry-hue Sherry-hue merged commit d150ed4 into lynx-family:main Sep 19, 2025
113 of 118 checks passed
colinaaa pushed a commit that referenced this pull request Sep 21, 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.114.0

### Minor Changes

- Partially fix the "cannot read property 'update' of undefined" error.
([#1771](#1771))

This error happens when rendering a JSX expression in a
[background-only](https://lynxjs.org/react/thinking-in-reactlynx.html)
context.

See
[#894](#894)
for more details.

### Patch Changes

- Reduce extra snapshot when children are pure text
([#1562](#1562))

- feat: Support `SelectorQuery` `animation` APIs
([#1768](#1768))

- Fix spread props inside list-item caused redundant snapshot patch
([#1760](#1760))

- fix: `ref is not initialized` error on template reload
([#1757](#1757))

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

### Minor Changes

- **BREAKING CHANGE:** Remove the `enableParallelElement` and
`pipelineSchedulerConfig` options.
([#1705](#1705))

Since the thread element resolution is still in experimental stage and
may have stability risks, it will be disabled by default after this
change.

- **BREAKING CHANGE**: Remove the `enableICU` option.
([#1800](#1800))

### Patch Changes

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

- Updated dependencies
\[[`24100ab`](24100ab),
[`24100ab`](24100ab),
[`d0ef559`](d0ef559)]:
    -   @lynx-js/template-webpack-plugin@0.9.0
    -   @lynx-js/react-webpack-plugin@0.7.1
    -   @lynx-js/css-extract-webpack-plugin@0.6.3
    -   @lynx-js/react-alias-rsbuild-plugin@0.11.0
    -   @lynx-js/use-sync-external-store@1.5.0
    -   @lynx-js/react-refresh-webpack-plugin@0.3.4

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

### Minor Changes

- Enable `lynxUIPlugins` (incl. `uiVariants`) by default. Fills the gap
left by missing pseudo- and data-attribute selectors in Lynx, offering
state and structural variants out of the box.
([#1774](#1774))

    Opt-out globally or per plugin:

    ```ts
    // disable all UI plugins
    createLynxPreset({ lynxUIPlugins: false });
    // or disable one plugin
    createLynxPreset({ lynxUIPlugins: { uiVariants: false } });
    ```

### Patch Changes

- Fixed transform-related CSS variables previously defined on `:root`;
they are now reset on `*` to prevent inheritance between parent and
child elements.
([#1773](#1773))

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

### Minor Changes

- break(web): temporary remove support for chunk split
([#1739](#1739))

Since the global variables cannot be accessed in the splited chunk, we
temporary remove supporting for chunk spliting

Developers could easily remove the chunk Split settings in Rspeedy for
migration

        import { defineConfig } from '@lynx-js/rspeedy'

        export default defineConfig({
          performance: {
            chunkSplit: {
              strategy: 'all-in-one',
            },
          },
        })

### Patch Changes

- fix: lazy component load error
([#1794](#1794))

Some special version template may have chunk loading error. We fixed it.

- fix: avoid duplicate style transformation
([#1748](#1748))

    After this commit, we use DAG methods to handle the styleInfos

- fix: add sandbox attribute to iframe for enhanced security
([#1709](#1709))

- fix: the default template loader won't fetch twice for one url
([#1709](#1709))

- Updated dependencies
\[[`721635d`](721635d),
[`93d707b`](93d707b),
[`d150ed4`](d150ed4)]:
    -   @lynx-js/web-mainthread-apis@0.17.0
    -   @lynx-js/web-constants@0.17.0
    -   @lynx-js/web-worker-runtime@0.17.0
    -   @lynx-js/web-worker-rpc@0.17.0

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

### Minor Changes

- **BREAKING CHANGE:** Remove the `enableParallelElement` and
`pipelineSchedulerConfig` options.
([#1705](#1705))

Since the thread element resolution is still in experimental stage and
may have stability risks, it will be disabled by default after this
change.

- **BREAKING CHANGE**: Remove the `enableICU` option.
([#1800](#1800))

## @lynx-js/rspeedy@0.11.3

### Patch Changes

- Use `output.chunkLoading: 'lynx'` for `environments.web`.
([#1737](#1737))

- Support `resolve.extensions`
([#1759](#1759))

- Set the default value of `output.cssModules.localIdentName` to
`[local]-[hash:base64:6]`.
([#1783](#1783))

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

### Patch Changes

- fix: avoid duplicate style transformation
([#1748](#1748))

    After this commit, we use DAG methods to handle the styleInfos

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

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

### Patch Changes

- The img within svg does not inherit the position
([#1769](#1769))

-   Updated dependencies \[]:
    -   @lynx-js/web-elements-template@0.8.7

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

### Patch Changes

- fix: \_\_QueryComponentImpl in mts should execute only once for same
url ([#1763](#1763))

- fix: avoid duplicate style transformation
([#1748](#1748))

    After this commit, we use DAG methods to handle the styleInfos

- feat: support lazy bundle with CSSOG(`enableCSSSelector: false`).
([#1770](#1770))

- Updated dependencies
\[[`93d707b`](93d707b)]:
    -   @lynx-js/web-constants@0.17.0
    -   @lynx-js/web-style-transformer@0.17.0

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

### Patch Changes

- Updated dependencies
\[[`721635d`](721635d),
[`93d707b`](93d707b),
[`d150ed4`](d150ed4)]:
    -   @lynx-js/web-mainthread-apis@0.17.0
    -   @lynx-js/web-constants@0.17.0
    -   @lynx-js/web-worker-rpc@0.17.0

## @lynx-js/css-extract-webpack-plugin@0.6.3

### Patch Changes

- Supports `@lynx-js/template-webpack-plugin` 0.9.0.
([#1705](#1705))

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

### Patch Changes

- Supports `@lynx-js/template-webpack-plugin` 0.9.0.
([#1705](#1705))

## create-rspeedy@0.11.3



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



## upgrade-rspeedy@0.11.3



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



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



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



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

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@coderabbitai coderabbitai Bot mentioned this pull request Dec 1, 2025
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants