Skip to content

feat: Support frame element on web#2604

Merged
PupilTong merged 1 commit into
lynx-family:mainfrom
PupilTong:codex/web-core-frame-element
May 12, 2026
Merged

feat: Support frame element on web#2604
PupilTong merged 1 commit into
lynx-family:mainfrom
PupilTong:codex/web-core-frame-element

Conversation

@PupilTong
Copy link
Copy Markdown
Collaborator

@PupilTong PupilTong commented May 11, 2026

Summary

  • Add <frame> creation support in web-core PAPI and the React snapshot transform.
  • Map frame to lynx-view in both TypeScript and Rust tag maps, including style selector decoding.
  • Wire frame-facing src, data, global-props, auto-height, auto-width, and bindload behavior through LynxView.
  • Add focused Playwright e2e coverage for each frame API behavior.

Validation

  • cargo test -p swc_plugin_snapshot basic_full_static
  • cargo test -p web-core test_type_selector
  • pnpm turbo build
  • pnpm exec playwright test tests/reactlynx.spec.ts --grep api-frame --project=chromium

Summary by CodeRabbit

  • New Features
    • Added support for the <frame> element on the web platform, enabling dynamic content loading from external bundles.
    • Frame element supports data passing, auto-sizing properties, and global props configuration.
    • Added bindload event for tracking frame load status with status code and message information.
    • Frame content updates now propagate when data changes dynamically.

Review Change Stack

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 11, 2026

🦋 Changeset detected

Latest commit: c3fa234

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

This PR includes changesets to release 9 packages
Name Type
@lynx-js/web-core Patch
upgrade-rspeedy Patch
@lynx-js/web-rsbuild-server-middleware Patch
@lynx-js/template-webpack-plugin Patch
@lynx-js/react-rsbuild-plugin Patch
create-rspeedy Patch
@lynx-js/web-worker-rpc Patch
@lynx-js/react-alias-rsbuild-plugin Patch
@lynx-js/rspeedy 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 May 11, 2026

📝 Walkthrough

Walkthrough

This PR adds comprehensive Lynx frame element support to the web platform. It establishes framelynx-view tag mappings, extends LynxViewElement with property aliases (src, data, globalProps), implements frame creation APIs for client and server, dispatches load events with status metadata, and includes eight E2E test cases covering element mapping, data/global-props propagation, data reactivity, load events, and auto-sizing behavior.

Changes

Frame Element API Implementation

Layer / File(s) Summary
Type Contracts
packages/web-platform/web-core/ts/types/IElementPAPI.ts
Export CreateFramePAPI type alias and add __CreateFrame to ElementPAPIs interface.
Tag Mappings
packages/web-platform/web-core/src/constants.rs, packages/web-platform/web-core/ts/constants.ts
Add "frame""lynx-view" mappings in both Rust and TypeScript constant maps.
LynxViewElement Properties
packages/web-platform/web-core/ts/client/mainthread/LynxView.ts
Expand observed attributes to include src and data; add src as alias for url; add global-props, init-data, and data accessors; parse string input for JSON properties; route attribute changes through public setters; require url for rendering; upgrade pre-connection properties.
Element Creation APIs
packages/web-platform/web-core/ts/server/elementAPIs/createElementAPI.ts, packages/web-platform/web-core/ts/client/mainthread/elementAPIs/createElementAPI.ts
Implement __CreateFrame in server and client element factories; create frame elements via tag mapping; register with wasm context; emit load event with status metadata on frame initialization.
Style Decoder Validation
packages/web-platform/web-core/src/template/template_sections/style_info/style_info_decoder.rs
Add unit test validating "frame" type selector decodes to "lynx-view" with correct CSS output.
Inner Frame Fixture
packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-inner/index.jsx
Create inner frame test page rendering status, init data label, and global props message for loading by outer test frames.
Outer Frame Fixtures
packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-*/index.jsx
Create ten test pages covering element mapping, src loading, static/dynamic data, global-props, bindload event handling, and auto-height/auto-width sizing.
E2E Test Cases
packages/web-platform/web-core-e2e/tests/reactlynx.spec.ts
Add eight Playwright tests validating frame tag name (LYNX-VIEW), src/data rendering, data update reactivity, global-props propagation, bindload event details, and auto-sizing attribute presence.
Release Notes
.changeset/frame-web-core.md
Document patch release for @lynx-js/web-core with frame element web support.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • lynx-family/lynx-stack#1497: Updates React/swc transformer to emit __CreateFrame(...) for <frame> — the counterpart to this PR's __CreateFrame implementations.
  • lynx-family/lynx-stack#2080: Extensive mainthread/element API and LynxView implementations that overlap with the frame element property additions in this PR.
  • lynx-family/lynx-stack#2360: Introduces runtime snapshot support and type-level references to __CreateFrame and frame element creation.

Suggested labels

platform:Web

Suggested reviewers

  • Sherry-hue
  • hzy

Poem

🐰 A frame takes shape upon the web,
lynx-view steps where data ebb,
Props cascade through load events bright,
Auto-sizing springs to height,
Tests hop along to check each case—
Frame's now home in cyberspace! 🌐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Support frame element on web' accurately describes the primary objective of the pull request, which is to add web support for the element by mapping it to and implementing related functionality.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

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

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.

@PupilTong PupilTong changed the title [codex] Support frame element on web feat: Support frame element on web May 11, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 11, 2026

Codecov Report

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

Files with missing lines Patch % Lines
...web-core/ts/server/elementAPIs/createElementAPI.ts 11.11% 8 Missing ⚠️

📢 Thoughts on this report? Let us know!

@PupilTong PupilTong marked this pull request as ready for review May 11, 2026 13:46
@PupilTong PupilTong requested a review from Sherry-hue as a code owner May 11, 2026 13:46
@PupilTong PupilTong force-pushed the codex/web-core-frame-element branch from b6f1897 to ea6461e Compare May 11, 2026 13:47
@PupilTong PupilTong force-pushed the codex/web-core-frame-element branch from ea6461e to c3fa234 Compare May 11, 2026 13:50
@PupilTong PupilTong self-assigned this May 11, 2026
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.

🧹 Nitpick comments (2)
packages/web-platform/web-core-e2e/tests/reactlynx.spec.ts (1)

305-327: 💤 Low value

Consider more explicit assertions for auto-sizing tests.

The current tests verify that auto-height='true' and height != 'auto', but not.toHaveAttribute passes in multiple scenarios (attribute missing, or attribute present with different value). While this may be intentional, more explicit assertions would make the test expectations clearer.

📝 More explicit alternative
  test('api-frame-auto-height', async ({ page }, { title }) => {
    await goto(page, title);
    await expect(page.locator('#target')).toHaveAttribute(
      'auto-height',
      'true',
    );
-   await expect(page.locator('#target')).not.toHaveAttribute(
-     'height',
-     'auto',
-   );
+   // More explicit: verify height attribute is absent entirely, or has explicit pixel value
+   const heightAttr = await page.locator('#target').getAttribute('height');
+   expect(heightAttr).not.toBe('auto');
  });

Or use a comment to clarify intent:

+   // Verify that explicit height dimension is not set to 'auto' when auto-height is enabled
    await expect(page.locator('#target')).not.toHaveAttribute(
      'height',
      'auto',
    );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web-platform/web-core-e2e/tests/reactlynx.spec.ts` around lines 305
- 327, The auto-sizing tests (tests 'api-frame-auto-height' and
'api-frame-auto-width' using page.locator('#target')) currently use
not.toHaveAttribute which is ambiguous; change these to explicit checks: either
assert the target does not have the attribute (expect(await
locator.getAttribute('height')).toBeNull()) or read the attribute value and
assert it's not the string 'auto' (const h = await
locator.getAttribute('height'); expect(h).not.toBe('auto')). Apply the same
explicit pattern for 'width' in the 'api-frame-auto-width' test so the intent is
unambiguous.
packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-bindload/index.jsx (1)

7-11: 💤 Low value

Consider a more semantic initial state for statusCode.

The initial statusCode: -1 works as a sentinel value, but using null or a separate loading state would be more explicit and avoid potential confusion with HTTP status codes.

💡 Alternative approach
-  const [detail, setDetail] = useState({
-    statusCode: -1,
-    statusMessage: '',
-    url: '',
-  });
+  const [detail, setDetail] = useState({
+    statusCode: null,
+    statusMessage: '',
+    url: '',
+  });

Or use a more explicit loading state:

+  const [isLoading, setIsLoading] = useState(true);
   const [detail, setDetail] = useState({
-    statusCode: -1,
+    statusCode: 0,
     statusMessage: '',
     url: '',
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-bindload/index.jsx`
around lines 7 - 11, The initial state for detail uses a sentinel -1 for
statusCode; change this to a more semantic value by using null for statusCode or
add an explicit loading flag (e.g., add isLoading to the state) so callers can
distinguish "not loaded" from valid HTTP codes; update the useState initializer
for detail and any code branches that read detail.statusCode (and any UI that
checks it) to handle null or consult the new isLoading flag instead of comparing
against -1.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/web-platform/web-core-e2e/tests/reactlynx.spec.ts`:
- Around line 305-327: The auto-sizing tests (tests 'api-frame-auto-height' and
'api-frame-auto-width' using page.locator('#target')) currently use
not.toHaveAttribute which is ambiguous; change these to explicit checks: either
assert the target does not have the attribute (expect(await
locator.getAttribute('height')).toBeNull()) or read the attribute value and
assert it's not the string 'auto' (const h = await
locator.getAttribute('height'); expect(h).not.toBe('auto')). Apply the same
explicit pattern for 'width' in the 'api-frame-auto-width' test so the intent is
unambiguous.

In
`@packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-bindload/index.jsx`:
- Around line 7-11: The initial state for detail uses a sentinel -1 for
statusCode; change this to a more semantic value by using null for statusCode or
add an explicit loading flag (e.g., add isLoading to the state) so callers can
distinguish "not loaded" from valid HTTP codes; update the useState initializer
for detail and any code branches that read detail.statusCode (and any UI that
checks it) to handle null or consult the new isLoading flag instead of comparing
against -1.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 972511bf-e35c-4c65-99da-f15d1cb9cf22

📥 Commits

Reviewing files that changed from the base of the PR and between 33b124f and c3fa234.

📒 Files selected for processing (18)
  • .changeset/frame-web-core.md
  • packages/web-platform/web-core-e2e/tests/reactlynx.spec.ts
  • packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-auto-height/index.jsx
  • packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-auto-width/index.jsx
  • packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-bindload/index.jsx
  • packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-data-update/index.jsx
  • packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-data/index.jsx
  • packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-element-map/index.jsx
  • packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-global-props/index.jsx
  • packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-inner/index.jsx
  • packages/web-platform/web-core-e2e/tests/reactlynx/api-frame-src/index.jsx
  • packages/web-platform/web-core/src/constants.rs
  • packages/web-platform/web-core/src/template/template_sections/style_info/style_info_decoder.rs
  • packages/web-platform/web-core/ts/client/mainthread/LynxView.ts
  • packages/web-platform/web-core/ts/client/mainthread/elementAPIs/createElementAPI.ts
  • packages/web-platform/web-core/ts/constants.ts
  • packages/web-platform/web-core/ts/server/elementAPIs/createElementAPI.ts
  • packages/web-platform/web-core/ts/types/IElementPAPI.ts

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 11, 2026

Merging this PR will degrade performance by 5.37%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 79 untouched benchmarks
⏩ 26 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
002-hello-reactLynx-destroyBackground 863.5 µs 912.4 µs -5.37%
transform 1000 view elements 43.1 ms 40 ms +7.68%

Comparing PupilTong:codex/web-core-frame-element (c3fa234) with main (33b124f)

Open in CodSpeed

Footnotes

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

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 11, 2026

Web Explorer

#9621 Bundle Size — 901.01KiB (+0.11%).

c3fa234(current) vs 33b124f main#9602(baseline)

Bundle metrics  Change 4 changes Regression 1 regression
                 Current
#9621
     Baseline
#9602
Regression  Initial JS 44.99KiB(+1.18%) 44.46KiB
No change  Initial CSS 2.22KiB 2.22KiB
Change  Cache Invalidation 32.89% 0%
No change  Chunks 9 9
No change  Assets 11 11
Change  Modules 228(-0.44%) 229
No change  Duplicate Modules 11 11
Change  Duplicate Code 27.26%(-0.07%) 27.28%
No change  Packages 10 10
No change  Duplicate Packages 0 0
Bundle size by type  Change 2 changes Regression 2 regressions
                 Current
#9621
     Baseline
#9602
Regression  JS 496.73KiB (+0.17%) 495.91KiB
Regression  Other 402.06KiB (+0.03%) 401.92KiB
No change  CSS 2.22KiB 2.22KiB

Bundle analysis reportBranch PupilTong:codex/web-core-frame-e...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 11, 2026

React MTF Example

#1179 Bundle Size — 206.6KiB (0%).

c3fa234(current) vs 33b124f main#1160(baseline)

Bundle metrics  no changes
                 Current
#1179
     Baseline
#1160
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 3 3
No change  Modules 192 192
No change  Duplicate Modules 77 77
No change  Duplicate Code 44.36% 44.36%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#1179
     Baseline
#1160
No change  IMG 111.23KiB 111.23KiB
No change  Other 95.37KiB 95.37KiB

Bundle analysis reportBranch PupilTong:codex/web-core-frame-e...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 11, 2026

React Example with Element Template

#314 Bundle Size — 197.79KiB (0%).

c3fa234(current) vs 33b124f main#295(baseline)

Bundle metrics  Change 2 changes
                 Current
#314
     Baseline
#295
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 4 4
Change  Modules 80(-1.23%) 81
No change  Duplicate Modules 23 23
Change  Duplicate Code 40.31%(+0.05%) 40.29%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#314
     Baseline
#295
No change  IMG 145.76KiB 145.76KiB
No change  Other 52.03KiB 52.03KiB

Bundle analysis reportBranch PupilTong:codex/web-core-frame-e...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 11, 2026

React Example

#8048 Bundle Size — 235.77KiB (0%).

c3fa234(current) vs 33b124f main#8029(baseline)

Bundle metrics  no changes
                 Current
#8048
     Baseline
#8029
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 4 4
No change  Modules 197 197
No change  Duplicate Modules 80 80
No change  Duplicate Code 44.85% 44.85%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#8048
     Baseline
#8029
No change  IMG 145.76KiB 145.76KiB
No change  Other 90.01KiB 90.01KiB

Bundle analysis reportBranch PupilTong:codex/web-core-frame-e...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 11, 2026

React External

#1162 Bundle Size — 690.27KiB (0%).

c3fa234(current) vs 33b124f main#1143(baseline)

Bundle metrics  no changes
                 Current
#1162
     Baseline
#1143
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 3 3
No change  Modules 17 17
No change  Duplicate Modules 5 5
No change  Duplicate Code 8.59% 8.59%
No change  Packages 0 0
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#1162
     Baseline
#1143
No change  Other 690.27KiB 690.27KiB

Bundle analysis reportBranch PupilTong:codex/web-core-frame-e...Project dashboard


Generated by RelativeCIDocumentationReport issue

@PupilTong PupilTong merged commit b989c1c into lynx-family:main May 12, 2026
81 of 85 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants