@sigx/lynx-plugin 0.2.4 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Andreas Ekdahl
3
+ Copyright (c) 2025-2026 Andreas Ekdahl
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -31,9 +31,9 @@ export default defineConfig({
31
31
  - Emits `registerWorkletInternal("main-thread", "<id>", function(...) { ... })` calls into the MT bundle so Lynx native can invoke the worklet body when it dispatches a touch event.
32
32
 
33
33
  3. **MT-bundle bootstrap.** Every file in the MT bundle gets three side-effect imports prepended:
34
- - `@sigx/runtime-lynx-main/entry-main` — installs the `processData` / `renderPage` / `sigxPatchUpdate` globals Lynx expects.
34
+ - `@sigx/lynx-runtime-main/entry-main` — installs the `processData` / `renderPage` / `sigxPatchUpdate` globals Lynx expects.
35
35
  - `@lynx-js/react/runtime/worklet-runtime/main.js` — populates `lynxWorkletImpl`, `registerWorkletInternal`, `runWorklet`.
36
- - `@sigx/runtime-lynx-main/install-hybrid-worklet` — registers the hybrid dispatcher used by the `bindtap` + `main-thread-bindtap` slot machine.
36
+ - `@sigx/lynx-runtime-main/install-hybrid-worklet` — registers the hybrid dispatcher used by the `bindtap` + `main-thread-bindtap` slot machine.
37
37
 
38
38
  Listing them as separate entries in webpack isn't sufficient because the chunk graph can evaluate user code before the bootstrap chain. Prepending side-effect imports per-file forces the dep-graph order.
39
39
 
package/dist/entry.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Dual-thread entry splitting for SignalX Lynx.
3
3
  *
4
4
  * For each user-defined rsbuild entry, creates two webpack entries:
5
- * - `<name>__main-thread` on the MAIN_THREAD layer (PAPI bootstrap via @sigx/runtime-lynx-main)
5
+ * - `<name>__main-thread` on the MAIN_THREAD layer (PAPI bootstrap via @sigx/lynx-runtime-main)
6
6
  * - `<name>` on the BACKGROUND layer (sigx renderer + user app)
7
7
  *
8
8
  * Then registers @lynx-js/template-webpack-plugin to stitch both bundles
@@ -13,7 +13,6 @@ export interface ApplyEntryOptions {
13
13
  enableCSSSelector?: boolean;
14
14
  enableCSSInheritance?: boolean;
15
15
  customCSSInheritanceList?: string[];
16
- enableCSSInlineVariables?: boolean;
17
16
  debugInfoOutside?: boolean;
18
17
  }
19
18
  export declare function applyEntry(api: RsbuildPluginAPI, opts?: ApplyEntryOptions): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -39,11 +39,6 @@ export interface PluginSigxLynxOptions {
39
39
  * Only effective when {@link enableCSSInheritance} is `true`.
40
40
  */
41
41
  customCSSInheritanceList?: string[];
42
- /**
43
- * Whether to enable CSS custom properties (variables) in inline styles.
44
- * @defaultValue false
45
- */
46
- enableCSSInlineVariables?: boolean;
47
42
  /**
48
43
  * Whether to place debug info outside the template bundle.
49
44
  * @defaultValue true
package/dist/index.js CHANGED
@@ -29,13 +29,16 @@ function a(e, n) {
29
29
  "STYLUS_INLINE"
30
30
  ].map((e) => f[e]).filter((e) => !!e && n.module.rules.has(e)).forEach((e) => {
31
31
  p(n.module.rule(e), c);
32
- }), n.plugin(c.PLUGIN.MINI_CSS_EXTRACT).tap(([e]) => [{
33
- ...e,
34
- enableRemoveCSSScope: !0,
35
- enableCSSSelector: a,
36
- enableCSSInvalidation: s,
37
- cssPlugins: []
38
- }]).init((e, t) => new d(...t)).end().end();
32
+ }), n.plugin(c.PLUGIN.MINI_CSS_EXTRACT).tap((e) => {
33
+ let [t] = e;
34
+ return [{
35
+ ...t,
36
+ enableRemoveCSSScope: !0,
37
+ enableCSSSelector: a,
38
+ enableCSSInvalidation: s,
39
+ cssPlugins: []
40
+ }];
41
+ }).init((e, t) => new d(...t)).end().end();
39
42
  function p(e, t) {
40
43
  e.uses.has(t.USE.LIGHTNINGCSS) && e.uses.delete(t.USE.LIGHTNINGCSS);
41
44
  }
@@ -59,6 +62,7 @@ var o = (e, t) => {
59
62
  }, s = "lynx:sigx-template", c = "lynx:sigx-mark-main-thread", l = "lynx:sigx-encode", u = ".rspeedy", d = t.dirname(n(import.meta.url));
60
63
  t.resolve(d, "..");
61
64
  var f = class {
65
+ mainThreadFilenames;
62
66
  constructor(e) {
63
67
  this.mainThreadFilenames = e;
64
68
  }
@@ -130,7 +134,7 @@ async function p(e, n = {}) {
130
134
  import: "@rspack/core/hot/dev-server"
131
135
  }), w.prepend({
132
136
  layer: r.BACKGROUND,
133
- import: "@sigx/runtime-lynx/mt-hmr-bridge"
137
+ import: "@sigx/lynx-runtime/mt-hmr-bridge"
134
138
  })), (b || x) && w.prepend({
135
139
  layer: r.BACKGROUND,
136
140
  import: "@lynx-js/webpack-dev-transport/client"
@@ -147,7 +151,6 @@ async function p(e, n = {}) {
147
151
  enableCSSInvalidation: n.enableCSSSelector ?? !0,
148
152
  enableCSSInheritance: n.enableCSSInheritance ?? !1,
149
153
  customCSSInheritanceList: n.customCSSInheritanceList,
150
- enableCSSInlineVariables: n.enableCSSInlineVariables ?? !1,
151
154
  enableRemoveCSSScope: !0,
152
155
  enableNewGesture: !0,
153
156
  removeDescendantSelectorScope: !0,
@@ -185,7 +188,7 @@ function v(e) {
185
188
  return t ? t[1] : "";
186
189
  }
187
190
  function y(e = {}) {
188
- let { enableCSSSelector: t = !0, enableCSSInheritance: n = !1, customCSSInheritanceList: r, enableCSSInlineVariables: i = !1, debugInfoOutside: o = !0 } = e;
191
+ let { enableCSSSelector: t = !0, enableCSSInheritance: n = !1, customCSSInheritanceList: r, debugInfoOutside: i = !0 } = e;
189
192
  return {
190
193
  name: "lynx:sigx",
191
194
  pre: [
@@ -208,7 +211,7 @@ function y(e = {}) {
208
211
  } }
209
212
  }
210
213
  }))), e.modifyBundlerChain((e) => {
211
- e.resolve.alias.set("@sigx/runtime-dom", "@sigx/runtime-lynx");
214
+ e.resolve.alias.set("@sigx/runtime-dom", "@sigx/lynx-runtime");
212
215
  }), e.modifyRsbuildConfig((e, { mergeRsbuildConfig: t }) => {
213
216
  let n = e.dev?.assetPrefix;
214
217
  if (typeof n != "string") return e;
@@ -223,10 +226,10 @@ function y(e = {}) {
223
226
  return e;
224
227
  }, o = a(n), s = e.server?.printUrls, c = typeof s == "function" ? (e) => {
225
228
  let t = s(e);
226
- return Array.isArray(t) ? t.map((e) => ({
229
+ return Array.isArray(t) ? t.map((e) => typeof e == "string" ? a(e) : {
227
230
  ...e,
228
231
  url: a(e.url)
229
- })) : t;
232
+ }) : t;
230
233
  } : void 0, l = t(e, {
231
234
  dev: {
232
235
  assetPrefix: o,
@@ -303,10 +306,9 @@ function y(e = {}) {
303
306
  enableCSSSelector: t,
304
307
  enableCSSInvalidation: n
305
308
  }), await p(e, {
306
- debugInfoOutside: o,
309
+ debugInfoOutside: i,
307
310
  enableCSSInheritance: n,
308
- customCSSInheritanceList: r,
309
- enableCSSInlineVariables: i
311
+ customCSSInheritanceList: r
310
312
  });
311
313
  }
312
314
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/layers.ts","../src/css.ts","../src/entry.ts","../src/index.ts"],"sourcesContent":["/** Webpack module layers used to separate the dual-thread bundles. */\nexport const LAYERS = {\n BACKGROUND: 'sigx:background',\n MAIN_THREAD: 'sigx:main-thread',\n} as const;\n","/**\n * CSS extraction pipeline for SignalX Lynx.\n *\n * Mirrors the behaviour of `@lynx-js/react-rsbuild-plugin`'s `applyCSS()`:\n * 1. Disables `style-loader` (forces CSS extraction via CssExtractPlugin).\n * 2. Replaces the rsbuild-default CssExtract plugin with\n * `@lynx-js/css-extract-webpack-plugin` which emits Lynx-compatible CSS.\n * 3. Removes `lightningcss-loader` (Lynx has its own CSS processor).\n * 4. Configures the Main-Thread layer to ignore CSS entirely.\n */\n\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport type { CSSLoaderOptions, RsbuildPluginAPI } from '@rsbuild/core';\n\nimport type {\n CssExtractRspackPluginOptions,\n CssExtractWebpackPluginOptions,\n} from '@lynx-js/css-extract-webpack-plugin';\n\nimport { LAYERS } from './layers.js';\n\nexport interface ApplyCSSOptions {\n enableCSSSelector: boolean;\n enableCSSInvalidation: boolean;\n}\n\nconst _dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport function applyCSS(\n api: RsbuildPluginAPI,\n options: ApplyCSSOptions,\n): void {\n const { enableCSSSelector, enableCSSInvalidation } = options;\n\n // ① Force CSS extraction (disable style-loader, enable CssExtractPlugin).\n // Without this, rsbuild injects CSS via JS — useless in Lynx's native env.\n api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => {\n return mergeRsbuildConfig(config, {\n output: { injectStyles: false },\n });\n });\n\n // ② Replace the rsbuild-default CSS extraction plugin with the Lynx-aware\n // one, configure loaders per layer, and remove lightningcss.\n api.modifyBundlerChain(\n async function handler(chain, { CHAIN_ID }) {\n const { CssExtractRspackPlugin, CssExtractWebpackPlugin } = await import(\n '@lynx-js/css-extract-webpack-plugin'\n );\n const CssExtractPlugin = api.context.bundlerType === 'rspack'\n ? CssExtractRspackPlugin\n : CssExtractWebpackPlugin;\n\n const cssRules = [\n CHAIN_ID.RULE.CSS,\n CHAIN_ID.RULE.SASS,\n CHAIN_ID.RULE.LESS,\n CHAIN_ID.RULE.STYLUS,\n ] as const;\n\n cssRules\n .filter((rule) => chain.module.rules.has(rule))\n .forEach((ruleName) => {\n const rule = chain.module.rule(ruleName);\n\n // Remove lightningcss-loader — Lynx processes CSS natively.\n removeLightningCSS(rule, CHAIN_ID);\n\n // Use the Lynx CssExtract loader for the Background layer.\n rule\n .issuerLayer(LAYERS.BACKGROUND)\n .use(CHAIN_ID.USE.MINI_CSS_EXTRACT)\n .loader(CssExtractPlugin.loader)\n .end();\n\n // Clone the existing CSS rule chain for the Main-Thread layer.\n // Main-Thread bundles never contain user CSS — only the PAPI\n // bootstrap code. We replace all loaders with ignore-css + a\n // css-loader configured for `exportOnlyLocals: true`.\n const uses = rule.uses.entries();\n const ruleEntries = rule.entries() as Record<string, any>;\n const cssLoaderRule = uses[CHAIN_ID.USE.CSS]?.entries() as\n | Record<string, any>\n | undefined;\n\n chain.module\n .rule(`${ruleName}:${LAYERS.MAIN_THREAD}`)\n .merge(ruleEntries)\n .issuerLayer(LAYERS.MAIN_THREAD)\n .use(CHAIN_ID.USE.IGNORE_CSS)\n .loader(path.resolve(_dirname, './loaders/ignore-css-loader'))\n .end()\n .uses.merge(uses)\n .delete(CHAIN_ID.USE.MINI_CSS_EXTRACT)\n .delete(CHAIN_ID.USE.LIGHTNINGCSS)\n .delete(CHAIN_ID.USE.CSS)\n .end();\n\n // Re-add css-loader with exportOnlyLocals for main-thread\n if (cssLoaderRule) {\n chain.module\n .rule(`${ruleName}:${LAYERS.MAIN_THREAD}`)\n .use(CHAIN_ID.USE.CSS)\n .after(CHAIN_ID.USE.IGNORE_CSS)\n .merge(cssLoaderRule)\n .options(\n normalizeCssLoaderOptions(\n cssLoaderRule.options as CSSLoaderOptions,\n true,\n ),\n )\n .end();\n }\n });\n\n // Also strip lightningcss from inline CSS rules (Rsbuild ≥1.3.0).\n const RULE = CHAIN_ID.RULE as Record<string, string | undefined>;\n const inlineCSSRuleNames = [\n 'CSS_INLINE',\n 'SASS_INLINE',\n 'LESS_INLINE',\n 'STYLUS_INLINE',\n ] as const;\n\n inlineCSSRuleNames\n .map((key) => RULE[key])\n .filter(\n (ruleName): ruleName is string =>\n !!ruleName && chain.module.rules.has(ruleName),\n )\n .forEach((ruleName) => {\n removeLightningCSS(chain.module.rule(ruleName), CHAIN_ID);\n });\n\n // ③ Replace the CssExtract plugin instance with the Lynx-aware one\n // and pass through the CSS selector / invalidation options.\n chain\n .plugin(CHAIN_ID.PLUGIN.MINI_CSS_EXTRACT)\n .tap(([pluginOptions]: [any]) => {\n return [\n {\n ...pluginOptions,\n enableRemoveCSSScope: true,\n enableCSSSelector,\n enableCSSInvalidation,\n cssPlugins: [],\n } as\n | CssExtractWebpackPluginOptions\n | CssExtractRspackPluginOptions,\n ];\n })\n .init((_: any, args: unknown[]) => {\n return new CssExtractPlugin(\n ...(args as [\n options:\n & CssExtractWebpackPluginOptions\n & CssExtractRspackPluginOptions,\n ]),\n );\n })\n .end()\n .end();\n\n function removeLightningCSS(\n rule: ReturnType<typeof chain.module.rule>,\n ids: typeof CHAIN_ID,\n ): void {\n if (rule.uses.has(ids.USE.LIGHTNINGCSS)) {\n rule.uses.delete(ids.USE.LIGHTNINGCSS);\n }\n }\n },\n );\n}\n\n/**\n * Force `exportOnlyLocals: true` on the css-loader modules config.\n * Copied from rsbuild internals — required when the target is not `web`\n * and CSS modules are enabled.\n */\nconst normalizeCssLoaderOptions = (\n options: CSSLoaderOptions,\n exportOnlyLocals: boolean,\n): CSSLoaderOptions => {\n if (options.modules && exportOnlyLocals) {\n let { modules } = options;\n if (modules === true) {\n modules = { exportOnlyLocals: true };\n } else if (typeof modules === 'string') {\n modules = {\n mode: modules as 'local',\n exportOnlyLocals: true,\n };\n } else {\n modules = {\n ...modules,\n exportOnlyLocals: true,\n };\n }\n\n return {\n ...options,\n modules,\n };\n }\n\n return options;\n};\n","/**\n * Dual-thread entry splitting for SignalX Lynx.\n *\n * For each user-defined rsbuild entry, creates two webpack entries:\n * - `<name>__main-thread` on the MAIN_THREAD layer (PAPI bootstrap via @sigx/runtime-lynx-main)\n * - `<name>` on the BACKGROUND layer (sigx renderer + user app)\n *\n * Then registers @lynx-js/template-webpack-plugin to stitch both bundles\n * into a single .lynx template.\n */\n\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport type { RsbuildPluginAPI } from '@rsbuild/core';\n\nimport { LAYERS } from './layers.js';\n\nconst PLUGIN_TEMPLATE = 'lynx:sigx-template';\nconst PLUGIN_MARK_MAIN_THREAD = 'lynx:sigx-mark-main-thread';\nconst PLUGIN_ENCODE = 'lynx:sigx-encode';\n\nconst DEFAULT_INTERMEDIATE = '.rspeedy';\n\nconst _dirname = path.dirname(fileURLToPath(import.meta.url));\n\n// sigx lynx-plugin package root — the plugin lives at <pkgRoot>/dist/,\n// so we resolve one level up from _dirname.\nconst sigxLynxRoot = path.resolve(_dirname, '..');\n\n/** Minimal typing for a webpack Chunk (avoids importing @rspack/core). */\ninterface WebpackChunk {\n getEntryOptions(): { layer?: string } | undefined;\n}\n\n/** Minimal typing for the webpack Compilation object. */\ninterface WebpackCompilation {\n hooks: {\n processAssets: {\n tap(\n options: { name: string; stage: number },\n callback: () => void,\n ): void;\n };\n additionalTreeRuntimeRequirements: {\n tap(\n name: string,\n callback: (chunk: WebpackChunk, set: Set<string>) => void,\n ): void;\n };\n };\n getAsset(\n filename: string,\n ): { source: unknown; info: Record<string, unknown> } | undefined;\n updateAsset(\n filename: string,\n source: unknown,\n info: Record<string, unknown>,\n ): void;\n}\n\n/** Minimal typing for the webpack Compiler object. */\ninterface WebpackCompiler {\n webpack: {\n Compilation: {\n PROCESS_ASSETS_STAGE_ADDITIONAL: number;\n };\n RuntimeGlobals: { startup: string; require: string };\n sources: { RawSource: new (source: string) => unknown };\n };\n hooks: {\n thisCompilation: {\n tap(\n name: string,\n callback: (compilation: WebpackCompilation) => void,\n ): void;\n };\n };\n}\n\n/**\n * SigxMarkMainThreadPlugin forces webpack to generate startup code for MT\n * entry chunks and marks their assets with `lynx:main-thread: true` so\n * LynxTemplatePlugin routes them to lepusCode.root (Lepus bytecode).\n */\nclass SigxMarkMainThreadPlugin {\n constructor(private readonly mainThreadFilenames: string[]) {}\n\n apply(compiler: WebpackCompiler): void {\n const { RuntimeGlobals } = compiler.webpack;\n\n compiler.hooks.thisCompilation.tap(\n PLUGIN_MARK_MAIN_THREAD,\n (compilation) => {\n // Force startup code generation for MT entry chunks.\n compilation.hooks.additionalTreeRuntimeRequirements.tap(\n PLUGIN_MARK_MAIN_THREAD,\n (chunk, set) => {\n const entryOptions = chunk.getEntryOptions();\n if (entryOptions?.layer === LAYERS.MAIN_THREAD) {\n set.add(RuntimeGlobals.startup);\n set.add(RuntimeGlobals.require);\n }\n },\n );\n\n // Mark MT assets with lynx:main-thread: true for LynxTemplatePlugin.\n compilation.hooks.processAssets.tap(\n {\n name: PLUGIN_MARK_MAIN_THREAD,\n stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,\n },\n () => {\n for (const filename of this.mainThreadFilenames) {\n const asset = compilation.getAsset(filename);\n if (asset) {\n compilation.updateAsset(filename, asset.source, {\n ...asset.info,\n 'lynx:main-thread': true,\n });\n }\n }\n },\n );\n },\n );\n }\n}\n\nexport interface ApplyEntryOptions {\n enableCSSSelector?: boolean;\n enableCSSInheritance?: boolean;\n customCSSInheritanceList?: string[];\n enableCSSInlineVariables?: boolean;\n debugInfoOutside?: boolean;\n}\n\nexport async function applyEntry(\n api: RsbuildPluginAPI,\n opts: ApplyEntryOptions = {},\n): Promise<void> {\n // Preload @lynx-js/template-webpack-plugin via dynamic ESM import.\n // rsbuild bundlerChain callbacks are sync, and template-webpack-plugin\n // is pure-ESM (no \"require\" condition in its exports map), so createRequire\n // fails. Stash the module in closure scope for the sync callback below.\n let templateMod:\n | typeof import('@lynx-js/template-webpack-plugin')\n | undefined;\n try {\n templateMod = await import('@lynx-js/template-webpack-plugin');\n } catch {\n // Optional peer — if missing, we'll still emit the two JS bundles.\n }\n\n // Preload @lynx-js/runtime-wrapper-webpack-plugin. This wraps the BG bundle\n // in `__init_card_bundle__(lynxCoreInject, lynx, ...)` so user code inside\n // can reference `lynx` and `lynxCoreInject` as bare identifiers — that's\n // how the BG transport (lynx.getNativeApp().callLepusMethod) and the event\n // dispatcher (lynxCoreInject.tt.publishEvent) get installed properly.\n // Without this wrapper we'd be forced to spelunk through globalThis.multiApps.\n let wrapperMod:\n | { RuntimeWrapperWebpackPlugin: new (opts: { test: RegExp; targetSdk?: string }) => unknown }\n | undefined;\n try {\n wrapperMod = (await import('@lynx-js/runtime-wrapper-webpack-plugin')) as typeof wrapperMod;\n } catch {\n // Optional peer — if missing, runtime-lynx will still attempt the\n // multiApps[appId]._nativeApp fallback, but proper hosts need the wrapper.\n }\n\n // Default to all-in-one chunk splitting to avoid async chunks that break\n // Lynx's single-file bundle requirement.\n api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => {\n const userConfig = api.getRsbuildConfig('original');\n if (!userConfig.performance?.chunkSplit?.strategy) {\n return mergeRsbuildConfig(config, {\n performance: { chunkSplit: { strategy: 'all-in-one' } },\n });\n }\n return config;\n });\n\n // Exclude main-thread chunks from chunk splitting so each remains\n // self-contained.\n api.modifyRspackConfig((rspackConfig) => {\n if (!rspackConfig.optimization) return rspackConfig;\n\n if (rspackConfig.optimization.splitChunks === false) {\n rspackConfig.optimization.splitChunks = {};\n }\n\n if (rspackConfig.optimization.splitChunks) {\n const prev = rspackConfig.optimization.splitChunks.chunks;\n // biome-ignore lint/suspicious/noExplicitAny: rspack Chunk type not importable\n rspackConfig.optimization.splitChunks.chunks = (chunk: any) => {\n if (chunk.name?.includes('__main-thread')) return false;\n if (typeof prev === 'function') return prev(chunk);\n if (prev === 'all') return true;\n if (prev === 'initial') return true;\n return false;\n };\n }\n\n return rspackConfig;\n });\n\n api.modifyBundlerChain((chain, { environment, isProd }) => {\n const isRspeedy = api.context.callerName === 'rspeedy';\n if (!isRspeedy) return;\n\n const isDev = !isProd;\n const isLynx =\n environment.name === 'lynx' || environment.name.startsWith('lynx-');\n const isWeb =\n environment.name === 'web' || environment.name.startsWith('web-');\n\n // HMR / Live Reload flags (same logic as vue-lynx / React plugin)\n const { hmr, liveReload } = environment.config.dev ?? {};\n const enabledHMR = isDev && !isWeb && hmr !== false;\n const enabledLiveReload = isDev && !isWeb && liveReload !== false;\n\n const entries = chain.entryPoints.entries() ?? {};\n\n chain.entryPoints.clear();\n\n // Collect all main-thread filenames to mark with lynx:main-thread\n const mainThreadFilenames: string[] = [];\n\n for (const [entryName, entryPoint] of Object.entries(entries)) {\n // Collect user imports from the original entry\n const imports: string[] = [];\n const ep = entryPoint as { values(): Iterable<unknown> };\n for (const val of ep.values()) {\n if (typeof val === 'string') {\n imports.push(val);\n } else if (typeof val === 'object' && val !== null && 'import' in val) {\n const imp = (val as { import?: string | string[] }).import;\n if (Array.isArray(imp)) imports.push(...imp);\n else if (imp) imports.push(imp);\n }\n }\n\n // ----------------------------------------------------------------\n // Filenames\n // ----------------------------------------------------------------\n const intermediate = isLynx ? DEFAULT_INTERMEDIATE : '';\n const mainThreadEntry = `${entryName}__main-thread`;\n const mainThreadName = path.posix.join(\n intermediate,\n `${entryName}/main-thread.js`,\n );\n const backgroundName = path.posix.join(\n intermediate,\n `${entryName}/background${isProd ? '.[contenthash:8]' : ''}.js`,\n );\n\n if (isLynx || isWeb) {\n mainThreadFilenames.push(mainThreadName);\n }\n\n // ----------------------------------------------------------------\n // Main Thread bundle – PAPI bootstrap only\n // ----------------------------------------------------------------\n // The MT entry ONLY imports @sigx/runtime-lynx-main, which registers\n // globalThis.renderPage, processData, sigxPatchUpdate and bridges\n // ops from the background thread.\n //\n // MT bundle evaluation order (critical):\n // The bootstrap (entry-main → worklet-runtime → install-hybrid-worklet)\n // is prepended to every user file by `worklet-loader-mt.ts` using\n // absolute paths resolved from the loader's install location. That\n // means we DON'T list those modules here as entry imports — the dep\n // graph that the loader-emitted preamble creates pulls them in, in\n // the right order, without forcing the user's app package.json to\n // declare @lynx-js/react as a direct dep.\n //\n // So the MT entry list is just: user imports. (CSS HMR runtime in\n // dev mode only.) Worklet registrations land via the dep graph.\n const mainThreadImports = !enabledHMR\n ? [...imports]\n : [\n '@lynx-js/css-extract-webpack-plugin/runtime/hotModuleReplacement.lepus.cjs',\n ...imports,\n ];\n\n chain\n .entry(mainThreadEntry)\n .add({\n layer: LAYERS.MAIN_THREAD,\n import: mainThreadImports,\n filename: mainThreadName,\n })\n .end();\n\n // ----------------------------------------------------------------\n // Background bundle – sigx renderer + user app\n // ----------------------------------------------------------------\n const bgImports: string[] = [];\n bgImports.push(...imports);\n\n const bgEntry = chain\n .entry(entryName)\n .add({\n layer: LAYERS.BACKGROUND,\n import: bgImports,\n filename: backgroundName,\n });\n\n // Inject standard rspack HMR client + Lynx WebSocket transport into\n // the BG entry (matching vue-lynx's approach). These must be prepended\n // so they initialise before user code.\n if (enabledHMR) {\n bgEntry.prepend({\n layer: LAYERS.BACKGROUND,\n import: '@rspack/core/hot/dev-server',\n });\n // BG → MT hot-update bridge. Subscribes to the same `webpackHotUpdate`\n // emitter event as `@rspack/core/hot/dev-server`, fetches the matching\n // `main__main-thread.<hash>.hot-update.js`, and forwards extracted\n // `registerWorkletInternal` calls to MT via `callLepusMethod`. Without\n // this, MT's `_workletMap` keeps the old worklet IDs from the static\n // bundle while BG sends ops referencing new content-hash IDs after a\n // save → bind-of-undefined on tap.\n bgEntry.prepend({\n layer: LAYERS.BACKGROUND,\n import: '@sigx/runtime-lynx/mt-hmr-bridge',\n });\n }\n if (enabledHMR || enabledLiveReload) {\n bgEntry.prepend({\n layer: LAYERS.BACKGROUND,\n import: '@lynx-js/webpack-dev-transport/client',\n });\n }\n\n bgEntry.end();\n\n // ----------------------------------------------------------------\n // LynxTemplatePlugin – packages both bundles into .lynx template\n // ----------------------------------------------------------------\n if ((isLynx || isWeb) && templateMod) {\n {\n const { LynxTemplatePlugin } = templateMod;\n\n const templateFilename =\n (typeof environment.config.output.filename === 'object'\n ? (environment.config.output.filename as { bundle?: string })\n .bundle\n : environment.config.output.filename) ??\n '[name].[platform].bundle';\n\n chain\n .plugin(`${PLUGIN_TEMPLATE}-${entryName}`)\n .use(LynxTemplatePlugin, [\n {\n ...LynxTemplatePlugin.defaultOptions,\n dsl: 'react_nodiff',\n chunks: [mainThreadEntry, entryName],\n filename: templateFilename\n .replaceAll('[name]', entryName)\n .replaceAll('[platform]', environment.name),\n intermediate: path.posix.join(intermediate, entryName),\n debugInfoOutside: opts.debugInfoOutside ?? true,\n enableCSSSelector: opts.enableCSSSelector ?? true,\n enableCSSInvalidation: opts.enableCSSSelector ?? true,\n enableCSSInheritance: opts.enableCSSInheritance ?? false,\n customCSSInheritanceList: opts.customCSSInheritanceList,\n enableCSSInlineVariables: opts.enableCSSInlineVariables ?? false,\n enableRemoveCSSScope: true,\n enableNewGesture: true,\n removeDescendantSelectorScope: true,\n cssPlugins: [],\n },\n ])\n .end();\n }\n }\n }\n\n // ------------------------------------------------------------------\n // SigxMarkMainThreadPlugin – mark MT assets for LynxTemplatePlugin\n // ------------------------------------------------------------------\n if ((isLynx || isWeb) && mainThreadFilenames.length > 0) {\n chain\n .plugin(PLUGIN_MARK_MAIN_THREAD)\n .use(SigxMarkMainThreadPlugin, [mainThreadFilenames])\n .end();\n }\n\n // ------------------------------------------------------------------\n // RuntimeWrapperWebpackPlugin – wrap BG bundle (NOT main-thread.js)\n // in __init_card_bundle__(lynxCoreInject, lynx, ...). Inside the\n // wrapper, runtime-lynx code can reference `lynx` and `lynxCoreInject`\n // as bare identifiers, giving us the official BG → MT bridge and\n // event dispatch hooks.\n // ------------------------------------------------------------------\n if (isLynx && wrapperMod) {\n const { RuntimeWrapperWebpackPlugin } = wrapperMod;\n chain\n .plugin('lynx:sigx-runtime-wrapper')\n .use(RuntimeWrapperWebpackPlugin, [\n {\n // Wrap everything except main-thread.js (and main-thread.[hash].js).\n test: /^(?!.*main-thread(?:\\.[A-Fa-f0-9]*)?\\.js$).*\\.js$/,\n },\n ])\n .end();\n }\n\n // ------------------------------------------------------------------\n // LynxEncodePlugin – binary-encode the .lynx template\n // ------------------------------------------------------------------\n if (isLynx && templateMod) {\n const { LynxEncodePlugin } = templateMod;\n chain\n .plugin(PLUGIN_ENCODE)\n .use(LynxEncodePlugin, [{}])\n .end();\n }\n\n // ------------------------------------------------------------------\n // HMR loader – inject registerHMRModule() + module.hot.accept()\n // into component files on the BG layer so they self-accept hot\n // updates and patch instances in-place (no structural tree ops).\n // ------------------------------------------------------------------\n if (enabledHMR) {\n chain.module\n .rule('sigx-hmr')\n .test(/\\.[jt]sx?$/)\n .issuerLayer(LAYERS.BACKGROUND)\n .exclude\n .add(/node_modules/)\n .add(/dist/)\n .end()\n .enforce('pre')\n .use('sigx-hmr-loader')\n .loader(path.resolve(_dirname, './loaders/hmr-loader'))\n .end();\n }\n\n // ------------------------------------------------------------------\n // Worklet loaders — both layers run @lynx-js/react/transform.\n // BG layer: target='JS' replaces 'main thread' functions with\n // { _wkltId, _c? } placeholders shipped via SET_WORKLET_EVENT.\n // MT layer: target='LEPUS' produces registerWorkletInternal(...) calls;\n // the loader extracts those + local-import edges, dropping\n // user component code so Lepus never executes it.\n // ------------------------------------------------------------------\n chain.module\n .rule('sigx-worklet')\n .test(/\\.[jt]sx?$/)\n .issuerLayer(LAYERS.BACKGROUND)\n .exclude\n .add(/node_modules/)\n .add(/dist/)\n .end()\n .enforce('pre')\n .use('sigx-worklet-loader')\n .loader(path.resolve(_dirname, './loaders/worklet-loader'))\n .end();\n\n chain.module\n .rule('sigx-worklet-mt')\n .test(/\\.[jt]sx?$/)\n .issuerLayer(LAYERS.MAIN_THREAD)\n .exclude\n .add(/node_modules/)\n .add(/dist/)\n .end()\n .enforce('pre')\n .use('sigx-worklet-mt-loader')\n .loader(path.resolve(_dirname, './loaders/worklet-loader-mt'))\n .end();\n\n // Disable IIFE wrapping – Lynx handles module scoping itself\n chain.output.set('iife', false);\n });\n}\n","/**\n * @packageDocumentation\n *\n * An rsbuild / rspeedy plugin that integrates SignalX with Lynx's dual-thread\n * architecture (Background Thread renderer + Main Thread PAPI executor).\n *\n * @example\n * ```ts\n * // lynx.config.ts\n * import { defineConfig } from '@lynx-js/rspeedy'\n * import { pluginSigxLynx } from '@sigx/lynx-plugin'\n *\n * export default defineConfig({\n * plugins: [pluginSigxLynx()],\n * })\n * ```\n */\n\nimport { networkInterfaces } from 'node:os';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { RsbuildPlugin } from '@rsbuild/core';\n\nimport { applyCSS } from './css.js';\nimport { applyEntry } from './entry.js';\nimport { LAYERS } from './layers.js';\n\nexport { LAYERS, applyEntry };\n\nconst _pluginDirname = path.dirname(fileURLToPath(import.meta.url));\nconst _sigxLynxRoot = path.resolve(_pluginDirname, '../..');\n\n/** Wildcard addresses that bind to all interfaces but aren't routable from other devices. */\nconst WILDCARD_HOSTS = new Set(['0.0.0.0', '::', '0:0:0:0:0:0:0:0']);\n\n/**\n * Interface names that are virtual adapters (Hyper-V, WSL, Docker, VPN, etc.)\n * and should be skipped when looking for the real LAN address.\n */\nconst VIRTUAL_IF_PATTERNS = /^(vEthernet|veth|docker|br-|virbr|vmnet|VirtualBox|Hyper-V|WSL|ham\\d)/i;\n\n/**\n * Detect the real LAN IPv4 address on this machine.\n * Skips virtual/container adapters (Hyper-V, WSL, Docker) and prefers\n * physical interfaces like Wi-Fi or Ethernet.\n * Falls back to the first external IPv4 if no physical match is found,\n * and ultimately to `'127.0.0.1'`.\n */\nfunction detectLanIPv4(): string {\n const ifaces = networkInterfaces();\n let fallback: string | undefined;\n\n for (const [name, nets] of Object.entries(ifaces)) {\n for (const net of nets ?? []) {\n if (net.family !== 'IPv4' || net.internal || !net.address) continue;\n // Remember first external address as fallback\n if (!fallback) fallback = net.address;\n // Skip virtual adapters\n if (VIRTUAL_IF_PATTERNS.test(name)) continue;\n return net.address;\n }\n }\n return fallback ?? '127.0.0.1';\n}\n\n/** Extract the hostname from a URL string (may be inside JSON quotes). */\nfunction extractHost(s: string): string {\n const m = s.match(/\\/\\/([^:/]+)/);\n return m ? m[1] : '';\n}\n\n/**\n * Options for {@link pluginSigxLynx}.\n * @public\n */\nexport interface PluginSigxLynxOptions {\n /**\n * Whether to enable CSS selector support in the Lynx template.\n * @defaultValue true\n */\n enableCSSSelector?: boolean;\n\n /**\n * Whether to enable CSS inheritance in the Lynx engine.\n * @defaultValue false\n */\n enableCSSInheritance?: boolean;\n\n /**\n * A list of additional CSS properties to inherit beyond the engine defaults.\n * Only effective when {@link enableCSSInheritance} is `true`.\n */\n customCSSInheritanceList?: string[];\n\n /**\n * Whether to enable CSS custom properties (variables) in inline styles.\n * @defaultValue false\n */\n enableCSSInlineVariables?: boolean;\n\n /**\n * Whether to place debug info outside the template bundle.\n * @defaultValue true\n */\n debugInfoOutside?: boolean;\n}\n\n/**\n * Create an rsbuild / rspeedy plugin for SignalX-Lynx dual-thread rendering.\n *\n * @public\n */\nexport function pluginSigxLynx(\n options: PluginSigxLynxOptions = {},\n): RsbuildPlugin {\n const {\n enableCSSSelector: _enableCSSSelector = true,\n enableCSSInheritance: _enableCSSInheritance = false,\n customCSSInheritanceList: _customCSSInheritanceList,\n enableCSSInlineVariables: _enableCSSInlineVariables = false,\n debugInfoOutside: _debugInfoOutside = true,\n } = options;\n\n return {\n name: 'lynx:sigx',\n // Must run after rspeedy's own config plugins (including pluginDev for URL fixes)\n pre: ['lynx:rsbuild:plugin-api', 'lynx:config', 'lynx:rsbuild:dev'],\n\n async setup(api) {\n api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => {\n // Compile all JS files (including node_modules) for ES2019 compat\n // with the Lynx JS engine, unless user explicitly sets source.include.\n const userConfig = api.getRsbuildConfig('original');\n if (typeof userConfig.source?.include === 'undefined') {\n config = mergeRsbuildConfig(config, {\n source: {\n include: [/\\.(?:js|mjs|cjs)$/],\n },\n });\n }\n\n return mergeRsbuildConfig(config, {\n source: {\n define: {\n __DEV__: 'process.env.NODE_ENV !== \\'production\\'',\n },\n },\n tools: {\n rspack: {\n output: {\n iife: false,\n },\n },\n swc: {\n jsc: {\n target: 'es2019',\n transform: {\n react: {\n runtime: 'automatic',\n importSource: '@sigx/lynx',\n throwIfNamespace: false,\n },\n },\n },\n },\n },\n });\n });\n\n api.modifyBundlerChain((chain) => {\n chain.resolve.alias.set(\n '@sigx/runtime-dom',\n '@sigx/runtime-lynx',\n );\n });\n\n // rspeedy's pluginDev uses `server.host` as the hostname for HMR\n // client URLs (publicPath, WebSocket URL, printUrls). When the user\n // sets server.host to '0.0.0.0' (bind all interfaces), those URLs\n // become unreachable from external devices (phones, emulators).\n //\n // Fix at the rsbuild config level (runs AFTER rspeedy's hooks thanks\n // to 'lynx:rsbuild:dev' in `pre`): replace wildcard hosts with the\n // actual LAN IP in dev.assetPrefix, dev.client.host, output.assetPrefix,\n // and the server.printUrls function.\n api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => {\n const devAssetPrefix = config.dev?.assetPrefix;\n if (typeof devAssetPrefix !== 'string') return config;\n\n // Only fix if the assetPrefix contains a wildcard host\n let needsFix = false;\n for (const wh of WILDCARD_HOSTS) {\n if (devAssetPrefix.includes(`//${wh}:`)) {\n needsFix = true;\n break;\n }\n }\n if (!needsFix) return config;\n\n const lanIP = detectLanIPv4();\n const replaceWildcard = (s: string): string => {\n for (const wh of WILDCARD_HOSTS) {\n s = s.replaceAll(`//${wh}:`, `//${lanIP}:`);\n }\n return s;\n };\n\n const fixedAssetPrefix = replaceWildcard(devAssetPrefix);\n\n // Override printUrls to show the correct LAN IP URL.\n // rspeedy's printUrls uses closure variables that still hold '0.0.0.0',\n // so we must replace the function entirely.\n const existingPrintUrls = config.server?.printUrls;\n const printUrlsFn = typeof existingPrintUrls === 'function'\n ? (param: { port: number; protocol: string; urls: string[] }) => {\n // Call rspeedy's original printUrls to get the URL list,\n // then fix the hostnames in each URL.\n const result = existingPrintUrls(param);\n if (Array.isArray(result)) {\n return result.map((item: { label: string; url: string }) => ({\n ...item,\n url: replaceWildcard(item.url),\n }));\n }\n return result;\n }\n : undefined;\n\n const merged = mergeRsbuildConfig(config, {\n dev: {\n assetPrefix: fixedAssetPrefix,\n client: {\n host: lanIP,\n },\n },\n output: {\n assetPrefix: fixedAssetPrefix,\n },\n });\n\n // Direct assignment — mergeRsbuildConfig can't reliably merge functions\n if (printUrlsFn) {\n merged.server = { ...merged.server, printUrls: printUrlsFn };\n }\n\n return merged;\n });\n\n // Rspack's default watcher-ignore is only /node_modules|\\.git/. In Lynx\n // app layouts the ios/ Pods tree and dist/ output drown macOS FSEvents,\n // causing edits to src/*.tsx to silently not fire rebuilds. Narrow the\n // watched set and stop chasing symlinks through pnpm's .pnpm/ store.\n //\n // Upstream: fixed in Rspack 2.0 (`fix(watcher): filter stale FSEvents\n // with mtime baseline comparison`). Rspeedy 0.14.2 still pins Rspack\n // 1.7.10, so we can't adopt the real fix yet — revisit when rspeedy\n // bumps to Rspack 2.0 and we can drop this hook.\n api.modifyRspackConfig((rspackConfig) => {\n const existing = rspackConfig.watchOptions ?? {};\n const existingIgnored = Array.isArray(existing.ignored)\n ? existing.ignored\n : typeof existing.ignored === 'string'\n ? [existing.ignored]\n : [];\n\n rspackConfig.watchOptions = {\n ...existing,\n ignored: [\n '**/node_modules/**',\n '**/.git/**',\n '**/dist/**',\n '**/ios/**',\n '**/android/**',\n '**/Pods/**',\n '**/.rspeedy/**',\n ...existingIgnored,\n ],\n followSymlinks: existing.followSymlinks ?? false,\n poll: existing.poll\n ?? (process.env.SIGX_LYNX_WATCH_POLL\n ? Number(process.env.SIGX_LYNX_WATCH_POLL) || true\n : undefined),\n };\n });\n\n // Belt-and-suspenders: also patch at the rspack config level in case\n // the rsbuild-level fix didn't propagate everywhere (e.g. resolve\n // aliases set by rspeedy's modifyBundlerChain using closure variables).\n api.modifyRspackConfig((rspackConfig) => {\n // Check if publicPath or any resolve alias contains a wildcard host\n let needsFix = false;\n const publicPath = rspackConfig.output?.publicPath;\n if (typeof publicPath === 'string') {\n for (const wh of WILDCARD_HOSTS) {\n if (publicPath.includes(`//${wh}:`)) { needsFix = true; break; }\n }\n }\n if (!needsFix) {\n const aliases = rspackConfig.resolve?.alias;\n if (aliases && typeof aliases === 'object' && !Array.isArray(aliases)) {\n for (const val of Object.values(aliases)) {\n if (typeof val === 'string') {\n for (const wh of WILDCARD_HOSTS) {\n if (val.includes(`hostname=${wh}`)) { needsFix = true; break; }\n }\n }\n if (needsFix) break;\n }\n }\n }\n if (!needsFix) return;\n\n const lanIP = detectLanIPv4();\n const replaceWildcard = (s: string): string => {\n for (const wh of WILDCARD_HOSTS) {\n s = s.replaceAll(`//${wh}:`, `//${lanIP}:`);\n s = s.replaceAll(`hostname=${wh}`, `hostname=${lanIP}`);\n }\n return s;\n };\n\n // Fix output.publicPath (used for hot-update fetch URLs)\n if (rspackConfig.output) {\n rspackConfig.output.publicPath = replaceWildcard(\n rspackConfig.output.publicPath as string,\n );\n }\n\n // Fix the resolve alias for @lynx-js/webpack-dev-transport/client\n // which embeds hostname=0.0.0.0 in query params for the WebSocket URL\n const aliases = rspackConfig.resolve?.alias;\n if (aliases && typeof aliases === 'object' && !Array.isArray(aliases)) {\n for (const [key, val] of Object.entries(aliases)) {\n if (typeof val === 'string') {\n const fixed = replaceWildcard(val);\n if (fixed !== val) {\n (aliases as Record<string, string>)[key] = fixed;\n }\n }\n }\n }\n\n // Fix ASSET_PREFIX in DefinePlugin definitions — these are stringified\n // JSON values so the wildcard appears inside quoted strings.\n for (const plugin of rspackConfig.plugins ?? []) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const defs = (plugin as any)?.definitions ?? (plugin as any)?._args?.[0];\n if (!defs || typeof defs !== 'object') continue;\n for (const [k, v] of Object.entries(defs)) {\n if (typeof v === 'string' && WILDCARD_HOSTS.has(extractHost(v))) {\n (defs as Record<string, string>)[k] = replaceWildcard(v);\n } else if (typeof v === 'object' && v !== null) {\n for (const [k2, v2] of Object.entries(v as Record<string, string>)) {\n if (typeof v2 === 'string' && WILDCARD_HOSTS.has(extractHost(v2))) {\n (v as Record<string, string>)[k2] = replaceWildcard(v2);\n }\n }\n }\n }\n }\n\n // Fix SourceMapDevToolPlugin publicPath\n for (const plugin of rspackConfig.plugins ?? []) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const opts = (plugin as any)?._options ?? (plugin as any)?._args?.[0];\n if (opts && typeof opts.publicPath === 'string') {\n opts.publicPath = replaceWildcard(opts.publicPath);\n }\n }\n });\n\n // Wire CSS handling — forces extraction via @lynx-js/css-extract-webpack-plugin,\n // strips lightningcss, and configures ignore-css-loader for main-thread layer.\n applyCSS(api, {\n enableCSSSelector: _enableCSSSelector,\n enableCSSInvalidation: _enableCSSInheritance,\n });\n\n // Wire dual-thread entry splitting (worklets skipped in v1)\n await applyEntry(api, {\n debugInfoOutside: _debugInfoOutside,\n enableCSSInheritance: _enableCSSInheritance,\n customCSSInheritanceList: _customCSSInheritanceList,\n enableCSSInlineVariables: _enableCSSInlineVariables,\n });\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/layers.ts","../src/css.ts","../src/entry.ts","../src/index.ts"],"sourcesContent":["/** Webpack module layers used to separate the dual-thread bundles. */\nexport const LAYERS = {\n BACKGROUND: 'sigx:background',\n MAIN_THREAD: 'sigx:main-thread',\n} as const;\n","/**\n * CSS extraction pipeline for SignalX Lynx.\n *\n * Mirrors the behaviour of `@lynx-js/react-rsbuild-plugin`'s `applyCSS()`:\n * 1. Disables `style-loader` (forces CSS extraction via CssExtractPlugin).\n * 2. Replaces the rsbuild-default CssExtract plugin with\n * `@lynx-js/css-extract-webpack-plugin` which emits Lynx-compatible CSS.\n * 3. Removes `lightningcss-loader` (Lynx has its own CSS processor).\n * 4. Configures the Main-Thread layer to ignore CSS entirely.\n */\n\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport type { CSSLoaderOptions, RsbuildPluginAPI } from '@rsbuild/core';\n\nimport type {\n CssExtractRspackPluginOptions,\n CssExtractWebpackPluginOptions,\n} from '@lynx-js/css-extract-webpack-plugin';\n\nimport { LAYERS } from './layers.js';\n\nexport interface ApplyCSSOptions {\n enableCSSSelector: boolean;\n enableCSSInvalidation: boolean;\n}\n\nconst _dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport function applyCSS(\n api: RsbuildPluginAPI,\n options: ApplyCSSOptions,\n): void {\n const { enableCSSSelector, enableCSSInvalidation } = options;\n\n // ① Force CSS extraction (disable style-loader, enable CssExtractPlugin).\n // Without this, rsbuild injects CSS via JS — useless in Lynx's native env.\n api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => {\n return mergeRsbuildConfig(config, {\n output: { injectStyles: false },\n });\n });\n\n // ② Replace the rsbuild-default CSS extraction plugin with the Lynx-aware\n // one, configure loaders per layer, and remove lightningcss.\n api.modifyBundlerChain(\n async function handler(chain, { CHAIN_ID }) {\n const { CssExtractRspackPlugin, CssExtractWebpackPlugin } = await import(\n '@lynx-js/css-extract-webpack-plugin'\n );\n const CssExtractPlugin = api.context.bundlerType === 'rspack'\n ? CssExtractRspackPlugin\n : CssExtractWebpackPlugin;\n\n const cssRules = [\n CHAIN_ID.RULE.CSS,\n CHAIN_ID.RULE.SASS,\n CHAIN_ID.RULE.LESS,\n CHAIN_ID.RULE.STYLUS,\n ] as const;\n\n cssRules\n .filter((rule) => chain.module.rules.has(rule))\n .forEach((ruleName) => {\n const rule = chain.module.rule(ruleName);\n\n // Remove lightningcss-loader — Lynx processes CSS natively.\n removeLightningCSS(rule, CHAIN_ID);\n\n // Use the Lynx CssExtract loader for the Background layer.\n rule\n .issuerLayer(LAYERS.BACKGROUND)\n .use(CHAIN_ID.USE.MINI_CSS_EXTRACT)\n .loader(CssExtractPlugin.loader)\n .end();\n\n // Clone the existing CSS rule chain for the Main-Thread layer.\n // Main-Thread bundles never contain user CSS — only the PAPI\n // bootstrap code. We replace all loaders with ignore-css + a\n // css-loader configured for `exportOnlyLocals: true`.\n const uses = rule.uses.entries();\n const ruleEntries = rule.entries() as Record<string, any>;\n const cssLoaderRule = uses[CHAIN_ID.USE.CSS]?.entries() as\n | Record<string, any>\n | undefined;\n\n chain.module\n .rule(`${ruleName}:${LAYERS.MAIN_THREAD}`)\n .merge(ruleEntries)\n .issuerLayer(LAYERS.MAIN_THREAD)\n .use(CHAIN_ID.USE.IGNORE_CSS)\n .loader(path.resolve(_dirname, './loaders/ignore-css-loader'))\n .end()\n .uses.merge(uses)\n .delete(CHAIN_ID.USE.MINI_CSS_EXTRACT)\n .delete(CHAIN_ID.USE.LIGHTNINGCSS)\n .delete(CHAIN_ID.USE.CSS)\n .end();\n\n // Re-add css-loader with exportOnlyLocals for main-thread\n if (cssLoaderRule) {\n chain.module\n .rule(`${ruleName}:${LAYERS.MAIN_THREAD}`)\n .use(CHAIN_ID.USE.CSS)\n .after(CHAIN_ID.USE.IGNORE_CSS)\n .merge(cssLoaderRule)\n .options(\n normalizeCssLoaderOptions(\n cssLoaderRule.options as CSSLoaderOptions,\n true,\n ),\n )\n .end();\n }\n });\n\n // Also strip lightningcss from inline CSS rules (Rsbuild ≥1.3.0).\n const RULE = CHAIN_ID.RULE as Record<string, string | undefined>;\n const inlineCSSRuleNames = [\n 'CSS_INLINE',\n 'SASS_INLINE',\n 'LESS_INLINE',\n 'STYLUS_INLINE',\n ] as const;\n\n inlineCSSRuleNames\n .map((key) => RULE[key])\n .filter(\n (ruleName): ruleName is string =>\n !!ruleName && chain.module.rules.has(ruleName),\n )\n .forEach((ruleName) => {\n removeLightningCSS(chain.module.rule(ruleName), CHAIN_ID);\n });\n\n // ③ Replace the CssExtract plugin instance with the Lynx-aware one\n // and pass through the CSS selector / invalidation options.\n chain\n .plugin(CHAIN_ID.PLUGIN.MINI_CSS_EXTRACT)\n .tap((args: any[]) => {\n const [pluginOptions] = args;\n return [\n {\n ...pluginOptions,\n enableRemoveCSSScope: true,\n enableCSSSelector,\n enableCSSInvalidation,\n cssPlugins: [],\n } as\n | CssExtractWebpackPluginOptions\n | CssExtractRspackPluginOptions,\n ];\n })\n .init((_: any, args: unknown[]) => {\n return new CssExtractPlugin(\n ...(args as [\n options:\n & CssExtractWebpackPluginOptions\n & CssExtractRspackPluginOptions,\n ]),\n );\n })\n .end()\n .end();\n\n function removeLightningCSS(\n rule: ReturnType<typeof chain.module.rule>,\n ids: typeof CHAIN_ID,\n ): void {\n if (rule.uses.has(ids.USE.LIGHTNINGCSS)) {\n rule.uses.delete(ids.USE.LIGHTNINGCSS);\n }\n }\n },\n );\n}\n\n/**\n * Force `exportOnlyLocals: true` on the css-loader modules config.\n * Copied from rsbuild internals — required when the target is not `web`\n * and CSS modules are enabled.\n */\nconst normalizeCssLoaderOptions = (\n options: CSSLoaderOptions,\n exportOnlyLocals: boolean,\n): CSSLoaderOptions => {\n if (options.modules && exportOnlyLocals) {\n let { modules } = options;\n if (modules === true) {\n modules = { exportOnlyLocals: true };\n } else if (typeof modules === 'string') {\n modules = {\n mode: modules as 'local',\n exportOnlyLocals: true,\n };\n } else {\n modules = {\n ...modules,\n exportOnlyLocals: true,\n };\n }\n\n return {\n ...options,\n modules,\n };\n }\n\n return options;\n};\n","/**\n * Dual-thread entry splitting for SignalX Lynx.\n *\n * For each user-defined rsbuild entry, creates two webpack entries:\n * - `<name>__main-thread` on the MAIN_THREAD layer (PAPI bootstrap via @sigx/lynx-runtime-main)\n * - `<name>` on the BACKGROUND layer (sigx renderer + user app)\n *\n * Then registers @lynx-js/template-webpack-plugin to stitch both bundles\n * into a single .lynx template.\n */\n\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport type { RsbuildPluginAPI } from '@rsbuild/core';\n\nimport { LAYERS } from './layers.js';\n\nconst PLUGIN_TEMPLATE = 'lynx:sigx-template';\nconst PLUGIN_MARK_MAIN_THREAD = 'lynx:sigx-mark-main-thread';\nconst PLUGIN_ENCODE = 'lynx:sigx-encode';\n\nconst DEFAULT_INTERMEDIATE = '.rspeedy';\n\nconst _dirname = path.dirname(fileURLToPath(import.meta.url));\n\n// sigx lynx-plugin package root — the plugin lives at <pkgRoot>/dist/,\n// so we resolve one level up from _dirname.\nconst sigxLynxRoot = path.resolve(_dirname, '..');\n\n/** Minimal typing for a webpack Chunk (avoids importing @rspack/core). */\ninterface WebpackChunk {\n getEntryOptions(): { layer?: string } | undefined;\n}\n\n/** Minimal typing for the webpack Compilation object. */\ninterface WebpackCompilation {\n hooks: {\n processAssets: {\n tap(\n options: { name: string; stage: number },\n callback: () => void,\n ): void;\n };\n additionalTreeRuntimeRequirements: {\n tap(\n name: string,\n callback: (chunk: WebpackChunk, set: Set<string>) => void,\n ): void;\n };\n };\n getAsset(\n filename: string,\n ): { source: unknown; info: Record<string, unknown> } | undefined;\n updateAsset(\n filename: string,\n source: unknown,\n info: Record<string, unknown>,\n ): void;\n}\n\n/** Minimal typing for the webpack Compiler object. */\ninterface WebpackCompiler {\n webpack: {\n Compilation: {\n PROCESS_ASSETS_STAGE_ADDITIONAL: number;\n };\n RuntimeGlobals: { startup: string; require: string };\n sources: { RawSource: new (source: string) => unknown };\n };\n hooks: {\n thisCompilation: {\n tap(\n name: string,\n callback: (compilation: WebpackCompilation) => void,\n ): void;\n };\n };\n}\n\n/**\n * SigxMarkMainThreadPlugin forces webpack to generate startup code for MT\n * entry chunks and marks their assets with `lynx:main-thread: true` so\n * LynxTemplatePlugin routes them to lepusCode.root (Lepus bytecode).\n */\nclass SigxMarkMainThreadPlugin {\n constructor(private readonly mainThreadFilenames: string[]) {}\n\n apply(compiler: WebpackCompiler): void {\n const { RuntimeGlobals } = compiler.webpack;\n\n compiler.hooks.thisCompilation.tap(\n PLUGIN_MARK_MAIN_THREAD,\n (compilation) => {\n // Force startup code generation for MT entry chunks.\n compilation.hooks.additionalTreeRuntimeRequirements.tap(\n PLUGIN_MARK_MAIN_THREAD,\n (chunk, set) => {\n const entryOptions = chunk.getEntryOptions();\n if (entryOptions?.layer === LAYERS.MAIN_THREAD) {\n set.add(RuntimeGlobals.startup);\n set.add(RuntimeGlobals.require);\n }\n },\n );\n\n // Mark MT assets with lynx:main-thread: true for LynxTemplatePlugin.\n compilation.hooks.processAssets.tap(\n {\n name: PLUGIN_MARK_MAIN_THREAD,\n stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,\n },\n () => {\n for (const filename of this.mainThreadFilenames) {\n const asset = compilation.getAsset(filename);\n if (asset) {\n compilation.updateAsset(filename, asset.source, {\n ...asset.info,\n 'lynx:main-thread': true,\n });\n }\n }\n },\n );\n },\n );\n }\n}\n\nexport interface ApplyEntryOptions {\n enableCSSSelector?: boolean;\n enableCSSInheritance?: boolean;\n customCSSInheritanceList?: string[];\n debugInfoOutside?: boolean;\n}\n\nexport async function applyEntry(\n api: RsbuildPluginAPI,\n opts: ApplyEntryOptions = {},\n): Promise<void> {\n // Preload @lynx-js/template-webpack-plugin via dynamic ESM import.\n // rsbuild bundlerChain callbacks are sync, and template-webpack-plugin\n // is pure-ESM (no \"require\" condition in its exports map), so createRequire\n // fails. Stash the module in closure scope for the sync callback below.\n let templateMod:\n | typeof import('@lynx-js/template-webpack-plugin')\n | undefined;\n try {\n templateMod = await import('@lynx-js/template-webpack-plugin');\n } catch {\n // Optional peer — if missing, we'll still emit the two JS bundles.\n }\n\n // Preload @lynx-js/runtime-wrapper-webpack-plugin. This wraps the BG bundle\n // in `__init_card_bundle__(lynxCoreInject, lynx, ...)` so user code inside\n // can reference `lynx` and `lynxCoreInject` as bare identifiers — that's\n // how the BG transport (lynx.getNativeApp().callLepusMethod) and the event\n // dispatcher (lynxCoreInject.tt.publishEvent) get installed properly.\n // Without this wrapper we'd be forced to spelunk through globalThis.multiApps.\n let wrapperMod:\n | { RuntimeWrapperWebpackPlugin: new (opts: { test: RegExp; targetSdk?: string }) => unknown }\n | undefined;\n try {\n wrapperMod = (await import('@lynx-js/runtime-wrapper-webpack-plugin')) as typeof wrapperMod;\n } catch {\n // Optional peer — if missing, lynx-runtime will still attempt the\n // multiApps[appId]._nativeApp fallback, but proper hosts need the wrapper.\n }\n\n // Default to all-in-one chunk splitting to avoid async chunks that break\n // Lynx's single-file bundle requirement.\n api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => {\n const userConfig = api.getRsbuildConfig('original');\n if (!userConfig.performance?.chunkSplit?.strategy) {\n return mergeRsbuildConfig(config, {\n performance: { chunkSplit: { strategy: 'all-in-one' } },\n });\n }\n return config;\n });\n\n // Exclude main-thread chunks from chunk splitting so each remains\n // self-contained.\n api.modifyRspackConfig((rspackConfig) => {\n if (!rspackConfig.optimization) return rspackConfig;\n\n if (rspackConfig.optimization.splitChunks === false) {\n rspackConfig.optimization.splitChunks = {};\n }\n\n if (rspackConfig.optimization.splitChunks) {\n const prev = rspackConfig.optimization.splitChunks.chunks;\n // biome-ignore lint/suspicious/noExplicitAny: rspack Chunk type not importable\n rspackConfig.optimization.splitChunks.chunks = (chunk: any) => {\n if (chunk.name?.includes('__main-thread')) return false;\n if (typeof prev === 'function') return prev(chunk);\n if (prev === 'all') return true;\n if (prev === 'initial') return true;\n return false;\n };\n }\n\n return rspackConfig;\n });\n\n api.modifyBundlerChain((chain, { environment, isProd }) => {\n const isRspeedy = api.context.callerName === 'rspeedy';\n if (!isRspeedy) return;\n\n const isDev = !isProd;\n const isLynx =\n environment.name === 'lynx' || environment.name.startsWith('lynx-');\n const isWeb =\n environment.name === 'web' || environment.name.startsWith('web-');\n\n // HMR / Live Reload flags (same logic as vue-lynx / React plugin)\n const { hmr, liveReload } = environment.config.dev ?? {};\n const enabledHMR = isDev && !isWeb && hmr !== false;\n const enabledLiveReload = isDev && !isWeb && liveReload !== false;\n\n const entries = chain.entryPoints.entries() ?? {};\n\n chain.entryPoints.clear();\n\n // Collect all main-thread filenames to mark with lynx:main-thread\n const mainThreadFilenames: string[] = [];\n\n for (const [entryName, entryPoint] of Object.entries(entries)) {\n // Collect user imports from the original entry\n const imports: string[] = [];\n const ep = entryPoint as { values(): Iterable<unknown> };\n for (const val of ep.values()) {\n if (typeof val === 'string') {\n imports.push(val);\n } else if (typeof val === 'object' && val !== null && 'import' in val) {\n const imp = (val as { import?: string | string[] }).import;\n if (Array.isArray(imp)) imports.push(...imp);\n else if (imp) imports.push(imp);\n }\n }\n\n // ----------------------------------------------------------------\n // Filenames\n // ----------------------------------------------------------------\n const intermediate = isLynx ? DEFAULT_INTERMEDIATE : '';\n const mainThreadEntry = `${entryName}__main-thread`;\n const mainThreadName = path.posix.join(\n intermediate,\n `${entryName}/main-thread.js`,\n );\n const backgroundName = path.posix.join(\n intermediate,\n `${entryName}/background${isProd ? '.[contenthash:8]' : ''}.js`,\n );\n\n if (isLynx || isWeb) {\n mainThreadFilenames.push(mainThreadName);\n }\n\n // ----------------------------------------------------------------\n // Main Thread bundle – PAPI bootstrap only\n // ----------------------------------------------------------------\n // The MT entry ONLY imports @sigx/lynx-runtime-main, which registers\n // globalThis.renderPage, processData, sigxPatchUpdate and bridges\n // ops from the background thread.\n //\n // MT bundle evaluation order (critical):\n // The bootstrap (entry-main → worklet-runtime → install-hybrid-worklet)\n // is prepended to every user file by `worklet-loader-mt.ts` using\n // absolute paths resolved from the loader's install location. That\n // means we DON'T list those modules here as entry imports — the dep\n // graph that the loader-emitted preamble creates pulls them in, in\n // the right order, without forcing the user's app package.json to\n // declare @lynx-js/react as a direct dep.\n //\n // So the MT entry list is just: user imports. (CSS HMR runtime in\n // dev mode only.) Worklet registrations land via the dep graph.\n const mainThreadImports = !enabledHMR\n ? [...imports]\n : [\n '@lynx-js/css-extract-webpack-plugin/runtime/hotModuleReplacement.lepus.cjs',\n ...imports,\n ];\n\n chain\n .entry(mainThreadEntry)\n .add({\n layer: LAYERS.MAIN_THREAD,\n import: mainThreadImports,\n filename: mainThreadName,\n })\n .end();\n\n // ----------------------------------------------------------------\n // Background bundle – sigx renderer + user app\n // ----------------------------------------------------------------\n const bgImports: string[] = [];\n bgImports.push(...imports);\n\n const bgEntry = chain\n .entry(entryName)\n .add({\n layer: LAYERS.BACKGROUND,\n import: bgImports,\n filename: backgroundName,\n });\n\n // Inject standard rspack HMR client + Lynx WebSocket transport into\n // the BG entry (matching vue-lynx's approach). These must be prepended\n // so they initialise before user code.\n if (enabledHMR) {\n bgEntry.prepend({\n layer: LAYERS.BACKGROUND,\n import: '@rspack/core/hot/dev-server',\n });\n // BG → MT hot-update bridge. Subscribes to the same `webpackHotUpdate`\n // emitter event as `@rspack/core/hot/dev-server`, fetches the matching\n // `main__main-thread.<hash>.hot-update.js`, and forwards extracted\n // `registerWorkletInternal` calls to MT via `callLepusMethod`. Without\n // this, MT's `_workletMap` keeps the old worklet IDs from the static\n // bundle while BG sends ops referencing new content-hash IDs after a\n // save → bind-of-undefined on tap.\n bgEntry.prepend({\n layer: LAYERS.BACKGROUND,\n import: '@sigx/lynx-runtime/mt-hmr-bridge',\n });\n }\n if (enabledHMR || enabledLiveReload) {\n bgEntry.prepend({\n layer: LAYERS.BACKGROUND,\n import: '@lynx-js/webpack-dev-transport/client',\n });\n }\n\n bgEntry.end();\n\n // ----------------------------------------------------------------\n // LynxTemplatePlugin – packages both bundles into .lynx template\n // ----------------------------------------------------------------\n if ((isLynx || isWeb) && templateMod) {\n {\n const { LynxTemplatePlugin } = templateMod;\n\n const templateFilename =\n (typeof environment.config.output.filename === 'object'\n ? (environment.config.output.filename as { bundle?: string })\n .bundle\n : environment.config.output.filename) ??\n '[name].[platform].bundle';\n\n chain\n .plugin(`${PLUGIN_TEMPLATE}-${entryName}`)\n .use(LynxTemplatePlugin, [\n {\n ...LynxTemplatePlugin.defaultOptions,\n dsl: 'react_nodiff',\n chunks: [mainThreadEntry, entryName],\n filename: templateFilename\n .replaceAll('[name]', entryName)\n .replaceAll('[platform]', environment.name),\n intermediate: path.posix.join(intermediate, entryName),\n debugInfoOutside: opts.debugInfoOutside ?? true,\n enableCSSSelector: opts.enableCSSSelector ?? true,\n enableCSSInvalidation: opts.enableCSSSelector ?? true,\n enableCSSInheritance: opts.enableCSSInheritance ?? false,\n customCSSInheritanceList: opts.customCSSInheritanceList,\n enableRemoveCSSScope: true,\n enableNewGesture: true,\n removeDescendantSelectorScope: true,\n cssPlugins: [],\n },\n ])\n .end();\n }\n }\n }\n\n // ------------------------------------------------------------------\n // SigxMarkMainThreadPlugin – mark MT assets for LynxTemplatePlugin\n // ------------------------------------------------------------------\n if ((isLynx || isWeb) && mainThreadFilenames.length > 0) {\n chain\n .plugin(PLUGIN_MARK_MAIN_THREAD)\n .use(SigxMarkMainThreadPlugin, [mainThreadFilenames])\n .end();\n }\n\n // ------------------------------------------------------------------\n // RuntimeWrapperWebpackPlugin – wrap BG bundle (NOT main-thread.js)\n // in __init_card_bundle__(lynxCoreInject, lynx, ...). Inside the\n // wrapper, lynx-runtime code can reference `lynx` and `lynxCoreInject`\n // as bare identifiers, giving us the official BG → MT bridge and\n // event dispatch hooks.\n // ------------------------------------------------------------------\n if (isLynx && wrapperMod) {\n const { RuntimeWrapperWebpackPlugin } = wrapperMod;\n chain\n .plugin('lynx:sigx-runtime-wrapper')\n .use(RuntimeWrapperWebpackPlugin, [\n {\n // Wrap everything except main-thread.js (and main-thread.[hash].js).\n test: /^(?!.*main-thread(?:\\.[A-Fa-f0-9]*)?\\.js$).*\\.js$/,\n },\n ])\n .end();\n }\n\n // ------------------------------------------------------------------\n // LynxEncodePlugin – binary-encode the .lynx template\n // ------------------------------------------------------------------\n if (isLynx && templateMod) {\n const { LynxEncodePlugin } = templateMod;\n chain\n .plugin(PLUGIN_ENCODE)\n .use(LynxEncodePlugin, [{}])\n .end();\n }\n\n // ------------------------------------------------------------------\n // HMR loader – inject registerHMRModule() + module.hot.accept()\n // into component files on the BG layer so they self-accept hot\n // updates and patch instances in-place (no structural tree ops).\n // ------------------------------------------------------------------\n if (enabledHMR) {\n chain.module\n .rule('sigx-hmr')\n .test(/\\.[jt]sx?$/)\n .issuerLayer(LAYERS.BACKGROUND)\n .exclude\n .add(/node_modules/)\n .add(/dist/)\n .end()\n .enforce('pre')\n .use('sigx-hmr-loader')\n .loader(path.resolve(_dirname, './loaders/hmr-loader'))\n .end();\n }\n\n // ------------------------------------------------------------------\n // Worklet loaders — both layers run @lynx-js/react/transform.\n // BG layer: target='JS' replaces 'main thread' functions with\n // { _wkltId, _c? } placeholders shipped via SET_WORKLET_EVENT.\n // MT layer: target='LEPUS' produces registerWorkletInternal(...) calls;\n // the loader extracts those + local-import edges, dropping\n // user component code so Lepus never executes it.\n // ------------------------------------------------------------------\n chain.module\n .rule('sigx-worklet')\n .test(/\\.[jt]sx?$/)\n .issuerLayer(LAYERS.BACKGROUND)\n .exclude\n .add(/node_modules/)\n .add(/dist/)\n .end()\n .enforce('pre')\n .use('sigx-worklet-loader')\n .loader(path.resolve(_dirname, './loaders/worklet-loader'))\n .end();\n\n chain.module\n .rule('sigx-worklet-mt')\n .test(/\\.[jt]sx?$/)\n .issuerLayer(LAYERS.MAIN_THREAD)\n .exclude\n .add(/node_modules/)\n .add(/dist/)\n .end()\n .enforce('pre')\n .use('sigx-worklet-mt-loader')\n .loader(path.resolve(_dirname, './loaders/worklet-loader-mt'))\n .end();\n\n // Disable IIFE wrapping – Lynx handles module scoping itself\n chain.output.set('iife', false);\n });\n}\n","/**\n * @packageDocumentation\n *\n * An rsbuild / rspeedy plugin that integrates SignalX with Lynx's dual-thread\n * architecture (Background Thread renderer + Main Thread PAPI executor).\n *\n * @example\n * ```ts\n * // lynx.config.ts\n * import { defineConfig } from '@lynx-js/rspeedy'\n * import { pluginSigxLynx } from '@sigx/lynx-plugin'\n *\n * export default defineConfig({\n * plugins: [pluginSigxLynx()],\n * })\n * ```\n */\n\nimport { networkInterfaces } from 'node:os';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { RsbuildPlugin } from '@rsbuild/core';\n\nimport { applyCSS } from './css.js';\nimport { applyEntry } from './entry.js';\nimport { LAYERS } from './layers.js';\n\nexport { LAYERS, applyEntry };\n\nconst _pluginDirname = path.dirname(fileURLToPath(import.meta.url));\nconst _sigxLynxRoot = path.resolve(_pluginDirname, '../..');\n\n/** Wildcard addresses that bind to all interfaces but aren't routable from other devices. */\nconst WILDCARD_HOSTS = new Set(['0.0.0.0', '::', '0:0:0:0:0:0:0:0']);\n\n/**\n * Interface names that are virtual adapters (Hyper-V, WSL, Docker, VPN, etc.)\n * and should be skipped when looking for the real LAN address.\n */\nconst VIRTUAL_IF_PATTERNS = /^(vEthernet|veth|docker|br-|virbr|vmnet|VirtualBox|Hyper-V|WSL|ham\\d)/i;\n\n/**\n * Detect the real LAN IPv4 address on this machine.\n * Skips virtual/container adapters (Hyper-V, WSL, Docker) and prefers\n * physical interfaces like Wi-Fi or Ethernet.\n * Falls back to the first external IPv4 if no physical match is found,\n * and ultimately to `'127.0.0.1'`.\n */\nfunction detectLanIPv4(): string {\n const ifaces = networkInterfaces();\n let fallback: string | undefined;\n\n for (const [name, nets] of Object.entries(ifaces)) {\n for (const net of nets ?? []) {\n if (net.family !== 'IPv4' || net.internal || !net.address) continue;\n // Remember first external address as fallback\n if (!fallback) fallback = net.address;\n // Skip virtual adapters\n if (VIRTUAL_IF_PATTERNS.test(name)) continue;\n return net.address;\n }\n }\n return fallback ?? '127.0.0.1';\n}\n\n/** Extract the hostname from a URL string (may be inside JSON quotes). */\nfunction extractHost(s: string): string {\n const m = s.match(/\\/\\/([^:/]+)/);\n return m ? m[1] : '';\n}\n\n/**\n * Options for {@link pluginSigxLynx}.\n * @public\n */\nexport interface PluginSigxLynxOptions {\n /**\n * Whether to enable CSS selector support in the Lynx template.\n * @defaultValue true\n */\n enableCSSSelector?: boolean;\n\n /**\n * Whether to enable CSS inheritance in the Lynx engine.\n * @defaultValue false\n */\n enableCSSInheritance?: boolean;\n\n /**\n * A list of additional CSS properties to inherit beyond the engine defaults.\n * Only effective when {@link enableCSSInheritance} is `true`.\n */\n customCSSInheritanceList?: string[];\n\n /**\n * Whether to place debug info outside the template bundle.\n * @defaultValue true\n */\n debugInfoOutside?: boolean;\n}\n\n/**\n * Create an rsbuild / rspeedy plugin for SignalX-Lynx dual-thread rendering.\n *\n * @public\n */\nexport function pluginSigxLynx(\n options: PluginSigxLynxOptions = {},\n): RsbuildPlugin {\n const {\n enableCSSSelector: _enableCSSSelector = true,\n enableCSSInheritance: _enableCSSInheritance = false,\n customCSSInheritanceList: _customCSSInheritanceList,\n debugInfoOutside: _debugInfoOutside = true,\n } = options;\n\n return {\n name: 'lynx:sigx',\n // Must run after rspeedy's own config plugins (including pluginDev for URL fixes)\n pre: ['lynx:rsbuild:plugin-api', 'lynx:config', 'lynx:rsbuild:dev'],\n\n async setup(api) {\n api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => {\n // Compile all JS files (including node_modules) for ES2019 compat\n // with the Lynx JS engine, unless user explicitly sets source.include.\n const userConfig = api.getRsbuildConfig('original');\n if (typeof userConfig.source?.include === 'undefined') {\n config = mergeRsbuildConfig(config, {\n source: {\n include: [/\\.(?:js|mjs|cjs)$/],\n },\n });\n }\n\n return mergeRsbuildConfig(config, {\n source: {\n define: {\n __DEV__: 'process.env.NODE_ENV !== \\'production\\'',\n },\n },\n tools: {\n rspack: {\n output: {\n iife: false,\n },\n },\n swc: {\n jsc: {\n target: 'es2019',\n transform: {\n react: {\n runtime: 'automatic',\n importSource: '@sigx/lynx',\n throwIfNamespace: false,\n },\n },\n },\n },\n },\n });\n });\n\n api.modifyBundlerChain((chain) => {\n chain.resolve.alias.set(\n '@sigx/runtime-dom',\n '@sigx/lynx-runtime',\n );\n });\n\n // rspeedy's pluginDev uses `server.host` as the hostname for HMR\n // client URLs (publicPath, WebSocket URL, printUrls). When the user\n // sets server.host to '0.0.0.0' (bind all interfaces), those URLs\n // become unreachable from external devices (phones, emulators).\n //\n // Fix at the rsbuild config level (runs AFTER rspeedy's hooks thanks\n // to 'lynx:rsbuild:dev' in `pre`): replace wildcard hosts with the\n // actual LAN IP in dev.assetPrefix, dev.client.host, output.assetPrefix,\n // and the server.printUrls function.\n api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => {\n const devAssetPrefix = config.dev?.assetPrefix;\n if (typeof devAssetPrefix !== 'string') return config;\n\n // Only fix if the assetPrefix contains a wildcard host\n let needsFix = false;\n for (const wh of WILDCARD_HOSTS) {\n if (devAssetPrefix.includes(`//${wh}:`)) {\n needsFix = true;\n break;\n }\n }\n if (!needsFix) return config;\n\n const lanIP = detectLanIPv4();\n const replaceWildcard = (s: string): string => {\n for (const wh of WILDCARD_HOSTS) {\n s = s.replaceAll(`//${wh}:`, `//${lanIP}:`);\n }\n return s;\n };\n\n const fixedAssetPrefix = replaceWildcard(devAssetPrefix);\n\n // Override printUrls to show the correct LAN IP URL.\n // rspeedy's printUrls uses closure variables that still hold '0.0.0.0',\n // so we must replace the function entirely.\n const existingPrintUrls = config.server?.printUrls;\n const printUrlsFn = typeof existingPrintUrls === 'function'\n ? (param: Parameters<typeof existingPrintUrls>[0]) => {\n // Call rspeedy's original printUrls to get the URL list,\n // then fix the hostnames in each URL.\n const result = existingPrintUrls(param);\n if (Array.isArray(result)) {\n return result.map((item: any) =>\n typeof item === 'string'\n ? replaceWildcard(item)\n : { ...item, url: replaceWildcard(item.url) }\n );\n }\n return result;\n }\n : undefined;\n\n const merged = mergeRsbuildConfig(config, {\n dev: {\n assetPrefix: fixedAssetPrefix,\n client: {\n host: lanIP,\n },\n },\n output: {\n assetPrefix: fixedAssetPrefix,\n },\n });\n\n // Direct assignment — mergeRsbuildConfig can't reliably merge functions\n if (printUrlsFn) {\n merged.server = { ...merged.server, printUrls: printUrlsFn };\n }\n\n return merged;\n });\n\n // Rspack's default watcher-ignore is only /node_modules|\\.git/. In Lynx\n // app layouts the ios/ Pods tree and dist/ output drown macOS FSEvents,\n // causing edits to src/*.tsx to silently not fire rebuilds. Narrow the\n // watched set and stop chasing symlinks through pnpm's .pnpm/ store.\n //\n // Upstream: fixed in Rspack 2.0 (`fix(watcher): filter stale FSEvents\n // with mtime baseline comparison`). Rspeedy 0.14.2 still pins Rspack\n // 1.7.10, so we can't adopt the real fix yet — revisit when rspeedy\n // bumps to Rspack 2.0 and we can drop this hook.\n api.modifyRspackConfig((rspackConfig) => {\n const existing = rspackConfig.watchOptions ?? {};\n const existingIgnored = Array.isArray(existing.ignored)\n ? existing.ignored\n : typeof existing.ignored === 'string'\n ? [existing.ignored]\n : [];\n\n rspackConfig.watchOptions = {\n ...existing,\n ignored: [\n '**/node_modules/**',\n '**/.git/**',\n '**/dist/**',\n '**/ios/**',\n '**/android/**',\n '**/Pods/**',\n '**/.rspeedy/**',\n ...existingIgnored,\n ],\n followSymlinks: existing.followSymlinks ?? false,\n poll: existing.poll\n ?? (process.env.SIGX_LYNX_WATCH_POLL\n ? Number(process.env.SIGX_LYNX_WATCH_POLL) || true\n : undefined),\n };\n });\n\n // Belt-and-suspenders: also patch at the rspack config level in case\n // the rsbuild-level fix didn't propagate everywhere (e.g. resolve\n // aliases set by rspeedy's modifyBundlerChain using closure variables).\n api.modifyRspackConfig((rspackConfig) => {\n // Check if publicPath or any resolve alias contains a wildcard host\n let needsFix = false;\n const publicPath = rspackConfig.output?.publicPath;\n if (typeof publicPath === 'string') {\n for (const wh of WILDCARD_HOSTS) {\n if (publicPath.includes(`//${wh}:`)) { needsFix = true; break; }\n }\n }\n if (!needsFix) {\n const aliases = rspackConfig.resolve?.alias;\n if (aliases && typeof aliases === 'object' && !Array.isArray(aliases)) {\n for (const val of Object.values(aliases)) {\n if (typeof val === 'string') {\n for (const wh of WILDCARD_HOSTS) {\n if (val.includes(`hostname=${wh}`)) { needsFix = true; break; }\n }\n }\n if (needsFix) break;\n }\n }\n }\n if (!needsFix) return;\n\n const lanIP = detectLanIPv4();\n const replaceWildcard = (s: string): string => {\n for (const wh of WILDCARD_HOSTS) {\n s = s.replaceAll(`//${wh}:`, `//${lanIP}:`);\n s = s.replaceAll(`hostname=${wh}`, `hostname=${lanIP}`);\n }\n return s;\n };\n\n // Fix output.publicPath (used for hot-update fetch URLs)\n if (rspackConfig.output) {\n rspackConfig.output.publicPath = replaceWildcard(\n rspackConfig.output.publicPath as string,\n );\n }\n\n // Fix the resolve alias for @lynx-js/webpack-dev-transport/client\n // which embeds hostname=0.0.0.0 in query params for the WebSocket URL\n const aliases = rspackConfig.resolve?.alias;\n if (aliases && typeof aliases === 'object' && !Array.isArray(aliases)) {\n for (const [key, val] of Object.entries(aliases)) {\n if (typeof val === 'string') {\n const fixed = replaceWildcard(val);\n if (fixed !== val) {\n (aliases as Record<string, string>)[key] = fixed;\n }\n }\n }\n }\n\n // Fix ASSET_PREFIX in DefinePlugin definitions — these are stringified\n // JSON values so the wildcard appears inside quoted strings.\n for (const plugin of rspackConfig.plugins ?? []) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const defs = (plugin as any)?.definitions ?? (plugin as any)?._args?.[0];\n if (!defs || typeof defs !== 'object') continue;\n for (const [k, v] of Object.entries(defs)) {\n if (typeof v === 'string' && WILDCARD_HOSTS.has(extractHost(v))) {\n (defs as Record<string, string>)[k] = replaceWildcard(v);\n } else if (typeof v === 'object' && v !== null) {\n for (const [k2, v2] of Object.entries(v as Record<string, string>)) {\n if (typeof v2 === 'string' && WILDCARD_HOSTS.has(extractHost(v2))) {\n (v as Record<string, string>)[k2] = replaceWildcard(v2);\n }\n }\n }\n }\n }\n\n // Fix SourceMapDevToolPlugin publicPath\n for (const plugin of rspackConfig.plugins ?? []) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const opts = (plugin as any)?._options ?? (plugin as any)?._args?.[0];\n if (opts && typeof opts.publicPath === 'string') {\n opts.publicPath = replaceWildcard(opts.publicPath);\n }\n }\n });\n\n // Wire CSS handling — forces extraction via @lynx-js/css-extract-webpack-plugin,\n // strips lightningcss, and configures ignore-css-loader for main-thread layer.\n applyCSS(api, {\n enableCSSSelector: _enableCSSSelector,\n enableCSSInvalidation: _enableCSSInheritance,\n });\n\n // Wire dual-thread entry splitting (worklets skipped in v1)\n await applyEntry(api, {\n debugInfoOutside: _debugInfoOutside,\n enableCSSInheritance: _enableCSSInheritance,\n customCSSInheritanceList: _customCSSInheritanceList,\n });\n },\n };\n}\n"],"mappings":"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"}
package/dist/layers.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** Webpack module layers used to separate the dual-thread bundles. */
2
2
  export declare const LAYERS: {
3
- readonly BACKGROUND: "sigx:background";
4
- readonly MAIN_THREAD: "sigx:main-thread";
3
+ readonly BACKGROUND: 'sigx:background';
4
+ readonly MAIN_THREAD: 'sigx:main-thread';
5
5
  };
@@ -5,7 +5,7 @@
5
5
  * loader prepends:
6
6
  * 1. An import of `__registerComponentPlugin` from `@sigx/lynx` — this
7
7
  * is the *same* bundle the app uses, so the plugin array is shared.
8
- * 2. An import of `initHMR` + `registerHMRModule` from `@sigx/runtime-lynx/hmr`.
8
+ * 2. An import of `initHMR` + `registerHMRModule` from `@sigx/lynx-runtime/hmr`.
9
9
  * 3. Calls to wire them up: `initHMR(__registerComponentPlugin)` (idempotent)
10
10
  * and `registerHMRModule(moduleId)`.
11
11
  * 4. (If `signal` is imported) A wrapper that preserves signal objects
@@ -6,7 +6,7 @@ function n(n) {
6
6
  i && (a = n.replace(t, (e, t, n, r) => `import {${t}signal as __origSignal${n}} from ${r}@sigx/lynx${r}`));
7
7
  let o = [
8
8
  "import { __registerComponentPlugin } from '@sigx/lynx';",
9
- "import { initHMR, registerHMRModule } from '@sigx/runtime-lynx/hmr';",
9
+ "import { initHMR, registerHMRModule } from '@sigx/lynx-runtime/hmr';",
10
10
  "initHMR(__registerComponentPlugin);",
11
11
  `registerHMRModule(${JSON.stringify(r)});`
12
12
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"hmr-loader.js","names":[],"sources":["../../src/loaders/hmr-loader.ts"],"sourcesContent":["/**\n * Rspack loader that injects HMR self-acceptance into component files.\n *\n * For every file that contains a `component(` or `component<` call, the\n * loader prepends:\n * 1. An import of `__registerComponentPlugin` from `@sigx/lynx` — this\n * is the *same* bundle the app uses, so the plugin array is shared.\n * 2. An import of `initHMR` + `registerHMRModule` from `@sigx/runtime-lynx/hmr`.\n * 3. Calls to wire them up: `initHMR(__registerComponentPlugin)` (idempotent)\n * and `registerHMRModule(moduleId)`.\n * 4. (If `signal` is imported) A wrapper that preserves signal objects\n * across HMR cycles via `module.hot.data`, so module-level reactive\n * state (e.g., a route signal) doesn't reset and cause structural tree\n * mutations that crash the Lynx native engine.\n *\n * And appends `module.hot.accept()` + a dispose handler that snapshots\n * preserved signals into `module.hot.data` for the next execution.\n *\n * On re-execution the HMR runtime patches existing component instances\n * in-place — only property-level ops are emitted, avoiding the structural\n * tree mutations that crash Lynx's native engine.\n */\n\nimport type { Rspack } from '@rsbuild/core';\n\n// Matches `component(` or `component<`\nconst COMPONENT_RE = /\\bcomponent\\s*[<(]/;\n\n// Matches an import statement from @sigx/lynx that destructures `signal`.\n// Captures: (1) before-signal names, (2) after-signal names, (3) quote char\n// e.g. import { signal, component } from '@sigx/lynx';\n// group 1: \"\" group 2: \", component \" group 3: \"'\"\nconst SIGNAL_IMPORT_RE =\n /import\\s*\\{([^}]*)\\bsignal\\b([^}]*)\\}\\s*from\\s*(['\"])@sigx\\/lynx\\3/;\n\nexport default function hmrLoader(\n this: Rspack.LoaderContext,\n source: string,\n): string {\n this.cacheable(false);\n\n if (!COMPONENT_RE.test(source)) {\n return source;\n }\n\n const moduleId = this.resourcePath\n .replace(/\\\\/g, '/')\n .replace(/\\.(tsx?|jsx)$/, '');\n\n // Check if the file imports `signal` from @sigx/lynx\n const signalImportMatch = source.match(SIGNAL_IMPORT_RE);\n const hasSignalImport = !!signalImportMatch;\n\n let transformedSource = source;\n\n if (hasSignalImport) {\n // Rename `signal` → `__origSignal` in the import statement so we can\n // shadow it with a preserving wrapper. All call-sites automatically\n // use the wrapper because the local binding name stays `signal`.\n transformedSource = source.replace(\n SIGNAL_IMPORT_RE,\n (_match, before, after, quote) =>\n `import {${before}signal as __origSignal${after}} from ${quote}@sigx/lynx${quote}`,\n );\n }\n\n const header: string[] = [\n `import { __registerComponentPlugin } from '@sigx/lynx';`,\n `import { initHMR, registerHMRModule } from '@sigx/runtime-lynx/hmr';`,\n `initHMR(__registerComponentPlugin);`,\n `registerHMRModule(${JSON.stringify(moduleId)});`,\n ];\n\n if (hasSignalImport) {\n // Inject a `signal` wrapper that returns the cached signal object from\n // the previous HMR cycle when one exists, or delegates to the real\n // `signal()` for new signals. This preserves module-level reactive\n // state (and component-level state inside setup — matching React Fast\n // Refresh behaviour where hooks state is preserved across HMR).\n header.push(\n `var __hmrSigPrev = (typeof module !== 'undefined' && module.hot && module.hot.data && module.hot.data.__hmrSigs) || {};`,\n `var __hmrSigStore = {};`,\n `var __hmrSigIdx = 0;`,\n `function signal() {`,\n ` var k = 's' + __hmrSigIdx++;`,\n ` if (k in __hmrSigPrev) { __hmrSigStore[k] = __hmrSigPrev[k]; return __hmrSigPrev[k]; }`,\n ` var s = __origSignal.apply(null, arguments);`,\n ` __hmrSigStore[k] = s;`,\n ` return s;`,\n `}`,\n );\n }\n\n header.push('');\n\n const footer: string[] = [''];\n\n if (hasSignalImport) {\n footer.push(\n `if (typeof module !== 'undefined' && module.hot) {`,\n ` module.hot.dispose(function(data) { data.__hmrSigs = __hmrSigStore; });`,\n ` module.hot.accept();`,\n `}`,\n );\n } else {\n footer.push(\n `if (typeof module !== 'undefined' && module.hot) { module.hot.accept(); }`,\n );\n }\n\n return header.join('\\n') + transformedSource + footer.join('\\n');\n}\n"],"mappings":";AA0BA,IAAM,IAAe,sBAMf,IACJ;AAEF,SAAwB,EAEtB,GACQ;AAGR,KAFA,KAAK,UAAU,GAAM,EAEjB,CAAC,EAAa,KAAK,EAAO,CAC5B,QAAO;CAGT,IAAM,IAAW,KAAK,aACnB,QAAQ,OAAO,IAAI,CACnB,QAAQ,iBAAiB,GAAG,EAIzB,IAAkB,CAAC,CADC,EAAO,MAAM,EAAiB,EAGpD,IAAoB;AAExB,CAAI,MAIF,IAAoB,EAAO,QACzB,IACC,GAAQ,GAAQ,GAAO,MACtB,WAAW,EAAO,wBAAwB,EAAM,SAAS,EAAM,YAAY,IAC9E;CAGH,IAAM,IAAmB;EACvB;EACA;EACA;EACA,qBAAqB,KAAK,UAAU,EAAS,CAAC;EAC/C;AAsBD,CApBI,KAMF,EAAO,KACL,2HACA,2BACA,wBACA,uBACA,kCACA,4FACA,kDACA,2BACA,eACA,IACD,EAGH,EAAO,KAAK,GAAG;CAEf,IAAM,IAAmB,CAAC,GAAG;AAe7B,QAbI,IACF,EAAO,KACL,sDACA,6EACA,0BACA,IACD,GAED,EAAO,KACL,4EACD,EAGI,EAAO,KAAK,KAAK,GAAG,IAAoB,EAAO,KAAK,KAAK"}
1
+ {"version":3,"file":"hmr-loader.js","names":[],"sources":["../../src/loaders/hmr-loader.ts"],"sourcesContent":["/**\n * Rspack loader that injects HMR self-acceptance into component files.\n *\n * For every file that contains a `component(` or `component<` call, the\n * loader prepends:\n * 1. An import of `__registerComponentPlugin` from `@sigx/lynx` — this\n * is the *same* bundle the app uses, so the plugin array is shared.\n * 2. An import of `initHMR` + `registerHMRModule` from `@sigx/lynx-runtime/hmr`.\n * 3. Calls to wire them up: `initHMR(__registerComponentPlugin)` (idempotent)\n * and `registerHMRModule(moduleId)`.\n * 4. (If `signal` is imported) A wrapper that preserves signal objects\n * across HMR cycles via `module.hot.data`, so module-level reactive\n * state (e.g., a route signal) doesn't reset and cause structural tree\n * mutations that crash the Lynx native engine.\n *\n * And appends `module.hot.accept()` + a dispose handler that snapshots\n * preserved signals into `module.hot.data` for the next execution.\n *\n * On re-execution the HMR runtime patches existing component instances\n * in-place — only property-level ops are emitted, avoiding the structural\n * tree mutations that crash Lynx's native engine.\n */\n\nimport type { Rspack } from '@rsbuild/core';\n\n// Matches `component(` or `component<`\nconst COMPONENT_RE = /\\bcomponent\\s*[<(]/;\n\n// Matches an import statement from @sigx/lynx that destructures `signal`.\n// Captures: (1) before-signal names, (2) after-signal names, (3) quote char\n// e.g. import { signal, component } from '@sigx/lynx';\n// group 1: \"\" group 2: \", component \" group 3: \"'\"\nconst SIGNAL_IMPORT_RE =\n /import\\s*\\{([^}]*)\\bsignal\\b([^}]*)\\}\\s*from\\s*(['\"])@sigx\\/lynx\\3/;\n\nexport default function hmrLoader(\n this: Rspack.LoaderContext,\n source: string,\n): string {\n this.cacheable(false);\n\n if (!COMPONENT_RE.test(source)) {\n return source;\n }\n\n const moduleId = this.resourcePath\n .replace(/\\\\/g, '/')\n .replace(/\\.(tsx?|jsx)$/, '');\n\n // Check if the file imports `signal` from @sigx/lynx\n const signalImportMatch = source.match(SIGNAL_IMPORT_RE);\n const hasSignalImport = !!signalImportMatch;\n\n let transformedSource = source;\n\n if (hasSignalImport) {\n // Rename `signal` → `__origSignal` in the import statement so we can\n // shadow it with a preserving wrapper. All call-sites automatically\n // use the wrapper because the local binding name stays `signal`.\n transformedSource = source.replace(\n SIGNAL_IMPORT_RE,\n (_match, before, after, quote) =>\n `import {${before}signal as __origSignal${after}} from ${quote}@sigx/lynx${quote}`,\n );\n }\n\n const header: string[] = [\n `import { __registerComponentPlugin } from '@sigx/lynx';`,\n `import { initHMR, registerHMRModule } from '@sigx/lynx-runtime/hmr';`,\n `initHMR(__registerComponentPlugin);`,\n `registerHMRModule(${JSON.stringify(moduleId)});`,\n ];\n\n if (hasSignalImport) {\n // Inject a `signal` wrapper that returns the cached signal object from\n // the previous HMR cycle when one exists, or delegates to the real\n // `signal()` for new signals. This preserves module-level reactive\n // state (and component-level state inside setup — matching React Fast\n // Refresh behaviour where hooks state is preserved across HMR).\n header.push(\n `var __hmrSigPrev = (typeof module !== 'undefined' && module.hot && module.hot.data && module.hot.data.__hmrSigs) || {};`,\n `var __hmrSigStore = {};`,\n `var __hmrSigIdx = 0;`,\n `function signal() {`,\n ` var k = 's' + __hmrSigIdx++;`,\n ` if (k in __hmrSigPrev) { __hmrSigStore[k] = __hmrSigPrev[k]; return __hmrSigPrev[k]; }`,\n ` var s = __origSignal.apply(null, arguments);`,\n ` __hmrSigStore[k] = s;`,\n ` return s;`,\n `}`,\n );\n }\n\n header.push('');\n\n const footer: string[] = [''];\n\n if (hasSignalImport) {\n footer.push(\n `if (typeof module !== 'undefined' && module.hot) {`,\n ` module.hot.dispose(function(data) { data.__hmrSigs = __hmrSigStore; });`,\n ` module.hot.accept();`,\n `}`,\n );\n } else {\n footer.push(\n `if (typeof module !== 'undefined' && module.hot) { module.hot.accept(); }`,\n );\n }\n\n return header.join('\\n') + transformedSource + footer.join('\\n');\n}\n"],"mappings":";AA0BA,IAAM,IAAe,sBAMf,IACJ;AAEF,SAAwB,EAEtB,GACQ;CAGR,IAFA,KAAK,UAAU,GAAM,EAEjB,CAAC,EAAa,KAAK,EAAO,EAC5B,OAAO;CAGT,IAAM,IAAW,KAAK,aACnB,QAAQ,OAAO,IAAI,CACnB,QAAQ,iBAAiB,GAAG,EAIzB,IAAkB,CAAC,CADC,EAAO,MAAM,EACb,EAEtB,IAAoB;CAExB,AAAI,MAIF,IAAoB,EAAO,QACzB,IACC,GAAQ,GAAQ,GAAO,MACtB,WAAW,EAAO,wBAAwB,EAAM,SAAS,EAAM,YAAY,IAC9E;CAGH,IAAM,IAAmB;EACvB;EACA;EACA;EACA,qBAAqB,KAAK,UAAU,EAAS,CAAC;EAC/C;CAsBD,AApBI,KAMF,EAAO,KACL,2HACA,2BACA,wBACA,uBACA,kCACA,4FACA,kDACA,2BACA,eACA,IACD,EAGH,EAAO,KAAK,GAAG;CAEf,IAAM,IAAmB,CAAC,GAAG;CAe7B,OAbI,IACF,EAAO,KACL,sDACA,6EACA,0BACA,IACD,GAED,EAAO,KACL,4EACD,EAGI,EAAO,KAAK,KAAK,GAAG,IAAoB,EAAO,KAAK,KAAK"}
@@ -1 +1 @@
1
- {"version":3,"file":"ignore-css-loader.js","names":[],"sources":["../../src/loaders/ignore-css-loader.ts"],"sourcesContent":["/**\n * Webpack/Rspack loader that strips CSS from Main-Thread bundles.\n *\n * In the Lynx dual-thread model, only the Background Thread needs CSS.\n * The Main-Thread layer uses `exportOnlyLocals` from css-loader to get\n * CSS module class name mappings without actual styles.\n */\n\nimport type { Rspack } from '@rsbuild/core';\n\nexport default function ignoreCssLoader(\n this: Rspack.LoaderContext,\n source: string,\n): string {\n this.cacheable(true);\n\n // If the source contains ___CSS_LOADER_EXPORT___, it is not a CSS Modules\n // file (exportOnlyLocals is enabled), so we don't need to preserve it.\n if (source.includes('___CSS_LOADER_EXPORT___')) {\n return 'export {}';\n }\n\n // Preserve CSS modules export for background layer.\n return source;\n}\n"],"mappings":";AAUA,SAAwB,EAEtB,GACQ;AAUR,QATA,KAAK,UAAU,GAAK,EAIhB,EAAO,SAAS,0BAA0B,GACrC,cAIF"}
1
+ {"version":3,"file":"ignore-css-loader.js","names":[],"sources":["../../src/loaders/ignore-css-loader.ts"],"sourcesContent":["/**\n * Webpack/Rspack loader that strips CSS from Main-Thread bundles.\n *\n * In the Lynx dual-thread model, only the Background Thread needs CSS.\n * The Main-Thread layer uses `exportOnlyLocals` from css-loader to get\n * CSS module class name mappings without actual styles.\n */\n\nimport type { Rspack } from '@rsbuild/core';\n\nexport default function ignoreCssLoader(\n this: Rspack.LoaderContext,\n source: string,\n): string {\n this.cacheable(true);\n\n // If the source contains ___CSS_LOADER_EXPORT___, it is not a CSS Modules\n // file (exportOnlyLocals is enabled), so we don't need to preserve it.\n if (source.includes('___CSS_LOADER_EXPORT___')) {\n return 'export {}';\n }\n\n // Preserve CSS modules export for background layer.\n return source;\n}\n"],"mappings":";AAUA,SAAwB,EAEtB,GACQ;CAUR,OATA,KAAK,UAAU,GAAK,EAIhB,EAAO,SAAS,0BAA0B,GACrC,cAIF"}
@@ -25,11 +25,11 @@ function a(e) {
25
25
  }
26
26
  //#endregion
27
27
  //#region src/loaders/worklet-loader-mt.ts
28
- var o = "@sigx/runtime-lynx-main", s = r(import.meta.url);
28
+ var o = "@sigx/lynx-runtime-main", s = r(import.meta.url);
29
29
  function c(n, r) {
30
30
  return t(e(s.resolve(`${n}/package.json`)), r);
31
31
  }
32
- var l = c("@sigx/runtime-lynx-main", "dist/entry-main.js"), u = c("@lynx-js/react", "runtime/worklet-runtime/main.js"), d = c("@sigx/runtime-lynx-main", "dist/install-hybrid-worklet.js"), f = `import ${JSON.stringify(l)};\nimport ${JSON.stringify(u)};\nimport ${JSON.stringify(d)};\n`;
32
+ var l = c("@sigx/lynx-runtime-main", "dist/entry-main.js"), u = c("@lynx-js/react", "runtime/worklet-runtime/main.js"), d = c("@sigx/lynx-runtime-main", "dist/install-hybrid-worklet.js"), f = `import ${JSON.stringify(l)};\nimport ${JSON.stringify(u)};\nimport ${JSON.stringify(d)};\n`;
33
33
  function p(e) {
34
34
  this.cacheable(!0);
35
35
  let t = i(e);
@@ -1 +1 @@
1
- {"version":3,"file":"worklet-loader-mt.js","names":[],"sources":["../../src/loaders/worklet-utils.ts","../../src/loaders/worklet-loader-mt.ts"],"sourcesContent":["/**\n * Helpers shared by worklet-loader (BG) and worklet-loader-mt (MT).\n *\n * Mirrors vue-lynx's `worklet-utils.ts` minus the `?vue` sub-module logic\n * (sigx has no Vue Single-File-Component pipeline) and minus the\n * `extractSharedImports` path (deferred to Phase 1c — see plan).\n */\n\n/**\n * Extract import statements whose target may contain `'main thread'` worklets\n * the MT bundle needs to register.\n *\n * Two import flavours qualify:\n * - Relative paths (`./foo`, `../bar`) — user code split across files.\n * - `@sigx/*` package paths — workspace component packages like\n * `@sigx/gestures` that ship `<Pressable>`/`<Draggable>` etc. These resolve\n * to workspace `src/` (not node_modules) so the MT loader's rule still\n * processes them; we just need to preserve the edge so rspack walks there.\n *\n * Converts named/default/namespace imports to side-effect-only imports\n * (`import '@sigx/gestures';`) so webpack still follows the dependency graph\n * without executing user code on the MT layer.\n *\n * Critical for the MT loader: an entry like `main.tsx` may not contain any\n * `'main thread'` directives itself, but it imports route/component files\n * that do. Without preserving these edges, webpack would never reach the\n * files with worklet registrations and MT-side hydration of BG worklet ctxs\n * would throw \"cannot read property bind of undefined\" when the unregistered\n * _wkltId is looked up in `lynxWorkletImpl._workletMap`.\n */\nexport function extractLocalImports(source: string): string {\n // Strip line and block comments so docstring examples like\n // `* import X from './foo'` don't get parsed as real imports.\n // String contents are left intact (we still catch `import './foo'` inside\n // a string template), but real source rarely encodes import-statement\n // shapes inside strings, and the false-positive rate with comments stripped\n // is acceptable for this preserve-edges-only loader.\n const stripped = source\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/(^|[^:])\\/\\/[^\\n]*/g, '$1');\n\n const specifiers = new Set<string>();\n\n // Relative paths (./foo, ../bar) and @sigx/* package paths.\n const re = /(?:from|import)\\s+['\"]((?:\\.[^'\"]+)|(?:@sigx\\/[^'\"]+))['\"]/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(stripped)) !== null) {\n specifiers.add(match[1]!);\n }\n\n if (specifiers.size === 0) return '';\n return [...specifiers].map((s) => `import '${s}';`).join('\\n');\n}\n\n/**\n * Extract `registerWorkletInternal(...)` calls from a LEPUS-target transform output.\n *\n * Upstream's LEPUS output includes:\n * - `import { loadWorkletRuntime as __loadWorkletRuntime } from \"<runtimePkg>\";`\n * - `var loadWorkletRuntime = __loadWorkletRuntime;`\n * - the original component code (which we drop — never invoked on MT)\n * - `const __workletRuntimeLoaded = loadWorkletRuntime(...);`\n * - `__workletRuntimeLoaded && registerWorkletInternal(\"main-thread\", \"<id>\", function(...) { ... });`\n *\n * We only need the `registerWorkletInternal(...)` calls — the loadWorkletRuntime\n * gating is redundant because we only inject the calls when the MT bundle is\n * actually being built. Bracket-depth counting handles nested braces in the\n * function body.\n */\nexport function extractRegistrations(lepusCode: string): string {\n const out: string[] = [];\n const marker = 'registerWorkletInternal(';\n let from = 0;\n\n while (true) {\n const idx = lepusCode.indexOf(marker, from);\n if (idx === -1) break;\n\n let depth = 0;\n let i = idx + marker.length - 1; // points at the opening '('\n for (; i < lepusCode.length; i++) {\n const ch = lepusCode[i];\n if (ch === '(') depth++;\n else if (ch === ')') {\n depth--;\n if (depth === 0) break;\n }\n }\n\n let end = i + 1;\n if (end < lepusCode.length && lepusCode[end] === ';') end++;\n out.push(lepusCode.slice(idx, end));\n from = end;\n }\n\n return out.join('\\n');\n}\n","/**\n * MT-layer rspack loader for the `'main thread'` worklet directive.\n *\n * Runs on every file in the MT bundle. For each file:\n * 1. Extract local relative-path imports → side-effect-only imports so\n * webpack still walks the dep graph to files that contain worklets.\n * 2. If the file has no `'main thread'` directive, return only those\n * imports (drops user component code from the MT bundle — Lepus must\n * not execute it).\n * 3. Otherwise call upstream's `transformReactLynxSync` with `target: 'LEPUS'`\n * and slice out only the `registerWorkletInternal(...)` calls via\n * `extractRegistrations`. Combine: `[localImports, registrations]`.\n *\n * The `loadWorkletRuntime` import that upstream's LEPUS output emits is\n * dropped — `extractRegistrations` only keeps the registration calls, and\n * `registerWorkletInternal` is installed as a global by `entry-main.ts`.\n *\n * Mirrors vue-lynx's `worklet-loader-mt.ts`, minus the `?vue` sub-module\n * branch (sigx has no Vue SFC pipeline) and minus the shared-imports path\n * (deferred to Phase 1c).\n */\n\nimport type { Rspack } from '@rsbuild/core';\nimport { transformReactLynxSync } from '@lynx-js/react/transform';\nimport { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { extractLocalImports, extractRegistrations } from './worklet-utils.js';\n\nconst RUNTIME_PKG = '@sigx/runtime-lynx-main';\n\n/**\n * Prepended to every MT-layer file so webpack's dep graph guarantees the\n * bootstrap modules evaluate BEFORE any user code that calls\n * `registerWorkletInternal(...)`. Listing these as separate entries in\n * `entry.ts` doesn't suffice — rspack walks the chunk graph, which can\n * eval user code first when nothing else explicitly depends on bootstrap.\n *\n * Order matters: entry-main's module body sets globalThis.SystemInfo before\n * worklet-runtime's IIFE reads it.\n *\n * Paths are resolved to absolute file URIs at loader-init time so user apps\n * don't need to declare @lynx-js/react as a direct dep — pnpm hoists it into\n * our package's node_modules and we hand rspack the resolved path. We resolve\n * the package's `package.json` (always reachable, no exports-map games), read\n * the dist subpath relative to it. createRequire(import.meta.url) lets us\n * walk up from the loader's install location via Node's CJS resolver.\n */\nconst _req = createRequire(import.meta.url);\n\nfunction resolvePackageSubpath(pkgName: string, subpath: string): string {\n const pkgJsonPath = _req.resolve(`${pkgName}/package.json`);\n return join(dirname(pkgJsonPath), subpath);\n}\n\nconst ENTRY_MAIN_PATH = resolvePackageSubpath(\n '@sigx/runtime-lynx-main',\n 'dist/entry-main.js',\n);\nconst WORKLET_RUNTIME_PATH = resolvePackageSubpath(\n '@lynx-js/react',\n 'runtime/worklet-runtime/main.js',\n);\nconst INSTALL_HYBRID_PATH = resolvePackageSubpath(\n '@sigx/runtime-lynx-main',\n 'dist/install-hybrid-worklet.js',\n);\n\nconst BOOTSTRAP_PREAMBLE =\n `import ${JSON.stringify(ENTRY_MAIN_PATH)};\\n`\n + `import ${JSON.stringify(WORKLET_RUNTIME_PATH)};\\n`\n + `import ${JSON.stringify(INSTALL_HYBRID_PATH)};\\n`;\n\nexport default function workletLoaderMT(\n this: Rspack.LoaderContext,\n source: string,\n): string {\n this.cacheable(true);\n\n const localImports = extractLocalImports(source);\n\n if (!source.includes('\\'main thread\\'') && !source.includes('\"main thread\"')) {\n return BOOTSTRAP_PREAMBLE + localImports;\n }\n\n const filename = this.resourcePath;\n const result = transformReactLynxSync(source, {\n pluginName: 'sigx:worklet-mt',\n filename,\n sourcemap: false,\n cssScope: false,\n shake: false,\n compat: false,\n refresh: false,\n defineDCE: false,\n directiveDCE: false,\n snapshot: false,\n worklet: { target: 'LEPUS', filename, runtimePkg: RUNTIME_PKG },\n });\n\n if (result.errors && result.errors.length > 0) {\n for (const err of result.errors) {\n this.emitError(new Error(`[sigx-worklet-mt] LEPUS transform: ${err.text}`));\n }\n return localImports;\n }\n\n const registrations = extractRegistrations(result.code);\n return BOOTSTRAP_PREAMBLE + [localImports, registrations].filter(Boolean).join('\\n');\n}\n"],"mappings":";;;;AA8BA,SAAgB,EAAoB,GAAwB;CAO1D,IAAM,IAAW,EACd,QAAQ,qBAAqB,GAAG,CAChC,QAAQ,uBAAuB,KAAK,EAEjC,oBAAa,IAAI,KAAa,EAG9B,IAAK,+DACP;AACJ,SAAQ,IAAQ,EAAG,KAAK,EAAS,MAAM,MACrC,GAAW,IAAI,EAAM,GAAI;AAI3B,QADI,EAAW,SAAS,IAAU,KAC3B,CAAC,GAAG,EAAW,CAAC,KAAK,MAAM,WAAW,EAAE,IAAI,CAAC,KAAK,KAAK;;AAkBhE,SAAgB,EAAqB,GAA2B;CAC9D,IAAM,IAAgB,EAAE,EAEpB,IAAO;AAEX,UAAa;EACX,IAAM,IAAM,EAAU,QAAQ,4BAAQ,EAAK;AAC3C,MAAI,MAAQ,GAAI;EAEhB,IAAI,IAAQ,GACR,IAAI,IAAM,KAAgB;AAC9B,SAAO,IAAI,EAAU,QAAQ,KAAK;GAChC,IAAM,IAAK,EAAU;AACrB,OAAI,MAAO,IAAK;YACP,MAAO,QACd,KACI,MAAU,GAAG;;EAIrB,IAAI,IAAM,IAAI;AAGd,EAFI,IAAM,EAAU,UAAU,EAAU,OAAS,OAAK,KACtD,EAAI,KAAK,EAAU,MAAM,GAAK,EAAI,CAAC,EACnC,IAAO;;AAGT,QAAO,EAAI,KAAK,KAAK;;;;ACnEvB,IAAM,IAAc,2BAmBd,IAAO,EAAc,OAAO,KAAK,IAAI;AAE3C,SAAS,EAAsB,GAAiB,GAAyB;AAEvE,QAAO,EAAK,EADQ,EAAK,QAAQ,GAAG,EAAQ,eAAe,CAC3B,EAAE,EAAQ;;AAG5C,IAAM,IAAkB,EACtB,2BACA,qBACD,EACK,IAAuB,EAC3B,kBACA,kCACD,EACK,IAAsB,EAC1B,2BACA,iCACD,EAEK,IACJ,UAAU,KAAK,UAAU,EAAgB,CAAC,YAC9B,KAAK,UAAU,EAAqB,CAAC,YACrC,KAAK,UAAU,EAAoB,CAAC;AAElD,SAAwB,EAEtB,GACQ;AACR,MAAK,UAAU,GAAK;CAEpB,IAAM,IAAe,EAAoB,EAAO;AAEhD,KAAI,CAAC,EAAO,SAAS,gBAAkB,IAAI,CAAC,EAAO,SAAS,kBAAgB,CAC1E,QAAO,IAAqB;CAG9B,IAAM,IAAW,KAAK,cAChB,IAAS,EAAuB,GAAQ;EAC5C,YAAY;EACZ;EACA,WAAW;EACX,UAAU;EACV,OAAO;EACP,QAAQ;EACR,SAAS;EACT,WAAW;EACX,cAAc;EACd,UAAU;EACV,SAAS;GAAE,QAAQ;GAAS;GAAU,YAAY;GAAa;EAChE,CAAC;AAEF,KAAI,EAAO,UAAU,EAAO,OAAO,SAAS,GAAG;AAC7C,OAAK,IAAM,KAAO,EAAO,OACvB,MAAK,UAAU,gBAAI,MAAM,sCAAsC,EAAI,OAAO,CAAC;AAE7E,SAAO;;AAIT,QAAO,IAAqB,CAAC,GADP,EAAqB,EAAO,KAAK,CACE,CAAC,OAAO,QAAQ,CAAC,KAAK,KAAK"}
1
+ {"version":3,"file":"worklet-loader-mt.js","names":[],"sources":["../../src/loaders/worklet-utils.ts","../../src/loaders/worklet-loader-mt.ts"],"sourcesContent":["/**\n * Helpers shared by worklet-loader (BG) and worklet-loader-mt (MT).\n *\n * Mirrors vue-lynx's `worklet-utils.ts` minus the `?vue` sub-module logic\n * (sigx has no Vue Single-File-Component pipeline) and minus the\n * `extractSharedImports` path (deferred to Phase 1c — see plan).\n */\n\n/**\n * Extract import statements whose target may contain `'main thread'` worklets\n * the MT bundle needs to register.\n *\n * Two import flavours qualify:\n * - Relative paths (`./foo`, `../bar`) — user code split across files.\n * - `@sigx/*` package paths — workspace component packages like\n * `@sigx/gestures` that ship `<Pressable>`/`<Draggable>` etc. These resolve\n * to workspace `src/` (not node_modules) so the MT loader's rule still\n * processes them; we just need to preserve the edge so rspack walks there.\n *\n * Converts named/default/namespace imports to side-effect-only imports\n * (`import '@sigx/gestures';`) so webpack still follows the dependency graph\n * without executing user code on the MT layer.\n *\n * Critical for the MT loader: an entry like `main.tsx` may not contain any\n * `'main thread'` directives itself, but it imports route/component files\n * that do. Without preserving these edges, webpack would never reach the\n * files with worklet registrations and MT-side hydration of BG worklet ctxs\n * would throw \"cannot read property bind of undefined\" when the unregistered\n * _wkltId is looked up in `lynxWorkletImpl._workletMap`.\n */\nexport function extractLocalImports(source: string): string {\n // Strip line and block comments so docstring examples like\n // `* import X from './foo'` don't get parsed as real imports.\n // String contents are left intact (we still catch `import './foo'` inside\n // a string template), but real source rarely encodes import-statement\n // shapes inside strings, and the false-positive rate with comments stripped\n // is acceptable for this preserve-edges-only loader.\n const stripped = source\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/(^|[^:])\\/\\/[^\\n]*/g, '$1');\n\n const specifiers = new Set<string>();\n\n // Relative paths (./foo, ../bar) and @sigx/* package paths.\n const re = /(?:from|import)\\s+['\"]((?:\\.[^'\"]+)|(?:@sigx\\/[^'\"]+))['\"]/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(stripped)) !== null) {\n specifiers.add(match[1]!);\n }\n\n if (specifiers.size === 0) return '';\n return [...specifiers].map((s) => `import '${s}';`).join('\\n');\n}\n\n/**\n * Extract `registerWorkletInternal(...)` calls from a LEPUS-target transform output.\n *\n * Upstream's LEPUS output includes:\n * - `import { loadWorkletRuntime as __loadWorkletRuntime } from \"<runtimePkg>\";`\n * - `var loadWorkletRuntime = __loadWorkletRuntime;`\n * - the original component code (which we drop — never invoked on MT)\n * - `const __workletRuntimeLoaded = loadWorkletRuntime(...);`\n * - `__workletRuntimeLoaded && registerWorkletInternal(\"main-thread\", \"<id>\", function(...) { ... });`\n *\n * We only need the `registerWorkletInternal(...)` calls — the loadWorkletRuntime\n * gating is redundant because we only inject the calls when the MT bundle is\n * actually being built. Bracket-depth counting handles nested braces in the\n * function body.\n */\nexport function extractRegistrations(lepusCode: string): string {\n const out: string[] = [];\n const marker = 'registerWorkletInternal(';\n let from = 0;\n\n while (true) {\n const idx = lepusCode.indexOf(marker, from);\n if (idx === -1) break;\n\n let depth = 0;\n let i = idx + marker.length - 1; // points at the opening '('\n for (; i < lepusCode.length; i++) {\n const ch = lepusCode[i];\n if (ch === '(') depth++;\n else if (ch === ')') {\n depth--;\n if (depth === 0) break;\n }\n }\n\n let end = i + 1;\n if (end < lepusCode.length && lepusCode[end] === ';') end++;\n out.push(lepusCode.slice(idx, end));\n from = end;\n }\n\n return out.join('\\n');\n}\n","/**\n * MT-layer rspack loader for the `'main thread'` worklet directive.\n *\n * Runs on every file in the MT bundle. For each file:\n * 1. Extract local relative-path imports → side-effect-only imports so\n * webpack still walks the dep graph to files that contain worklets.\n * 2. If the file has no `'main thread'` directive, return only those\n * imports (drops user component code from the MT bundle — Lepus must\n * not execute it).\n * 3. Otherwise call upstream's `transformReactLynxSync` with `target: 'LEPUS'`\n * and slice out only the `registerWorkletInternal(...)` calls via\n * `extractRegistrations`. Combine: `[localImports, registrations]`.\n *\n * The `loadWorkletRuntime` import that upstream's LEPUS output emits is\n * dropped — `extractRegistrations` only keeps the registration calls, and\n * `registerWorkletInternal` is installed as a global by `entry-main.ts`.\n *\n * Mirrors vue-lynx's `worklet-loader-mt.ts`, minus the `?vue` sub-module\n * branch (sigx has no Vue SFC pipeline) and minus the shared-imports path\n * (deferred to Phase 1c).\n */\n\nimport type { Rspack } from '@rsbuild/core';\nimport { transformReactLynxSync } from '@lynx-js/react/transform';\nimport { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { extractLocalImports, extractRegistrations } from './worklet-utils.js';\n\nconst RUNTIME_PKG = '@sigx/lynx-runtime-main';\n\n/**\n * Prepended to every MT-layer file so webpack's dep graph guarantees the\n * bootstrap modules evaluate BEFORE any user code that calls\n * `registerWorkletInternal(...)`. Listing these as separate entries in\n * `entry.ts` doesn't suffice — rspack walks the chunk graph, which can\n * eval user code first when nothing else explicitly depends on bootstrap.\n *\n * Order matters: entry-main's module body sets globalThis.SystemInfo before\n * worklet-runtime's IIFE reads it.\n *\n * Paths are resolved to absolute file URIs at loader-init time so user apps\n * don't need to declare @lynx-js/react as a direct dep — pnpm hoists it into\n * our package's node_modules and we hand rspack the resolved path. We resolve\n * the package's `package.json` (always reachable, no exports-map games), read\n * the dist subpath relative to it. createRequire(import.meta.url) lets us\n * walk up from the loader's install location via Node's CJS resolver.\n */\nconst _req = createRequire(import.meta.url);\n\nfunction resolvePackageSubpath(pkgName: string, subpath: string): string {\n const pkgJsonPath = _req.resolve(`${pkgName}/package.json`);\n return join(dirname(pkgJsonPath), subpath);\n}\n\nconst ENTRY_MAIN_PATH = resolvePackageSubpath(\n '@sigx/lynx-runtime-main',\n 'dist/entry-main.js',\n);\nconst WORKLET_RUNTIME_PATH = resolvePackageSubpath(\n '@lynx-js/react',\n 'runtime/worklet-runtime/main.js',\n);\nconst INSTALL_HYBRID_PATH = resolvePackageSubpath(\n '@sigx/lynx-runtime-main',\n 'dist/install-hybrid-worklet.js',\n);\n\nconst BOOTSTRAP_PREAMBLE =\n `import ${JSON.stringify(ENTRY_MAIN_PATH)};\\n`\n + `import ${JSON.stringify(WORKLET_RUNTIME_PATH)};\\n`\n + `import ${JSON.stringify(INSTALL_HYBRID_PATH)};\\n`;\n\nexport default function workletLoaderMT(\n this: Rspack.LoaderContext,\n source: string,\n): string {\n this.cacheable(true);\n\n const localImports = extractLocalImports(source);\n\n if (!source.includes('\\'main thread\\'') && !source.includes('\"main thread\"')) {\n return BOOTSTRAP_PREAMBLE + localImports;\n }\n\n const filename = this.resourcePath;\n const result = transformReactLynxSync(source, {\n pluginName: 'sigx:worklet-mt',\n filename,\n sourcemap: false,\n cssScope: false,\n shake: false,\n compat: false,\n refresh: false,\n defineDCE: false,\n directiveDCE: false,\n snapshot: false,\n worklet: { target: 'LEPUS', filename, runtimePkg: RUNTIME_PKG },\n });\n\n if (result.errors && result.errors.length > 0) {\n for (const err of result.errors) {\n this.emitError(new Error(`[sigx-worklet-mt] LEPUS transform: ${err.text}`));\n }\n return localImports;\n }\n\n const registrations = extractRegistrations(result.code);\n return BOOTSTRAP_PREAMBLE + [localImports, registrations].filter(Boolean).join('\\n');\n}\n"],"mappings":";;;;AA8BA,SAAgB,EAAoB,GAAwB;CAO1D,IAAM,IAAW,EACd,QAAQ,qBAAqB,GAAG,CAChC,QAAQ,uBAAuB,KAAK,EAEjC,oBAAa,IAAI,KAAa,EAG9B,IAAK,+DACP;CACJ,QAAQ,IAAQ,EAAG,KAAK,EAAS,MAAM,OACrC,EAAW,IAAI,EAAM,GAAI;CAI3B,OADI,EAAW,SAAS,IAAU,KAC3B,CAAC,GAAG,EAAW,CAAC,KAAK,MAAM,WAAW,EAAE,IAAI,CAAC,KAAK,KAAK;;AAkBhE,SAAgB,EAAqB,GAA2B;CAC9D,IAAM,IAAgB,EAAE,EAEpB,IAAO;CAEX,SAAa;EACX,IAAM,IAAM,EAAU,QAAQ,4BAAQ,EAAK;EAC3C,IAAI,MAAQ,IAAI;EAEhB,IAAI,IAAQ,GACR,IAAI,IAAM,KAAgB;EAC9B,OAAO,IAAI,EAAU,QAAQ,KAAK;GAChC,IAAM,IAAK,EAAU;GACrB,IAAI,MAAO,KAAK;QACX,IAAI,MAAO,QACd,KACI,MAAU,IAAG;;EAIrB,IAAI,IAAM,IAAI;EAGd,AAFI,IAAM,EAAU,UAAU,EAAU,OAAS,OAAK,KACtD,EAAI,KAAK,EAAU,MAAM,GAAK,EAAI,CAAC,EACnC,IAAO;;CAGT,OAAO,EAAI,KAAK,KAAK;;;;ACnEvB,IAAM,IAAc,2BAmBd,IAAO,EAAc,OAAO,KAAK,IAAI;AAE3C,SAAS,EAAsB,GAAiB,GAAyB;CAEvE,OAAO,EAAK,EADQ,EAAK,QAAQ,GAAG,EAAQ,eACxB,CAAY,EAAE,EAAQ;;AAG5C,IAAM,IAAkB,EACtB,2BACA,qBACD,EACK,IAAuB,EAC3B,kBACA,kCACD,EACK,IAAsB,EAC1B,2BACA,iCACD,EAEK,IACJ,UAAU,KAAK,UAAU,EAAgB,CAAC,YAC9B,KAAK,UAAU,EAAqB,CAAC,YACrC,KAAK,UAAU,EAAoB,CAAC;AAElD,SAAwB,EAEtB,GACQ;CACR,KAAK,UAAU,GAAK;CAEpB,IAAM,IAAe,EAAoB,EAAO;CAEhD,IAAI,CAAC,EAAO,SAAS,gBAAkB,IAAI,CAAC,EAAO,SAAS,kBAAgB,EAC1E,OAAO,IAAqB;CAG9B,IAAM,IAAW,KAAK,cAChB,IAAS,EAAuB,GAAQ;EAC5C,YAAY;EACZ;EACA,WAAW;EACX,UAAU;EACV,OAAO;EACP,QAAQ;EACR,SAAS;EACT,WAAW;EACX,cAAc;EACd,UAAU;EACV,SAAS;GAAE,QAAQ;GAAS;GAAU,YAAY;GAAa;EAChE,CAAC;CAEF,IAAI,EAAO,UAAU,EAAO,OAAO,SAAS,GAAG;EAC7C,KAAK,IAAM,KAAO,EAAO,QACvB,KAAK,UAAU,gBAAI,MAAM,sCAAsC,EAAI,OAAO,CAAC;EAE7E,OAAO;;CAIT,OAAO,IAAqB,CAAC,GADP,EAAqB,EAAO,KACP,CAAc,CAAC,OAAO,QAAQ,CAAC,KAAK,KAAK"}
@@ -1,6 +1,6 @@
1
1
  import { transformReactLynxSync as e } from "@lynx-js/react/transform";
2
2
  //#region src/loaders/worklet-loader.ts
3
- var t = "@sigx/runtime-lynx";
3
+ var t = "@sigx/lynx-runtime";
4
4
  function n(n) {
5
5
  if (this.cacheable(!0), !n.includes("'main thread'") && !n.includes("\"main thread\"")) return n;
6
6
  let r = this.resourcePath, i = e(n, {
@@ -1 +1 @@
1
- {"version":3,"file":"worklet-loader.js","names":[],"sources":["../../src/loaders/worklet-loader.ts"],"sourcesContent":["/**\n * BG-layer rspack loader for the `'main thread'` worklet directive.\n *\n * Delegates to upstream's `transformReactLynxSync` (a framework-agnostic SWC\n * worklet transform shared with vue-lynx and react-lynx — see\n * docs/mts-upstream-spike.md). With `target: 'JS'`, each `'main thread'`-marked\n * function is replaced by a `{ _wkltId, _c? }` placeholder object that the\n * sigx BG runtime ships through SET_WORKLET_EVENT to MT.\n *\n * Files without the directive are passed through unchanged. The MT side is\n * handled by the sibling `worklet-loader-mt.ts`.\n */\n\nimport type { Rspack } from '@rsbuild/core';\nimport { transformReactLynxSync } from '@lynx-js/react/transform';\n\n// runtimePkg controls where SWC emits `import { transformToWorklet }` for the\n// BG bundle (used when `runOnBackground(fn)` appears inline inside a\n// `'main thread'` body). Point at @sigx/runtime-lynx — the BG runtime —\n// because that's where transformToWorklet is exported. The MT loader uses\n// @sigx/runtime-lynx-main; identifier matching for runOnMainThread /\n// runOnBackground is by name and works regardless of source.\nconst RUNTIME_PKG = '@sigx/runtime-lynx';\n\nexport default function workletLoader(\n this: Rspack.LoaderContext,\n source: string,\n): string {\n this.cacheable(true);\n\n if (!source.includes('\\'main thread\\'') && !source.includes('\"main thread\"')) {\n return source;\n }\n\n const filename = this.resourcePath;\n const result = transformReactLynxSync(source, {\n pluginName: 'sigx:worklet',\n filename,\n sourcemap: false,\n cssScope: false,\n shake: false,\n compat: false,\n refresh: false,\n defineDCE: false,\n directiveDCE: false,\n snapshot: false,\n worklet: { target: 'JS', filename, runtimePkg: RUNTIME_PKG },\n });\n\n if (result.errors && result.errors.length > 0) {\n for (const err of result.errors) {\n this.emitError(new Error(`[sigx-worklet] JS transform: ${err.text}`));\n }\n return source;\n }\n\n return result.code;\n}\n"],"mappings":";;AAsBA,IAAM,IAAc;AAEpB,SAAwB,EAEtB,GACQ;AAGR,KAFA,KAAK,UAAU,GAAK,EAEhB,CAAC,EAAO,SAAS,gBAAkB,IAAI,CAAC,EAAO,SAAS,kBAAgB,CAC1E,QAAO;CAGT,IAAM,IAAW,KAAK,cAChB,IAAS,EAAuB,GAAQ;EAC5C,YAAY;EACZ;EACA,WAAW;EACX,UAAU;EACV,OAAO;EACP,QAAQ;EACR,SAAS;EACT,WAAW;EACX,cAAc;EACd,UAAU;EACV,SAAS;GAAE,QAAQ;GAAM;GAAU,YAAY;GAAa;EAC7D,CAAC;AAEF,KAAI,EAAO,UAAU,EAAO,OAAO,SAAS,GAAG;AAC7C,OAAK,IAAM,KAAO,EAAO,OACvB,MAAK,UAAU,gBAAI,MAAM,gCAAgC,EAAI,OAAO,CAAC;AAEvE,SAAO;;AAGT,QAAO,EAAO"}
1
+ {"version":3,"file":"worklet-loader.js","names":[],"sources":["../../src/loaders/worklet-loader.ts"],"sourcesContent":["/**\n * BG-layer rspack loader for the `'main thread'` worklet directive.\n *\n * Delegates to upstream's `transformReactLynxSync` (a framework-agnostic SWC\n * worklet transform shared with vue-lynx and react-lynx — see\n * docs/mts-upstream-spike.md). With `target: 'JS'`, each `'main thread'`-marked\n * function is replaced by a `{ _wkltId, _c? }` placeholder object that the\n * sigx BG runtime ships through SET_WORKLET_EVENT to MT.\n *\n * Files without the directive are passed through unchanged. The MT side is\n * handled by the sibling `worklet-loader-mt.ts`.\n */\n\nimport type { Rspack } from '@rsbuild/core';\nimport { transformReactLynxSync } from '@lynx-js/react/transform';\n\n// runtimePkg controls where SWC emits `import { transformToWorklet }` for the\n// BG bundle (used when `runOnBackground(fn)` appears inline inside a\n// `'main thread'` body). Point at @sigx/lynx-runtime — the BG runtime —\n// because that's where transformToWorklet is exported. The MT loader uses\n// @sigx/lynx-runtime-main; identifier matching for runOnMainThread /\n// runOnBackground is by name and works regardless of source.\nconst RUNTIME_PKG = '@sigx/lynx-runtime';\n\nexport default function workletLoader(\n this: Rspack.LoaderContext,\n source: string,\n): string {\n this.cacheable(true);\n\n if (!source.includes('\\'main thread\\'') && !source.includes('\"main thread\"')) {\n return source;\n }\n\n const filename = this.resourcePath;\n const result = transformReactLynxSync(source, {\n pluginName: 'sigx:worklet',\n filename,\n sourcemap: false,\n cssScope: false,\n shake: false,\n compat: false,\n refresh: false,\n defineDCE: false,\n directiveDCE: false,\n snapshot: false,\n worklet: { target: 'JS', filename, runtimePkg: RUNTIME_PKG },\n });\n\n if (result.errors && result.errors.length > 0) {\n for (const err of result.errors) {\n this.emitError(new Error(`[sigx-worklet] JS transform: ${err.text}`));\n }\n return source;\n }\n\n return result.code;\n}\n"],"mappings":";;AAsBA,IAAM,IAAc;AAEpB,SAAwB,EAEtB,GACQ;CAGR,IAFA,KAAK,UAAU,GAAK,EAEhB,CAAC,EAAO,SAAS,gBAAkB,IAAI,CAAC,EAAO,SAAS,kBAAgB,EAC1E,OAAO;CAGT,IAAM,IAAW,KAAK,cAChB,IAAS,EAAuB,GAAQ;EAC5C,YAAY;EACZ;EACA,WAAW;EACX,UAAU;EACV,OAAO;EACP,QAAQ;EACR,SAAS;EACT,WAAW;EACX,cAAc;EACd,UAAU;EACV,SAAS;GAAE,QAAQ;GAAM;GAAU,YAAY;GAAa;EAC7D,CAAC;CAEF,IAAI,EAAO,UAAU,EAAO,OAAO,SAAS,GAAG;EAC7C,KAAK,IAAM,KAAO,EAAO,QACvB,KAAK,UAAU,gBAAI,MAAM,gCAAgC,EAAI,OAAO,CAAC;EAEvE,OAAO;;CAGT,OAAO,EAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigx/lynx-plugin",
3
- "version": "0.2.4",
3
+ "version": "0.2.7",
4
4
  "description": "Rspack/Rspeedy plugin for SignalX Lynx dual-thread rendering",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,16 +25,16 @@
25
25
  "license": "MIT",
26
26
  "repository": {
27
27
  "type": "git",
28
- "url": "git+https://github.com/signalxjs/core.git",
28
+ "url": "git+https://github.com/signalxjs/lynx.git",
29
29
  "directory": "packages/lynx-plugin"
30
30
  },
31
- "homepage": "https://github.com/signalxjs",
31
+ "homepage": "https://github.com/signalxjs/lynx/tree/main/packages/lynx-plugin",
32
32
  "bugs": {
33
- "url": "https://github.com/signalxjs/core/issues"
33
+ "url": "https://github.com/signalxjs/lynx/issues"
34
34
  },
35
35
  "dependencies": {
36
- "@lynx-js/react": "^0.119.0",
37
- "@sigx/runtime-lynx-internal": "0.2.4"
36
+ "@lynx-js/react": "^0.120.0",
37
+ "@sigx/lynx-runtime-internal": "0.2.6"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@rspack/core": ">=1.0.0",
@@ -65,10 +65,14 @@
65
65
  }
66
66
  },
67
67
  "devDependencies": {
68
- "@types/node": "^20.0.0",
69
- "typescript": "^5.9.3",
70
- "vite": "^8.0.3",
71
- "@sigx/vite": "^0.4.1"
68
+ "@rsbuild/core": "^1.7.5",
69
+ "@sigx/vite": "^0.4.3",
70
+ "@types/node": "^25.7.0",
71
+ "typescript": "^6.0.3",
72
+ "vite": "^8.0.12"
73
+ },
74
+ "publishConfig": {
75
+ "access": "public"
72
76
  },
73
77
  "scripts": {
74
78
  "build": "vite build && tsgo --emitDeclarationOnly",