vite-plugin-taro 0.3.2 → 0.4.0
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/README.en.md +44 -0
- package/README.md +22 -497
- package/client.d.ts +9 -0
- package/dist/node/plugins/client/client-taro.d.ts +4 -0
- package/dist/node/plugins/client/client-taro.js +19 -0
- package/dist/node/plugins/client/constant.d.ts +4 -0
- package/dist/node/plugins/client/constant.js +4 -0
- package/dist/node/plugins/conditional/conditional-directives.d.ts +4 -0
- package/dist/node/plugins/{conditional-directives.js → conditional/conditional-directives.js} +27 -11
- package/dist/node/plugins/css/plugins.d.ts +4 -0
- package/dist/node/plugins/css/plugins.js +84 -0
- package/dist/node/plugins/h5/constant.d.ts +2 -0
- package/dist/node/plugins/h5/constant.js +3 -0
- package/dist/node/plugins/h5/plugins.d.ts +4 -0
- package/dist/node/plugins/h5/plugins.js +161 -0
- package/dist/node/plugins/h5/resolver/module-resolver.d.ts +14 -0
- package/dist/node/plugins/h5/resolver/module-resolver.js +19 -0
- package/dist/node/plugins/h5/transform-app.d.ts +10 -0
- package/dist/node/plugins/h5/transform-app.js +48 -0
- package/dist/node/plugins/wx/dev/dev-host.d.ts +15 -0
- package/dist/node/plugins/wx/dev/dev-host.js +352 -0
- package/dist/node/plugins/wx/dev/hmr-files.d.ts +28 -0
- package/dist/node/plugins/wx/dev/hmr-files.js +34 -0
- package/dist/node/plugins/wx/dev/patch-publisher.d.ts +22 -0
- package/dist/node/plugins/wx/dev/patch-publisher.js +40 -0
- package/dist/node/plugins/wx/dev/plugin.d.ts +7 -0
- package/dist/node/plugins/wx/dev/plugin.js +73 -0
- package/dist/node/plugins/wx/dev/react-refresh.d.ts +20 -0
- package/dist/node/plugins/wx/dev/react-refresh.js +198 -0
- package/dist/node/plugins/wx/module.d.ts +45 -0
- package/dist/node/plugins/wx/module.js +66 -0
- package/dist/node/plugins/wx/native/compile-native-component-interface.d.ts +21 -0
- package/dist/node/plugins/wx/native/compile-native-component-interface.js +29 -0
- package/dist/node/plugins/wx/native/create-native-component-output.d.ts +15 -0
- package/dist/node/plugins/wx/native/create-native-component-output.js +39 -0
- package/dist/node/plugins/wx/native/native-component-assets.d.ts +26 -0
- package/dist/node/plugins/wx/native/native-component-assets.js +76 -0
- package/dist/node/plugins/wx/native/native-component-interface.d.ts +12 -0
- package/dist/node/plugins/wx/native/native-component-interface.js +201 -0
- package/dist/node/plugins/wx/output/files.d.ts +12 -0
- package/dist/node/plugins/wx/output/files.js +12 -0
- package/dist/node/plugins/wx/output/json.d.ts +14 -0
- package/dist/node/plugins/wx/output/json.js +52 -0
- package/dist/node/plugins/wx/output/relative-root.d.ts +2 -0
- package/dist/node/plugins/wx/output/relative-root.js +6 -0
- package/dist/node/plugins/wx/output/templates.d.ts +7 -0
- package/dist/node/plugins/wx/output/templates.js +100 -0
- package/dist/node/plugins/wx/placement/placer.d.ts +78 -0
- package/dist/node/plugins/wx/placement/placer.js +145 -0
- package/dist/node/plugins/wx/placement/plan.d.ts +46 -0
- package/dist/node/plugins/wx/placement/plan.js +210 -0
- package/dist/node/plugins/wx/plugins.d.ts +4 -0
- package/dist/node/plugins/wx/plugins.js +137 -0
- package/dist/node/plugins/wx/render/capsule-wrapper.d.ts +3 -0
- package/dist/node/plugins/wx/render/capsule-wrapper.js +64 -0
- package/dist/node/plugins/wx/render/capsule.d.ts +4 -0
- package/dist/node/plugins/wx/render/capsule.js +13 -0
- package/dist/node/plugins/wx/render/native.d.ts +9 -0
- package/dist/node/plugins/wx/render/native.js +45 -0
- package/dist/node/plugins/wx/render/transport.d.ts +17 -0
- package/dist/node/plugins/wx/render/transport.js +94 -0
- package/dist/node/plugins/wx/resolve/resolver.d.ts +7 -0
- package/dist/node/plugins/wx/resolve/resolver.js +86 -0
- package/dist/node/plugins/wx/resolve/specialize-bootstrap.d.ts +9 -0
- package/dist/node/plugins/wx/resolve/specialize-bootstrap.js +9 -0
- package/dist/node/plugins/wx/resolve/specialize-page-capsule.d.ts +9 -0
- package/dist/node/plugins/wx/resolve/specialize-page-capsule.js +11 -0
- package/dist/node/utils/constant.d.ts +1 -0
- package/dist/node/utils/constant.js +1 -0
- package/dist/node/utils/memoize.d.ts +122 -0
- package/dist/node/utils/memoize.js +86 -0
- package/dist/node/utils/modules.d.ts +20 -24
- package/dist/node/utils/modules.js +21 -34
- package/dist/node/utils/once.d.ts +10 -0
- package/dist/node/utils/once.js +20 -0
- package/dist/node/utils/packages.d.ts +1 -0
- package/dist/node/utils/packages.js +1 -1
- package/dist/node/utils/project-config.d.ts +3 -0
- package/dist/node/utils/project-config.js +8 -0
- package/dist/node/utils/serialized-task-queue.d.ts +9 -0
- package/dist/node/utils/serialized-task-queue.js +17 -0
- package/dist/node/utils/transform.d.ts +11 -0
- package/dist/node/utils/transform.js +58 -0
- package/dist/node/vite-plugin.d.ts +1 -1
- package/dist/node/vite-plugin.js +11 -27
- package/dist/options.d.ts +3 -4
- package/dist/runtime/{taro → client/taro}/api.d.ts +0 -1
- package/dist/runtime/client/taro/api.js +9 -0
- package/dist/runtime/client/taro/component.d.ts +1 -0
- package/dist/runtime/client/taro/component.js +1 -0
- package/dist/runtime/client/taro/define-native-component.d.ts +7 -0
- package/dist/runtime/client/taro/define-native-component.js +4 -0
- package/dist/runtime/h5/app.d.ts +2 -0
- package/dist/runtime/h5/app.js +15 -0
- package/dist/runtime/h5/taro-runtime.d.ts +1 -1
- package/dist/runtime/h5/taro-runtime.js +1 -4
- package/dist/runtime/wx/amphibious/bootstrap.d.ts +4 -0
- package/dist/runtime/wx/amphibious/bootstrap.js +16 -0
- package/dist/runtime/wx/amphibious/transport.d.ts +2 -0
- package/dist/runtime/wx/amphibious/transport.js +4 -0
- package/dist/runtime/wx/capsule/app.d.ts +2 -0
- package/dist/runtime/wx/capsule/app.js +7 -0
- package/dist/runtime/wx/capsule/component.d.ts +3 -0
- package/dist/runtime/wx/capsule/component.js +4 -0
- package/dist/runtime/wx/capsule/page.d.ts +3 -0
- package/dist/runtime/wx/capsule/page.js +68 -0
- package/dist/runtime/wx/capsule/taro-runtime.d.ts +6 -0
- package/dist/runtime/wx/capsule/taro-runtime.js +6 -0
- package/dist/runtime/wx/dev/dev-runtime.d.ts +1 -0
- package/dist/runtime/wx/dev/dev-runtime.js +246 -0
- package/dist/runtime/wx/native/app.d.ts +1 -0
- package/dist/runtime/wx/native/app.js +3 -0
- package/dist/runtime/wx/native/component.d.ts +1 -0
- package/dist/runtime/wx/native/component.js +3 -0
- package/dist/runtime/wx/native/page.d.ts +1 -0
- package/dist/runtime/wx/native/page.js +4 -0
- package/dist/runtime/wx/systemjs/system-core.d.ts +4 -0
- package/dist/runtime/wx/systemjs/system-core.js +331 -0
- package/package.json +21 -14
- package/src/node/plugins/client/client-taro.ts +23 -0
- package/src/node/plugins/client/constant.ts +5 -0
- package/src/node/plugins/{conditional-directives.ts → conditional/conditional-directives.ts} +33 -13
- package/src/node/plugins/css/plugins.ts +96 -0
- package/src/node/plugins/h5/constant.ts +4 -0
- package/src/node/plugins/h5/plugins.ts +197 -0
- package/src/node/plugins/h5/resolver/module-resolver.ts +32 -0
- package/src/node/plugins/h5/transform-app.ts +90 -0
- package/src/node/plugins/wx/dev/dev-host.ts +448 -0
- package/src/node/plugins/wx/dev/hmr-files.ts +55 -0
- package/src/node/plugins/wx/dev/patch-publisher.ts +49 -0
- package/src/node/plugins/wx/dev/plugin.ts +82 -0
- package/src/node/plugins/wx/dev/react-refresh.ts +227 -0
- package/src/node/plugins/wx/module.ts +97 -0
- package/src/node/plugins/wx/native/compile-native-component-interface.ts +47 -0
- package/src/node/plugins/wx/native/create-native-component-output.ts +57 -0
- package/src/node/plugins/wx/native/native-component-assets.ts +114 -0
- package/src/node/plugins/wx/native/native-component-interface.ts +265 -0
- package/src/node/plugins/wx/output/files.ts +27 -0
- package/src/node/plugins/wx/output/json.ts +79 -0
- package/src/node/plugins/wx/output/relative-root.ts +7 -0
- package/src/node/plugins/wx/output/templates.ts +141 -0
- package/src/node/plugins/wx/placement/placer.ts +172 -0
- package/src/node/plugins/wx/placement/plan.ts +306 -0
- package/src/node/plugins/wx/plugins.ts +165 -0
- package/src/node/plugins/wx/render/capsule-wrapper.ts +86 -0
- package/src/node/plugins/wx/render/capsule.ts +21 -0
- package/src/node/plugins/wx/render/native.ts +84 -0
- package/src/node/plugins/wx/render/transport.ts +157 -0
- package/src/node/plugins/wx/resolve/resolver.ts +125 -0
- package/src/node/plugins/wx/resolve/specialize-bootstrap.ts +27 -0
- package/src/node/plugins/wx/resolve/specialize-page-capsule.ts +29 -0
- package/src/node/utils/constant.ts +1 -0
- package/src/node/utils/memoize.ts +149 -0
- package/src/node/utils/modules.ts +36 -38
- package/src/node/utils/once.ts +21 -0
- package/src/node/utils/packages.ts +1 -1
- package/src/node/utils/project-config.ts +10 -0
- package/src/node/utils/serialized-task-queue.ts +20 -0
- package/src/node/utils/transform.ts +82 -0
- package/src/node/vite-plugin.ts +12 -32
- package/src/options.ts +3 -4
- package/src/runtime/client/taro/api.ts +11 -0
- package/src/runtime/client/taro/component.ts +1 -0
- package/src/runtime/client/taro/define-native-component.ts +15 -0
- package/src/runtime/h5/app.ts +25 -0
- package/src/runtime/h5/taro-runtime.ts +1 -4
- package/src/runtime/wx/amphibious/bootstrap.ts +22 -0
- package/src/runtime/wx/amphibious/transport.ts +10 -0
- package/src/runtime/wx/capsule/app.ts +9 -0
- package/src/runtime/wx/capsule/component.ts +6 -0
- package/src/runtime/wx/capsule/page.ts +96 -0
- package/src/runtime/wx/capsule/taro-runtime.ts +14 -0
- package/src/runtime/wx/dev/dev-runtime.ts +317 -0
- package/src/runtime/wx/native/app.ts +4 -0
- package/src/runtime/wx/native/component.ts +4 -0
- package/src/runtime/wx/native/page.ts +6 -0
- package/src/runtime/wx/systemjs/LICENSE +10 -0
- package/src/runtime/wx/systemjs/system-core.js +370 -0
- package/src/runtime/wx/systemjs/system.d.ts +55 -0
- package/src/runtime/wx/wechat.d.ts +52 -0
- package/README.zh.md +0 -521
- package/dist/node/build-context.d.ts +0 -25
- package/dist/node/build-context.js +0 -47
- package/dist/node/css/css-pipeline.d.ts +0 -35
- package/dist/node/css/css-pipeline.js +0 -154
- package/dist/node/plugins/conditional-directives.d.ts +0 -3
- package/dist/node/plugins/taro-runtime.d.ts +0 -5
- package/dist/node/plugins/taro-runtime.js +0 -18
- package/dist/node/targets/h5/plugin.d.ts +0 -6
- package/dist/node/targets/h5/plugin.js +0 -117
- package/dist/node/targets/h5/virtual-modules.d.ts +0 -5
- package/dist/node/targets/h5/virtual-modules.js +0 -60
- package/dist/node/targets/wx/companion-assets.d.ts +0 -19
- package/dist/node/targets/wx/companion-assets.js +0 -129
- package/dist/node/targets/wx/dev-server/development-session.d.ts +0 -32
- package/dist/node/targets/wx/dev-server/development-session.js +0 -215
- package/dist/node/targets/wx/dev-server/full-build-scheduler.d.ts +0 -14
- package/dist/node/targets/wx/dev-server/full-build-scheduler.js +0 -60
- package/dist/node/targets/wx/dev-server/js-utils.d.ts +0 -5
- package/dist/node/targets/wx/dev-server/js-utils.js +0 -28
- package/dist/node/targets/wx/dev-server/output.d.ts +0 -19
- package/dist/node/targets/wx/dev-server/output.js +0 -44
- package/dist/node/targets/wx/dev-server/rolldown-runtime-source.d.ts +0 -8
- package/dist/node/targets/wx/dev-server/rolldown-runtime-source.js +0 -95
- package/dist/node/targets/wx/dev-server/update-server-state.d.ts +0 -65
- package/dist/node/targets/wx/dev-server/update-server-state.js +0 -116
- package/dist/node/targets/wx/dev-server/update-transport.d.ts +0 -28
- package/dist/node/targets/wx/dev-server/update-transport.js +0 -212
- package/dist/node/targets/wx/dev-server/vite-bundled-dev-adapter.d.ts +0 -44
- package/dist/node/targets/wx/dev-server/vite-bundled-dev-adapter.js +0 -145
- package/dist/node/targets/wx/development-files.d.ts +0 -8
- package/dist/node/targets/wx/development-files.js +0 -8
- package/dist/node/targets/wx/plugin.d.ts +0 -6
- package/dist/node/targets/wx/plugin.js +0 -144
- package/dist/node/targets/wx/react-refresh.d.ts +0 -4
- package/dist/node/targets/wx/react-refresh.js +0 -38
- package/dist/node/targets/wx/virtual-modules.d.ts +0 -16
- package/dist/node/targets/wx/virtual-modules.js +0 -120
- package/dist/node/utils/async.d.ts +0 -8
- package/dist/node/utils/async.js +0 -16
- package/dist/node/utils/filesystem.d.ts +0 -13
- package/dist/node/utils/filesystem.js +0 -43
- package/dist/runtime/taro/api.js +0 -11
- package/dist/runtime/taro/components.d.ts +0 -2
- package/dist/runtime/taro/components.js +0 -2
- package/dist/runtime/wx/page-update.d.ts +0 -6
- package/dist/runtime/wx/page-update.js +0 -157
- package/dist/runtime/wx/taro-runtime.d.ts +0 -5
- package/dist/runtime/wx/taro-runtime.js +0 -6
- package/dist/runtime/wx/update-client-state.d.ts +0 -68
- package/dist/runtime/wx/update-client-state.js +0 -84
- package/dist/runtime/wx/update-client.d.ts +0 -1
- package/dist/runtime/wx/update-client.js +0 -171
- package/src/node/build-context.ts +0 -62
- package/src/node/css/css-pipeline.ts +0 -171
- package/src/node/plugins/taro-runtime.ts +0 -22
- package/src/node/targets/h5/plugin.ts +0 -135
- package/src/node/targets/h5/virtual-modules.ts +0 -71
- package/src/node/targets/wx/companion-assets.ts +0 -174
- package/src/node/targets/wx/dev-server/development-session.ts +0 -271
- package/src/node/targets/wx/dev-server/full-build-scheduler.ts +0 -62
- package/src/node/targets/wx/dev-server/js-utils.ts +0 -33
- package/src/node/targets/wx/dev-server/output.ts +0 -56
- package/src/node/targets/wx/dev-server/rolldown-runtime-source.ts +0 -95
- package/src/node/targets/wx/dev-server/update-server-state.ts +0 -183
- package/src/node/targets/wx/dev-server/update-transport.ts +0 -261
- package/src/node/targets/wx/dev-server/vite-bundled-dev-adapter.ts +0 -203
- package/src/node/targets/wx/development-files.ts +0 -11
- package/src/node/targets/wx/plugin.ts +0 -164
- package/src/node/targets/wx/react-refresh.ts +0 -51
- package/src/node/targets/wx/virtual-modules.ts +0 -152
- package/src/node/utils/async.ts +0 -19
- package/src/node/utils/filesystem.ts +0 -45
- package/src/runtime/taro/api.ts +0 -13
- package/src/runtime/taro/components.ts +0 -2
- package/src/runtime/wx/page-update.ts +0 -230
- package/src/runtime/wx/react-refresh.d.ts +0 -20
- package/src/runtime/wx/taro-runtime.ts +0 -7
- package/src/runtime/wx/update-client-state.ts +0 -138
- package/src/runtime/wx/update-client.ts +0 -223
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { types } from '@babel/core';
|
|
2
|
+
import { memoize } from '../../../utils/memoize.js';
|
|
3
|
+
import { transformWithBabel } from '../../../utils/transform.js';
|
|
4
|
+
/** The React DevTools hook protocol name; free references must target `global` in wx. */
|
|
5
|
+
const reactDevtoolsHookProtocol = '__REACT_DEVTOOLS_GLOBAL_HOOK__';
|
|
6
|
+
/**
|
|
7
|
+
* Creates the serve-only React Refresh adaptation transforms for the wx target.
|
|
8
|
+
*
|
|
9
|
+
* @vitejs/plugin-react's generated refresh code assumes the web HTML preamble and a browser
|
|
10
|
+
* global scope; wx has neither. Each transform adapts one piece of that contract:
|
|
11
|
+
* - the refresh runtime module (id-filtered): the vendored runtime reads and assigns
|
|
12
|
+
* `window` protocol globals (rewritten to `global`) and must inject itself at evaluation
|
|
13
|
+
* — the preamble's `injectIntoGlobalHook` call has no HTML home in wx;
|
|
14
|
+
* - react-family modules (filtered on free references): the DevTools hook is read as a free
|
|
15
|
+
* variable, which the WeChat runtime scope never resolves against `global` — every free
|
|
16
|
+
* reference becomes an explicit member access;
|
|
17
|
+
* - boundary modules (filtered on the guard): the preamble's `$RefreshReg$` global is not
|
|
18
|
+
* needed because the transform generates local wrappers over the imported refresh
|
|
19
|
+
* runtime, so the guard that checks for the global is removed.
|
|
20
|
+
*
|
|
21
|
+
* Each transform's filter is its routing: the three domains are disjoint, so a module is
|
|
22
|
+
* transformed by at most one of them, and modules outside all three never reach a handler.
|
|
23
|
+
*/
|
|
24
|
+
export function createWxReactRefreshTransforms() {
|
|
25
|
+
return [
|
|
26
|
+
{
|
|
27
|
+
name: 'vpt:wx-react-refresh-runtime',
|
|
28
|
+
apply: 'serve',
|
|
29
|
+
transform: {
|
|
30
|
+
order: 'post',
|
|
31
|
+
// The vendored refresh runtime module; id-filtered, so no code scan.
|
|
32
|
+
filter: { id: /^\/@react-refresh(?:\?|$)/ },
|
|
33
|
+
handler(code, id) {
|
|
34
|
+
return fixRefreshRuntime({ code, id });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'vpt:wx-react-devtools-hook',
|
|
40
|
+
apply: 'serve',
|
|
41
|
+
transform: {
|
|
42
|
+
order: 'post',
|
|
43
|
+
// Matches only free references (react-family modules). The member accesses in
|
|
44
|
+
// the refresh runtime and the dev runtime chunk never match, so they need no
|
|
45
|
+
// id exclusion.
|
|
46
|
+
filter: { code: /(^|[^.\w$])__REACT_DEVTOOLS_GLOBAL_HOOK__/ },
|
|
47
|
+
handler(code, id) {
|
|
48
|
+
return fixReactDevtoolsHook({ code, id });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'vpt:wx-refresh-preamble-guard',
|
|
54
|
+
apply: 'serve',
|
|
55
|
+
transform: {
|
|
56
|
+
order: 'post',
|
|
57
|
+
// Vite's documented refresh protocol global; the generated guard is its only
|
|
58
|
+
// occurrence, in boundary modules.
|
|
59
|
+
filter: { code: /window\.\$RefreshReg\$/ },
|
|
60
|
+
handler(code, id) {
|
|
61
|
+
return transformWithBabel(code, id, [removeRefreshPreambleGuard], false);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* React-family modules: free `__REACT_DEVTOOLS_GLOBAL_HOOK__` reads must target `global`.
|
|
69
|
+
*
|
|
70
|
+
* The renderer checks the hook with `typeof __REACT_DEVTOOLS_GLOBAL_HOOK__` and injects via
|
|
71
|
+
* `hook.inject(...)` — but in the WeChat runtime, free-variable reads never resolve against
|
|
72
|
+
* `global`'s properties (verified: the free lookup is undefined while
|
|
73
|
+
* `global.__REACT_DEVTOOLS_GLOBAL_HOOK__` exists), so the renderer would silently skip
|
|
74
|
+
* injection and React Refresh would have no renderer to schedule re-renders on.
|
|
75
|
+
*
|
|
76
|
+
* The name is unique to the React DevTools protocol, so rewriting every free reference to an
|
|
77
|
+
* explicit member access is precise. The hook itself is created on `global` by the dev
|
|
78
|
+
* runtime chunk (see dev-runtime.ts).
|
|
79
|
+
*/
|
|
80
|
+
function rewriteReactDevtoolsHookGlobal() {
|
|
81
|
+
return {
|
|
82
|
+
name: 'vpt:wx-react-devtools-hook-global',
|
|
83
|
+
visitor: {
|
|
84
|
+
Identifier(identifierPath) {
|
|
85
|
+
const node = identifierPath.node;
|
|
86
|
+
if (!types.isIdentifier(node, { name: reactDevtoolsHookProtocol })) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const parent = identifierPath.parentPath;
|
|
90
|
+
// A member expression property (e.g. `global.__REACT_DEVTOOLS_GLOBAL_HOOK__`)
|
|
91
|
+
// is already explicit and must not be rewritten again.
|
|
92
|
+
if (parent.isMemberExpression() && parent.node.property === node) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
identifierPath.replaceWith(types.memberExpression(types.identifier('global'), types.identifier(node.name)));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Refresh runtime module: self-inject at evaluation — the wx App heap has no HTML preamble.
|
|
102
|
+
*
|
|
103
|
+
* In web Vite, the HTML preamble calls `injectIntoGlobalHook(window)` before any module
|
|
104
|
+
* loads; nothing does that in wx. The call must live in this module itself:
|
|
105
|
+
* - its closure owns the refresh state (helpersByRendererID, mountedRoots), so the same
|
|
106
|
+
* instance that the generated boundary code imports must bootstrap itself;
|
|
107
|
+
* - the dev runtime chunk cannot reach it: the module is in a lazily-loaded chunk that
|
|
108
|
+
* requires the runtime chunk first, so it does not exist when the runtime evaluates.
|
|
109
|
+
*
|
|
110
|
+
* Unlike the preamble's `$RefreshReg$` globals (removed by removeRefreshPreambleGuard
|
|
111
|
+
* because boundary modules define local wrappers), the hook machinery has no local
|
|
112
|
+
* equivalent — without it the refresh runtime never learns the renderer or the mounted
|
|
113
|
+
* roots, so the injection is the one preamble responsibility that must be replicated.
|
|
114
|
+
*
|
|
115
|
+
* Timing is safe because injectIntoGlobalHook replays hook.renderers: the renderer already
|
|
116
|
+
* injected into the hook (created by the dev runtime chunk) when the App mounted, and the
|
|
117
|
+
* replay captures it; the patched commit hooks then track every later mount, including the
|
|
118
|
+
* remounts on re-execution.
|
|
119
|
+
*/
|
|
120
|
+
function injectRefreshGlobalHook() {
|
|
121
|
+
return {
|
|
122
|
+
name: 'vpt:wx-refresh-global-hook-injection',
|
|
123
|
+
visitor: {
|
|
124
|
+
Program(programPath) {
|
|
125
|
+
// The renderer already injected into the hook (created by the dev runtime
|
|
126
|
+
// chunk) when the App mounted; injectIntoGlobalHook replays its renderers.
|
|
127
|
+
programPath.pushContainer('body', types.expressionStatement(types.callExpression(types.identifier('injectIntoGlobalHook'), [types.identifier('global')])));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Refresh runtime module: rewrites the generated `window.<protocol>` accesses to `global`.
|
|
134
|
+
*
|
|
135
|
+
* The vendored refresh runtime is written for browsers and uses `window` for its protocol
|
|
136
|
+
* globals, but the WeChat runtime has no `window` — the free identifier is undefined — so the
|
|
137
|
+
* top-level assignment would throw at module evaluation, and the ignored-exports read
|
|
138
|
+
* inside the refresh validator would crash every update pass.
|
|
139
|
+
*
|
|
140
|
+
* Only the exact known protocol names are rewritten, one by one, so unrelated `window`
|
|
141
|
+
* accesses are never touched and future protocol additions are deliberate.
|
|
142
|
+
*/
|
|
143
|
+
function rewriteRefreshRuntimeWindowAccess() {
|
|
144
|
+
/**
|
|
145
|
+
* Refresh protocol globals that must land on the WeChat `global`:
|
|
146
|
+
* - `__registerBeforePerformReactRefresh`: assigned at module scope; in web, the HMR
|
|
147
|
+
* client registers pre-refresh callbacks through it — the assignment throws on
|
|
148
|
+
* undefined `window`;
|
|
149
|
+
* - `__getReactRefreshIgnoredExports`: read in validateRefreshBoundaryAndEnqueueUpdate
|
|
150
|
+
* as an optional extension point — a read on undefined `window` crashes.
|
|
151
|
+
*/
|
|
152
|
+
const refreshRuntimeWindowGlobals = ['__registerBeforePerformReactRefresh', '__getReactRefreshIgnoredExports'];
|
|
153
|
+
return {
|
|
154
|
+
name: 'vpt:wx-refresh-runtime-window-access',
|
|
155
|
+
visitor: {
|
|
156
|
+
MemberExpression(memberPath) {
|
|
157
|
+
const member = memberPath.node;
|
|
158
|
+
if (!types.isIdentifier(member.object, { name: 'window' }) ||
|
|
159
|
+
!types.isIdentifier(member.property) ||
|
|
160
|
+
!refreshRuntimeWindowGlobals.includes(member.property.name)) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// `global` is the WeChat global object — the same one the hook injection
|
|
164
|
+
// and the rest of the wx glue speak — so the protocol globals land on the
|
|
165
|
+
// App heap like any other global hook.
|
|
166
|
+
member.object = types.identifier('global');
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/** Boundary modules: remove the generated `if (!window.$RefreshReg$) throw Error(...)` guard. */
|
|
172
|
+
function removeRefreshPreambleGuard() {
|
|
173
|
+
return {
|
|
174
|
+
name: 'vpt:wx-refresh-preamble-guard',
|
|
175
|
+
visitor: {
|
|
176
|
+
IfStatement(ifPath) {
|
|
177
|
+
// The guard is a web-only sanity check that the HTML preamble installed the
|
|
178
|
+
// `$RefreshReg$` global. wx has no preamble and no such global — but the
|
|
179
|
+
// boundary module does not need it: the plugin transform generates local
|
|
180
|
+
// `$RefreshReg$`/`$RefreshSig$` wrappers that delegate to the imported
|
|
181
|
+
// refresh runtime, so registration works without the global. The guard
|
|
182
|
+
// itself only crashes on the undefined `window`, so it is removed.
|
|
183
|
+
const test = ifPath.node.test;
|
|
184
|
+
if (types.isUnaryExpression(test, { operator: '!' }) &&
|
|
185
|
+
types.isMemberExpression(test.argument) &&
|
|
186
|
+
types.isIdentifier(test.argument.object, { name: 'window' }) &&
|
|
187
|
+
types.isIdentifier(test.argument.property, { name: '$RefreshReg$' })) {
|
|
188
|
+
ifPath.remove();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
// The refresh runtime module and the react-family modules are immutable for the server's
|
|
195
|
+
// lifetime (they only change when the plugin is rebuilt), so their Babel transforms run once
|
|
196
|
+
// per module and every build reuses the output.
|
|
197
|
+
const fixRefreshRuntime = memoize(({ code, id }) => transformWithBabel(code, id, [rewriteRefreshRuntimeWindowAccess, injectRefreshGlobalHook], false), { getCacheKey: ({ code }) => code });
|
|
198
|
+
const fixReactDevtoolsHook = memoize(({ code, id }) => transformWithBabel(code, id, [rewriteReactDevtoolsHookGlobal], false), { getCacheKey: ({ code }) => code });
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Rolldown } from 'vite';
|
|
2
|
+
/** Identifies Rolldown's generated helper module independently of its unstable output filename. */
|
|
3
|
+
export declare const rolldownRuntimeId = "\0rolldown/runtime.js";
|
|
4
|
+
/** Resolves the direct React Reconciler dependency without assuming pnpm's layout. */
|
|
5
|
+
export declare const reactReconcilerRoot: string;
|
|
6
|
+
/** Identifies the amphibious bootstrap that initializes SystemJS and serves every native shell. */
|
|
7
|
+
export declare const bootstrapPath: string;
|
|
8
|
+
/** Identifies the native transport source materialized before Rolldown finalizes content hashes. */
|
|
9
|
+
export declare const transportPath: string;
|
|
10
|
+
/** Redirects Vite's injected browser preload helper to the bootstrap identity loader. */
|
|
11
|
+
export declare const vitePreloadId = "\0vite/preload-helper.js";
|
|
12
|
+
/** Forces the native App shell entry to emit at WeChat's required root path. */
|
|
13
|
+
export declare const appShellFileName = "app.js";
|
|
14
|
+
/** Identifies the synchronous native App shell source. */
|
|
15
|
+
export declare const appShellPath: string;
|
|
16
|
+
/** Identifies the App capsule kept behind the native shell boundary. */
|
|
17
|
+
export declare const appCapsulePath: string;
|
|
18
|
+
/** Forces Taro's recursive native Component entry to emit at its configured root path. */
|
|
19
|
+
export declare const componentShellFileName = "comp.js";
|
|
20
|
+
/** Identifies the synchronous recursive Component shell source. */
|
|
21
|
+
export declare const componentShellPath: string;
|
|
22
|
+
/** Identifies the recursive Component capsule kept behind the native shell boundary. */
|
|
23
|
+
export declare const componentCapsulePath: string;
|
|
24
|
+
/** Resolves the configured Page component from its route-qualified capsule importer. */
|
|
25
|
+
export declare const pageComponentId = "\0vpt:page-component";
|
|
26
|
+
/** Gives every Page shell one private capsule target that can be resolved using its route. */
|
|
27
|
+
export declare const pageCapsuleId = "\0vpt:page-capsule";
|
|
28
|
+
/** Provides the Page capsule source specialized through a stable route query. */
|
|
29
|
+
export declare const pageCapsulePath: string;
|
|
30
|
+
/** Identifies the reusable synchronous native Page shell source. */
|
|
31
|
+
export declare const pageShellPath: string;
|
|
32
|
+
export type WxChunk = Rolldown.PreRenderedChunk | Rolldown.RenderedChunk;
|
|
33
|
+
/** Build-graph role of an explicit native lifecycle entry. */
|
|
34
|
+
export type WxEntryRole = 'shell' | 'capsule';
|
|
35
|
+
/** Runtime domain in which one final wx JavaScript chunk executes. */
|
|
36
|
+
export type WxExecutionKind = 'native' | 'capsule' | 'amphibious';
|
|
37
|
+
/** Returns the one explicit lifecycle role owned by a chunk. */
|
|
38
|
+
export declare function getWxEntryRole(chunk: WxChunk): WxEntryRole | undefined;
|
|
39
|
+
/** Tests whether a chunk contains the physical transport implementation. */
|
|
40
|
+
export declare function isTransportModule(chunk: WxChunk): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Classifies one final output chunk by execution domain. Entry role is deliberately independent: explicit capsule entries
|
|
43
|
+
* normally fall through to capsule rendering, but a capsule containing an amphibious runtime executes in both domains.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getWxExecutionKind(chunk: WxChunk): WxExecutionKind;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { normalizeModuleId } from '../../utils/modules.js';
|
|
3
|
+
import { packageRequire, resolvePackageFile } from '../../utils/packages.js';
|
|
4
|
+
/** Identifies Rolldown's generated helper module independently of its unstable output filename. */
|
|
5
|
+
export const rolldownRuntimeId = '\0rolldown/runtime.js';
|
|
6
|
+
/** Resolves the direct React Reconciler dependency without assuming pnpm's layout. */
|
|
7
|
+
export const reactReconcilerRoot = normalizeModuleId(path.dirname(packageRequire.resolve('react-reconciler/package.json')));
|
|
8
|
+
/** Identifies the amphibious bootstrap that initializes SystemJS and serves every native shell. */
|
|
9
|
+
export const bootstrapPath = resolvePackageFile('dist/runtime/wx/amphibious/bootstrap.js');
|
|
10
|
+
/** Identifies the native transport source materialized before Rolldown finalizes content hashes. */
|
|
11
|
+
export const transportPath = resolvePackageFile('dist/runtime/wx/amphibious/transport.js');
|
|
12
|
+
/** Redirects Vite's injected browser preload helper to the bootstrap identity loader. */
|
|
13
|
+
export const vitePreloadId = '\0vite/preload-helper.js';
|
|
14
|
+
/** Forces the native App shell entry to emit at WeChat's required root path. */
|
|
15
|
+
export const appShellFileName = 'app.js';
|
|
16
|
+
/** Identifies the synchronous native App shell source. */
|
|
17
|
+
export const appShellPath = resolvePackageFile('dist/runtime/wx/native/app.js');
|
|
18
|
+
/** Identifies the App capsule kept behind the native shell boundary. */
|
|
19
|
+
export const appCapsulePath = resolvePackageFile('dist/runtime/wx/capsule/app.js');
|
|
20
|
+
/** Forces Taro's recursive native Component entry to emit at its configured root path. */
|
|
21
|
+
export const componentShellFileName = 'comp.js';
|
|
22
|
+
/** Identifies the synchronous recursive Component shell source. */
|
|
23
|
+
export const componentShellPath = resolvePackageFile('dist/runtime/wx/native/component.js');
|
|
24
|
+
/** Identifies the recursive Component capsule kept behind the native shell boundary. */
|
|
25
|
+
export const componentCapsulePath = resolvePackageFile('dist/runtime/wx/capsule/component.js');
|
|
26
|
+
/** Resolves the configured Page component from its route-qualified capsule importer. */
|
|
27
|
+
export const pageComponentId = '\0vpt:page-component';
|
|
28
|
+
/** Gives every Page shell one private capsule target that can be resolved using its route. */
|
|
29
|
+
export const pageCapsuleId = '\0vpt:page-capsule';
|
|
30
|
+
/** Provides the Page capsule source specialized through a stable route query. */
|
|
31
|
+
export const pageCapsulePath = resolvePackageFile('dist/runtime/wx/capsule/page.js');
|
|
32
|
+
/** Identifies the reusable synchronous native Page shell source. */
|
|
33
|
+
export const pageShellPath = resolvePackageFile('dist/runtime/wx/native/page.js');
|
|
34
|
+
// These fixed source identities describe entry roles independently from the final execution kind. A capsule entry may,
|
|
35
|
+
// for example, become amphibious when Rolldown coalesces its generated runtime into the same output chunk.
|
|
36
|
+
const shellModuleIds = new Set([appShellPath, componentShellPath, pageShellPath]);
|
|
37
|
+
const capsuleModuleIds = new Set([appCapsulePath, componentCapsulePath, pageCapsulePath]);
|
|
38
|
+
const amphibiousModuleIds = new Set([bootstrapPath, rolldownRuntimeId]);
|
|
39
|
+
/** Returns the one explicit lifecycle role owned by a chunk. */
|
|
40
|
+
export function getWxEntryRole(chunk) {
|
|
41
|
+
const ownsShell = containsModule(chunk, shellModuleIds);
|
|
42
|
+
const ownsCapsule = containsModule(chunk, capsuleModuleIds);
|
|
43
|
+
if (ownsShell && ownsCapsule) {
|
|
44
|
+
throw new Error(`wx chunk mixes shell and capsule entries: ${chunk.moduleIds.join(', ')}`);
|
|
45
|
+
}
|
|
46
|
+
return ownsShell ? 'shell' : ownsCapsule ? 'capsule' : undefined;
|
|
47
|
+
}
|
|
48
|
+
/** Tests whether a chunk contains the physical transport implementation. */
|
|
49
|
+
export function isTransportModule(chunk) {
|
|
50
|
+
return chunk.moduleIds.includes(transportPath);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Classifies one final output chunk by execution domain. Entry role is deliberately independent: explicit capsule entries
|
|
54
|
+
* normally fall through to capsule rendering, but a capsule containing an amphibious runtime executes in both domains.
|
|
55
|
+
*/
|
|
56
|
+
export function getWxExecutionKind(chunk) {
|
|
57
|
+
const entryRole = getWxEntryRole(chunk);
|
|
58
|
+
if (containsModule(chunk, amphibiousModuleIds)) {
|
|
59
|
+
return 'amphibious';
|
|
60
|
+
}
|
|
61
|
+
return entryRole === 'shell' || isTransportModule(chunk) ? 'native' : 'capsule';
|
|
62
|
+
}
|
|
63
|
+
/** Tests normalized chunk module IDs against one fixed identity set. */
|
|
64
|
+
function containsModule(chunk, moduleIds) {
|
|
65
|
+
return chunk.moduleIds.some((moduleId) => moduleIds.has(normalizeModuleId(moduleId)));
|
|
66
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Compiles one JSX interface module and attaches its opaque native sources to Rolldown metadata. */
|
|
2
|
+
export declare function compileNativeComponentInterface({ code, id, sourcemap, addWatchFile }: {
|
|
3
|
+
code: string;
|
|
4
|
+
id: string;
|
|
5
|
+
sourcemap: boolean;
|
|
6
|
+
addWatchFile: (file: string) => void;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
code: string;
|
|
9
|
+
map: import("rolldown").ExistingRawSourceMap | null;
|
|
10
|
+
meta: {
|
|
11
|
+
"vpt:native-components": {
|
|
12
|
+
sources: (import("./native-component-interface.ts").NativeComponentDefinition & {
|
|
13
|
+
assets: readonly {
|
|
14
|
+
relativePath: string;
|
|
15
|
+
byteLength: number;
|
|
16
|
+
}[];
|
|
17
|
+
})[];
|
|
18
|
+
assetBytes: number;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
}>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { normalizeModuleId } from '../../../utils/modules.js';
|
|
3
|
+
import { collectNativeComponentAssets, nativeComponentMetaKey } from './native-component-assets.js';
|
|
4
|
+
import { transformNativeComponentInterfaces } from './native-component-interface.js';
|
|
5
|
+
/** Compiles one JSX interface module and attaches its opaque native sources to Rolldown metadata. */
|
|
6
|
+
export async function compileNativeComponentInterface({ code, id, sourcemap, addWatchFile }) {
|
|
7
|
+
const transformed = transformNativeComponentInterfaces(code, id, sourcemap);
|
|
8
|
+
const interfacePath = normalizeModuleId(id);
|
|
9
|
+
const nativeComponents = await Promise.all(transformed.definitions.map((definition) => collectNativeComponentAssets(definition, interfacePath)));
|
|
10
|
+
nativeComponents.forEach((source) => {
|
|
11
|
+
addWatchFile(source.folder);
|
|
12
|
+
source.assets.forEach((asset) => {
|
|
13
|
+
addWatchFile(path.join(source.folder, asset.relativePath));
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
const assetBytes = nativeComponents.reduce((sourceTotal, source) => {
|
|
17
|
+
return sourceTotal + source.assets.reduce((assetTotal, asset) => assetTotal + asset.byteLength, 0);
|
|
18
|
+
}, 0);
|
|
19
|
+
return {
|
|
20
|
+
code: transformed.code,
|
|
21
|
+
map: transformed.map,
|
|
22
|
+
meta: {
|
|
23
|
+
[nativeComponentMetaKey]: {
|
|
24
|
+
sources: nativeComponents,
|
|
25
|
+
assetBytes
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Rolldown } from 'vite';
|
|
2
|
+
/** Creates opaque native files and their registrations from each surviving JSX interface module. */
|
|
3
|
+
export declare function createNativeComponentOutput({ bundle, getModuleInfo }: {
|
|
4
|
+
bundle: Rolldown.OutputBundle;
|
|
5
|
+
getModuleInfo: (moduleId: string) => {
|
|
6
|
+
meta: Rolldown.CustomPluginOptions;
|
|
7
|
+
} | null;
|
|
8
|
+
}): Promise<{
|
|
9
|
+
files: Rolldown.EmittedAsset[];
|
|
10
|
+
registrations: {
|
|
11
|
+
name: string;
|
|
12
|
+
componentPath: string;
|
|
13
|
+
fields: readonly string[];
|
|
14
|
+
}[];
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { isGeneratedSubpackageFile } from '../placement/plan.js';
|
|
4
|
+
import { getNativeComponentSources } from './native-component-assets.js';
|
|
5
|
+
/** Creates opaque native files and their registrations from each surviving JSX interface module. */
|
|
6
|
+
export async function createNativeComponentOutput({ bundle, getModuleInfo }) {
|
|
7
|
+
// Files and registrations accumulate in final chunk order for deterministic output.
|
|
8
|
+
const files = [];
|
|
9
|
+
const registrations = [];
|
|
10
|
+
for (const output of Object.values(bundle)) {
|
|
11
|
+
if (output.type !== 'chunk') {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
const packageRoot = isGeneratedSubpackageFile(output.fileName)
|
|
15
|
+
? path.posix.dirname(path.posix.dirname(output.fileName))
|
|
16
|
+
: undefined;
|
|
17
|
+
for (const moduleId of output.moduleIds) {
|
|
18
|
+
const sources = getNativeComponentSources(getModuleInfo(moduleId)?.meta);
|
|
19
|
+
for (const source of sources) {
|
|
20
|
+
const name = path.posix.basename(source.folder);
|
|
21
|
+
const componentFolder = path.posix.join('components', name);
|
|
22
|
+
const outputFolder = packageRoot ? path.posix.join(packageRoot, componentFolder) : componentFolder;
|
|
23
|
+
registrations.push({
|
|
24
|
+
name,
|
|
25
|
+
componentPath: `/${path.posix.join(outputFolder, source.entry)}`,
|
|
26
|
+
fields: source.fields
|
|
27
|
+
});
|
|
28
|
+
for (const asset of source.assets) {
|
|
29
|
+
files.push({
|
|
30
|
+
type: 'asset',
|
|
31
|
+
fileName: path.posix.join(outputFolder, asset.relativePath),
|
|
32
|
+
source: await readFile(path.join(source.folder, asset.relativePath))
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return { files, registrations };
|
|
39
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Rolldown } from 'vite';
|
|
2
|
+
import type { NativeComponentDefinition } from './native-component-interface.ts';
|
|
3
|
+
type NativeComponentAsset = {
|
|
4
|
+
relativePath: string;
|
|
5
|
+
byteLength: number;
|
|
6
|
+
};
|
|
7
|
+
export declare const nativeComponentMetaKey = "vpt:native-components";
|
|
8
|
+
type NativeComponentSource = NativeComponentDefinition & {
|
|
9
|
+
assets: readonly NativeComponentAsset[];
|
|
10
|
+
};
|
|
11
|
+
type NativeComponentMetadata = {
|
|
12
|
+
sources: readonly NativeComponentSource[];
|
|
13
|
+
assetBytes: number;
|
|
14
|
+
};
|
|
15
|
+
declare module 'rolldown' {
|
|
16
|
+
interface CustomPluginOptions {
|
|
17
|
+
[nativeComponentMetaKey]?: NativeComponentMetadata;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Reads the native contribution to a transformed module's package weight. */
|
|
21
|
+
export declare function getNativeComponentAssetBytes(meta: Rolldown.CustomPluginOptions | undefined): number;
|
|
22
|
+
/** Reads native sources attached to one transformed JSX interface module. */
|
|
23
|
+
export declare function getNativeComponentSources(meta: Rolldown.CustomPluginOptions | undefined): readonly NativeComponentSource[];
|
|
24
|
+
/** Collects a native component folder as opaque, recursively ordered assets without copying its interface module. */
|
|
25
|
+
export declare function collectNativeComponentAssets(definition: NativeComponentDefinition, interfacePath: string): Promise<NativeComponentSource>;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { readdir, stat } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { normalizeModuleId } from '../../../utils/modules.js';
|
|
4
|
+
export const nativeComponentMetaKey = 'vpt:native-components';
|
|
5
|
+
/** Reads the native contribution to a transformed module's package weight. */
|
|
6
|
+
export function getNativeComponentAssetBytes(meta) {
|
|
7
|
+
return meta?.[nativeComponentMetaKey]?.assetBytes ?? 0;
|
|
8
|
+
}
|
|
9
|
+
/** Reads native sources attached to one transformed JSX interface module. */
|
|
10
|
+
export function getNativeComponentSources(meta) {
|
|
11
|
+
return meta?.[nativeComponentMetaKey]?.sources ?? [];
|
|
12
|
+
}
|
|
13
|
+
/** Collects a native component folder as opaque, recursively ordered assets without copying its interface module. */
|
|
14
|
+
export async function collectNativeComponentAssets(definition, interfacePath) {
|
|
15
|
+
await requireNativeComponentDirectory(definition.folder);
|
|
16
|
+
await requireNativeComponentEntry(definition);
|
|
17
|
+
// This mutable accumulator is local to one traversal and avoids repeatedly copying growing asset arrays.
|
|
18
|
+
const assets = [];
|
|
19
|
+
await collectDirectory(definition.folder, [], assets, normalizeModuleId(interfacePath));
|
|
20
|
+
return { ...definition, assets };
|
|
21
|
+
}
|
|
22
|
+
/** Rejects a missing or non-directory source before Rolldown starts its recursive traversal. */
|
|
23
|
+
async function requireNativeComponentDirectory(folder) {
|
|
24
|
+
try {
|
|
25
|
+
if ((await stat(folder)).isDirectory()) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (Error.isError(error) && 'code' in error && error.code === 'ENOENT') {
|
|
31
|
+
throw new Error(`Native component folder does not exist: ${folder}`, { cause: error });
|
|
32
|
+
}
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`Native component source is not a directory: ${folder}`);
|
|
36
|
+
}
|
|
37
|
+
/** Rejects a missing or non-file JavaScript entry before native output registration. */
|
|
38
|
+
async function requireNativeComponentEntry(definition) {
|
|
39
|
+
const entryPath = path.join(definition.folder, `${definition.entry}.js`);
|
|
40
|
+
try {
|
|
41
|
+
if ((await stat(entryPath)).isFile()) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (Error.isError(error) && 'code' in error && error.code === 'ENOENT') {
|
|
47
|
+
throw new Error(`Native component entry file does not exist: ${entryPath}`, { cause: error });
|
|
48
|
+
}
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
throw new Error(`Native component entry is not a file: ${entryPath}`);
|
|
52
|
+
}
|
|
53
|
+
/** Traverses entries lexically so output remains deterministic across filesystems. */
|
|
54
|
+
async function collectDirectory(folder, segments, assets, interfacePath) {
|
|
55
|
+
const directory = path.join(folder, ...segments);
|
|
56
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
57
|
+
entries.sort((left, right) => left.name.localeCompare(right.name));
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
const entrySegments = [...segments, entry.name];
|
|
60
|
+
if (entry.isDirectory()) {
|
|
61
|
+
await collectDirectory(folder, entrySegments, assets, interfacePath);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (!entry.isFile()) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const sourcePath = path.join(folder, ...entrySegments);
|
|
68
|
+
if (normalizeModuleId(sourcePath) === interfacePath) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
assets.push({
|
|
72
|
+
relativePath: entrySegments.join('/'),
|
|
73
|
+
byteLength: (await stat(sourcePath)).size
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ExistingRawSourceMap } from 'rolldown';
|
|
2
|
+
export type NativeComponentDefinition = {
|
|
3
|
+
folder: string;
|
|
4
|
+
entry: string;
|
|
5
|
+
fields: readonly string[];
|
|
6
|
+
};
|
|
7
|
+
/** Replaces native component interface calls with source-folder names and returns their static metadata. */
|
|
8
|
+
export declare function transformNativeComponentInterfaces(code: string, id: string, sourcemap: boolean): {
|
|
9
|
+
code: string;
|
|
10
|
+
map: ExistingRawSourceMap | null;
|
|
11
|
+
definitions: NativeComponentDefinition[];
|
|
12
|
+
};
|