vxrn 1.25.8 → 1.25.9
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/dist/config/getViteServerConfig.mjs +6 -0
- package/dist/config/getViteServerConfig.mjs.map +1 -1
- package/dist/config/getViteServerConfig.native.js +6 -0
- package/dist/config/getViteServerConfig.native.js.map +1 -1
- package/dist/config/getViteServerConfig.test.mjs +26 -0
- package/dist/config/getViteServerConfig.test.mjs.map +1 -0
- package/dist/config/getViteServerConfig.test.native.js +26 -0
- package/dist/config/getViteServerConfig.test.native.js.map +1 -0
- package/dist/exports/dev.mjs +26 -1
- package/dist/exports/dev.mjs.map +1 -1
- package/dist/exports/dev.native.js +26 -1
- package/dist/exports/dev.native.js.map +1 -1
- package/dist/plugins/reactNativeDevServer.mjs +80 -7
- package/dist/plugins/reactNativeDevServer.mjs.map +1 -1
- package/dist/plugins/reactNativeDevServer.native.js +80 -7
- package/dist/plugins/reactNativeDevServer.native.js.map +1 -1
- package/dist/runtime/native-prelude.mjs +7 -0
- package/dist/runtime/native-prelude.mjs.map +1 -1
- package/dist/runtime/native-prelude.native.js +7 -0
- package/dist/runtime/native-prelude.native.js.map +1 -1
- package/dist/utils/createNativeDevEngine.mjs +302 -197
- package/dist/utils/createNativeDevEngine.mjs.map +1 -1
- package/dist/utils/createNativeDevEngine.native.js +410 -221
- package/dist/utils/createNativeDevEngine.native.js.map +1 -1
- package/dist/utils/createNativeDevEngine.test.mjs +536 -6
- package/dist/utils/createNativeDevEngine.test.mjs.map +1 -1
- package/dist/utils/createNativeDevEngine.test.native.js +559 -6
- package/dist/utils/createNativeDevEngine.test.native.js.map +1 -1
- package/package.json +11 -11
- package/src/config/getViteServerConfig.test.ts +29 -0
- package/src/config/getViteServerConfig.ts +11 -0
- package/src/exports/dev.ts +34 -3
- package/src/plugins/reactNativeDevServer.ts +89 -12
- package/src/runtime/native-prelude.ts +7 -0
- package/src/utils/createNativeDevEngine.test.ts +682 -5
- package/src/utils/createNativeDevEngine.ts +516 -229
- package/types/config/getViteServerConfig.d.ts.map +1 -1
- package/types/config/getViteServerConfig.test.d.ts +2 -0
- package/types/config/getViteServerConfig.test.d.ts.map +1 -0
- package/types/exports/dev.d.ts.map +1 -1
- package/types/plugins/reactNativeDevServer.d.ts +1 -0
- package/types/plugins/reactNativeDevServer.d.ts.map +1 -1
- package/types/runtime/native-prelude.d.ts.map +1 -1
- package/types/utils/createNativeDevEngine.d.ts +40 -2
- package/types/utils/createNativeDevEngine.d.ts.map +1 -1
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import { basename, dirname, extname, join, relative, resolve } from "node:path";
|
|
2
|
-
import { copyFileSync,
|
|
3
|
+
import { copyFileSync, mkdirSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
3
4
|
import { pathToFileURL } from "node:url";
|
|
4
|
-
import { normalizePath } from "vite";
|
|
5
|
+
import { loadEnv, normalizePath } from "vite";
|
|
5
6
|
import { DEFAULT_ASSET_EXTS } from "../constants/defaults.mjs";
|
|
6
7
|
import { getNativePrelude } from "../runtime/native-prelude.mjs";
|
|
7
8
|
const FLOW_FILE_PATTERN = /node_modules[\\/](?:react-native|@react-native)[\\/].*\.js$/;
|
|
8
|
-
const HERMES_CLASS_TRANSFORMS = ["transform-classes", "transform-parameters", "transform-class-properties", "transform-class-static-block", "transform-private-methods", "transform-private-property-in-object"];
|
|
9
|
-
const
|
|
9
|
+
const HERMES_CLASS_TRANSFORMS = ["transform-classes", "transform-parameters", "transform-block-scoping", "transform-class-properties", "transform-class-static-block", "transform-private-methods", "transform-private-property-in-object"];
|
|
10
|
+
const HERMES_ASYNC_TRANSFORMS = ["transform-async-to-generator"];
|
|
10
11
|
function getHermesSWCIncludes(dev) {
|
|
11
|
-
return [...HERMES_CLASS_TRANSFORMS, ...
|
|
12
|
+
return [...HERMES_CLASS_TRANSFORMS, ...HERMES_ASYNC_TRANSFORMS];
|
|
12
13
|
}
|
|
13
14
|
function getResolveExtensions(platform) {
|
|
14
15
|
const platformExts = platform === "ios" ? [".ios.tsx", ".ios.ts", ".ios.jsx", ".ios.js"] : [".android.tsx", ".android.ts", ".android.jsx", ".android.js"];
|
|
@@ -19,7 +20,7 @@ function getResolveExtensions(platform) {
|
|
|
19
20
|
function getNativeResolveConfig(platform) {
|
|
20
21
|
return {
|
|
21
22
|
extensions: getResolveExtensions(platform),
|
|
22
|
-
conditionNames: ["react-native"
|
|
23
|
+
conditionNames: ["react-native"],
|
|
23
24
|
mainFields: ["react-native", "module", "main"]
|
|
24
25
|
};
|
|
25
26
|
}
|
|
@@ -54,28 +55,13 @@ function getNativeTransformConfig(platform, dev, root) {
|
|
|
54
55
|
})
|
|
55
56
|
};
|
|
56
57
|
})();
|
|
57
|
-
const envDefines = (() => {
|
|
58
|
-
const defines = {};
|
|
59
|
-
try {
|
|
60
|
-
const mode2 = dev ? "development" : "production";
|
|
61
|
-
for (const envFile of [".env", ".env.local", `.env.${mode2}`, `.env.${mode2}.local`]) {
|
|
62
|
-
const envPath = join(root, envFile);
|
|
63
|
-
if (!existsSync(envPath)) continue;
|
|
64
|
-
const content = readFileSync(envPath, "utf8");
|
|
65
|
-
for (const line of content.split("\n")) {
|
|
66
|
-
const match = line.match(/^\s*(VITE_\w+)\s*=\s*(.*)$/);
|
|
67
|
-
if (match) {
|
|
68
|
-
const [, key, rawVal] = match;
|
|
69
|
-
const val = rawVal.replace(/^['"]|['"]$/g, "").trim();
|
|
70
|
-
defines[`import.meta.env.${key}`] = JSON.stringify(val);
|
|
71
|
-
defines[`process.env.${key}`] = JSON.stringify(val);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
} catch {}
|
|
76
|
-
return defines;
|
|
77
|
-
})();
|
|
78
58
|
const mode = dev ? "development" : "production";
|
|
59
|
+
const publicEnv = loadEnv(mode, root, ["VITE_", "EXPO_PUBLIC_"]);
|
|
60
|
+
const envDefines = {};
|
|
61
|
+
for (const [key, value] of Object.entries(publicEnv)) {
|
|
62
|
+
envDefines[`import.meta.env.${key}`] = JSON.stringify(value);
|
|
63
|
+
envDefines[`process.env.${key}`] = JSON.stringify(value);
|
|
64
|
+
}
|
|
79
65
|
const envObject = {
|
|
80
66
|
MODE: mode,
|
|
81
67
|
DEV: dev,
|
|
@@ -126,14 +112,15 @@ function getNativeTransformConfig(platform, dev, root) {
|
|
|
126
112
|
}
|
|
127
113
|
};
|
|
128
114
|
}
|
|
129
|
-
function getNativePlugins(root, platform, viteImportGlobPlugin, dev, assetsDest) {
|
|
115
|
+
function getNativePlugins(root, platform, viteImportGlobPlugin, dev, assetsDest, onAsset, sourceMaps = false) {
|
|
130
116
|
return [...(globalThis.__vxrnAddNativePlugins || []), serverFileExclusionPlugin(), environmentGuardPlugin(), hmrClientNoopPlugin(), cssStubPlugin(), viteImportGlobPlugin({
|
|
131
117
|
root
|
|
132
|
-
}), vxrnCompilerPlugin(platform, dev, root), flowStripPlugin(), nativeAnimatedGuardPlugin(), assetPlugin({
|
|
118
|
+
}), vxrnCompilerPlugin(platform, dev, root, sourceMaps), flowStripPlugin(), nativeAnimatedGuardPlugin(), assetPlugin({
|
|
133
119
|
root,
|
|
134
120
|
platform,
|
|
135
|
-
assetsDest
|
|
136
|
-
|
|
121
|
+
assetsDest,
|
|
122
|
+
onAsset
|
|
123
|
+
}), hermesCompatSWCPlugin(dev, sourceMaps)];
|
|
137
124
|
}
|
|
138
125
|
function getNativeOutputOptions(prelude, sourcemap) {
|
|
139
126
|
return {
|
|
@@ -144,7 +131,12 @@ function getNativeOutputOptions(prelude, sourcemap) {
|
|
|
144
131
|
strictExecutionOrder: true
|
|
145
132
|
};
|
|
146
133
|
}
|
|
134
|
+
function normalizeNativeCommonJSInterop(code) {
|
|
135
|
+
return code.replace(/(\b__toESM(?:\$\d+)?\(\s*require[\w$]*\(\)\s*),\s*1(\s*\))/g, "$1$2");
|
|
136
|
+
}
|
|
147
137
|
function postProcessNativeBundle(code) {
|
|
138
|
+
code = normalizeNativeCommonJSInterop(code);
|
|
139
|
+
code = code.replace(/\btypeof\s+import\.meta\b/g, "\"object\"");
|
|
148
140
|
code = code.replace(/^\s*export\s*\{[^}]*\}\s*;?\s*$/gm, "");
|
|
149
141
|
code = code.replace(/^\s*export\s+default\s+([^;\n]+);?\s*$/gm, "$1;");
|
|
150
142
|
code = code.replace(/^if \(import\.meta\.hot\).*$/gm, "");
|
|
@@ -181,41 +173,43 @@ async function downlevelClassFieldsInBundle(code) {
|
|
|
181
173
|
if (endIdx === -1) return code;
|
|
182
174
|
const runtimeEnd = endIdx + 12;
|
|
183
175
|
const runtimeSection = code.slice(startIdx, runtimeEnd);
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
include: [...HERMES_CLASS_TRANSFORMS]
|
|
176
|
+
const originalNewlines = runtimeSection.match(/\n/g)?.length ?? 0;
|
|
177
|
+
const transformedCode = (await (await import("@swc/core")).transform(runtimeSection, {
|
|
178
|
+
filename: "rolldown-runtime.js",
|
|
179
|
+
configFile: false,
|
|
180
|
+
swcrc: false,
|
|
181
|
+
sourceMaps: false,
|
|
182
|
+
inputSourceMap: false,
|
|
183
|
+
isModule: false,
|
|
184
|
+
minify: true,
|
|
185
|
+
env: {
|
|
186
|
+
targets: {
|
|
187
|
+
node: 9999
|
|
197
188
|
},
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
externalHelpers: false,
|
|
208
|
-
assumptions: {
|
|
209
|
-
setPublicClassFields: true,
|
|
210
|
-
privateFieldsAsProperties: true
|
|
189
|
+
include: [...HERMES_CLASS_TRANSFORMS]
|
|
190
|
+
},
|
|
191
|
+
jsc: {
|
|
192
|
+
parser: {
|
|
193
|
+
syntax: "ecmascript"
|
|
194
|
+
},
|
|
195
|
+
transform: {
|
|
196
|
+
react: {
|
|
197
|
+
runtime: "preserve"
|
|
211
198
|
}
|
|
199
|
+
},
|
|
200
|
+
externalHelpers: false,
|
|
201
|
+
assumptions: {
|
|
202
|
+
setPublicClassFields: true,
|
|
203
|
+
privateFieldsAsProperties: true
|
|
212
204
|
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
205
|
+
}
|
|
206
|
+
})).code.trimEnd();
|
|
207
|
+
const transformed = transformedCode.includes(startMarker) ? transformedCode : `${startMarker}
|
|
208
|
+
${transformedCode}`;
|
|
209
|
+
const transformedNewlines = transformed.match(/\n/g)?.length ?? 0;
|
|
210
|
+
if (transformedNewlines > originalNewlines) throw new Error("[vxrn] Hermes runtime transform added lines and would invalidate the production source map");
|
|
211
|
+
const linePreservingRuntime = transformed + "\n".repeat(originalNewlines - transformedNewlines);
|
|
212
|
+
return code.slice(0, startIdx) + linePreservingRuntime + code.slice(runtimeEnd);
|
|
219
213
|
}
|
|
220
214
|
async function createNativeDevEngine(options) {
|
|
221
215
|
const {
|
|
@@ -237,6 +231,7 @@ async function createNativeDevEngine(options) {
|
|
|
237
231
|
platform,
|
|
238
232
|
serverUrl: serverUrl || `http://${host}:${port}`
|
|
239
233
|
});
|
|
234
|
+
const assetRegistry = createNativeDevAssetRegistry();
|
|
240
235
|
let currentBundle = null;
|
|
241
236
|
let firstBuildError = null;
|
|
242
237
|
let bundleResolve = null;
|
|
@@ -265,7 +260,7 @@ async function createNativeDevEngine(options) {
|
|
|
265
260
|
},
|
|
266
261
|
plugins: [nativeVirtualEntryPlugin(root, {
|
|
267
262
|
dev: true
|
|
268
|
-
}), ...getNativePlugins(root, platform, viteImportGlobPlugin, true), ...userPlugins]
|
|
263
|
+
}), ...getNativePlugins(root, platform, viteImportGlobPlugin, true, void 0, assetRegistry.register, false), ...userPlugins]
|
|
269
264
|
}, {
|
|
270
265
|
...getNativeOutputOptions(prelude, false),
|
|
271
266
|
outro: `
|
|
@@ -384,6 +379,9 @@ try {
|
|
|
384
379
|
}
|
|
385
380
|
return bundlePromise;
|
|
386
381
|
},
|
|
382
|
+
getAsset(pathname, hash) {
|
|
383
|
+
return assetRegistry.resolve(pathname, hash);
|
|
384
|
+
},
|
|
387
385
|
async close() {
|
|
388
386
|
await engine.close();
|
|
389
387
|
}
|
|
@@ -427,7 +425,7 @@ async function buildNativeBundle(options) {
|
|
|
427
425
|
},
|
|
428
426
|
plugins: [...(entryFile ? [] : [nativeVirtualEntryPlugin(root, {
|
|
429
427
|
dev
|
|
430
|
-
})]), ...getNativePlugins(root, platform, viteImportGlobPlugin, dev, assetsDest), ...userPlugins],
|
|
428
|
+
})]), ...getNativePlugins(root, platform, viteImportGlobPlugin, dev, assetsDest, void 0, sourcemap), ...userPlugins],
|
|
431
429
|
output: getNativeOutputOptions(prelude, sourcemap)
|
|
432
430
|
})).output.find(o => o.type === "chunk" && o.isEntry);
|
|
433
431
|
if (!chunk || !("code" in chunk)) throw new Error("[vxrn] production build produced no output");
|
|
@@ -507,8 +505,14 @@ function nativeAnimatedGuardPlugin() {
|
|
|
507
505
|
const target = "const method = nullthrows(NativeAnimatedModule)[methodName];";
|
|
508
506
|
if (!code.includes(target)) return;
|
|
509
507
|
return {
|
|
510
|
-
code: code.replace(target,
|
|
511
|
-
|
|
508
|
+
code: code.replace(target, `${target} if (typeof method !== 'function') return;`),
|
|
509
|
+
map: {
|
|
510
|
+
version: 3,
|
|
511
|
+
sources: [id],
|
|
512
|
+
sourcesContent: [code],
|
|
513
|
+
names: [],
|
|
514
|
+
mappings: code.split("\n").map((_, index) => index === 0 ? "AAAA" : "AACA").join(";")
|
|
515
|
+
}
|
|
512
516
|
};
|
|
513
517
|
}
|
|
514
518
|
};
|
|
@@ -587,7 +591,7 @@ function cssStubPlugin() {
|
|
|
587
591
|
}
|
|
588
592
|
};
|
|
589
593
|
}
|
|
590
|
-
function vxrnCompilerPlugin(platform, dev, projectRoot = process.cwd()) {
|
|
594
|
+
function vxrnCompilerPlugin(platform, dev, projectRoot = process.cwd(), sourceMaps = false) {
|
|
591
595
|
let compiler = null;
|
|
592
596
|
const isRefreshCandidate = id => dev && !id.includes("node_modules") && !id.includes("__virtual-native-entry") && /\.[tj]sx?$/.test(id);
|
|
593
597
|
return {
|
|
@@ -596,33 +600,37 @@ function vxrnCompilerPlugin(platform, dev, projectRoot = process.cwd()) {
|
|
|
596
600
|
if (!/\.[cm]?[jt]sx?$/.test(id)) return;
|
|
597
601
|
if (id.includes("\0") || id.includes("virtual:")) return;
|
|
598
602
|
const needsRefresh = isRefreshCandidate(id);
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
603
|
+
if (!compiler) compiler = await import("@vxrn/compiler");
|
|
604
|
+
const props = {
|
|
605
|
+
id,
|
|
606
|
+
code,
|
|
607
|
+
projectRoot,
|
|
608
|
+
development: dev,
|
|
609
|
+
environment: platform,
|
|
610
|
+
reactForRNVersion: "19"
|
|
611
|
+
};
|
|
612
|
+
let babelOptions = compiler.getBabelOptions(props);
|
|
613
|
+
if (needsRefresh) {
|
|
614
|
+
const existingPlugins = babelOptions?.plugins || [];
|
|
615
|
+
babelOptions = {
|
|
616
|
+
...babelOptions,
|
|
617
|
+
plugins: [...existingPlugins, ["react-refresh/babel", {
|
|
618
|
+
skipEnvCheck: true,
|
|
619
|
+
refreshReg: "__vxrnRefreshReg",
|
|
620
|
+
refreshSig: "__vxrnRefreshSig"
|
|
621
|
+
}]]
|
|
608
622
|
};
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
}
|
|
621
|
-
if (!babelOptions) return;
|
|
622
|
-
const result = await compiler.transformBabel(id, code, babelOptions);
|
|
623
|
-
if (result?.code) {
|
|
624
|
-
let out = result.code;
|
|
625
|
-
if (needsRefresh) out = `
|
|
623
|
+
}
|
|
624
|
+
if (!babelOptions) return;
|
|
625
|
+
if (sourceMaps) babelOptions = {
|
|
626
|
+
...babelOptions,
|
|
627
|
+
sourceMaps: true,
|
|
628
|
+
sourceFileName: id
|
|
629
|
+
};
|
|
630
|
+
const result = await compiler.transformBabel(id, code, babelOptions);
|
|
631
|
+
if (result?.code) {
|
|
632
|
+
let out = result.code;
|
|
633
|
+
if (needsRefresh) out = `
|
|
626
634
|
var __prevRefreshReg = globalThis.$RefreshReg$;
|
|
627
635
|
var __prevRefreshSig = globalThis.$RefreshSig$;
|
|
628
636
|
if (globalThis.__ReactRefresh) {
|
|
@@ -640,23 +648,16 @@ ${out}
|
|
|
640
648
|
globalThis.$RefreshReg$ = __prevRefreshReg;
|
|
641
649
|
globalThis.$RefreshSig$ = __prevRefreshSig;
|
|
642
650
|
if (import.meta.hot) {
|
|
643
|
-
import.meta.hot.
|
|
651
|
+
import.meta.hot.acceptReactRefresh(function() {
|
|
644
652
|
if (globalThis.__ReactRefresh) {
|
|
645
653
|
setTimeout(function() { globalThis.__ReactRefresh.performReactRefresh(); }, 30);
|
|
646
654
|
}
|
|
647
655
|
});
|
|
648
656
|
}
|
|
649
657
|
`;
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
}
|
|
654
|
-
} catch (err) {
|
|
655
|
-
if (dev) console.warn(`[vxrn:compiler] ${id}: ${err.message || err}`);
|
|
656
|
-
if (needsRefresh) return {
|
|
657
|
-
code: code + `
|
|
658
|
-
if (import.meta.hot) { import.meta.hot.accept(); }
|
|
659
|
-
`
|
|
658
|
+
return {
|
|
659
|
+
code: out,
|
|
660
|
+
map: sourceMaps ? result.map : void 0
|
|
660
661
|
};
|
|
661
662
|
}
|
|
662
663
|
}
|
|
@@ -668,21 +669,17 @@ function flowStripPlugin() {
|
|
|
668
669
|
transform: {
|
|
669
670
|
async handler(code, id) {
|
|
670
671
|
if (!FLOW_FILE_PATTERN.test(id)) return;
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
};
|
|
683
|
-
} catch (err) {
|
|
684
|
-
console.warn(`[vxrn:flow-strip] ${id}: ${err.message}`);
|
|
685
|
-
}
|
|
672
|
+
const result = await (await import("fast-flow-transform")).default({
|
|
673
|
+
filename: id,
|
|
674
|
+
source: code,
|
|
675
|
+
sourcemap: true,
|
|
676
|
+
dialect: "flow",
|
|
677
|
+
format: "pretty"
|
|
678
|
+
});
|
|
679
|
+
return {
|
|
680
|
+
code: result.code,
|
|
681
|
+
map: result.map
|
|
682
|
+
};
|
|
686
683
|
}
|
|
687
684
|
}
|
|
688
685
|
};
|
|
@@ -694,37 +691,9 @@ function assetPlugin(opts) {
|
|
|
694
691
|
load: {
|
|
695
692
|
async handler(id) {
|
|
696
693
|
if (!assetRegex.test(id)) return;
|
|
697
|
-
const
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
const relativePath = relative(opts.root, id);
|
|
701
|
-
const assetData = {
|
|
702
|
-
__packager_asset: true,
|
|
703
|
-
name,
|
|
704
|
-
type: ext,
|
|
705
|
-
scales: [1],
|
|
706
|
-
httpServerLocation: "/assets/" + dirname(relativePath).replace(/\\/g, "/"),
|
|
707
|
-
fileSystemLocation: dir,
|
|
708
|
-
hash: "",
|
|
709
|
-
width: void 0,
|
|
710
|
-
height: void 0
|
|
711
|
-
};
|
|
712
|
-
if (["png", "jpg", "jpeg", "gif", "webp", "bmp"].includes(ext)) try {
|
|
713
|
-
const {
|
|
714
|
-
imageSize
|
|
715
|
-
} = await import("image-size");
|
|
716
|
-
const dims = imageSize(id);
|
|
717
|
-
assetData.width = dims.width;
|
|
718
|
-
assetData.height = dims.height;
|
|
719
|
-
} catch {}
|
|
720
|
-
if (opts.assetsDest) {
|
|
721
|
-
const relativeAssetDir = dirname(relativePath).replace(/\\/g, "/");
|
|
722
|
-
const assetDestDir = join(opts.assetsDest, "assets", relativeAssetDir);
|
|
723
|
-
mkdirSync(assetDestDir, {
|
|
724
|
-
recursive: true
|
|
725
|
-
});
|
|
726
|
-
copyFileSync(id, join(assetDestDir, `${name}.${ext}`));
|
|
727
|
-
}
|
|
694
|
+
const assetData = await getNativeAssetData(id, opts.root, opts.platform);
|
|
695
|
+
opts.onAsset?.(assetData);
|
|
696
|
+
if (opts.assetsDest) copyNativeAssetFiles(assetData, opts.assetsDest, opts.platform);
|
|
728
697
|
return {
|
|
729
698
|
code: `module.exports = require('react-native/Libraries/Image/AssetRegistry').registerAsset(${JSON.stringify(assetData)});`,
|
|
730
699
|
moduleType: "js"
|
|
@@ -733,7 +702,116 @@ function assetPlugin(opts) {
|
|
|
733
702
|
}
|
|
734
703
|
};
|
|
735
704
|
}
|
|
736
|
-
function
|
|
705
|
+
function createNativeDevAssetRegistry() {
|
|
706
|
+
const assets = /* @__PURE__ */new Map();
|
|
707
|
+
return {
|
|
708
|
+
register(asset) {
|
|
709
|
+
for (const [index, scale] of asset.scales.entries()) {
|
|
710
|
+
const filePath = asset.files[index];
|
|
711
|
+
if (!filePath) continue;
|
|
712
|
+
const fileName = `${asset.name}${scale === 1 ? "" : `@${scale}x`}.${asset.type}`;
|
|
713
|
+
assets.set(`${asset.httpServerLocation}/${fileName}`, {
|
|
714
|
+
filePath,
|
|
715
|
+
hash: asset.hash,
|
|
716
|
+
type: asset.type
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
},
|
|
720
|
+
resolve(pathname, hash) {
|
|
721
|
+
const asset = assets.get(pathname);
|
|
722
|
+
if (!asset || hash !== void 0 && hash !== asset.hash) return;
|
|
723
|
+
return asset;
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
const NATIVE_IMAGE_EXTS = /* @__PURE__ */new Set(["png", "jpg", "jpeg", "gif", "webp", "bmp", "psd", "svg", "tiff", "ktx"]);
|
|
728
|
+
function parseNativeAssetName(filePath) {
|
|
729
|
+
const type = extname(filePath).slice(1);
|
|
730
|
+
if (!type) return;
|
|
731
|
+
const stem = basename(filePath, `.${type}`);
|
|
732
|
+
const platformMatch = stem.match(/^(.*)\.(ios|android)$/);
|
|
733
|
+
const platform = platformMatch?.[2];
|
|
734
|
+
const scaleMatch = (platformMatch?.[1] ?? stem).match(/^(.+?)(?:@([\d.]+)x)?$/);
|
|
735
|
+
if (!scaleMatch) return;
|
|
736
|
+
const scale = scaleMatch[2] === void 0 ? 1 : Number.parseFloat(scaleMatch[2]);
|
|
737
|
+
if (!Number.isFinite(scale) || scale <= 0) return;
|
|
738
|
+
return {
|
|
739
|
+
name: scaleMatch[1],
|
|
740
|
+
scale,
|
|
741
|
+
platform,
|
|
742
|
+
type
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
function getNativeAssetUrlDirectory(root, assetDirectory) {
|
|
746
|
+
const safeDirectory = relative(realpathSync(root), realpathSync(assetDirectory)).replace(/\\/g, "/").split("/").filter(segment => segment && segment !== ".").map(segment => segment === ".." ? "_" : segment).join("/");
|
|
747
|
+
return safeDirectory ? `/assets/${safeDirectory}` : "/assets";
|
|
748
|
+
}
|
|
749
|
+
async function getNativeAssetData(id, root, platform) {
|
|
750
|
+
const requested = parseNativeAssetName(id);
|
|
751
|
+
if (!requested) throw new Error(`[vxrn] invalid native asset path: ${id}`);
|
|
752
|
+
const assetDirectory = dirname(id);
|
|
753
|
+
const filesByScale = /* @__PURE__ */new Map();
|
|
754
|
+
for (const fileName of readdirSync(assetDirectory)) {
|
|
755
|
+
const candidate = parseNativeAssetName(fileName);
|
|
756
|
+
if (!candidate || candidate.name !== requested.name || candidate.type !== requested.type || candidate.platform !== void 0 && candidate.platform !== platform) continue;
|
|
757
|
+
const platformSpecific = candidate.platform === platform;
|
|
758
|
+
const existing = filesByScale.get(candidate.scale);
|
|
759
|
+
if (!existing || platformSpecific && !existing.platformSpecific) filesByScale.set(candidate.scale, {
|
|
760
|
+
file: join(assetDirectory, fileName),
|
|
761
|
+
platformSpecific
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
const scales = [...filesByScale.keys()].sort((a, b) => a - b);
|
|
765
|
+
const files = scales.map(scale => filesByScale.get(scale).file);
|
|
766
|
+
if (files.length === 0) throw new Error(`[vxrn] native asset has no files for ${platform}: ${id}`);
|
|
767
|
+
const hash = createHash("md5");
|
|
768
|
+
for (const file of files) hash.update(readFileSync(file));
|
|
769
|
+
const assetData = {
|
|
770
|
+
__packager_asset: true,
|
|
771
|
+
name: requested.name,
|
|
772
|
+
type: requested.type,
|
|
773
|
+
scales,
|
|
774
|
+
files,
|
|
775
|
+
httpServerLocation: getNativeAssetUrlDirectory(root, assetDirectory),
|
|
776
|
+
fileSystemLocation: assetDirectory,
|
|
777
|
+
hash: hash.digest("hex")
|
|
778
|
+
};
|
|
779
|
+
if (NATIVE_IMAGE_EXTS.has(requested.type)) try {
|
|
780
|
+
const {
|
|
781
|
+
imageSize
|
|
782
|
+
} = await import("image-size");
|
|
783
|
+
const dims = imageSize(files[0]);
|
|
784
|
+
assetData.width = dims.width === void 0 ? void 0 : dims.width / scales[0];
|
|
785
|
+
assetData.height = dims.height === void 0 ? void 0 : dims.height / scales[0];
|
|
786
|
+
} catch {}
|
|
787
|
+
return assetData;
|
|
788
|
+
}
|
|
789
|
+
function getIOSAssetScales(scales) {
|
|
790
|
+
const supported = scales.filter(scale => scale === 1 || scale === 2 || scale === 3);
|
|
791
|
+
if (supported.length > 0 || scales.length === 0) return supported;
|
|
792
|
+
return [scales.find(scale => scale > 3) ?? scales[scales.length - 1]];
|
|
793
|
+
}
|
|
794
|
+
function getAndroidAssetDirectory(type, scale) {
|
|
795
|
+
if (!(/* @__PURE__ */new Set(["gif", "heic", "heif", "jpeg", "jpg", "ktx", "png", "webp", "xml"])).has(type)) return "raw";
|
|
796
|
+
const density = (/* @__PURE__ */new Map([[.75, "ldpi"], [1, "mdpi"], [1.5, "hdpi"], [2, "xhdpi"], [3, "xxhdpi"], [4, "xxxhdpi"]])).get(scale);
|
|
797
|
+
if (density) return `drawable-${density}`;
|
|
798
|
+
return `drawable-${Math.round(scale * 160)}dpi`;
|
|
799
|
+
}
|
|
800
|
+
function getAndroidAssetName(asset) {
|
|
801
|
+
return `${asset.httpServerLocation}/${asset.name}`.toLowerCase().replace(/^\//, "").replace(/\//g, "_").replace(/([^a-z0-9_])/g, "").replace(/^assets_/, "");
|
|
802
|
+
}
|
|
803
|
+
function copyNativeAssetFiles(asset, assetsDest, platform) {
|
|
804
|
+
const validIOSScales = new Set(getIOSAssetScales(asset.scales));
|
|
805
|
+
for (const [index, scale] of asset.scales.entries()) {
|
|
806
|
+
if (platform === "ios" && !validIOSScales.has(scale)) continue;
|
|
807
|
+
const destination = platform === "android" ? join(assetsDest, getAndroidAssetDirectory(asset.type, scale), `${getAndroidAssetName(asset)}.${asset.type}`) : join(assetsDest, asset.httpServerLocation.slice(1), `${asset.name}${scale === 1 ? "" : `@${scale}x`}.${asset.type}`);
|
|
808
|
+
mkdirSync(dirname(destination), {
|
|
809
|
+
recursive: true
|
|
810
|
+
});
|
|
811
|
+
copyFileSync(asset.files[index], destination);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
function hermesCompatSWCPlugin(dev, sourceMaps = false) {
|
|
737
815
|
let swc = null;
|
|
738
816
|
return {
|
|
739
817
|
name: "vxrn:hermes-compat",
|
|
@@ -741,45 +819,47 @@ function hermesCompatSWCPlugin(dev) {
|
|
|
741
819
|
if (!/\.[cm]?[jt]sx?$/.test(id)) return;
|
|
742
820
|
if (id.includes("\0") || id.includes("virtual:")) return;
|
|
743
821
|
const hasClass = code.includes("class ") || code.includes("class{");
|
|
744
|
-
const hasAsync =
|
|
745
|
-
|
|
822
|
+
const hasAsync = code.includes("async ");
|
|
823
|
+
const hasBlockScopedLoop = /\bfor\s*\(\s*(?:const|let)\b/.test(code);
|
|
824
|
+
if (!hasClass && !hasAsync && !hasBlockScopedLoop) return;
|
|
746
825
|
if (code.length > 5e5) return;
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
826
|
+
if (!swc) swc = await import("@swc/core");
|
|
827
|
+
const envIncludes = getHermesSWCIncludes(dev);
|
|
828
|
+
const result = await swc.transform(code, {
|
|
829
|
+
filename: id,
|
|
830
|
+
configFile: false,
|
|
831
|
+
swcrc: false,
|
|
832
|
+
sourceMaps,
|
|
833
|
+
sourceFileName: sourceMaps ? id : void 0,
|
|
834
|
+
inputSourceMap: false,
|
|
835
|
+
env: {
|
|
836
|
+
targets: {
|
|
837
|
+
node: 9999
|
|
838
|
+
},
|
|
839
|
+
include: envIncludes
|
|
840
|
+
},
|
|
841
|
+
jsc: {
|
|
842
|
+
parser: {
|
|
843
|
+
syntax: "typescript",
|
|
844
|
+
tsx: true
|
|
845
|
+
},
|
|
846
|
+
transform: {
|
|
847
|
+
react: {
|
|
848
|
+
runtime: "preserve"
|
|
849
|
+
}
|
|
850
|
+
},
|
|
851
|
+
externalHelpers: false,
|
|
852
|
+
assumptions: {
|
|
853
|
+
setPublicClassFields: true,
|
|
854
|
+
privateFieldsAsProperties: true
|
|
855
|
+
}
|
|
856
|
+
},
|
|
857
|
+
isModule: !id.endsWith(".cjs")
|
|
858
|
+
});
|
|
859
|
+
return {
|
|
860
|
+
code: result.code,
|
|
861
|
+
map: sourceMaps ? result.map : void 0
|
|
862
|
+
};
|
|
783
863
|
}
|
|
784
864
|
};
|
|
785
865
|
}
|
|
@@ -801,6 +881,7 @@ class ReactNativeDevRuntime extends BaseDevRuntime {
|
|
|
801
881
|
var runtime = this;
|
|
802
882
|
var ctx = {
|
|
803
883
|
acceptCallbacks: [],
|
|
884
|
+
reactRefreshAcceptCallback: null,
|
|
804
885
|
accept: function(deps, callback) {
|
|
805
886
|
if (typeof deps === 'function' || !deps) {
|
|
806
887
|
ctx.acceptCallbacks.push({
|
|
@@ -816,6 +897,9 @@ class ReactNativeDevRuntime extends BaseDevRuntime {
|
|
|
816
897
|
ctx.acceptCallbacks.push({ deps: deps, fn: callback || function() {} });
|
|
817
898
|
}
|
|
818
899
|
},
|
|
900
|
+
acceptReactRefresh: function(callback) {
|
|
901
|
+
ctx.reactRefreshAcceptCallback = callback;
|
|
902
|
+
},
|
|
819
903
|
invalidate: function() { runtime.requestReload('module invalidated: ' + moduleId); },
|
|
820
904
|
on: function() {},
|
|
821
905
|
off: function() {},
|
|
@@ -849,9 +933,18 @@ class ReactNativeDevRuntime extends BaseDevRuntime {
|
|
|
849
933
|
|
|
850
934
|
isSelfAccepted(moduleId) {
|
|
851
935
|
var ctx = this.moduleHotContexts[moduleId];
|
|
852
|
-
|
|
936
|
+
var explicitlyAccepted = !!(ctx && ctx.acceptCallbacks.some(function(callback) {
|
|
853
937
|
return callback.deps.indexOf(moduleId) !== -1;
|
|
854
938
|
}));
|
|
939
|
+
if (explicitlyAccepted) return { accepted: true, reactRefresh: false };
|
|
940
|
+
if (!ctx || !ctx.reactRefreshAcceptCallback || !globalThis.__ReactRefresh) {
|
|
941
|
+
return { accepted: false, reactRefresh: false };
|
|
942
|
+
}
|
|
943
|
+
var exports = this.loadExports(moduleId);
|
|
944
|
+
return {
|
|
945
|
+
accepted: ctx.refreshUtils.isReactRefreshBoundary(exports),
|
|
946
|
+
reactRefresh: true
|
|
947
|
+
};
|
|
855
948
|
}
|
|
856
949
|
|
|
857
950
|
acceptsDependency(parentId, moduleId) {
|
|
@@ -866,8 +959,13 @@ class ReactNativeDevRuntime extends BaseDevRuntime {
|
|
|
866
959
|
traversed.add(moduleId);
|
|
867
960
|
updateSet.add(moduleId);
|
|
868
961
|
|
|
869
|
-
|
|
870
|
-
|
|
962
|
+
var selfAcceptance = this.isSelfAccepted(moduleId);
|
|
963
|
+
if (selfAcceptance.accepted) {
|
|
964
|
+
boundaries.push({
|
|
965
|
+
boundary: moduleId,
|
|
966
|
+
acceptedVia: moduleId,
|
|
967
|
+
reactRefresh: selfAcceptance.reactRefresh
|
|
968
|
+
});
|
|
871
969
|
return true;
|
|
872
970
|
}
|
|
873
971
|
|
|
@@ -903,12 +1001,19 @@ class ReactNativeDevRuntime extends BaseDevRuntime {
|
|
|
903
1001
|
|
|
904
1002
|
var callbacks = boundaries.map(function(item) {
|
|
905
1003
|
var ctx = this.moduleHotContexts[item.boundary];
|
|
1004
|
+
var selectedCallbacks = ctx ? ctx.acceptCallbacks.filter(function(callback) {
|
|
1005
|
+
return callback.deps.indexOf(item.acceptedVia) !== -1;
|
|
1006
|
+
}) : [];
|
|
1007
|
+
if (item.reactRefresh && ctx && ctx.reactRefreshAcceptCallback) {
|
|
1008
|
+
selectedCallbacks.push({
|
|
1009
|
+
deps: [item.acceptedVia],
|
|
1010
|
+
fn: function() { ctx.reactRefreshAcceptCallback(); }
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
906
1013
|
return {
|
|
907
1014
|
boundary: item.boundary,
|
|
908
1015
|
acceptedVia: item.acceptedVia,
|
|
909
|
-
callbacks:
|
|
910
|
-
return callback.deps.indexOf(item.acceptedVia) !== -1;
|
|
911
|
-
}) : []
|
|
1016
|
+
callbacks: selectedCallbacks
|
|
912
1017
|
};
|
|
913
1018
|
}, this);
|
|
914
1019
|
|
|
@@ -959,5 +1064,5 @@ class ReactNativeDevRuntime extends BaseDevRuntime {
|
|
|
959
1064
|
globalThis.__rolldown_runtime__ = new ReactNativeDevRuntime();
|
|
960
1065
|
`;
|
|
961
1066
|
}
|
|
962
|
-
export { buildNativeBundle, createNativeDevEngine, getHermesSWCIncludes, getHmrRuntimeSource, getNativeTransformConfig, hermesCompatSWCPlugin, hmrClientNoopPlugin, vxrnCompilerPlugin, wrapNativeBundleModuleScope };
|
|
1067
|
+
export { buildNativeBundle, createNativeDevAssetRegistry, createNativeDevEngine, getHermesSWCIncludes, getHmrRuntimeSource, getNativeAssetData, getNativeTransformConfig, hermesCompatSWCPlugin, hmrClientNoopPlugin, nativeAnimatedGuardPlugin, normalizeNativeCommonJSInterop, vxrnCompilerPlugin, wrapNativeBundleModuleScope };
|
|
963
1068
|
//# sourceMappingURL=createNativeDevEngine.mjs.map
|