Skip to content

fix: rename exposed symbol to LynxBundlePlugin#2311

Open
Huxpro wants to merge 1 commit intomainfrom
Huxpro/align-terms-expose
Open

fix: rename exposed symbol to LynxBundlePlugin#2311
Huxpro wants to merge 1 commit intomainfrom
Huxpro/align-terms-expose

Conversation

@Huxpro
Copy link
Copy Markdown
Collaborator

@Huxpro Huxpro commented Mar 6, 2026

Summary

  • Rename exposed symbol from LynxTemplatePlugin to LynxBundlePlugin with backward compatibility
  • Producer (pluginReactLynx) exposes under both new and old symbol names
  • Consumer (pluginLynxConfig) uses fallback pattern: useExposed('LynxBundlePlugin') ?? useExposed('LynxTemplatePlugin')

Test plan

  • Build passes for @lynx-js/react-rsbuild-plugin
  • Tests pass for @lynx-js/react-rsbuild-plugin
  • Tests pass for @lynx-js/config-rsbuild-plugin
  • Backward compat verified with both old and new symbol names

Summary by CodeRabbit

  • New Features
    • Exposed LynxBundlePlugin as the new primary public plugin API symbol for React and Config Rsbuild plugins, with improved error messaging.
    • LynxTemplatePlugin symbol fully retained for backward compatibility without requiring any code updates to existing integrations.

…ugin

Expose plugin hooks under the new Symbol.for('LynxBundlePlugin') while
keeping backward compat with the old Symbol.for('LynxTemplatePlugin').
Consumer side uses fallback pattern for compatibility with older versions.
Copilot AI review requested due to automatic review settings March 6, 2026 02:49
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 6, 2026

🦋 Changeset detected

Latest commit: 19267fc

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

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

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

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 6, 2026

📝 Walkthrough

Walkthrough

A symbol renaming initiative updates the exported API from LynxTemplatePlugin to LynxBundlePlugin across multiple packages. The changes introduce dual exposure handling for backward compatibility, update configuration logic to resolve the new symbol with fallback to the old name, and modify test suites to reflect the new API surface while maintaining legacy symbol access.

Changes

Cohort / File(s) Summary
Changeset Documentation
.changeset/expose-symbol-rename.md
Documents patch-level version bumps and public API change: LynxTemplatePlugin renamed to LynxBundlePlugin with backward compatibility.
Plugin Configuration
packages/rspeedy/plugin-config/src/pluginLynxConfig.ts, packages/rspeedy/plugin-config/test/pluginLynxConfig.test.ts
Updates configuration logic to handle dual exposure (exposedNew and exposedOld), derives plugin class from either symbol with fallback, and adjusts test expectations and error messages to reference LynxBundlePlugin.
Plugin React Exposure
packages/rspeedy/plugin-react/src/pluginReactLynx.ts, packages/rspeedy/plugin-react/test/expose.test.ts
Refactors public exposure to register LynxBundlePlugin as primary symbol while aliasing the legacy LynxTemplatePlugin symbol to the same payload. Test suite updated with new assertions and backward-compatibility validation for old symbol access.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

framework:React

Suggested reviewers

  • upupming
  • colinaaa
  • luhc228

Poem

🐰 A bundler's new name takes the stage so bright,
From Template to Bundle, the symbols unite,
Backward paths preserved for those of old,
A graceful transition, as renaming should hold,
The plugins now dance 'neath their shiny new crown! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: rename exposed symbol to LynxBundlePlugin' directly and accurately describes the main change: renaming an exposed symbol while preserving backward compatibility.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch Huxpro/align-terms-expose

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

❤️ Share

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

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 6, 2026

Codecov Report

❌ Patch coverage is 90.90909% with 1 line in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...ages/rspeedy/plugin-config/src/pluginLynxConfig.ts 85.71% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR renames the exposed symbol used for inter-plugin communication from LynxTemplatePlugin to LynxBundlePlugin, updating both the producer (pluginReactLynx) and the consumer (pluginLynxConfig) while attempting to maintain backward compatibility with both old and new symbol names.

Changes:

  • Rename the exposed symbol from LynxTemplatePlugin to LynxBundlePlugin in the producer plugin, exposing under both new and old symbol names for backward compat
  • Update the consumer plugin to try the new symbol first, falling back to the old symbol, with a runtime in check to resolve the correct property key
  • Update tests and inline snapshots to reflect the new naming, and add a backward compat test in the producer

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/rspeedy/plugin-react/src/pluginReactLynx.ts Producer: expose under both LynxBundlePlugin and LynxTemplatePlugin symbols with the new key structure
packages/rspeedy/plugin-config/src/pluginLynxConfig.ts Consumer: try new symbol first, fall back to old, use in check to resolve correct property key
packages/rspeedy/plugin-react/test/expose.test.ts Updated test for new symbol name and added backward compat test
packages/rspeedy/plugin-config/test/pluginLynxConfig.test.ts Updated inline snapshots and mock structure for new symbol/key naming
.changeset/expose-symbol-rename.md Changeset for both packages

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +398 to +400
api.expose(Symbol.for('LynxBundlePlugin'), exposedLynxBundlePlugin)
// Backward compat: keep exposing under the old symbol
api.expose(Symbol.for('LynxTemplatePlugin'), exposedLynxBundlePlugin)
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The backward compatibility is incomplete for the scenario where a new pluginReactLynx (producer) is used with an old pluginLynxConfig (consumer).

The old consumer code (before this PR) destructured LynxTemplatePlugin from the exposed object:

const { LynxTemplatePlugin: LynxTemplatePluginClass } = exposed

But the new producer exposes { LynxBundlePlugin: ... } under the old Symbol.for('LynxTemplatePlugin') symbol. This means the old consumer would get undefined for LynxTemplatePluginClass, causing a runtime error.

To fix this, the object exposed under the old symbol should also include the old key name. For example, include both keys (LynxBundlePlugin and LynxTemplatePlugin) in the object exposed under the old symbol, or expose a separate object with the old key name under the old symbol.

Copilot uses AI. Check for mistakes.
Comment on lines +95 to +127
test('backward compat: old LynxTemplatePlugin symbol still works', async () => {
const { pluginReactLynx } = await import('../src/index.js')

let expose: { LynxBundlePlugin: LynxTemplatePlugin } | undefined

const rsbuild = await createRspeedy({
rspeedyConfig: {
source: {
entry: {
main: new URL('./fixtures/basic.tsx', import.meta.url).pathname,
},
},
plugins: [
pluginReactLynx(),
pluginStubRspeedyAPI(),
{
name: 'pluginThatUsesOldSymbol',
setup(api) {
expose = api.useExposed<
{ LynxBundlePlugin: LynxTemplatePlugin }
>(Symbol.for('LynxTemplatePlugin'))
},
} as RsbuildPlugin,
],
},
})

await rsbuild.initConfigs()
expect(expose).toBeDefined()
expect(expose!.LynxBundlePlugin).toBeDefined()
expect(expose!.LynxBundlePlugin.getLynxTemplatePluginHooks).toBeTypeOf(
'function',
)
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

This backward compatibility test does not accurately simulate what an old consumer would do. An old consumer (pre-rename) would look up Symbol.for('LynxTemplatePlugin') and then access the LynxTemplatePlugin property from the result — not LynxBundlePlugin.

The test should use { LynxTemplatePlugin: LynxTemplatePlugin } as the type and assert expose!.LynxTemplatePlugin is defined and has getLynxTemplatePluginHooks. As written, this test passes but doesn't catch the real backward compatibility issue: the old key LynxTemplatePlugin is missing from the object exposed under the old symbol.

Copilot uses AI. Check for mistakes.
Comment on lines +107 to +108
api.expose(Symbol.for('LynxBundlePlugin'), {
LynxBundlePlugin: { getLynxTemplatePluginHooks },
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

Missing test coverage for the backward compatibility path in the consumer. There's no test verifying that pluginLynxConfig works when the producer only exposes under the old Symbol.for('LynxTemplatePlugin') with the old { LynxTemplatePlugin: ... } key structure (i.e., old producer + new consumer scenario). This is the scenario addressed by lines 120-124 and 159-161 of pluginLynxConfig.ts, and it would be valuable to have a test covering it to prevent regressions.

Copilot uses AI. Check for mistakes.
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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/rspeedy/plugin-react/src/pluginReactLynx.ts`:
- Around line 392-400: The code currently exposes exposedLynxBundlePlugin under
both Symbol.for('LynxBundlePlugin') and Symbol.for('LynxTemplatePlugin') but the
latter keeps the new payload shape, breaking consumers expecting a
LynxTemplatePlugin property; fix by creating a legacy wrapper object that
includes a LynxTemplatePlugin property (pointing to the same
getLynxTemplatePluginHooks bound function) and use that when calling
api.expose(Symbol.for('LynxTemplatePlugin'), ...); reference
exposedLynxBundlePlugin, LynxTemplatePlugin.getLynxTemplatePluginHooks, and the
api.expose calls when making the change.

In `@packages/rspeedy/plugin-react/test/expose.test.ts`:
- Around line 95-127: The test "backward compat: old LynxTemplatePlugin symbol
still works" currently asserts expose!.LynxBundlePlugin but should assert the
legacy property expose!.LynxTemplatePlugin to prove backward compatibility;
update the assertions that check the exposed property (the variable expose) to
reference LynxTemplatePlugin and verify its getLynxTemplatePluginHooks is a
function, keeping the Symbol.for('LynxTemplatePlugin') usage and existing
pluginReactLynx/imports intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 05248147-8796-4b33-95ff-651162b46d63

📥 Commits

Reviewing files that changed from the base of the PR and between c877fbd and 19267fc.

📒 Files selected for processing (5)
  • .changeset/expose-symbol-rename.md
  • packages/rspeedy/plugin-config/src/pluginLynxConfig.ts
  • packages/rspeedy/plugin-config/test/pluginLynxConfig.test.ts
  • packages/rspeedy/plugin-react/src/pluginReactLynx.ts
  • packages/rspeedy/plugin-react/test/expose.test.ts

Comment on lines +392 to +400
const exposedLynxBundlePlugin = {
LynxBundlePlugin: {
getLynxTemplatePluginHooks: LynxTemplatePlugin
.getLynxTemplatePluginHooks.bind(LynxTemplatePlugin),
},
})
}
api.expose(Symbol.for('LynxBundlePlugin'), exposedLynxBundlePlugin)
// Backward compat: keep exposing under the old symbol
api.expose(Symbol.for('LynxTemplatePlugin'), exposedLynxBundlePlugin)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep the legacy wrapper under Symbol.for('LynxTemplatePlugin').

This preserves the old symbol name, but not the old payload shape. Any consumer still doing api.useExposed(Symbol.for('LynxTemplatePlugin'))?.LynxTemplatePlugin will now get undefined, so the backward-compat contract is broken.

💡 Proposed fix
-        const exposedLynxBundlePlugin = {
-          LynxBundlePlugin: {
-            getLynxTemplatePluginHooks: LynxTemplatePlugin
-              .getLynxTemplatePluginHooks.bind(LynxTemplatePlugin),
-          },
-        }
-        api.expose(Symbol.for('LynxBundlePlugin'), exposedLynxBundlePlugin)
-        // Backward compat: keep exposing under the old symbol
-        api.expose(Symbol.for('LynxTemplatePlugin'), exposedLynxBundlePlugin)
+        const lynxBundlePlugin = {
+          getLynxTemplatePluginHooks: LynxTemplatePlugin
+            .getLynxTemplatePluginHooks.bind(LynxTemplatePlugin),
+        }
+        api.expose(Symbol.for('LynxBundlePlugin'), {
+          LynxBundlePlugin: lynxBundlePlugin,
+        })
+        // Backward compat: keep the old symbol and the old property name.
+        api.expose(Symbol.for('LynxTemplatePlugin'), {
+          LynxTemplatePlugin: lynxBundlePlugin,
+          LynxBundlePlugin: lynxBundlePlugin,
+        })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/rspeedy/plugin-react/src/pluginReactLynx.ts` around lines 392 - 400,
The code currently exposes exposedLynxBundlePlugin under both
Symbol.for('LynxBundlePlugin') and Symbol.for('LynxTemplatePlugin') but the
latter keeps the new payload shape, breaking consumers expecting a
LynxTemplatePlugin property; fix by creating a legacy wrapper object that
includes a LynxTemplatePlugin property (pointing to the same
getLynxTemplatePluginHooks bound function) and use that when calling
api.expose(Symbol.for('LynxTemplatePlugin'), ...); reference
exposedLynxBundlePlugin, LynxTemplatePlugin.getLynxTemplatePluginHooks, and the
api.expose calls when making the change.

Comment on lines +95 to +127
test('backward compat: old LynxTemplatePlugin symbol still works', async () => {
const { pluginReactLynx } = await import('../src/index.js')

let expose: { LynxBundlePlugin: LynxTemplatePlugin } | undefined

const rsbuild = await createRspeedy({
rspeedyConfig: {
source: {
entry: {
main: new URL('./fixtures/basic.tsx', import.meta.url).pathname,
},
},
plugins: [
pluginReactLynx(),
pluginStubRspeedyAPI(),
{
name: 'pluginThatUsesOldSymbol',
setup(api) {
expose = api.useExposed<
{ LynxBundlePlugin: LynxTemplatePlugin }
>(Symbol.for('LynxTemplatePlugin'))
},
} as RsbuildPlugin,
],
},
})

await rsbuild.initConfigs()
expect(expose).toBeDefined()
expect(expose!.LynxBundlePlugin).toBeDefined()
expect(expose!.LynxBundlePlugin.getLynxTemplatePluginHooks).toBeTypeOf(
'function',
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Assert the legacy property when claiming backward compatibility.

This test only proves that the old symbol resolves; it does not prove that old consumers still work. To verify the legacy contract, the assertion needs to read .LynxTemplatePlugin, not .LynxBundlePlugin.

💡 Proposed fix
-    let expose: { LynxBundlePlugin: LynxTemplatePlugin } | undefined
+    let expose:
+      | {
+          LynxTemplatePlugin: LynxTemplatePlugin
+          LynxBundlePlugin?: LynxTemplatePlugin
+        }
+      | undefined
@@
-    expect(expose!.LynxBundlePlugin).toBeDefined()
-    expect(expose!.LynxBundlePlugin.getLynxTemplatePluginHooks).toBeTypeOf(
+    expect(expose!.LynxTemplatePlugin).toBeDefined()
+    expect(expose!.LynxTemplatePlugin.getLynxTemplatePluginHooks).toBeTypeOf(
       'function',
     )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/rspeedy/plugin-react/test/expose.test.ts` around lines 95 - 127, The
test "backward compat: old LynxTemplatePlugin symbol still works" currently
asserts expose!.LynxBundlePlugin but should assert the legacy property
expose!.LynxTemplatePlugin to prove backward compatibility; update the
assertions that check the exposed property (the variable expose) to reference
LynxTemplatePlugin and verify its getLynxTemplatePluginHooks is a function,
keeping the Symbol.for('LynxTemplatePlugin') usage and existing
pluginReactLynx/imports intact.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Mar 6, 2026

Merging this PR will improve performance by 44.06%

⚡ 1 improved benchmark
✅ 71 untouched benchmarks
⏩ 3 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
basic-performance-large-css 23.1 ms 16.1 ms +44.06%

Comparing Huxpro/align-terms-expose (19267fc) with main (c877fbd)

Open in CodSpeed

Footnotes

  1. 3 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 Mar 6, 2026

Web Explorer

#8007 Bundle Size — 384.21KiB (0%).

19267fc(current) vs c877fbd main#8005(baseline)

Bundle metrics  no changes
                 Current
#8007
     Baseline
#8005
No change  Initial JS 155.31KiB 155.31KiB
No change  Initial CSS 35.1KiB 35.1KiB
No change  Cache Invalidation 0% 0%
No change  Chunks 8 8
No change  Assets 8 8
No change  Modules 239 239
No change  Duplicate Modules 16 16
No change  Duplicate Code 2.98% 2.98%
No change  Packages 4 4
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#8007
     Baseline
#8005
No change  JS 253.26KiB 253.26KiB
No change  Other 95.85KiB 95.85KiB
No change  CSS 35.1KiB 35.1KiB

Bundle analysis reportBranch Huxpro/align-terms-exposeProject dashboard


Generated by RelativeCIDocumentationReport issue

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