@vxrn/compiler 1.25.16 → 1.26.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/dist/cjs/cache.cjs +4 -2
- package/dist/cjs/configure.cjs +9 -1
- package/dist/cjs/index.cjs +87 -5
- package/dist/cjs/reactNativeCodegen.cjs +140 -0
- package/dist/cjs/reactNativeViewConfig.cjs +489 -0
- package/dist/cjs/transformBabel.cjs +15 -20
- package/dist/cjs/transformBabel.test.cjs +260 -0
- package/dist/cjs/transformHermesAsync.cjs +61 -0
- package/dist/cjs/transformHermesLoops.cjs +319 -0
- package/dist/cjs/transformHermesLoops.test.cjs +257 -0
- package/dist/cjs/transformSWC.cjs +110 -138
- package/dist/cjs/transformSWC.test.cjs +117 -0
- package/dist/cjs/transformWorklets.cjs +123 -0
- package/dist/cjs/transformWorklets.test.cjs +604 -0
- package/dist/cjs/worklets/autoworklet.cjs +265 -0
- package/dist/cjs/worklets/globals.cjs +73 -0
- package/dist/cjs/worklets/hash.cjs +38 -0
- package/dist/cjs/worklets/scope.cjs +370 -0
- package/dist/cjs/worklets/serialize.cjs +101 -0
- package/dist/cjs/worklets/transform.cjs +266 -0
- package/dist/cjs/worklets/types.cjs +18 -0
- package/dist/esm/cache.mjs +5 -3
- package/dist/esm/cache.mjs.map +1 -1
- package/dist/esm/configure.mjs +8 -1
- package/dist/esm/configure.mjs.map +1 -1
- package/dist/esm/index.js +75 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +75 -6
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/reactNativeCodegen.mjs +104 -0
- package/dist/esm/reactNativeCodegen.mjs.map +1 -0
- package/dist/esm/reactNativeViewConfig.mjs +460 -0
- package/dist/esm/reactNativeViewConfig.mjs.map +1 -0
- package/dist/esm/transformBabel.mjs +14 -19
- package/dist/esm/transformBabel.mjs.map +1 -1
- package/dist/esm/transformBabel.test.mjs +261 -1
- package/dist/esm/transformBabel.test.mjs.map +1 -1
- package/dist/esm/transformHermesAsync.mjs +25 -0
- package/dist/esm/transformHermesAsync.mjs.map +1 -0
- package/dist/esm/transformHermesLoops.mjs +283 -0
- package/dist/esm/transformHermesLoops.mjs.map +1 -0
- package/dist/esm/transformHermesLoops.test.mjs +234 -0
- package/dist/esm/transformHermesLoops.test.mjs.map +1 -0
- package/dist/esm/transformSWC.mjs +96 -139
- package/dist/esm/transformSWC.mjs.map +1 -1
- package/dist/esm/transformSWC.test.mjs +118 -0
- package/dist/esm/transformSWC.test.mjs.map +1 -0
- package/dist/esm/transformWorklets.mjs +82 -0
- package/dist/esm/transformWorklets.mjs.map +1 -0
- package/dist/esm/transformWorklets.test.mjs +581 -0
- package/dist/esm/transformWorklets.test.mjs.map +1 -0
- package/dist/esm/worklets/autoworklet.mjs +234 -0
- package/dist/esm/worklets/autoworklet.mjs.map +1 -0
- package/dist/esm/worklets/globals.mjs +46 -0
- package/dist/esm/worklets/globals.mjs.map +1 -0
- package/dist/esm/worklets/hash.mjs +13 -0
- package/dist/esm/worklets/hash.mjs.map +1 -0
- package/dist/esm/worklets/scope.mjs +345 -0
- package/dist/esm/worklets/scope.mjs.map +1 -0
- package/dist/esm/worklets/serialize.mjs +75 -0
- package/dist/esm/worklets/serialize.mjs.map +1 -0
- package/dist/esm/worklets/transform.mjs +229 -0
- package/dist/esm/worklets/transform.mjs.map +1 -0
- package/dist/esm/worklets/types.mjs +2 -0
- package/dist/esm/worklets/types.mjs.map +1 -0
- package/package.json +11 -6
- package/src/cache.ts +10 -3
- package/src/configure.ts +12 -0
- package/src/index.ts +96 -13
- package/src/reactNativeCodegen.ts +181 -0
- package/src/reactNativeViewConfig.ts +593 -0
- package/src/transformBabel.test.ts +268 -1
- package/src/transformBabel.ts +21 -31
- package/src/transformHermesAsync.ts +30 -0
- package/src/transformHermesLoops.test.ts +341 -0
- package/src/transformHermesLoops.ts +435 -0
- package/src/transformSWC.test.ts +132 -0
- package/src/transformSWC.ts +121 -161
- package/src/transformWorklets.test.ts +708 -0
- package/src/transformWorklets.ts +160 -0
- package/src/types.ts +4 -4
- package/src/worklets/autoworklet.ts +391 -0
- package/src/worklets/globals.ts +129 -0
- package/src/worklets/hash.ts +14 -0
- package/src/worklets/scope.ts +401 -0
- package/src/worklets/serialize.ts +114 -0
- package/src/worklets/transform.ts +319 -0
- package/src/worklets/types.ts +26 -0
- package/types/cache.d.ts +1 -0
- package/types/cache.d.ts.map +1 -1
- package/types/configure.d.ts +2 -0
- package/types/configure.d.ts.map +1 -1
- package/types/index.d.ts +6 -0
- package/types/index.d.ts.map +1 -1
- package/types/reactNativeCodegen.d.ts +5 -0
- package/types/reactNativeCodegen.d.ts.map +1 -0
- package/types/reactNativeViewConfig.d.ts +35 -0
- package/types/reactNativeViewConfig.d.ts.map +1 -0
- package/types/transformBabel.d.ts +3 -3
- package/types/transformBabel.d.ts.map +1 -1
- package/types/transformHermesAsync.d.ts +5 -0
- package/types/transformHermesAsync.d.ts.map +1 -0
- package/types/transformHermesLoops.d.ts +5 -0
- package/types/transformHermesLoops.d.ts.map +1 -0
- package/types/transformHermesLoops.test.d.ts +2 -0
- package/types/transformHermesLoops.test.d.ts.map +1 -0
- package/types/transformSWC.d.ts +13 -3
- package/types/transformSWC.d.ts.map +1 -1
- package/types/transformSWC.test.d.ts +2 -0
- package/types/transformSWC.test.d.ts.map +1 -0
- package/types/transformWorklets.d.ts +23 -0
- package/types/transformWorklets.d.ts.map +1 -0
- package/types/transformWorklets.test.d.ts +2 -0
- package/types/transformWorklets.test.d.ts.map +1 -0
- package/types/types.d.ts +4 -4
- package/types/types.d.ts.map +1 -1
- package/types/worklets/autoworklet.d.ts +14 -0
- package/types/worklets/autoworklet.d.ts.map +1 -0
- package/types/worklets/globals.d.ts +4 -0
- package/types/worklets/globals.d.ts.map +1 -0
- package/types/worklets/hash.d.ts +5 -0
- package/types/worklets/hash.d.ts.map +1 -0
- package/types/worklets/scope.d.ts +7 -0
- package/types/worklets/scope.d.ts.map +1 -0
- package/types/worklets/serialize.d.ts +12 -0
- package/types/worklets/serialize.d.ts.map +1 -0
- package/types/worklets/transform.d.ts +10 -0
- package/types/worklets/transform.d.ts.map +1 -0
- package/types/worklets/types.d.ts +21 -0
- package/types/worklets/types.d.ts.map +1 -0
|
@@ -97,4 +97,264 @@ var import_transformBabel = require("./transformBabel.cjs");
|
|
|
97
97
|
plugins: [negativeControl]
|
|
98
98
|
})).rejects.toThrow("NATIVE_TRANSFORM_NEGATIVE_CONTROL");
|
|
99
99
|
});
|
|
100
|
+
});
|
|
101
|
+
(0, import_vitest.describe)("transformOxcReactCompiler", () => {
|
|
102
|
+
const componentCode = `
|
|
103
|
+
import { useState } from 'react'
|
|
104
|
+
|
|
105
|
+
export function Counter() {
|
|
106
|
+
const [count, setCount] = useState(0)
|
|
107
|
+
return <button onClick={() => setCount(count + 1)}>{count}</button>
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
(0, import_vitest.it)("compiles and memoizes React components with Rust React Compiler", async () => {
|
|
111
|
+
const result = await (0, import_transformBabel.transformOxcReactCompiler)("/project/Counter.tsx", componentCode, "19", false);
|
|
112
|
+
(0, import_vitest.expect)(result.code).toContain("_c(");
|
|
113
|
+
(0, import_vitest.expect)(result.code).toContain("react/compiler-runtime");
|
|
114
|
+
(0, import_vitest.expect)(result.map).toBeUndefined();
|
|
115
|
+
});
|
|
116
|
+
(0, import_vitest.it)("generates source maps when requested", async () => {
|
|
117
|
+
const result = await (0, import_transformBabel.transformOxcReactCompiler)("/project/Counter.tsx", componentCode, "19", true);
|
|
118
|
+
(0, import_vitest.expect)(result.code).toContain("_c(");
|
|
119
|
+
(0, import_vitest.expect)(result.map).toBeDefined();
|
|
120
|
+
(0, import_vitest.expect)(result.map?.mappings).toBeDefined();
|
|
121
|
+
});
|
|
122
|
+
(0, import_vitest.it)("supports target 18", async () => {
|
|
123
|
+
const result = await (0, import_transformBabel.transformOxcReactCompiler)("/project/Counter.tsx", componentCode, "18", false);
|
|
124
|
+
(0, import_vitest.expect)(result.code).toContain("_c(");
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
(0, import_vitest.describe)("compiler plugin multi-stage source map composition", () => {
|
|
128
|
+
(0, import_vitest.it)("composes earlier compiler maps when Babel also runs", async () => {
|
|
129
|
+
const {
|
|
130
|
+
createVXRNCompilerPlugin
|
|
131
|
+
} = await import("./index");
|
|
132
|
+
const {
|
|
133
|
+
TraceMap,
|
|
134
|
+
originalPositionFor
|
|
135
|
+
} = await import("@jridgewell/trace-mapping");
|
|
136
|
+
const origSourceMap = process.env.VXRN_ENABLE_SOURCE_MAP;
|
|
137
|
+
const origBabelGen = process.env.VXRN_USE_BABEL_FOR_GENERATORS;
|
|
138
|
+
process.env.VXRN_ENABLE_SOURCE_MAP = "1";
|
|
139
|
+
process.env.VXRN_USE_BABEL_FOR_GENERATORS = "1";
|
|
140
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
141
|
+
enableCompiler: true
|
|
142
|
+
});
|
|
143
|
+
const tempFile = import_node_path.default.join(import_node_os.default.tmpdir(), `Counter-${Date.now()}.tsx`);
|
|
144
|
+
import_node_fs.default.writeFileSync(tempFile, `import { useState } from 'react'
|
|
145
|
+
|
|
146
|
+
export function Counter() {
|
|
147
|
+
const [count, setCount] = useState(0)
|
|
148
|
+
return <button onClick={() => setCount(count + 1)}>{count}</button>
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export async function* generatorProbe() {
|
|
152
|
+
throw new Error("MARKER")
|
|
153
|
+
}
|
|
154
|
+
`);
|
|
155
|
+
try {
|
|
156
|
+
const plugins = await createVXRNCompilerPlugin();
|
|
157
|
+
const plugin = plugins.find(p => p.name === "one:compiler");
|
|
158
|
+
await plugin.configResolved({
|
|
159
|
+
root: import_node_os.default.tmpdir(),
|
|
160
|
+
build: {}
|
|
161
|
+
});
|
|
162
|
+
const hook = plugin.transform.handler || plugin.transform;
|
|
163
|
+
const code = import_node_fs.default.readFileSync(tempFile, "utf8");
|
|
164
|
+
const context = {
|
|
165
|
+
environment: {
|
|
166
|
+
name: "client"
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
const result = await hook.call(context, code, tempFile);
|
|
170
|
+
(0, import_vitest.expect)(result).toBeDefined();
|
|
171
|
+
(0, import_vitest.expect)(result.map).toBeDefined();
|
|
172
|
+
const tracer = new TraceMap(result.map);
|
|
173
|
+
const lines = result.code.split("\n");
|
|
174
|
+
const markerLineIndex = lines.findIndex(l => l.includes("MARKER"));
|
|
175
|
+
(0, import_vitest.expect)(markerLineIndex).toBeGreaterThan(0);
|
|
176
|
+
const markerCol = lines[markerLineIndex].indexOf("throw");
|
|
177
|
+
const pos = originalPositionFor(tracer, {
|
|
178
|
+
line: markerLineIndex + 1,
|
|
179
|
+
column: markerCol
|
|
180
|
+
});
|
|
181
|
+
(0, import_vitest.expect)(pos.source).toBe(tempFile);
|
|
182
|
+
(0, import_vitest.expect)(pos.line).toBe(9);
|
|
183
|
+
} finally {
|
|
184
|
+
if (origSourceMap !== void 0) {
|
|
185
|
+
process.env.VXRN_ENABLE_SOURCE_MAP = origSourceMap;
|
|
186
|
+
} else {
|
|
187
|
+
delete process.env.VXRN_ENABLE_SOURCE_MAP;
|
|
188
|
+
}
|
|
189
|
+
if (origBabelGen !== void 0) {
|
|
190
|
+
process.env.VXRN_USE_BABEL_FOR_GENERATORS = origBabelGen;
|
|
191
|
+
} else {
|
|
192
|
+
delete process.env.VXRN_USE_BABEL_FOR_GENERATORS;
|
|
193
|
+
}
|
|
194
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
195
|
+
enableCompiler: false
|
|
196
|
+
});
|
|
197
|
+
import_node_fs.default.rmSync(tempFile, {
|
|
198
|
+
force: true
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
(0, import_vitest.describe)("shared compiler worklets backend selection", () => {
|
|
204
|
+
(0, import_vitest.it)("retains Babel for worklets by default when enableNativeWorklets is false", async () => {
|
|
205
|
+
const {
|
|
206
|
+
vi
|
|
207
|
+
} = await import("vitest");
|
|
208
|
+
const {
|
|
209
|
+
createVXRNCompilerPlugin
|
|
210
|
+
} = await import("./index");
|
|
211
|
+
const workletsModule = await import("./transformWorklets");
|
|
212
|
+
const workletSpy = vi.spyOn(workletsModule, "transformWorklets");
|
|
213
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
214
|
+
enableReanimated: true,
|
|
215
|
+
enableNativeWorklets: false
|
|
216
|
+
});
|
|
217
|
+
const tempFile = import_node_path.default.join(process.cwd(), `test-default-worklet-${Date.now()}.tsx`);
|
|
218
|
+
const inputCode = `export function fn() { 'worklet'; return 1 }`;
|
|
219
|
+
import_node_fs.default.writeFileSync(tempFile, inputCode);
|
|
220
|
+
try {
|
|
221
|
+
const plugins = await createVXRNCompilerPlugin();
|
|
222
|
+
const plugin = plugins.find(p => p.name === "one:compiler");
|
|
223
|
+
await plugin.configResolved({
|
|
224
|
+
root: process.cwd(),
|
|
225
|
+
build: {}
|
|
226
|
+
});
|
|
227
|
+
const hook = plugin.transform.handler || plugin.transform;
|
|
228
|
+
const context = {
|
|
229
|
+
environment: {
|
|
230
|
+
name: "ios"
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
const result = await hook.call(context, inputCode, tempFile);
|
|
234
|
+
(0, import_vitest.expect)(result).toBeDefined();
|
|
235
|
+
(0, import_vitest.expect)(workletSpy).not.toHaveBeenCalled();
|
|
236
|
+
} finally {
|
|
237
|
+
workletSpy.mockRestore();
|
|
238
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
239
|
+
enableReanimated: false,
|
|
240
|
+
enableNativeWorklets: false
|
|
241
|
+
});
|
|
242
|
+
import_node_fs.default.rmSync(tempFile, {
|
|
243
|
+
force: true
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
(0, import_vitest.it)("uses native SWC for worklets when enableNativeWorklets is true", async () => {
|
|
248
|
+
const compiler = await import("./index");
|
|
249
|
+
const {
|
|
250
|
+
vi
|
|
251
|
+
} = await import("vitest");
|
|
252
|
+
const workletsModule = await import("./transformWorklets");
|
|
253
|
+
const workletSpy = vi.spyOn(workletsModule, "transformWorklets");
|
|
254
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
255
|
+
enableReanimated: true,
|
|
256
|
+
enableNativeWorklets: true
|
|
257
|
+
});
|
|
258
|
+
const tempFile = import_node_path.default.join(process.cwd(), `test-native-worklet-${Date.now()}.tsx`);
|
|
259
|
+
const inputCode = `export function fn() { 'worklet'; return 1 }`;
|
|
260
|
+
import_node_fs.default.writeFileSync(tempFile, inputCode);
|
|
261
|
+
try {
|
|
262
|
+
const plugins = await compiler.createVXRNCompilerPlugin();
|
|
263
|
+
const plugin = plugins.find(p => p.name === "one:compiler");
|
|
264
|
+
await plugin.configResolved({
|
|
265
|
+
root: process.cwd(),
|
|
266
|
+
build: {}
|
|
267
|
+
});
|
|
268
|
+
const hook = plugin.transform.handler || plugin.transform;
|
|
269
|
+
const context = {
|
|
270
|
+
environment: {
|
|
271
|
+
name: "ios"
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
const result = await hook.call(context, inputCode, tempFile);
|
|
275
|
+
(0, import_vitest.expect)(result).toBeDefined();
|
|
276
|
+
(0, import_vitest.expect)(workletSpy).toHaveBeenCalled();
|
|
277
|
+
} finally {
|
|
278
|
+
workletSpy.mockRestore();
|
|
279
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
280
|
+
enableReanimated: false,
|
|
281
|
+
enableNativeWorklets: false
|
|
282
|
+
});
|
|
283
|
+
import_node_fs.default.rmSync(tempFile, {
|
|
284
|
+
force: true
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
(0, import_vitest.it)("invalidates cache when toggling worklets backend on the same unchanged file", async () => {
|
|
289
|
+
const compiler = await import("./index");
|
|
290
|
+
const {
|
|
291
|
+
vi
|
|
292
|
+
} = await import("vitest");
|
|
293
|
+
const workletsModule = await import("./transformWorklets");
|
|
294
|
+
const workletSpy = vi.spyOn(workletsModule, "transformWorklets");
|
|
295
|
+
const tempFile = import_node_path.default.join(process.cwd(), `test-cache-toggle-${Date.now()}.tsx`);
|
|
296
|
+
const inputCode = `export function fn() { 'worklet'; return 1 }`;
|
|
297
|
+
import_node_fs.default.writeFileSync(tempFile, inputCode);
|
|
298
|
+
try {
|
|
299
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
300
|
+
enableReanimated: true,
|
|
301
|
+
enableNativeWorklets: false
|
|
302
|
+
});
|
|
303
|
+
const plugins1 = await compiler.createVXRNCompilerPlugin();
|
|
304
|
+
const plugin1 = plugins1.find(p => p.name === "one:compiler");
|
|
305
|
+
await plugin1.configResolved({
|
|
306
|
+
root: process.cwd(),
|
|
307
|
+
build: {}
|
|
308
|
+
});
|
|
309
|
+
const hook1 = plugin1.transform.handler || plugin1.transform;
|
|
310
|
+
const context = {
|
|
311
|
+
environment: {
|
|
312
|
+
name: "ios"
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
const res1 = await hook1.call(context, inputCode, tempFile);
|
|
316
|
+
(0, import_vitest.expect)(res1).toBeDefined();
|
|
317
|
+
(0, import_vitest.expect)(workletSpy).toHaveBeenCalledTimes(0);
|
|
318
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
319
|
+
enableReanimated: true,
|
|
320
|
+
enableNativeWorklets: true
|
|
321
|
+
});
|
|
322
|
+
const plugins2 = await compiler.createVXRNCompilerPlugin();
|
|
323
|
+
const plugin2 = plugins2.find(p => p.name === "one:compiler");
|
|
324
|
+
await plugin2.configResolved({
|
|
325
|
+
root: process.cwd(),
|
|
326
|
+
build: {}
|
|
327
|
+
});
|
|
328
|
+
const hook2 = plugin2.transform.handler || plugin2.transform;
|
|
329
|
+
const res2 = await hook2.call(context, inputCode, tempFile);
|
|
330
|
+
(0, import_vitest.expect)(res2).toBeDefined();
|
|
331
|
+
(0, import_vitest.expect)(workletSpy).toHaveBeenCalledTimes(1);
|
|
332
|
+
const res3 = await hook2.call(context, inputCode, tempFile);
|
|
333
|
+
(0, import_vitest.expect)(res3).toBeDefined();
|
|
334
|
+
(0, import_vitest.expect)(workletSpy).toHaveBeenCalledTimes(1);
|
|
335
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
336
|
+
enableReanimated: true,
|
|
337
|
+
enableNativeWorklets: false
|
|
338
|
+
});
|
|
339
|
+
const plugins3 = await compiler.createVXRNCompilerPlugin();
|
|
340
|
+
const plugin3 = plugins3.find(p => p.name === "one:compiler");
|
|
341
|
+
await plugin3.configResolved({
|
|
342
|
+
root: process.cwd(),
|
|
343
|
+
build: {}
|
|
344
|
+
});
|
|
345
|
+
const hook3 = plugin3.transform.handler || plugin3.transform;
|
|
346
|
+
const res4 = await hook3.call(context, inputCode, tempFile);
|
|
347
|
+
(0, import_vitest.expect)(res4).toBeDefined();
|
|
348
|
+
(0, import_vitest.expect)(workletSpy).toHaveBeenCalledTimes(1);
|
|
349
|
+
} finally {
|
|
350
|
+
workletSpy.mockRestore();
|
|
351
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
352
|
+
enableReanimated: false,
|
|
353
|
+
enableNativeWorklets: false
|
|
354
|
+
});
|
|
355
|
+
import_node_fs.default.rmSync(tempFile, {
|
|
356
|
+
force: true
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
});
|
|
100
360
|
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all) __defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: true
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
16
|
+
get: () => from[key],
|
|
17
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
28
|
+
value: mod,
|
|
29
|
+
enumerable: true
|
|
30
|
+
}) : target, mod));
|
|
31
|
+
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
32
|
+
value: true
|
|
33
|
+
}), mod);
|
|
34
|
+
var transformHermesAsync_exports = {};
|
|
35
|
+
__export(transformHermesAsync_exports, {
|
|
36
|
+
transformHermesAsync: () => transformHermesAsync
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(transformHermesAsync_exports);
|
|
39
|
+
async function transformHermesAsync(code, filename, sourceMaps = false, format) {
|
|
40
|
+
if (!format && !code.includes("async")) return;
|
|
41
|
+
const {
|
|
42
|
+
transformSync
|
|
43
|
+
} = await import("esbuild");
|
|
44
|
+
const cleanId = filename.split("?")[0];
|
|
45
|
+
const result = transformSync(code, {
|
|
46
|
+
loader: /\.[cm]?ts$/.test(cleanId) ? "ts" : cleanId.endsWith(".tsx") ? "tsx" : "jsx",
|
|
47
|
+
jsx: "preserve",
|
|
48
|
+
format,
|
|
49
|
+
supported: {
|
|
50
|
+
"async-await": false,
|
|
51
|
+
"async-generator": false,
|
|
52
|
+
"for-await": false
|
|
53
|
+
},
|
|
54
|
+
sourcefile: filename,
|
|
55
|
+
sourcemap: sourceMaps ? "external" : false
|
|
56
|
+
});
|
|
57
|
+
return {
|
|
58
|
+
code: result.code,
|
|
59
|
+
map: result.map ? JSON.parse(result.map) : void 0
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all) __defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: true
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
16
|
+
get: () => from[key],
|
|
17
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
28
|
+
value: mod,
|
|
29
|
+
enumerable: true
|
|
30
|
+
}) : target, mod));
|
|
31
|
+
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
32
|
+
value: true
|
|
33
|
+
}), mod);
|
|
34
|
+
var transformHermesLoops_exports = {};
|
|
35
|
+
__export(transformHermesLoops_exports, {
|
|
36
|
+
transformHermesLoops: () => transformHermesLoops
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(transformHermesLoops_exports);
|
|
39
|
+
var import_magic_string = __toESM(require("magic-string"), 1);
|
|
40
|
+
var import_oxc_parser = require("oxc-parser");
|
|
41
|
+
const LOOP_RE = /\b(?:for|while)\s*(?:await\s+)?\(/;
|
|
42
|
+
const LEXICAL_RE = /\b(?:let|const|class)\b/;
|
|
43
|
+
function langFor(filename) {
|
|
44
|
+
const ext = filename.split("?")[0].split(".").pop() || "js";
|
|
45
|
+
if (ext === "ts" || ext === "cts" || ext === "mts") return "ts";
|
|
46
|
+
if (ext === "tsx") return "tsx";
|
|
47
|
+
return "jsx";
|
|
48
|
+
}
|
|
49
|
+
function collectPatternNames(node, out) {
|
|
50
|
+
if (!node || typeof node !== "object") return;
|
|
51
|
+
switch (node.type) {
|
|
52
|
+
case "Identifier":
|
|
53
|
+
out.push(node.name);
|
|
54
|
+
return;
|
|
55
|
+
case "ObjectPattern":
|
|
56
|
+
for (const p of node.properties || []) {
|
|
57
|
+
collectPatternNames(p.value ?? p.argument, out);
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
case "ArrayPattern":
|
|
61
|
+
for (const el of node.elements || []) collectPatternNames(el, out);
|
|
62
|
+
return;
|
|
63
|
+
case "AssignmentPattern":
|
|
64
|
+
collectPatternNames(node.left, out);
|
|
65
|
+
return;
|
|
66
|
+
case "RestElement":
|
|
67
|
+
collectPatternNames(node.argument, out);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const FUNCTION_TYPES = /* @__PURE__ */new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]);
|
|
72
|
+
function eachChild(node, fn) {
|
|
73
|
+
for (const key in node) {
|
|
74
|
+
if (key === "type" || key === "start" || key === "end" || key === "parent") continue;
|
|
75
|
+
const value = node[key];
|
|
76
|
+
if (Array.isArray(value)) {
|
|
77
|
+
for (const item of value) {
|
|
78
|
+
if (item && typeof item.type === "string") fn(item);
|
|
79
|
+
}
|
|
80
|
+
} else if (value && typeof value === "object" && typeof value.type === "string") {
|
|
81
|
+
fn(value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function capturesInClosure(body, names) {
|
|
86
|
+
let found = false;
|
|
87
|
+
function scanInsideFunction(node, shadowed) {
|
|
88
|
+
if (found || !node || typeof node !== "object") return;
|
|
89
|
+
if (node.type === "Identifier" && names.has(node.name) && !shadowed.has(node.name)) {
|
|
90
|
+
found = true;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (FUNCTION_TYPES.has(node.type)) {
|
|
94
|
+
const inner = new Set(shadowed);
|
|
95
|
+
const params = [];
|
|
96
|
+
for (const p of node.params || []) collectPatternNames(p, params);
|
|
97
|
+
for (const p of params) inner.add(p);
|
|
98
|
+
if (node.id?.name) inner.add(node.id.name);
|
|
99
|
+
eachChild(node, c => scanInsideFunction(c, inner));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (node.type === "MemberExpression" && !node.computed) {
|
|
103
|
+
scanInsideFunction(node.object, shadowed);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (node.type === "Property" && !node.computed && node.key === node.value) {
|
|
107
|
+
scanInsideFunction(node.value, shadowed);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
eachChild(node, c => scanInsideFunction(c, shadowed));
|
|
111
|
+
}
|
|
112
|
+
function walk(node) {
|
|
113
|
+
if (found || !node || typeof node !== "object") return;
|
|
114
|
+
if (FUNCTION_TYPES.has(node.type)) {
|
|
115
|
+
const shadowed = /* @__PURE__ */new Set();
|
|
116
|
+
const params = [];
|
|
117
|
+
for (const p of node.params || []) collectPatternNames(p, params);
|
|
118
|
+
for (const p of params) shadowed.add(p);
|
|
119
|
+
eachChild(node, c => scanInsideFunction(c, shadowed));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
eachChild(node, walk);
|
|
123
|
+
}
|
|
124
|
+
walk(body);
|
|
125
|
+
return found;
|
|
126
|
+
}
|
|
127
|
+
function analyzeBody(body, names) {
|
|
128
|
+
const facts = {
|
|
129
|
+
hasBreak: false,
|
|
130
|
+
hasContinue: false,
|
|
131
|
+
hasReturn: false,
|
|
132
|
+
hasAwait: false,
|
|
133
|
+
hasYield: false,
|
|
134
|
+
assignsBinding: false,
|
|
135
|
+
hasLabeledJump: false
|
|
136
|
+
};
|
|
137
|
+
function walk(node, inNestedBreakable, inNestedLoop, inFunction) {
|
|
138
|
+
if (!node || typeof node !== "object") return;
|
|
139
|
+
if (FUNCTION_TYPES.has(node.type)) {
|
|
140
|
+
eachChild(node, c => walk(c, inNestedBreakable, inNestedLoop, true));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
switch (node.type) {
|
|
144
|
+
case "BreakStatement":
|
|
145
|
+
if (node.label) facts.hasLabeledJump = true;else if (!inNestedBreakable) facts.hasBreak = true;
|
|
146
|
+
break;
|
|
147
|
+
case "ContinueStatement":
|
|
148
|
+
if (node.label) facts.hasLabeledJump = true;else if (!inNestedLoop) facts.hasContinue = true;
|
|
149
|
+
break;
|
|
150
|
+
case "ReturnStatement":
|
|
151
|
+
if (!inFunction) facts.hasReturn = true;
|
|
152
|
+
break;
|
|
153
|
+
case "AwaitExpression":
|
|
154
|
+
if (!inFunction) facts.hasAwait = true;
|
|
155
|
+
break;
|
|
156
|
+
case "YieldExpression":
|
|
157
|
+
if (!inFunction) facts.hasYield = true;
|
|
158
|
+
break;
|
|
159
|
+
case "AssignmentExpression":
|
|
160
|
+
if (node.left?.type === "Identifier" && names.has(node.left.name)) {
|
|
161
|
+
facts.assignsBinding = true;
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
case "UpdateExpression":
|
|
165
|
+
if (node.argument?.type === "Identifier" && names.has(node.argument.name)) {
|
|
166
|
+
facts.assignsBinding = true;
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
const isLoop = node.type === "ForStatement" || node.type === "ForOfStatement" || node.type === "ForInStatement" || node.type === "WhileStatement" || node.type === "DoWhileStatement";
|
|
171
|
+
const isBreakable = isLoop || node.type === "SwitchStatement";
|
|
172
|
+
eachChild(node, c => walk(c, inNestedBreakable || isBreakable, inNestedLoop || isLoop, inFunction));
|
|
173
|
+
}
|
|
174
|
+
walk(body, false, false, false);
|
|
175
|
+
return facts;
|
|
176
|
+
}
|
|
177
|
+
function collectBodyLexicalNames(node, out) {
|
|
178
|
+
if (!node || typeof node !== "object" || typeof node.type !== "string") return;
|
|
179
|
+
if (FUNCTION_TYPES.has(node.type) || node.type === "ClassBody") return;
|
|
180
|
+
if (node.type === "VariableDeclaration") {
|
|
181
|
+
if (node.kind === "let" || node.kind === "const") {
|
|
182
|
+
for (const d of node.declarations || []) collectPatternNames(d.id, out);
|
|
183
|
+
}
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (node.type === "ClassDeclaration") {
|
|
187
|
+
if (node.id?.name) out.push(node.id.name);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
eachChild(node, c => collectBodyLexicalNames(c, out));
|
|
191
|
+
}
|
|
192
|
+
const LOOP_TYPES = /* @__PURE__ */new Set(["ForStatement", "ForOfStatement", "ForInStatement", "WhileStatement", "DoWhileStatement"]);
|
|
193
|
+
function headDeclaration(node) {
|
|
194
|
+
if (node.type === "ForStatement") return node.init;
|
|
195
|
+
if (node.type === "ForOfStatement" || node.type === "ForInStatement") return node.left;
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
function transformOnce(code, filename) {
|
|
199
|
+
const parsed = (0, import_oxc_parser.parseSync)(filename, code, {
|
|
200
|
+
lang: langFor(filename)
|
|
201
|
+
});
|
|
202
|
+
if (!parsed?.program || parsed.errors?.length) return null;
|
|
203
|
+
const candidates = [];
|
|
204
|
+
function findLoops(node, insideCandidate) {
|
|
205
|
+
if (!node || typeof node !== "object") return;
|
|
206
|
+
let isCandidate = false;
|
|
207
|
+
if (LOOP_TYPES.has(node.type) && node.body) {
|
|
208
|
+
const names = [];
|
|
209
|
+
const decl = headDeclaration(node);
|
|
210
|
+
if (decl?.type === "VariableDeclaration" && (decl.kind === "let" || decl.kind === "const")) {
|
|
211
|
+
for (const d of decl.declarations || []) collectPatternNames(d.id, names);
|
|
212
|
+
}
|
|
213
|
+
const shared = [...names];
|
|
214
|
+
collectBodyLexicalNames(node.body, shared);
|
|
215
|
+
if (shared.length && capturesInClosure(node.body, new Set(shared))) {
|
|
216
|
+
isCandidate = true;
|
|
217
|
+
if (!insideCandidate) candidates.push({
|
|
218
|
+
node,
|
|
219
|
+
names
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
eachChild(node, c => findLoops(c, insideCandidate || isCandidate));
|
|
224
|
+
}
|
|
225
|
+
findLoops(parsed.program, false);
|
|
226
|
+
if (!candidates.length) return null;
|
|
227
|
+
const s = new import_magic_string.default(code);
|
|
228
|
+
let counter = 0;
|
|
229
|
+
let changed = false;
|
|
230
|
+
for (const {
|
|
231
|
+
node,
|
|
232
|
+
names
|
|
233
|
+
} of candidates) {
|
|
234
|
+
const nameSet = new Set(names);
|
|
235
|
+
const facts = analyzeBody(node.body, nameSet);
|
|
236
|
+
if (facts.hasYield || facts.assignsBinding || facts.hasLabeledJump) continue;
|
|
237
|
+
const fnName = `_hermesLoop${counter++}`;
|
|
238
|
+
const params = names.join(", ");
|
|
239
|
+
let bodyText = code.slice(node.body.start, node.body.end);
|
|
240
|
+
if (node.body.type !== "BlockStatement") {
|
|
241
|
+
bodyText = `{ ${bodyText} }`;
|
|
242
|
+
}
|
|
243
|
+
if (facts.hasBreak || facts.hasReturn || facts.hasContinue) {
|
|
244
|
+
bodyText = rewriteJumps(bodyText, node.body, code, nameSet);
|
|
245
|
+
}
|
|
246
|
+
const asyncKw = facts.hasAwait ? "async " : "";
|
|
247
|
+
const awaitKw = facts.hasAwait ? "await " : "";
|
|
248
|
+
let call = `${awaitKw}${fnName}(${params})`;
|
|
249
|
+
if (facts.hasBreak || facts.hasReturn) {
|
|
250
|
+
const checks = [];
|
|
251
|
+
if (facts.hasBreak) checks.push("if (_r === 1) break;");
|
|
252
|
+
if (facts.hasReturn) checks.push("if (_r) return _r.v;");
|
|
253
|
+
call = `{ var _r = ${call}; ${checks.join(" ")} }`;
|
|
254
|
+
} else {
|
|
255
|
+
call = `{ ${call}; }`;
|
|
256
|
+
}
|
|
257
|
+
s.overwrite(node.body.start, node.body.end, call);
|
|
258
|
+
s.appendLeft(node.start, `{
|
|
259
|
+
var ${fnName} = ${asyncKw}(${params}) => ${bodyText};
|
|
260
|
+
`);
|
|
261
|
+
s.appendLeft(node.end, "\n}");
|
|
262
|
+
changed = true;
|
|
263
|
+
}
|
|
264
|
+
if (!changed) return null;
|
|
265
|
+
return {
|
|
266
|
+
code: s.toString(),
|
|
267
|
+
map: s.generateMap({
|
|
268
|
+
hires: true,
|
|
269
|
+
source: filename,
|
|
270
|
+
includeContent: false
|
|
271
|
+
})
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
function rewriteJumps(bodyText, bodyNode, code, names) {
|
|
275
|
+
const offset = bodyNode.start;
|
|
276
|
+
const s = new import_magic_string.default(bodyText);
|
|
277
|
+
const pad = bodyNode.type === "BlockStatement" ? 0 : 2;
|
|
278
|
+
function walk(node, inNestedBreakable, inNestedLoop, inFunction) {
|
|
279
|
+
if (!node || typeof node !== "object") return;
|
|
280
|
+
if (FUNCTION_TYPES.has(node.type)) {
|
|
281
|
+
eachChild(node, c => walk(c, inNestedBreakable, inNestedLoop, true));
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (node.type === "BreakStatement" && !node.label && !inNestedBreakable) {
|
|
285
|
+
s.overwrite(node.start - offset + pad, node.end - offset + pad, "return 1;");
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (node.type === "ContinueStatement" && !node.label && !inNestedLoop) {
|
|
289
|
+
s.overwrite(node.start - offset + pad, node.end - offset + pad, "return;");
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (node.type === "ReturnStatement" && !inFunction) {
|
|
293
|
+
const arg = node.argument;
|
|
294
|
+
const replacement = arg ? `return { v: ${code.slice(arg.start, arg.end)} };` : "return { v: undefined };";
|
|
295
|
+
s.overwrite(node.start - offset + pad, node.end - offset + pad, replacement);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const isLoop = node.type === "ForStatement" || node.type === "ForOfStatement" || node.type === "ForInStatement" || node.type === "WhileStatement" || node.type === "DoWhileStatement";
|
|
299
|
+
const isBreakable = isLoop || node.type === "SwitchStatement";
|
|
300
|
+
eachChild(node, c => walk(c, inNestedBreakable || isBreakable, inNestedLoop || isLoop, inFunction));
|
|
301
|
+
}
|
|
302
|
+
walk(bodyNode, false, false, false);
|
|
303
|
+
return s.toString();
|
|
304
|
+
}
|
|
305
|
+
function transformHermesLoops(code, filename) {
|
|
306
|
+
if (!LOOP_RE.test(code) || !LEXICAL_RE.test(code)) return null;
|
|
307
|
+
let current = code;
|
|
308
|
+
const maps = [];
|
|
309
|
+
for (let i = 0; i < 10; i++) {
|
|
310
|
+
const next = transformOnce(current, filename);
|
|
311
|
+
if (!next) break;
|
|
312
|
+
current = next.code;
|
|
313
|
+
maps.push(next.map);
|
|
314
|
+
}
|
|
315
|
+
return maps.length ? {
|
|
316
|
+
code: current,
|
|
317
|
+
maps
|
|
318
|
+
} : null;
|
|
319
|
+
}
|