vxrn 1.26.0 → 1.26.1
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/plugins/reactNativeDevServer.mjs +123 -42
- package/dist/plugins/reactNativeDevServer.mjs.map +1 -1
- package/dist/plugins/reactNativeDevServer.native.js +209 -44
- package/dist/plugins/reactNativeDevServer.native.js.map +1 -1
- package/dist/rn-commands/bundle/buildBundle.mjs +29 -10
- package/dist/rn-commands/bundle/buildBundle.mjs.map +1 -1
- package/dist/rn-commands/bundle/buildBundle.native.js +29 -10
- package/dist/rn-commands/bundle/buildBundle.native.js.map +1 -1
- package/dist/utils/createNativeDevEngine.mjs +220 -83
- package/dist/utils/createNativeDevEngine.mjs.map +1 -1
- package/dist/utils/createNativeDevEngine.native.js +257 -84
- package/dist/utils/createNativeDevEngine.native.js.map +1 -1
- package/dist/utils/createNativeDevEngine.test.mjs +285 -23
- package/dist/utils/createNativeDevEngine.test.mjs.map +1 -1
- package/dist/utils/createNativeDevEngine.test.native.js +319 -23
- package/dist/utils/createNativeDevEngine.test.native.js.map +1 -1
- package/dist/utils/patches.test.mjs.map +1 -1
- package/dist/utils/patches.test.native.js.map +1 -1
- package/dist/utils/symbolicateNativeStack.mjs +66 -0
- package/dist/utils/symbolicateNativeStack.mjs.map +1 -0
- package/dist/utils/symbolicateNativeStack.native.js +70 -0
- package/dist/utils/symbolicateNativeStack.native.js.map +1 -0
- package/dist/utils/symbolicateNativeStack.test.mjs +96 -0
- package/dist/utils/symbolicateNativeStack.test.mjs.map +1 -0
- package/dist/utils/symbolicateNativeStack.test.native.js +96 -0
- package/dist/utils/symbolicateNativeStack.test.native.js.map +1 -0
- package/package.json +12 -11
- package/src/plugins/reactNativeDevServer.ts +162 -50
- package/src/rn-commands/bundle/buildBundle.ts +28 -9
- package/src/utils/createNativeDevEngine.test.ts +581 -193
- package/src/utils/createNativeDevEngine.ts +434 -115
- package/src/utils/patches.test.ts +1 -4
- package/src/utils/symbolicateNativeStack.test.ts +78 -0
- package/src/utils/symbolicateNativeStack.ts +129 -0
- package/types/plugins/reactNativeDevServer.d.ts.map +1 -1
- package/types/rn-commands/bundle/buildBundle.d.ts.map +1 -1
- package/types/utils/createNativeDevEngine.d.ts +23 -4
- package/types/utils/createNativeDevEngine.d.ts.map +1 -1
- package/types/utils/symbolicateNativeStack.d.ts +46 -0
- package/types/utils/symbolicateNativeStack.d.ts.map +1 -0
- package/types/utils/symbolicateNativeStack.test.d.ts +2 -0
- package/types/utils/symbolicateNativeStack.test.d.ts.map +1 -0
|
@@ -1,14 +1,95 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
1
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
2
2
|
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { createContext, runInContext, runInNewContext } from "node:vm";
|
|
6
|
+
import { TraceMap, originalPositionFor } from "@jridgewell/trace-mapping";
|
|
6
7
|
import { rolldown } from "rolldown";
|
|
7
8
|
import { dev } from "rolldown/experimental";
|
|
9
|
+
import { normalizePath } from "vite";
|
|
8
10
|
import { describe, expect, it, vi } from "vitest";
|
|
9
11
|
import { getNativePrelude } from "../runtime/native-prelude.mjs";
|
|
10
12
|
import { workletImportsPlugin } from "../plugins/workletImportsPlugin.mjs";
|
|
11
|
-
import { buildNativeBundle, createNativeDevAssetRegistry, createNativeDevEngine, getHermesSWCIncludes, getHmrRuntimeSource, getNativeAssetData, getNativeTransformConfig, hermesCompatSWCPlugin, hmrClientNoopPlugin, nativeAnimatedGuardPlugin, normalizeNativeCommonJSInterop, vxrnCompilerPlugin, wrapNativeBundleModuleScope } from "./createNativeDevEngine.mjs";
|
|
13
|
+
import { buildNativeBundle, createNativeDevAssetRegistry, createNativeDevEngine, getHermesSWCIncludes, getHmrRuntimeSource, getNativeAssetData, getNativeTransformConfig, hermesCompatSWCPlugin, hmrClientNoopPlugin, nativeAnimatedGuardPlugin, normalizeNativeCommonJSInterop, postProcessNativeBundle, vxrnCompilerPlugin, wrapNativeBundleModuleScope } from "./createNativeDevEngine.mjs";
|
|
14
|
+
describe.each(["ios", "android"])("native plugin adapters on %s", platform => {
|
|
15
|
+
it.each(["dev", "build"])("binds configured plugins to the %s bundle", async mode => {
|
|
16
|
+
const root2 = await mkdtemp(join(tmpdir(), "vxrn-native-plugin-adapter-"));
|
|
17
|
+
await writeFile(join(root2, "entry.js"), `globalThis.nativePluginResult = [__GLOBAL_PLUGIN__, __DIRECT_PLUGIN__, 'plain-plugin']`);
|
|
18
|
+
const factories = ["global", "direct"].map(name => vi.fn(context => ({
|
|
19
|
+
name: `${name}-native`,
|
|
20
|
+
transform(code, id) {
|
|
21
|
+
if (id.endsWith("/entry.js")) return code.replace(`__${name.toUpperCase()}_PLUGIN__`, JSON.stringify({
|
|
22
|
+
name,
|
|
23
|
+
...context
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
})));
|
|
27
|
+
const plugins = factories.map((vxrnNative, index) => ({
|
|
28
|
+
name: `adapter-${index}`,
|
|
29
|
+
api: {
|
|
30
|
+
vxrnNative
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
33
|
+
const previousPlugins = globalThis.__vxrnAddNativePlugins;
|
|
34
|
+
globalThis.__vxrnAddNativePlugins = [plugins[0]];
|
|
35
|
+
const configuredPlugins = [plugins[1], {
|
|
36
|
+
name: "plain-native-plugin",
|
|
37
|
+
transform(code, id) {
|
|
38
|
+
if (id.endsWith("/__virtual-native-entry.tsx")) return `import './entry.js'`;
|
|
39
|
+
if (id.endsWith("/entry.js")) return code.replace("plain-plugin", "plain");
|
|
40
|
+
}
|
|
41
|
+
}];
|
|
42
|
+
let native;
|
|
43
|
+
try {
|
|
44
|
+
let code;
|
|
45
|
+
if (mode === "dev") {
|
|
46
|
+
native = await createNativeDevEngine({
|
|
47
|
+
root: root2,
|
|
48
|
+
platform,
|
|
49
|
+
port: 0,
|
|
50
|
+
plugins: configuredPlugins
|
|
51
|
+
});
|
|
52
|
+
code = (await native.getBundle()).code;
|
|
53
|
+
} else code = (await buildNativeBundle({
|
|
54
|
+
root: root2,
|
|
55
|
+
platform,
|
|
56
|
+
entryFile: "entry.js",
|
|
57
|
+
plugins: configuredPlugins
|
|
58
|
+
})).code;
|
|
59
|
+
const context = {
|
|
60
|
+
console,
|
|
61
|
+
setTimeout,
|
|
62
|
+
clearTimeout,
|
|
63
|
+
__GLOBAL_PLUGIN__: "unadapted",
|
|
64
|
+
__DIRECT_PLUGIN__: "unadapted"
|
|
65
|
+
};
|
|
66
|
+
runInNewContext(code, context);
|
|
67
|
+
expect(Reflect.get(context, "nativePluginResult")).toEqual([{
|
|
68
|
+
name: "global",
|
|
69
|
+
root: root2,
|
|
70
|
+
platform,
|
|
71
|
+
dev: mode === "dev"
|
|
72
|
+
}, {
|
|
73
|
+
name: "direct",
|
|
74
|
+
root: root2,
|
|
75
|
+
platform,
|
|
76
|
+
dev: mode === "dev"
|
|
77
|
+
}, "plain"]);
|
|
78
|
+
for (const factory of factories) expect(factory).toHaveBeenCalledExactlyOnceWith({
|
|
79
|
+
root: root2,
|
|
80
|
+
platform,
|
|
81
|
+
dev: mode === "dev"
|
|
82
|
+
});
|
|
83
|
+
} finally {
|
|
84
|
+
await native?.close();
|
|
85
|
+
globalThis.__vxrnAddNativePlugins = previousPlugins;
|
|
86
|
+
await rm(root2, {
|
|
87
|
+
recursive: true,
|
|
88
|
+
force: true
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
});
|
|
12
93
|
const nativeTransformProbe = `
|
|
13
94
|
export const transformProbe = () => {
|
|
14
95
|
'worklet'
|
|
@@ -85,12 +166,12 @@ globalThis.result = (function(parentArgument) {
|
|
|
85
166
|
expect(result.events.filter(value => value === "finally")).toHaveLength(3);
|
|
86
167
|
expect(result.events.filter(value => value === "closed")).toHaveLength(1);
|
|
87
168
|
const {
|
|
88
|
-
originalPositionFor,
|
|
89
|
-
TraceMap
|
|
169
|
+
originalPositionFor: originalPositionFor2,
|
|
170
|
+
TraceMap: TraceMap2
|
|
90
171
|
} = await import("@jridgewell/trace-mapping");
|
|
91
172
|
const lines = output.code.split("\n");
|
|
92
173
|
const line = lines.findIndex(value => value.includes("after-await"));
|
|
93
|
-
const position =
|
|
174
|
+
const position = originalPositionFor2(new TraceMap2(output.map), {
|
|
94
175
|
line: line + 1,
|
|
95
176
|
column: lines[line].indexOf("events.push")
|
|
96
177
|
});
|
|
@@ -110,8 +191,8 @@ describe.each(["shared", "rolldown", "metro"])("React Compiler worklets through
|
|
|
110
191
|
default: MagicString
|
|
111
192
|
} = await import("magic-string");
|
|
112
193
|
const {
|
|
113
|
-
TraceMap,
|
|
114
|
-
originalPositionFor
|
|
194
|
+
TraceMap: TraceMap2,
|
|
195
|
+
originalPositionFor: originalPositionFor2
|
|
115
196
|
} = await import("@jridgewell/trace-mapping");
|
|
116
197
|
const projectRoot = await createWorkletsProject(false);
|
|
117
198
|
const sourceMaps = process.env.VXRN_ENABLE_SOURCE_MAP;
|
|
@@ -210,7 +291,7 @@ return ${pipeline === "metro" ? "module.exports.useProbe" : "useProbe"}`)(memo,
|
|
|
210
291
|
const lines = result.code.split("\n");
|
|
211
292
|
const line = lines.findIndex(text => text.includes("function useProbe("));
|
|
212
293
|
expect(line).toBeGreaterThanOrEqual(0);
|
|
213
|
-
const position =
|
|
294
|
+
const position = originalPositionFor2(new TraceMap2(result.map), {
|
|
214
295
|
line: line + 1,
|
|
215
296
|
column: lines[line].indexOf("function")
|
|
216
297
|
});
|
|
@@ -378,6 +459,7 @@ if (import.meta.hot) import.meta.hot.accept(() => {})
|
|
|
378
459
|
"pure-math": ["default", "reads"]
|
|
379
460
|
})]
|
|
380
461
|
});
|
|
462
|
+
expect(production.code).not.toContain("__esmMin");
|
|
381
463
|
const productionRN = {
|
|
382
464
|
console
|
|
383
465
|
};
|
|
@@ -386,6 +468,23 @@ if (import.meta.hot) import.meta.hot.accept(() => {})
|
|
|
386
468
|
expect(reconstruct(productionRN.calculate)(10)).toBe(109);
|
|
387
469
|
expect(reconstruct(productionRN.reads)()).toBe(3);
|
|
388
470
|
expect(productionRN.reads()).toBe(1);
|
|
471
|
+
const unminifiedProduction = await buildNativeBundle({
|
|
472
|
+
root: root2,
|
|
473
|
+
platform: "android",
|
|
474
|
+
entryFile: "production.mjs",
|
|
475
|
+
minify: false,
|
|
476
|
+
plugins: [workletImportsPlugin({
|
|
477
|
+
"pure-math": ["default", "reads"]
|
|
478
|
+
})]
|
|
479
|
+
});
|
|
480
|
+
expect(unminifiedProduction.code).toContain("__esmMin");
|
|
481
|
+
const unminifiedRN = {
|
|
482
|
+
console
|
|
483
|
+
};
|
|
484
|
+
runInNewContext(unminifiedProduction.code, unminifiedRN);
|
|
485
|
+
expect(unminifiedRN.calculate(10)).toBe(109);
|
|
486
|
+
expect(reconstruct(unminifiedRN.calculate)(10)).toBe(109);
|
|
487
|
+
expect(reconstruct(unminifiedRN.reads)()).toBe(3);
|
|
389
488
|
const sharedPlugin = workletImportsPlugin({
|
|
390
489
|
"pure-math": ["default", "reads"]
|
|
391
490
|
});
|
|
@@ -1047,8 +1146,8 @@ describe("native required transform failures", () => {
|
|
|
1047
1146
|
});
|
|
1048
1147
|
it("composes source maps across React Compiler, Fast Refresh, and module wrapper back to original source lines", async () => {
|
|
1049
1148
|
const {
|
|
1050
|
-
TraceMap,
|
|
1051
|
-
originalPositionFor
|
|
1149
|
+
TraceMap: TraceMap2,
|
|
1150
|
+
originalPositionFor: originalPositionFor2
|
|
1052
1151
|
} = await import("@jridgewell/trace-mapping");
|
|
1053
1152
|
const compiler = await import("@vxrn/compiler");
|
|
1054
1153
|
compiler.configureVXRNCompilerPlugin({
|
|
@@ -1068,10 +1167,10 @@ export function Counter() {
|
|
|
1068
1167
|
const result = await Reflect.apply(plugin.transform, void 0, [inputCode, id]);
|
|
1069
1168
|
expect(result).toBeDefined();
|
|
1070
1169
|
expect(result.map).toBeDefined();
|
|
1071
|
-
const tracer = new
|
|
1170
|
+
const tracer = new TraceMap2(result.map);
|
|
1072
1171
|
const counterLineIndex = result.code.split("\n").findIndex(l => l.includes("function Counter"));
|
|
1073
1172
|
expect(counterLineIndex).toBeGreaterThan(0);
|
|
1074
|
-
const pos =
|
|
1173
|
+
const pos = originalPositionFor2(tracer, {
|
|
1075
1174
|
line: counterLineIndex + 1,
|
|
1076
1175
|
column: 16
|
|
1077
1176
|
});
|
|
@@ -1085,8 +1184,8 @@ export function Counter() {
|
|
|
1085
1184
|
});
|
|
1086
1185
|
it("composes source maps accurately across mixed path (React Compiler + Babel + Fast Refresh + module wrapper)", async () => {
|
|
1087
1186
|
const {
|
|
1088
|
-
TraceMap,
|
|
1089
|
-
originalPositionFor
|
|
1187
|
+
TraceMap: TraceMap2,
|
|
1188
|
+
originalPositionFor: originalPositionFor2
|
|
1090
1189
|
} = await import("@jridgewell/trace-mapping");
|
|
1091
1190
|
const compiler = await import("@vxrn/compiler");
|
|
1092
1191
|
const origEnv = process.env.VXRN_USE_BABEL_FOR_GENERATORS;
|
|
@@ -1113,12 +1212,12 @@ export async function* probe() { throw new Error("MARKER"); }
|
|
|
1113
1212
|
expect(result).toBeDefined();
|
|
1114
1213
|
expect(result.map).toBeDefined();
|
|
1115
1214
|
expect(result.code.includes("_wrapAsyncGenerator") || result.code.includes("regeneratorRuntime")).toBe(true);
|
|
1116
|
-
const tracer = new
|
|
1215
|
+
const tracer = new TraceMap2(result.map);
|
|
1117
1216
|
const lines = result.code.split("\n");
|
|
1118
1217
|
const markerLineIndex = lines.findIndex(l => l.includes("MARKER"));
|
|
1119
1218
|
expect(markerLineIndex).toBeGreaterThan(0);
|
|
1120
1219
|
const markerCol = lines[markerLineIndex].indexOf("throw");
|
|
1121
|
-
const pos =
|
|
1220
|
+
const pos = originalPositionFor2(tracer, {
|
|
1122
1221
|
line: markerLineIndex + 1,
|
|
1123
1222
|
column: markerCol
|
|
1124
1223
|
});
|
|
@@ -1127,7 +1226,7 @@ export async function* probe() { throw new Error("MARKER"); }
|
|
|
1127
1226
|
expect(pos.column).toBe(33);
|
|
1128
1227
|
const compilerOut = await compiler.transformOxcReactCompiler(id, inputCode, "19", true);
|
|
1129
1228
|
const remapping = (await import("@jridgewell/remapping")).default;
|
|
1130
|
-
const badPos =
|
|
1229
|
+
const badPos = originalPositionFor2(new TraceMap2(remapping([result.map, compilerOut.map], () => null)), {
|
|
1131
1230
|
line: markerLineIndex + 1,
|
|
1132
1231
|
column: markerCol
|
|
1133
1232
|
});
|
|
@@ -1142,8 +1241,8 @@ export async function* probe() { throw new Error("MARKER"); }
|
|
|
1142
1241
|
});
|
|
1143
1242
|
it("transforms worklets via native Rust/Wasm SWC with zero Babel execution and accurate sourcemaps", async () => {
|
|
1144
1243
|
const {
|
|
1145
|
-
TraceMap,
|
|
1146
|
-
originalPositionFor
|
|
1244
|
+
TraceMap: TraceMap2,
|
|
1245
|
+
originalPositionFor: originalPositionFor2
|
|
1147
1246
|
} = await import("@jridgewell/trace-mapping");
|
|
1148
1247
|
const compiler = await import("@vxrn/compiler");
|
|
1149
1248
|
const {
|
|
@@ -1175,10 +1274,10 @@ export function Box() {
|
|
|
1175
1274
|
expect(result.code).toContain("__closure");
|
|
1176
1275
|
expect(babelSpy).not.toHaveBeenCalled();
|
|
1177
1276
|
expect(result.map).toBeDefined();
|
|
1178
|
-
const tracer = new
|
|
1277
|
+
const tracer = new TraceMap2(result.map);
|
|
1179
1278
|
const boxLineIndex = result.code.split("\n").findIndex(l => l.includes("export function Box"));
|
|
1180
1279
|
expect(boxLineIndex).toBeGreaterThan(0);
|
|
1181
|
-
const pos =
|
|
1280
|
+
const pos = originalPositionFor2(tracer, {
|
|
1182
1281
|
line: boxLineIndex + 1,
|
|
1183
1282
|
column: 16
|
|
1184
1283
|
});
|
|
@@ -1270,6 +1369,90 @@ export function Box() {
|
|
|
1270
1369
|
}
|
|
1271
1370
|
});
|
|
1272
1371
|
});
|
|
1372
|
+
describe("native production minification", () => {
|
|
1373
|
+
async function writeMinifyFixture() {
|
|
1374
|
+
const root2 = await mkdtemp(join(tmpdir(), "vxrn-native-minify-"));
|
|
1375
|
+
const dep = join(root2, "node_modules", "legacy-color");
|
|
1376
|
+
await mkdir(dep, {
|
|
1377
|
+
recursive: true
|
|
1378
|
+
});
|
|
1379
|
+
await writeFile(join(dep, "package.json"), JSON.stringify({
|
|
1380
|
+
name: "legacy-color",
|
|
1381
|
+
main: "index.js"
|
|
1382
|
+
}));
|
|
1383
|
+
await writeFile(join(dep, "index.js"), `function LegacyColor(value) { this.value = value }
|
|
1384
|
+
LegacyColor.prototype.describe = function () { return 'legacy:' + this.value }
|
|
1385
|
+
module.exports = LegacyColor`);
|
|
1386
|
+
await writeFile(join(root2, "views.js"), `'use strict';
|
|
1387
|
+
import LegacyColor from 'legacy-color'
|
|
1388
|
+
import { level } from './entry.js'
|
|
1389
|
+
export const describeHeader = () => new LegacyColor(level()).describe()`);
|
|
1390
|
+
await writeFile(join(root2, "entry.js"), `import { describeHeader } from './views.js'
|
|
1391
|
+
export const level = () => 'header'
|
|
1392
|
+
globalThis.minifyProbe = describeHeader()`);
|
|
1393
|
+
return root2;
|
|
1394
|
+
}
|
|
1395
|
+
function runFixture(code) {
|
|
1396
|
+
const context = {
|
|
1397
|
+
console
|
|
1398
|
+
};
|
|
1399
|
+
runInNewContext(code, context);
|
|
1400
|
+
return Reflect.get(context, "minifyProbe");
|
|
1401
|
+
}
|
|
1402
|
+
it("minifies when asked, leaves the bundle alone when not, and both behave the same", async () => {
|
|
1403
|
+
const root2 = await writeMinifyFixture();
|
|
1404
|
+
try {
|
|
1405
|
+
const [plain, minified] = await Promise.all([false, true].map(minify => buildNativeBundle({
|
|
1406
|
+
root: root2,
|
|
1407
|
+
platform: "ios",
|
|
1408
|
+
entryFile: "entry.js",
|
|
1409
|
+
minify
|
|
1410
|
+
})));
|
|
1411
|
+
expect(plain.code).toContain("__toESM");
|
|
1412
|
+
expect(plain.code).toContain("describeHeader");
|
|
1413
|
+
expect(plain.code.split("\n").length).toBeGreaterThan(40);
|
|
1414
|
+
expect(minified.code).not.toContain("describeHeader");
|
|
1415
|
+
expect(minified.code).not.toContain("//#region");
|
|
1416
|
+
expect(minified.code.length).toBeLessThan(plain.code.length * .7);
|
|
1417
|
+
expect(runFixture(minified.code)).toBe("legacy:header");
|
|
1418
|
+
expect(runFixture(plain.code)).toBe("legacy:header");
|
|
1419
|
+
} finally {
|
|
1420
|
+
await rm(root2, {
|
|
1421
|
+
recursive: true,
|
|
1422
|
+
force: true
|
|
1423
|
+
});
|
|
1424
|
+
}
|
|
1425
|
+
});
|
|
1426
|
+
it("defaults to react native's rule: minify a production bundle, never a dev one", async () => {
|
|
1427
|
+
const root2 = await writeMinifyFixture();
|
|
1428
|
+
try {
|
|
1429
|
+
const [prod, devBundle, explicitOff] = await Promise.all([buildNativeBundle({
|
|
1430
|
+
root: root2,
|
|
1431
|
+
platform: "ios",
|
|
1432
|
+
entryFile: "entry.js"
|
|
1433
|
+
}), buildNativeBundle({
|
|
1434
|
+
root: root2,
|
|
1435
|
+
platform: "ios",
|
|
1436
|
+
entryFile: "entry.js",
|
|
1437
|
+
dev: true
|
|
1438
|
+
}), buildNativeBundle({
|
|
1439
|
+
root: root2,
|
|
1440
|
+
platform: "ios",
|
|
1441
|
+
entryFile: "entry.js",
|
|
1442
|
+
minify: false
|
|
1443
|
+
})]);
|
|
1444
|
+
expect(prod.code).not.toContain("describeHeader");
|
|
1445
|
+
expect(devBundle.code).toContain("describeHeader");
|
|
1446
|
+
expect(explicitOff.code).toContain("describeHeader");
|
|
1447
|
+
expect(prod.code.length).toBeLessThan(explicitOff.code.length);
|
|
1448
|
+
} finally {
|
|
1449
|
+
await rm(root2, {
|
|
1450
|
+
recursive: true,
|
|
1451
|
+
force: true
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
});
|
|
1455
|
+
});
|
|
1273
1456
|
describe("native production assets", () => {
|
|
1274
1457
|
it("registers scale siblings and keeps monorepo assets inside assetsDest", async () => {
|
|
1275
1458
|
const testRoot = await mkdtemp(join(tmpdir(), "vxrn-native-assets-"));
|
|
@@ -1303,12 +1486,23 @@ globalThis.__nativeAssetProbe = [icon, back]
|
|
|
1303
1486
|
expect(registry.resolve("/assets/assets/icon@2x.png", assetData.hash)?.filePath).toBe(join(appAssets, "icon@2x.png"));
|
|
1304
1487
|
expect(registry.resolve("/assets/assets/icon.png", "stale-content-hash")).toBeUndefined();
|
|
1305
1488
|
expect(registry.resolve("/assets/../../package.json", assetData.hash)).toBeUndefined();
|
|
1306
|
-
|
|
1489
|
+
const result = await buildNativeBundle({
|
|
1307
1490
|
root: appRoot,
|
|
1308
1491
|
platform: "ios",
|
|
1309
1492
|
entryFile: "entry.js",
|
|
1310
1493
|
assetsDest
|
|
1311
|
-
})
|
|
1494
|
+
});
|
|
1495
|
+
const registered = [];
|
|
1496
|
+
runInNewContext(result.code, {
|
|
1497
|
+
console,
|
|
1498
|
+
require: id => id === "react-native/Libraries/Image/AssetRegistry" ? {
|
|
1499
|
+
registerAsset: asset => {
|
|
1500
|
+
registered.push(asset);
|
|
1501
|
+
return asset;
|
|
1502
|
+
}
|
|
1503
|
+
} : {}
|
|
1504
|
+
});
|
|
1505
|
+
expect(registered.map(asset => [asset.name, asset.scales])).toEqual([["icon", [1, 2, 3]], ["back", [1, 2]]]);
|
|
1312
1506
|
for (const file of ["icon.png", "icon@2x.png", "icon@3x.png"]) expect(existsSync(join(assetsDest, "assets/assets", file))).toBe(true);
|
|
1313
1507
|
for (const file of ["back.png", "back@2x.png"]) expect(existsSync(join(assetsDest, "assets/_/_/node_modules/example/assets", file))).toBe(true);
|
|
1314
1508
|
expect(existsSync(join(testRoot, "node_modules/example/assets/back.png"))).toBe(false);
|
|
@@ -1523,4 +1717,72 @@ globalThis.__vxrnFlowProbe = new Flowy().measure({ value: 41 }) + 1
|
|
|
1523
1717
|
}
|
|
1524
1718
|
});
|
|
1525
1719
|
});
|
|
1720
|
+
describe("native bundle source maps", () => {
|
|
1721
|
+
const generatedPositionOf = (code, marker) => {
|
|
1722
|
+
const index = code.indexOf(marker);
|
|
1723
|
+
expect(index).toBeGreaterThan(-1);
|
|
1724
|
+
const before = code.slice(0, index);
|
|
1725
|
+
const lastNewline = before.lastIndexOf("\n");
|
|
1726
|
+
return {
|
|
1727
|
+
line: (before.match(/\n/g)?.length ?? 0) + 1,
|
|
1728
|
+
column: index - lastNewline - 1
|
|
1729
|
+
};
|
|
1730
|
+
};
|
|
1731
|
+
it("resolves a frame to the authored file and line across an app file and a package file", {
|
|
1732
|
+
timeout: 6e4
|
|
1733
|
+
}, async () => {
|
|
1734
|
+
const testRoot = realpathSync(await mkdtemp(join(tmpdir(), "vxrn-native-sourcemap-")));
|
|
1735
|
+
const packageRoot = join(testRoot, "node_modules/probe-package");
|
|
1736
|
+
await mkdir(packageRoot, {
|
|
1737
|
+
recursive: true
|
|
1738
|
+
});
|
|
1739
|
+
await writeFile(join(packageRoot, "package.json"), JSON.stringify({
|
|
1740
|
+
name: "probe-package",
|
|
1741
|
+
main: "index.js",
|
|
1742
|
+
type: "module"
|
|
1743
|
+
}));
|
|
1744
|
+
await writeFile(join(packageRoot, "index.js"), [`function packageThrow() {`, ` throw new Error('__probe_package__')`, `}`, ``, `export default packageThrow`].join("\n"));
|
|
1745
|
+
await writeFile(join(testRoot, "entry.js"), [`import packageThrow from 'probe-package'`, ``, `function appThrow() {`, ` throw new Error('__probe_app__')`, `}`, ``, `globalThis.__probe = [appThrow, packageThrow]`].join("\n"));
|
|
1746
|
+
try {
|
|
1747
|
+
const result = await buildNativeBundle({
|
|
1748
|
+
root: testRoot,
|
|
1749
|
+
platform: "ios",
|
|
1750
|
+
entryFile: "entry.js",
|
|
1751
|
+
dev: true,
|
|
1752
|
+
sourcemap: true
|
|
1753
|
+
});
|
|
1754
|
+
expect(result.map).toBeTruthy();
|
|
1755
|
+
const traced = new TraceMap(JSON.parse(result.map));
|
|
1756
|
+
const app = originalPositionFor(traced, generatedPositionOf(result.code, "__probe_app__"));
|
|
1757
|
+
const pkg = originalPositionFor(traced, generatedPositionOf(result.code, "__probe_package__"));
|
|
1758
|
+
expect(app.source?.endsWith("/entry.js")).toBe(true);
|
|
1759
|
+
expect(app.line).toBe(4);
|
|
1760
|
+
expect(pkg.source?.endsWith("/index.js")).toBe(true);
|
|
1761
|
+
expect(pkg.line).toBe(2);
|
|
1762
|
+
expect(app.source).toBe(normalizePath(join(testRoot, "entry.js")));
|
|
1763
|
+
expect(pkg.source).toBe(normalizePath(join(packageRoot, "index.js")));
|
|
1764
|
+
} finally {
|
|
1765
|
+
await rm(testRoot, {
|
|
1766
|
+
recursive: true,
|
|
1767
|
+
force: true
|
|
1768
|
+
});
|
|
1769
|
+
}
|
|
1770
|
+
});
|
|
1771
|
+
});
|
|
1772
|
+
describe("postProcessNativeBundle", () => {
|
|
1773
|
+
const lines = code => code.split("\n").length;
|
|
1774
|
+
it("keeps the blank line above an export default", () => {
|
|
1775
|
+
const input = ["var a = 1;", "", "export default a;", "var b = 2;", ""].join("\n");
|
|
1776
|
+
const out = postProcessNativeBundle(input);
|
|
1777
|
+
expect(lines(out)).toBe(lines(input));
|
|
1778
|
+
expect(out.split("\n")[2]).toBe("a;");
|
|
1779
|
+
});
|
|
1780
|
+
it("keeps the lines of a multi-line export statement", () => {
|
|
1781
|
+
const input = ["var a = 1;", "export {", " a", "};", "var b = 2;", ""].join("\n");
|
|
1782
|
+
const out = postProcessNativeBundle(input);
|
|
1783
|
+
expect(lines(out)).toBe(lines(input));
|
|
1784
|
+
expect(out).not.toContain("export {");
|
|
1785
|
+
expect(out.split("\n")[4]).toBe("var b = 2;");
|
|
1786
|
+
});
|
|
1787
|
+
});
|
|
1526
1788
|
//# sourceMappingURL=createNativeDevEngine.test.mjs.map
|