vite-plugin-taro 0.6.1 → 0.6.3

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.
Files changed (63) hide show
  1. package/README.en.md +6 -1
  2. package/README.md +6 -1
  3. package/dist/node/plugins/h5/transform-app.js +1 -1
  4. package/dist/node/plugins/wx/dev/plugins.d.ts +2 -12
  5. package/dist/node/plugins/wx/dev/plugins.js +12 -66
  6. package/dist/node/plugins/wx/dev/react-refresh.d.ts +9 -3
  7. package/dist/node/plugins/wx/dev/react-refresh.js +35 -7
  8. package/dist/node/plugins/wx/dev/wx-dev-options.js +3 -4
  9. package/dist/node/plugins/wx/{module.js → module/module.js} +2 -2
  10. package/dist/node/plugins/wx/placer/placement.d.ts +1 -0
  11. package/dist/node/plugins/wx/placer/placement.js +1 -1
  12. package/dist/node/plugins/wx/placer/placer.d.ts +17 -1
  13. package/dist/node/plugins/wx/placer/placer.js +25 -1
  14. package/dist/node/plugins/wx/plugins.js +1 -1
  15. package/dist/node/plugins/wx/render/capsule.d.ts +35 -3
  16. package/dist/node/plugins/wx/render/capsule.js +53 -12
  17. package/dist/node/plugins/wx/render/native.d.ts +20 -2
  18. package/dist/node/plugins/wx/render/native.js +539 -35
  19. package/dist/node/plugins/wx/render/system-js/string-editor.d.ts +24 -0
  20. package/dist/node/plugins/wx/render/system-js/string-editor.js +93 -0
  21. package/dist/node/plugins/wx/render/system-js/system-js.d.ts +23 -0
  22. package/dist/node/plugins/wx/render/system-js/system-js.js +602 -0
  23. package/dist/node/plugins/wx/render/transport.js +3 -3
  24. package/dist/node/plugins/wx/resolve/resolver.js +5 -5
  25. package/dist/node/plugins/wx/resolve/{specialize-bootstrap.d.ts → specialize-app-capsule.d.ts} +2 -2
  26. package/dist/node/plugins/wx/resolve/{specialize-bootstrap.js → specialize-app-capsule.js} +3 -3
  27. package/dist/node/plugins/wx/resolve/specialize-page-capsule.js +1 -1
  28. package/dist/node/utils/transform.d.ts +0 -3
  29. package/dist/node/utils/transform.js +0 -23
  30. package/dist/runtime/wx/amphibious/bootstrap.d.ts +0 -2
  31. package/dist/runtime/wx/amphibious/bootstrap.js +0 -2
  32. package/dist/runtime/wx/capsule/app.d.ts +2 -2
  33. package/dist/runtime/wx/capsule/app.js +2 -2
  34. package/dist/runtime/wx/dev/dev-runtime.js +55 -79
  35. package/package.json +8 -6
  36. package/src/node/plugins/h5/transform-app.ts +1 -1
  37. package/src/node/plugins/wx/dev/plugins.ts +12 -69
  38. package/src/node/plugins/wx/dev/react-refresh.ts +36 -7
  39. package/src/node/plugins/wx/dev/wx-dev-options.ts +3 -4
  40. package/src/node/plugins/wx/{module.ts → module/module.ts} +2 -2
  41. package/src/node/plugins/wx/placer/placement.ts +1 -1
  42. package/src/node/plugins/wx/placer/placer.ts +27 -2
  43. package/src/node/plugins/wx/plugins.ts +1 -1
  44. package/src/node/plugins/wx/render/capsule.ts +53 -17
  45. package/src/node/plugins/wx/render/native.ts +670 -55
  46. package/src/node/plugins/wx/render/system-js/string-editor.ts +115 -0
  47. package/src/node/plugins/wx/render/system-js/system-js.ts +831 -0
  48. package/src/node/plugins/wx/render/transport.ts +3 -3
  49. package/src/node/plugins/wx/resolve/resolver.ts +5 -5
  50. package/src/node/plugins/wx/resolve/{specialize-bootstrap.ts → specialize-app-capsule.ts} +3 -3
  51. package/src/node/plugins/wx/resolve/specialize-page-capsule.ts +1 -1
  52. package/src/node/utils/transform.ts +0 -30
  53. package/src/runtime/wx/amphibious/bootstrap.ts +0 -5
  54. package/src/runtime/wx/capsule/app.ts +5 -2
  55. package/src/runtime/wx/dev/dev-runtime.ts +71 -120
  56. package/src/runtime/wx/wechat.d.ts +1 -2
  57. package/dist/node/plugins/wx/render/capsule-wrapper.d.ts +0 -3
  58. package/dist/node/plugins/wx/render/capsule-wrapper.js +0 -64
  59. package/src/node/plugins/wx/render/capsule-wrapper.ts +0 -86
  60. /package/dist/node/plugins/wx/{chunk-path.d.ts → module/chunk-path.d.ts} +0 -0
  61. /package/dist/node/plugins/wx/{chunk-path.js → module/chunk-path.js} +0 -0
  62. /package/dist/node/plugins/wx/{module.d.ts → module/module.d.ts} +0 -0
  63. /package/src/node/plugins/wx/{chunk-path.ts → module/chunk-path.ts} +0 -0
@@ -1,9 +1,9 @@
1
1
  import path from 'node:path'
2
- import { types } from '@babel/core'
2
+ import * as types from '@babel/types'
3
3
  import type { Rolldown } from 'vite'
4
4
  import { type AstTransformResult, replaceWithAst } from '../../../utils/transform.ts'
5
- import { toLogicalChunkId } from '../chunk-path.ts'
6
- import { getWxExecutionKind } from '../module.ts'
5
+ import { toLogicalChunkId } from '../module/chunk-path.ts'
6
+ import { getWxExecutionKind } from '../module/module.ts'
7
7
 
8
8
  const transportPlaceholder = '__VPT_TRANSPORT__'
9
9
  const moduleIdParameter = 'moduleId'
@@ -17,8 +17,8 @@ import {
17
17
  pageShellPath,
18
18
  transportPath,
19
19
  vitePreloadId
20
- } from '../module.ts'
21
- import { specializeBootstrap } from './specialize-bootstrap.ts'
20
+ } from '../module/module.ts'
21
+ import { specializeAppCapsule } from './specialize-app-capsule.ts'
22
22
  import { specializePageCapsule } from './specialize-page-capsule.ts'
23
23
 
24
24
  /** Resolves one exact plugin-private ID using its importer and configured project root. */
@@ -26,7 +26,7 @@ type PrivateIdResolver = (importer: string | undefined, projectRoot: string) =>
26
26
 
27
27
  /** Creates the resolver and source specializer for the wx module graph. */
28
28
  export function createResolver(options: VptOptions) {
29
- const normalizedBootstrapPath = normalizePath(bootstrapPath)
29
+ const normalizedAppCapsulePath = normalizePath(appCapsulePath)
30
30
  const normalizedPageCapsulePath = normalizePath(pageCapsulePath)
31
31
 
32
32
  // Construct output input and application traversal roots together once so style order cannot drift from route order.
@@ -70,8 +70,8 @@ export function createResolver(options: VptOptions) {
70
70
  specialize(code: string, id: string, sourcemap = true) {
71
71
  const normalizedId = normalizeModuleId(id)
72
72
 
73
- if (normalizedId === normalizedBootstrapPath) {
74
- return specializeBootstrap({ code, id, appConfig: createAppConfig(options), sourcemap })
73
+ if (normalizedId === normalizedAppCapsulePath) {
74
+ return specializeAppCapsule({ code, id, appConfig: createAppConfig(options), sourcemap })
75
75
  }
76
76
 
77
77
  if (normalizedId === normalizedPageCapsulePath) {
@@ -1,11 +1,11 @@
1
- import { types } from '@babel/core'
1
+ import * as types from '@babel/types'
2
2
  import type { VptJsonObject } from '../../../../options.ts'
3
3
  import { type AstTransformResult, replaceWithAst } from '../../../utils/transform.ts'
4
4
 
5
5
  const appConfigPlaceholder = '__VPT_APP_CONFIG__'
6
6
 
7
- /** Specializes the amphibious bootstrap with the shared App configuration. */
8
- export function specializeBootstrap({
7
+ /** Specializes the App capsule with its normalized native configuration. */
8
+ export function specializeAppCapsule({
9
9
  code,
10
10
  id,
11
11
  appConfig,
@@ -1,4 +1,4 @@
1
- import { types } from '@babel/core'
1
+ import * as types from '@babel/types'
2
2
  import type { VptPageOption } from '../../../../options.ts'
3
3
  import { type AstTransformResult, replaceWithAst } from '../../../utils/transform.ts'
4
4
 
@@ -1,4 +1,3 @@
1
- import { type PluginItem, transformSync } from '@babel/core'
2
1
  import { generate } from '@babel/generator'
3
2
  import { type Rolldown, transformWithOxc } from 'vite'
4
3
  import { esTarget } from './constant.ts'
@@ -51,32 +50,3 @@ function requireOnePlaceholder(code: string, placeholder: string): void {
51
50
  throw new Error(`Expected one placeholder ${placeholder}, found ${replacementCount}`)
52
51
  }
53
52
  }
54
-
55
- /** Transforms one module with Babel's shared parser and source-map configuration. */
56
- export function transformWithBabel(
57
- code: string,
58
- filename: string,
59
- plugins: PluginItem[],
60
- sourcemap = true
61
- ): AstTransformResult {
62
- const transformed = transformSync(code, {
63
- babelrc: false,
64
- compact: true,
65
- minified: true,
66
- comments: false,
67
- configFile: false,
68
- filename,
69
- plugins,
70
- sourceFileName: filename,
71
- sourceMaps: sourcemap,
72
- sourceType: 'module'
73
- })
74
- if (!transformed?.code || (sourcemap && !transformed.map)) {
75
- throw new Error(`Failed to transform ${filename} with Babel`)
76
- }
77
-
78
- return {
79
- code: transformed.code,
80
- map: sourcemap ? (transformed.map as Rolldown.ExistingRawSourceMap) : null
81
- }
82
- }
@@ -2,11 +2,6 @@
2
2
  import '../systemjs/system-core.js'
3
3
  import { transport } from './transport.ts'
4
4
 
5
- declare const __VPT_APP_CONFIG__: Record<string, unknown>
6
-
7
- /** Shares one App configuration object between the specialized bootstrap and App capsule. */
8
- export const appConfig = __VPT_APP_CONFIG__
9
-
10
5
  // WX has no modulepreload transport. Genuine application import() boundaries retain System.import() and may load
11
6
  // asynchronous subpackage or top-level-await graphs through this identity wrapper.
12
7
  export const __vitePreload = <Value>(load: () => Value): Value => load()
@@ -1,9 +1,12 @@
1
1
  // biome-ignore assist/source/organizeImports: Taro must initialize before the App component.
2
2
  import { createReactApp, ReactDOM } from './taro-runtime.ts'
3
3
  import React from 'react'
4
- import { appConfig } from '../amphibious/bootstrap.ts'
5
4
 
6
5
  // @ts-expect-error: The wx build resolves this private App component.
7
6
  import AppComponent from '\0vpt:app-component'
8
7
 
9
- export default createReactApp(AppComponent, React, ReactDOM, appConfig)
8
+ declare const __VPT_APP_CONFIG__: Record<string, unknown>
9
+
10
+ const config = createReactApp(AppComponent, React, ReactDOM, __VPT_APP_CONFIG__)
11
+
12
+ export default config
@@ -5,7 +5,7 @@
5
5
  // The `DevRuntime` base class is injected into the chunk by Rolldown's dev-mode
6
6
  // transform, so the WX host only extends it.
7
7
  //
8
- // Every Page explicitly passes the inert hmr/patches.js export here before importing its capsule. The runtime applies that
8
+ // Every Page explicitly passes the inert hmr/patches.js export here before native Page registration. The runtime applies that
9
9
  // cumulative suffix synchronously, reports its successful application frontier, and ignores sequences replayed by other Pages.
10
10
 
11
11
  import type { DevRuntime as RolldownDevRuntime } from 'rolldown/experimental/runtime-types'
@@ -54,54 +54,30 @@ type HmrUpdate = Readonly<{
54
54
 
55
55
  type AcceptCallback = (moduleExports: unknown) => void
56
56
 
57
- type PageSnapshot = Readonly<{
58
- $taroPath: string
59
- $taroParams: Record<string, unknown>
60
- data: Record<string, unknown>
61
- }>
62
-
63
57
  type NativePage = {
64
- $taroPath: string
65
- $taroParams: Record<string, unknown>
66
58
  data: Record<string, unknown>
67
- setData(data: Record<string, unknown>): void
59
+ }
60
+
61
+ const pageHmrStateKey: unique symbol = Symbol('vpt.pageHmrState')
62
+
63
+ type PageHmrState = {
64
+ /** True only across the unload/load/show sequence triggered by one native re-registration. */
65
+ isReregistering: boolean
66
+ /** The Page bound to `this` by ordinary onLoad, retained until ordinary onUnload. */
67
+ mountedPage: NativePage | undefined
68
68
  }
69
69
 
70
70
  type HmrPageConfig = {
71
+ data: Record<string, unknown>
71
72
  onUnload?: unknown
72
73
  onLoad?: unknown
73
74
  onShow?: unknown
75
+ [pageHmrStateKey]?: PageHmrState
74
76
  }
75
77
 
76
- type TaroRoot = {
77
- ctx: unknown
78
- }
79
-
80
- /** Immutable bridge references plus replacement transactions owned by one Taro singleton. */
81
- type TaroState = {
82
- /** Taro's existing current-page source of truth; replacement onLoad switches its receiver. */
83
- readonly current: { page: NativePage | null }
84
- /** Taro's virtual document, used to find the retained root by its preserved unique path. */
85
- readonly document: { getElementById(path: string): unknown }
86
- /** Replaces Taro's native lifecycle receiver without remounting the retained React subtree. */
87
- readonly injectPageInstance: (instance: unknown, path: string) => void
88
- /**
89
- * Short-lived route transactions. Absence means ordinary lifecycle; null means armed
90
- * before onUnload or snapshot-consumed before onShow; a snapshot exists only between
91
- * replacement onUnload and onLoad. The large data reference is therefore released in
92
- * onLoad, while the null marker remains just long enough to suppress synthetic onShow.
93
- */
94
- readonly pageReplacements: Map<string, PageSnapshot | null>
95
- }
96
-
97
- /** Forwards a native lifecycle with its original Page receiver. */
98
- function forward(handler: unknown, receiver: unknown, args: unknown[]): void {
99
- if (typeof handler === 'function') handler.apply(receiver, args)
100
- }
101
-
102
- /** Narrows the untyped element returned across the Taro connection boundary. */
103
- function isTaroRoot(value: unknown): value is TaroRoot {
104
- return typeof value === 'object' && value !== null && 'ctx' in value
78
+ /** Calls a native lifecycle with the same Page bound to `this` and the same arguments. */
79
+ function forward(handler: unknown, page: unknown, args: unknown[]): void {
80
+ if (typeof handler === 'function') handler.apply(page, args)
105
81
  }
106
82
 
107
83
  /** Shared no-op CSS contract because physical rebuilds replace styles wholesale. */
@@ -285,109 +261,90 @@ class WxDevRuntime extends DevRuntime {
285
261
  this.session = { ...info, appliedSeq: 0 }
286
262
  }
287
263
 
288
- /**
289
- * One-shot bridge to the application's Taro singleton. It cannot be imported into this
290
- * separately bundled global runtime without creating a second Taro identity. Undefined
291
- * only before the serve-only facade connection; route transactions share its lifetime.
292
- */
293
- private taro: TaroState | undefined
294
-
295
- /** Connects HMR to the same Taro singleton used by the application module graph. */
296
- connectTaro(
297
- current: TaroState['current'],
298
- document: TaroState['document'],
299
- injectPageInstance: TaroState['injectPageInstance']
300
- ): void {
301
- if (this.taro) {
302
- return
303
- }
264
+ /** Tracks the mounted native Page and prepares its static config for HMR re-registration. */
265
+ injectPageHmr(config: HmrPageConfig): HmrPageConfig {
266
+ const existingState = config[pageHmrStateKey]
267
+
268
+ if (existingState) {
269
+ const mountedPage = existingState.mountedPage
270
+ /*
271
+ * The static config can outlive a native Page instance. Before its first ordinary onLoad, or after a real onUnload,
272
+ * there is no mounted Page or current view-model to carry into another registration. Leave the lifecycle gate
273
+ * unarmed and preserve the config's existing initial data so a future real onLoad still enters Taro normally.
274
+ */
275
+ if (!mountedPage) {
276
+ return config
277
+ }
304
278
 
305
- this.taro = {
306
- current,
307
- document,
308
- injectPageInstance,
309
- pageReplacements: new Map()
279
+ /*
280
+ * Arm the lifecycle wrappers on this exact static config before it is passed back to `Page(config)`. DevTools then
281
+ * triggers an unload/load/show sequence for that native re-registration: unload and load observe `true` and return
282
+ * before entering Taro, preserving the mounted React tree and its original Page connection; show consumes the
283
+ * one-shot gate by restoring `false`. Ordinary navigation never enters this branch, and every Page config owns an
284
+ * independent state object, so no route map, global phase, or Page identity comparison participates in the decision.
285
+ */
286
+ existingState.isReregistering = true
287
+ /*
288
+ * `Page(config)` reads `config.data` as the initial native view-model for this registration. Supplying the mounted
289
+ * Page's latest data before that call prevents the temporary Page used for re-registration callbacks from starting
290
+ * empty. This is an O(1) reference assignment in vpt: it does not clone the recursive data tree, call `setData`, move
291
+ * React state, or rebind Taro. The ordinary Taro lifecycle remains suppressed until re-registration onShow, so its
292
+ * React tree and output connection stay attached to `mountedPage`; every later registration reads its latest data.
293
+ */
294
+ config.data = mountedPage.data
295
+
296
+ return config
310
297
  }
311
- }
312
298
 
313
- /** Injects snapshot-preserving behavior into one route-specific Taro Page configuration. */
314
- injectPageHmr(config: HmrPageConfig, route: string): void {
315
299
  const originalOnUnload = config.onUnload
316
300
  const originalOnLoad = config.onLoad
317
301
  const originalOnShow = config.onShow
318
- const runtime = this
302
+
303
+ const state: PageHmrState = {
304
+ isReregistering: false,
305
+ mountedPage: undefined
306
+ }
307
+
308
+ /*
309
+ * Attach the one mutable HMR state object to this exact static config. The lifecycle wrappers below close over the same
310
+ * object, while a later `injectPageHmr(config)` call finds it through the symbol and knows wrapping is already complete.
311
+ * A symbol cannot collide with WeChat or Taro's string-named Page options, and config-local ownership avoids route maps,
312
+ * a runtime-wide WeakMap, or state shared by two Page configs. The state becomes unreachable together with the config.
313
+ */
314
+ config[pageHmrStateKey] = state
319
315
 
320
316
  config.onUnload = function (this: NativePage, ...args: unknown[]) {
321
- const taro = runtime.requireTaro()
322
- if (taro.pageReplacements.has(route)) {
323
- taro.pageReplacements.set(route, {
324
- $taroPath: this.$taroPath,
325
- $taroParams: this.$taroParams,
326
- // WeChat owns this serializable view-model. Keeping its reference is O(1),
327
- // unlike cloning the complete recursive projection before every edit.
328
- data: this.data
329
- })
317
+ if (state.isReregistering) {
330
318
  return
331
319
  }
320
+
332
321
  forward(originalOnUnload, this, args)
322
+ state.mountedPage = undefined
333
323
  }
334
324
 
335
325
  config.onLoad = function (this: NativePage, ...args: unknown[]) {
336
- const taro = runtime.requireTaro()
337
- const snapshot = taro.pageReplacements.get(route)
338
- if (snapshot) {
339
- // Replace the transaction before native work so exceptions cannot retain the
340
- // large data snapshot while the route waits for its synthetic onShow.
341
- taro.pageReplacements.set(route, null)
342
-
343
- // Snapshot paint is the first bridge operation and removes the empty-page gap.
344
- this.setData(snapshot.data)
345
- this.$taroPath = snapshot.$taroPath
346
- this.$taroParams = snapshot.$taroParams
347
- runtime.bindPage(this, snapshot.$taroPath)
326
+ if (state.isReregistering) {
348
327
  return
349
328
  }
329
+
350
330
  forward(originalOnLoad, this, args)
331
+ state.mountedPage = this
351
332
  }
352
333
 
353
334
  config.onShow = function (this: NativePage, ...args: unknown[]) {
354
- if (runtime.requireTaro().pageReplacements.delete(route)) {
355
- // Synthetic shows must not repeat requests or reset application state.
335
+ if (state.isReregistering) {
336
+ state.isReregistering = false
356
337
  return
357
338
  }
358
339
 
359
340
  forward(originalOnShow, this, args)
360
341
  }
361
- }
362
-
363
- /** Returns the Taro connection or fails at the first incorrectly ordered use. */
364
- private requireTaro(): TaroState {
365
- if (!this.taro) throw new Error('[vpt] WX HMR used before the Taro runtime was connected')
366
- return this.taro
367
- }
368
-
369
- /** Returns a retained Taro root after normal Page mount has created it. */
370
- private findRoot(path: string): TaroRoot | undefined {
371
- const root = this.requireTaro().document.getElementById(path)
372
- return isTaroRoot(root) ? root : undefined
373
- }
374
-
375
- /** Rebinds a retained Taro tree to one replacement native Page without repainting. */
376
- private bindPage(instance: NativePage, path: string): void {
377
- const taro = this.requireTaro()
378
- taro.injectPageInstance(instance, path)
379
- taro.current.page = instance
380
-
381
- const pageElement = this.findRoot(path)
382
- if (!pageElement) {
383
- throw new Error(`[vpt] retained Taro page not found: ${path}`)
384
- }
385
342
 
386
- pageElement.ctx = instance
343
+ return config
387
344
  }
388
345
 
389
- /** Applies one Page-delivered payload and arms its route for native replacement. */
390
- applyPatches(payload: PatchPayload | undefined, route?: string): void {
346
+ /** Applies one Page-delivered payload before its native shell registers the static route configuration. */
347
+ applyPatches(payload: PatchPayload | undefined): void {
391
348
  // The initial physical dependency exports undefined until the host has a patch range.
392
349
  if (!payload) return
393
350
 
@@ -397,12 +354,6 @@ class WxDevRuntime extends DevRuntime {
397
354
  return
398
355
  }
399
356
 
400
- // A replayed payload still causes DevTools to replace this physical Page. Arm the
401
- // route independently of whether this App heap already applied its patch sequence.
402
- if (route) {
403
- this.requireTaro().pageReplacements.set(route, null)
404
- }
405
-
406
357
  // Apply synchronously: the page's imports below the require resolve against the
407
358
  // freshly registered modules, so the re-executed Page evaluates with the new code.
408
359
  if (this.applyPatchBatch(session, payload.patches)) {
@@ -8,8 +8,7 @@ type WeChatGlobal = object
8
8
  /** The App-global Rolldown dev runtime; present only in wx development builds. */
9
9
  declare const __rolldown_runtime__:
10
10
  | {
11
- connectTaro(current: object, document: object, injectPageInstance: (...args: unknown[]) => unknown): void
12
- injectPageHmr(config: object, route: string): void
11
+ injectPageHmr(config: object): object
13
12
  }
14
13
  | undefined
15
14
 
@@ -1,3 +0,0 @@
1
- import { type PluginObj } from '@babel/core';
2
- /** Wraps System.register as an inert CommonJS capsule tuple with canonical final dependency IDs. */
3
- export declare function wrapCapsulePlugin(fileName: string): PluginObj;
@@ -1,64 +0,0 @@
1
- import { types } from '@babel/core';
2
- import { resolveLogicalChunkReference } from '../chunk-path.js';
3
- /** Wraps System.register as an inert CommonJS capsule tuple with canonical final dependency IDs. */
4
- export function wrapCapsulePlugin(fileName) {
5
- return {
6
- name: 'vpt:wrap-capsule',
7
- visitor: {},
8
- post(file) {
9
- const program = file.ast.program;
10
- const [statement] = program.body;
11
- const registration = statement && types.isExpressionStatement(statement) ? statement.expression : undefined;
12
- if (program.body.length !== 1 ||
13
- !types.isCallExpression(registration) ||
14
- !types.isMemberExpression(registration.callee) ||
15
- registration.callee.computed ||
16
- !types.isIdentifier(registration.callee.object, { name: 'System' }) ||
17
- !types.isIdentifier(registration.callee.property, { name: 'register' })) {
18
- throw new Error(`Expected one anonymous System.register call in ${fileName}`);
19
- }
20
- const [dependencies, declaration] = registration.arguments;
21
- if (registration.arguments.length !== 2 ||
22
- !types.isArrayExpression(dependencies) ||
23
- !types.isFunctionExpression(declaration)) {
24
- throw new Error(`Expected System.register(dependencies, declaration) in ${fileName}`);
25
- }
26
- dependencies.elements.forEach((dependency) => {
27
- canonicalizeStaticReference(dependency, fileName);
28
- });
29
- const context = declaration.params[1];
30
- if (types.isIdentifier(context)) {
31
- file.path.traverse({
32
- CallExpression(callPath) {
33
- const callee = callPath.node.callee;
34
- if (!types.isMemberExpression(callee) ||
35
- callee.computed ||
36
- !types.isIdentifier(callee.object, { name: context.name }) ||
37
- !types.isIdentifier(callee.property, { name: 'import' })) {
38
- return;
39
- }
40
- const [dependency] = callPath.node.arguments;
41
- canonicalizeDynamicReference(dependency, fileName);
42
- }
43
- });
44
- }
45
- program.directives = [];
46
- program.body = [
47
- types.expressionStatement(types.assignmentExpression('=', types.memberExpression(types.identifier('module'), types.identifier('exports')), types.arrayExpression([dependencies, declaration])))
48
- ];
49
- }
50
- };
51
- }
52
- /** Resolves one generated static reference while the final importing chunk filename is known. */
53
- function canonicalizeStaticReference(reference, fileName) {
54
- if (!types.isStringLiteral(reference)) {
55
- throw new Error(`Expected a literal System.register dependency in ${fileName}`);
56
- }
57
- reference.value = resolveLogicalChunkReference(fileName, reference.value);
58
- }
59
- /** Resolves application literals while preserving runtime-computed IDs injected by the development runtime. */
60
- function canonicalizeDynamicReference(reference, fileName) {
61
- if (types.isStringLiteral(reference) && (reference.value.startsWith('./') || reference.value.startsWith('../'))) {
62
- reference.value = resolveLogicalChunkReference(fileName, reference.value);
63
- }
64
- }
@@ -1,86 +0,0 @@
1
- import { type PluginObj, types } from '@babel/core'
2
- import { resolveLogicalChunkReference } from '../chunk-path.ts'
3
-
4
- /** Wraps System.register as an inert CommonJS capsule tuple with canonical final dependency IDs. */
5
- export function wrapCapsulePlugin(fileName: string): PluginObj {
6
- return {
7
- name: 'vpt:wrap-capsule',
8
- visitor: {},
9
-
10
- post(file) {
11
- const program = file.ast.program
12
- const [statement] = program.body
13
- const registration = statement && types.isExpressionStatement(statement) ? statement.expression : undefined
14
-
15
- if (
16
- program.body.length !== 1 ||
17
- !types.isCallExpression(registration) ||
18
- !types.isMemberExpression(registration.callee) ||
19
- registration.callee.computed ||
20
- !types.isIdentifier(registration.callee.object, { name: 'System' }) ||
21
- !types.isIdentifier(registration.callee.property, { name: 'register' })
22
- ) {
23
- throw new Error(`Expected one anonymous System.register call in ${fileName}`)
24
- }
25
-
26
- const [dependencies, declaration] = registration.arguments
27
- if (
28
- registration.arguments.length !== 2 ||
29
- !types.isArrayExpression(dependencies) ||
30
- !types.isFunctionExpression(declaration)
31
- ) {
32
- throw new Error(`Expected System.register(dependencies, declaration) in ${fileName}`)
33
- }
34
-
35
- dependencies.elements.forEach((dependency) => {
36
- canonicalizeStaticReference(dependency, fileName)
37
- })
38
-
39
- const context = declaration.params[1]
40
- if (types.isIdentifier(context)) {
41
- file.path.traverse({
42
- CallExpression(callPath) {
43
- const callee = callPath.node.callee
44
- if (
45
- !types.isMemberExpression(callee) ||
46
- callee.computed ||
47
- !types.isIdentifier(callee.object, { name: context.name }) ||
48
- !types.isIdentifier(callee.property, { name: 'import' })
49
- ) {
50
- return
51
- }
52
-
53
- const [dependency] = callPath.node.arguments
54
- canonicalizeDynamicReference(dependency, fileName)
55
- }
56
- })
57
- }
58
-
59
- program.directives = []
60
- program.body = [
61
- types.expressionStatement(
62
- types.assignmentExpression(
63
- '=',
64
- types.memberExpression(types.identifier('module'), types.identifier('exports')),
65
- types.arrayExpression([dependencies, declaration])
66
- )
67
- )
68
- ]
69
- }
70
- }
71
- }
72
-
73
- /** Resolves one generated static reference while the final importing chunk filename is known. */
74
- function canonicalizeStaticReference(reference: types.Node | null | undefined, fileName: string): void {
75
- if (!types.isStringLiteral(reference)) {
76
- throw new Error(`Expected a literal System.register dependency in ${fileName}`)
77
- }
78
- reference.value = resolveLogicalChunkReference(fileName, reference.value)
79
- }
80
-
81
- /** Resolves application literals while preserving runtime-computed IDs injected by the development runtime. */
82
- function canonicalizeDynamicReference(reference: types.Node | null | undefined, fileName: string): void {
83
- if (types.isStringLiteral(reference) && (reference.value.startsWith('./') || reference.value.startsWith('../'))) {
84
- reference.value = resolveLogicalChunkReference(fileName, reference.value)
85
- }
86
- }