@vxrn/compiler 2.0.0-beta.33.1 → 2.0.0-beta.362.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.
Files changed (115) hide show
  1. package/dist/cjs/cache.cjs +112 -109
  2. package/dist/cjs/configure.cjs +26 -28
  3. package/dist/cjs/constants.cjs +56 -60
  4. package/dist/cjs/index.cjs +428 -438
  5. package/dist/cjs/reactNativeCodegen.cjs +105 -114
  6. package/dist/cjs/reactNativeViewConfig.cjs +362 -381
  7. package/dist/cjs/refresh-runtime.cjs +390 -397
  8. package/dist/cjs/transformBabel.cjs +247 -221
  9. package/dist/cjs/transformHermesAsync.cjs +36 -47
  10. package/dist/cjs/transformHermesClasses.cjs +51 -0
  11. package/dist/cjs/transformHermesLoops.cjs +279 -281
  12. package/dist/cjs/transformSWC.cjs +183 -200
  13. package/dist/cjs/transformWorklets.cjs +107 -95
  14. package/dist/cjs/types.cjs +9 -11
  15. package/dist/cjs/workletUtils.cjs +30 -0
  16. package/dist/cjs/worklets/autoworklet.cjs +277 -222
  17. package/dist/cjs/worklets/globals.cjs +145 -60
  18. package/dist/cjs/worklets/hash.cjs +23 -27
  19. package/dist/cjs/worklets/scope.cjs +338 -359
  20. package/dist/cjs/worklets/serialize.cjs +73 -75
  21. package/dist/cjs/worklets/transform.cjs +217 -222
  22. package/dist/cjs/worklets/types.cjs +9 -11
  23. package/dist/esm/cache.mjs +96 -89
  24. package/dist/esm/cache.mjs.map +1 -1
  25. package/dist/esm/configure.mjs +11 -10
  26. package/dist/esm/configure.mjs.map +1 -1
  27. package/dist/esm/constants.mjs +41 -41
  28. package/dist/esm/constants.mjs.map +1 -1
  29. package/dist/esm/index.js +426 -420
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/index.mjs +426 -420
  32. package/dist/esm/index.mjs.map +1 -1
  33. package/dist/esm/reactNativeCodegen.mjs +90 -88
  34. package/dist/esm/reactNativeCodegen.mjs.map +1 -1
  35. package/dist/esm/reactNativeViewConfig.mjs +347 -362
  36. package/dist/esm/reactNativeViewConfig.mjs.map +1 -1
  37. package/dist/esm/refresh-runtime.mjs +372 -376
  38. package/dist/esm/refresh-runtime.mjs.map +1 -1
  39. package/dist/esm/transformBabel.mjs +231 -198
  40. package/dist/esm/transformBabel.mjs.map +1 -1
  41. package/dist/esm/transformHermesAsync.mjs +20 -21
  42. package/dist/esm/transformHermesAsync.mjs.map +1 -1
  43. package/dist/esm/transformHermesClasses.mjs +25 -0
  44. package/dist/esm/transformHermesClasses.mjs.map +1 -0
  45. package/dist/esm/transformHermesLoops.mjs +264 -255
  46. package/dist/esm/transformHermesLoops.mjs.map +1 -1
  47. package/dist/esm/transformSWC.mjs +163 -171
  48. package/dist/esm/transformSWC.mjs.map +1 -1
  49. package/dist/esm/transformWorklets.mjs +89 -69
  50. package/dist/esm/transformWorklets.mjs.map +1 -1
  51. package/dist/esm/types.mjs +0 -2
  52. package/dist/esm/workletUtils.mjs +5 -0
  53. package/dist/esm/worklets/autoworklet.mjs +258 -200
  54. package/dist/esm/worklets/autoworklet.mjs.map +1 -1
  55. package/dist/esm/worklets/globals.mjs +130 -42
  56. package/dist/esm/worklets/globals.mjs.map +1 -1
  57. package/dist/esm/worklets/hash.mjs +10 -9
  58. package/dist/esm/worklets/hash.mjs.map +1 -1
  59. package/dist/esm/worklets/scope.mjs +325 -341
  60. package/dist/esm/worklets/scope.mjs.map +1 -1
  61. package/dist/esm/worklets/serialize.mjs +60 -58
  62. package/dist/esm/worklets/serialize.mjs.map +1 -1
  63. package/dist/esm/worklets/transform.mjs +201 -197
  64. package/dist/esm/worklets/transform.mjs.map +1 -1
  65. package/dist/esm/worklets/types.mjs +0 -2
  66. package/package.json +15 -6
  67. package/src/cache.ts +37 -7
  68. package/src/index.ts +44 -19
  69. package/src/reactNativeViewConfig.ts +6 -1
  70. package/src/transformBabel.test.ts +351 -17
  71. package/src/transformBabel.ts +137 -96
  72. package/src/transformHermesClasses.ts +34 -0
  73. package/src/transformSWC.ts +12 -1
  74. package/src/transformWorklets.test.ts +80 -5
  75. package/src/workletUtils.ts +4 -0
  76. package/src/worklets/autoworklet.ts +5 -2
  77. package/src/worklets/globals.ts +23 -0
  78. package/src/worklets/serialize.ts +1 -1
  79. package/types/cache.d.ts +2 -2
  80. package/types/cache.d.ts.map +1 -1
  81. package/types/index.d.ts +1 -0
  82. package/types/index.d.ts.map +1 -1
  83. package/types/reactNativeViewConfig.d.ts.map +1 -1
  84. package/types/transformBabel.d.ts +16 -1
  85. package/types/transformBabel.d.ts.map +1 -1
  86. package/types/transformHermesClasses.d.ts +5 -0
  87. package/types/transformHermesClasses.d.ts.map +1 -0
  88. package/types/transformSWC.d.ts +1 -4
  89. package/types/transformSWC.d.ts.map +1 -1
  90. package/types/workletUtils.d.ts +4 -0
  91. package/types/workletUtils.d.ts.map +1 -0
  92. package/types/worklets/autoworklet.d.ts.map +1 -1
  93. package/types/worklets/globals.d.ts.map +1 -1
  94. package/dist/cjs/transformBabel.test.cjs +0 -360
  95. package/dist/cjs/transformHermesLoops.test.cjs +0 -257
  96. package/dist/cjs/transformSWC.test.cjs +0 -117
  97. package/dist/cjs/transformWorklets.test.cjs +0 -604
  98. package/dist/esm/transformBabel.test.mjs +0 -337
  99. package/dist/esm/transformBabel.test.mjs.map +0 -1
  100. package/dist/esm/transformHermesLoops.test.mjs +0 -234
  101. package/dist/esm/transformHermesLoops.test.mjs.map +0 -1
  102. package/dist/esm/transformSWC.test.mjs +0 -118
  103. package/dist/esm/transformSWC.test.mjs.map +0 -1
  104. package/dist/esm/transformWorklets.test.mjs +0 -581
  105. package/dist/esm/transformWorklets.test.mjs.map +0 -1
  106. package/dist/esm/types.mjs.map +0 -1
  107. package/dist/esm/worklets/types.mjs.map +0 -1
  108. package/types/transformBabel.test.d.ts +0 -2
  109. package/types/transformBabel.test.d.ts.map +0 -1
  110. package/types/transformHermesLoops.test.d.ts +0 -2
  111. package/types/transformHermesLoops.test.d.ts.map +0 -1
  112. package/types/transformSWC.test.d.ts +0 -2
  113. package/types/transformSWC.test.d.ts.map +0 -1
  114. package/types/transformWorklets.test.d.ts +0 -2
  115. package/types/transformWorklets.test.d.ts.map +0 -1
@@ -1,25 +1,24 @@
1
1
  async function transformHermesAsync(code, filename, sourceMaps = false, format) {
2
- if (!format && !code.includes("async")) return;
3
- const {
4
- transformSync
5
- } = await import("esbuild");
6
- const cleanId = filename.split("?")[0];
7
- const result = transformSync(code, {
8
- loader: /\.[cm]?ts$/.test(cleanId) ? "ts" : cleanId.endsWith(".tsx") ? "tsx" : "jsx",
9
- jsx: "preserve",
10
- format,
11
- supported: {
12
- "async-await": false,
13
- "async-generator": false,
14
- "for-await": false
15
- },
16
- sourcefile: filename,
17
- sourcemap: sourceMaps ? "external" : false
18
- });
19
- return {
20
- code: result.code,
21
- map: result.map ? JSON.parse(result.map) : void 0
22
- };
2
+ if (!format && !code.includes("async")) return;
3
+ const { transformSync } = await import("esbuild");
4
+ const cleanId = filename.split("?")[0];
5
+ const result = transformSync(code, {
6
+ loader: /\.[cm]?ts$/.test(cleanId) ? "ts" : cleanId.endsWith(".tsx") ? "tsx" : "jsx",
7
+ jsx: "preserve",
8
+ format,
9
+ supported: {
10
+ "async-await": false,
11
+ "async-generator": false,
12
+ "for-await": false
13
+ },
14
+ sourcefile: filename,
15
+ sourcemap: sourceMaps ? "external" : false
16
+ });
17
+ return {
18
+ code: result.code,
19
+ map: result.map ? JSON.parse(result.map) : void 0
20
+ };
23
21
  }
22
+
24
23
  export { transformHermesAsync };
25
24
  //# sourceMappingURL=transformHermesAsync.mjs.map
@@ -1 +1 @@
1
- {"version":3,"names":["transformHermesAsync","code","filename","sourceMaps","format","includes","transformSync","cleanId","split","result","loader","test","endsWith","jsx","supported","sourcefile","sourcemap","map","JSON","parse"],"sources":["../../src/transformHermesAsync.ts"],"sourcesContent":[null],"mappings":"AAGA,eAAsBA,qBACpBC,IAAA,EACAC,QAAA,EACAC,UAAA,GAAa,OACbC,MAAA,EACkD;EAClD,IAAI,CAACA,MAAA,IAAU,CAACH,IAAA,CAAKI,QAAA,CAAS,OAAO,GAAG;EAExC,MAAM;IAAEC;EAAc,IAAI,MAAM,OAAO,SAAS;EAChD,MAAMC,OAAA,GAAUL,QAAA,CAASM,KAAA,CAAM,GAAG,EAAE,CAAC;EACrC,MAAMC,MAAA,GAASH,aAAA,CAAcL,IAAA,EAAM;IACjCS,MAAA,EAAQ,aAAaC,IAAA,CAAKJ,OAAO,IAAI,OAAOA,OAAA,CAAQK,QAAA,CAAS,MAAM,IAAI,QAAQ;IAC/EC,GAAA,EAAK;IACLT,MAAA;IACAU,SAAA,EAAW;MACT,eAAe;MACf,mBAAmB;MACnB,aAAa;IACf;IACAC,UAAA,EAAYb,QAAA;IACZc,SAAA,EAAWb,UAAA,GAAa,aAAa;EACvC,CAAC;EACD,OAAO;IACLF,IAAA,EAAMQ,MAAA,CAAOR,IAAA;IACbgB,GAAA,EAAKR,MAAA,CAAOQ,GAAA,GAAMC,IAAA,CAAKC,KAAA,CAAMV,MAAA,CAAOQ,GAAG,IAAI;EAC7C;AACF","ignoreList":[]}
1
+ {"version":3,"file":"transformHermesAsync.js","names":[],"sources":["esm/transformHermesAsync.js"],"sourcesContent":["async function transformHermesAsync(code, filename, sourceMaps = false, format) {\n if (!format && !code.includes(\"async\")) return;\n const { transformSync } = await import(\"esbuild\");\n const cleanId = filename.split(\"?\")[0];\n const result = transformSync(code, {\n loader: /\\.[cm]?ts$/.test(cleanId) ? \"ts\" : cleanId.endsWith(\".tsx\") ? \"tsx\" : \"jsx\",\n jsx: \"preserve\",\n format,\n supported: {\n \"async-await\": false,\n \"async-generator\": false,\n \"for-await\": false\n },\n sourcefile: filename,\n sourcemap: sourceMaps ? \"external\" : false\n });\n return {\n code: result.code,\n map: result.map ? JSON.parse(result.map) : void 0\n };\n}\nexport {\n transformHermesAsync\n};\n//# sourceMappingURL=transformHermesAsync.js.map\n"],"mappings":";AAAA,eAAe,qBAAqB,MAAM,UAAU,aAAa,OAAO,QAAQ;CAC9E,IAAI,CAAC,UAAU,CAAC,KAAK,SAAS,OAAO,GAAG;CACxC,MAAM,EAAE,kBAAkB,MAAM,OAAO;CACvC,MAAM,UAAU,SAAS,MAAM,GAAG,CAAC,CAAC;CACpC,MAAM,SAAS,cAAc,MAAM;EACjC,QAAQ,aAAa,KAAK,OAAO,IAAI,OAAO,QAAQ,SAAS,MAAM,IAAI,QAAQ;EAC/E,KAAK;EACL;EACA,WAAW;GACT,eAAe;GACf,mBAAmB;GACnB,aAAa;EACf;EACA,YAAY;EACZ,WAAW,aAAa,aAAa;CACvC,CAAC;CACD,OAAO;EACL,MAAM,OAAO;EACb,KAAK,OAAO,MAAM,KAAK,MAAM,OAAO,GAAG,IAAI,KAAK;CAClD;AACF"}
@@ -0,0 +1,25 @@
1
+ async function transformHermesClasses(code, filename, sourceMaps = false) {
2
+ if (!/\b(?:class(?:\s|\{)|(?:let|const)\s)/.test(code)) return;
3
+ const [{ transformAsync }, { default: transformClasses }, { default: transformBlockScoping }] = await Promise.all([
4
+ import("@babel/core"),
5
+ import("@babel/plugin-transform-classes"),
6
+ import("@babel/plugin-transform-block-scoping")
7
+ ]);
8
+ const result = await transformAsync(code, {
9
+ filename,
10
+ babelrc: false,
11
+ configFile: false,
12
+ sourceMaps,
13
+ inputSourceMap: false,
14
+ parserOpts: { plugins: ["jsx"] },
15
+ plugins: [transformClasses, transformBlockScoping]
16
+ });
17
+ if (!result?.code) return;
18
+ return {
19
+ code: result.code,
20
+ map: result.map
21
+ };
22
+ }
23
+
24
+ export { transformHermesClasses };
25
+ //# sourceMappingURL=transformHermesClasses.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformHermesClasses.js","names":[],"sources":["esm/transformHermesClasses.js"],"sourcesContent":["async function transformHermesClasses(code, filename, sourceMaps = false) {\n if (!/\\b(?:class(?:\\s|\\{)|(?:let|const)\\s)/.test(code)) return;\n const [\n { transformAsync },\n { default: transformClasses },\n { default: transformBlockScoping }\n ] = await Promise.all([\n import(\"@babel/core\"),\n import(\"@babel/plugin-transform-classes\"),\n import(\"@babel/plugin-transform-block-scoping\")\n ]);\n const result = await transformAsync(code, {\n filename,\n babelrc: false,\n configFile: false,\n sourceMaps,\n // the caller composes stage maps itself; a file's own sourceMappingURL\n // composed here would give the stage map several sources\n // @ts-expect-error @types/babel__core omits false, which babel accepts\n inputSourceMap: false,\n parserOpts: { plugins: [\"jsx\"] },\n // Legacy Hermes hoists lexical names, including in class-free functions.\n // Lower block scope so minification cannot shadow parameters or constructors.\n plugins: [transformClasses, transformBlockScoping]\n });\n if (!result?.code) return;\n return { code: result.code, map: result.map };\n}\nexport {\n transformHermesClasses\n};\n//# sourceMappingURL=transformHermesClasses.js.map\n"],"mappings":";AAAA,eAAe,uBAAuB,MAAM,UAAU,aAAa,OAAO;CACxE,IAAI,CAAC,uCAAuC,KAAK,IAAI,GAAG;CACxD,MAAM,CACJ,EAAE,kBACF,EAAE,SAAS,oBACX,EAAE,SAAS,2BACT,MAAM,QAAQ,IAAI;EACpB,OAAO;EACP,OAAO;EACP,OAAO;CACT,CAAC;CACD,MAAM,SAAS,MAAM,eAAe,MAAM;EACxC;EACA,SAAS;EACT,YAAY;EACZ;EAIA,gBAAgB;EAChB,YAAY,EAAE,SAAS,CAAC,KAAK,EAAE;EAG/B,SAAS,CAAC,kBAAkB,qBAAqB;CACnD,CAAC;CACD,IAAI,CAAC,QAAQ,MAAM;CACnB,OAAO;EAAE,MAAM,OAAO;EAAM,KAAK,OAAO;CAAI;AAC9C"}
@@ -1,283 +1,292 @@
1
1
  import MagicString from "magic-string";
2
2
  import { parseSync } from "oxc-parser";
3
+
3
4
  const LOOP_RE = /\b(?:for|while)\s*(?:await\s+)?\(/;
4
5
  const LEXICAL_RE = /\b(?:let|const|class)\b/;
5
6
  function langFor(filename) {
6
- const ext = filename.split("?")[0].split(".").pop() || "js";
7
- if (ext === "ts" || ext === "cts" || ext === "mts") return "ts";
8
- if (ext === "tsx") return "tsx";
9
- return "jsx";
7
+ const ext = filename.split("?")[0].split(".").pop() || "js";
8
+ if (ext === "ts" || ext === "cts" || ext === "mts") return "ts";
9
+ if (ext === "tsx") return "tsx";
10
+ return "jsx";
10
11
  }
11
12
  function collectPatternNames(node, out) {
12
- if (!node || typeof node !== "object") return;
13
- switch (node.type) {
14
- case "Identifier":
15
- out.push(node.name);
16
- return;
17
- case "ObjectPattern":
18
- for (const p of node.properties || []) {
19
- collectPatternNames(p.value ?? p.argument, out);
20
- }
21
- return;
22
- case "ArrayPattern":
23
- for (const el of node.elements || []) collectPatternNames(el, out);
24
- return;
25
- case "AssignmentPattern":
26
- collectPatternNames(node.left, out);
27
- return;
28
- case "RestElement":
29
- collectPatternNames(node.argument, out);
30
- return;
31
- }
13
+ if (!node || typeof node !== "object") return;
14
+ switch (node.type) {
15
+ case "Identifier":
16
+ out.push(node.name);
17
+ return;
18
+ case "ObjectPattern":
19
+ for (const p of node.properties || []) {
20
+ collectPatternNames(p.value ?? p.argument, out);
21
+ }
22
+ return;
23
+ case "ArrayPattern":
24
+ for (const el of node.elements || []) collectPatternNames(el, out);
25
+ return;
26
+ case "AssignmentPattern":
27
+ collectPatternNames(node.left, out);
28
+ return;
29
+ case "RestElement":
30
+ collectPatternNames(node.argument, out);
31
+ return;
32
+ }
32
33
  }
33
- const FUNCTION_TYPES = /* @__PURE__ */new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]);
34
+ const FUNCTION_TYPES = /* @__PURE__ */ new Set([
35
+ "FunctionDeclaration",
36
+ "FunctionExpression",
37
+ "ArrowFunctionExpression"
38
+ ]);
34
39
  function eachChild(node, fn) {
35
- for (const key in node) {
36
- if (key === "type" || key === "start" || key === "end" || key === "parent") continue;
37
- const value = node[key];
38
- if (Array.isArray(value)) {
39
- for (const item of value) {
40
- if (item && typeof item.type === "string") fn(item);
41
- }
42
- } else if (value && typeof value === "object" && typeof value.type === "string") {
43
- fn(value);
44
- }
45
- }
40
+ for (const key in node) {
41
+ if (key === "type" || key === "start" || key === "end" || key === "parent") continue;
42
+ const value = node[key];
43
+ if (Array.isArray(value)) {
44
+ for (const item of value) {
45
+ if (item && typeof item.type === "string") fn(item);
46
+ }
47
+ } else if (value && typeof value === "object" && typeof value.type === "string") {
48
+ fn(value);
49
+ }
50
+ }
46
51
  }
47
52
  function capturesInClosure(body, names) {
48
- let found = false;
49
- function scanInsideFunction(node, shadowed) {
50
- if (found || !node || typeof node !== "object") return;
51
- if (node.type === "Identifier" && names.has(node.name) && !shadowed.has(node.name)) {
52
- found = true;
53
- return;
54
- }
55
- if (FUNCTION_TYPES.has(node.type)) {
56
- const inner = new Set(shadowed);
57
- const params = [];
58
- for (const p of node.params || []) collectPatternNames(p, params);
59
- for (const p of params) inner.add(p);
60
- if (node.id?.name) inner.add(node.id.name);
61
- eachChild(node, c => scanInsideFunction(c, inner));
62
- return;
63
- }
64
- if (node.type === "MemberExpression" && !node.computed) {
65
- scanInsideFunction(node.object, shadowed);
66
- return;
67
- }
68
- if (node.type === "Property" && !node.computed && node.key === node.value) {
69
- scanInsideFunction(node.value, shadowed);
70
- return;
71
- }
72
- eachChild(node, c => scanInsideFunction(c, shadowed));
73
- }
74
- function walk(node) {
75
- if (found || !node || typeof node !== "object") return;
76
- if (FUNCTION_TYPES.has(node.type)) {
77
- const shadowed = /* @__PURE__ */new Set();
78
- const params = [];
79
- for (const p of node.params || []) collectPatternNames(p, params);
80
- for (const p of params) shadowed.add(p);
81
- eachChild(node, c => scanInsideFunction(c, shadowed));
82
- return;
83
- }
84
- eachChild(node, walk);
85
- }
86
- walk(body);
87
- return found;
53
+ let found = false;
54
+ function scanInsideFunction(node, shadowed) {
55
+ if (found || !node || typeof node !== "object") return;
56
+ if (node.type === "Identifier" && names.has(node.name) && !shadowed.has(node.name)) {
57
+ found = true;
58
+ return;
59
+ }
60
+ if (FUNCTION_TYPES.has(node.type)) {
61
+ const inner = new Set(shadowed);
62
+ const params = [];
63
+ for (const p of node.params || []) collectPatternNames(p, params);
64
+ for (const p of params) inner.add(p);
65
+ if (node.id?.name) inner.add(node.id.name);
66
+ eachChild(node, (c) => scanInsideFunction(c, inner));
67
+ return;
68
+ }
69
+ if (node.type === "MemberExpression" && !node.computed) {
70
+ scanInsideFunction(node.object, shadowed);
71
+ return;
72
+ }
73
+ if (node.type === "Property" && !node.computed && node.key === node.value) {
74
+ scanInsideFunction(node.value, shadowed);
75
+ return;
76
+ }
77
+ eachChild(node, (c) => scanInsideFunction(c, shadowed));
78
+ }
79
+ function walk(node) {
80
+ if (found || !node || typeof node !== "object") return;
81
+ if (FUNCTION_TYPES.has(node.type)) {
82
+ const shadowed = /* @__PURE__ */ new Set();
83
+ const params = [];
84
+ for (const p of node.params || []) collectPatternNames(p, params);
85
+ for (const p of params) shadowed.add(p);
86
+ eachChild(node, (c) => scanInsideFunction(c, shadowed));
87
+ return;
88
+ }
89
+ eachChild(node, walk);
90
+ }
91
+ walk(body);
92
+ return found;
88
93
  }
89
94
  function analyzeBody(body, names) {
90
- const facts = {
91
- hasBreak: false,
92
- hasContinue: false,
93
- hasReturn: false,
94
- hasAwait: false,
95
- hasYield: false,
96
- assignsBinding: false,
97
- hasLabeledJump: false
98
- };
99
- function walk(node, inNestedBreakable, inNestedLoop, inFunction) {
100
- if (!node || typeof node !== "object") return;
101
- if (FUNCTION_TYPES.has(node.type)) {
102
- eachChild(node, c => walk(c, inNestedBreakable, inNestedLoop, true));
103
- return;
104
- }
105
- switch (node.type) {
106
- case "BreakStatement":
107
- if (node.label) facts.hasLabeledJump = true;else if (!inNestedBreakable) facts.hasBreak = true;
108
- break;
109
- case "ContinueStatement":
110
- if (node.label) facts.hasLabeledJump = true;else if (!inNestedLoop) facts.hasContinue = true;
111
- break;
112
- case "ReturnStatement":
113
- if (!inFunction) facts.hasReturn = true;
114
- break;
115
- case "AwaitExpression":
116
- if (!inFunction) facts.hasAwait = true;
117
- break;
118
- case "YieldExpression":
119
- if (!inFunction) facts.hasYield = true;
120
- break;
121
- case "AssignmentExpression":
122
- if (node.left?.type === "Identifier" && names.has(node.left.name)) {
123
- facts.assignsBinding = true;
124
- }
125
- break;
126
- case "UpdateExpression":
127
- if (node.argument?.type === "Identifier" && names.has(node.argument.name)) {
128
- facts.assignsBinding = true;
129
- }
130
- break;
131
- }
132
- const isLoop = node.type === "ForStatement" || node.type === "ForOfStatement" || node.type === "ForInStatement" || node.type === "WhileStatement" || node.type === "DoWhileStatement";
133
- const isBreakable = isLoop || node.type === "SwitchStatement";
134
- eachChild(node, c => walk(c, inNestedBreakable || isBreakable, inNestedLoop || isLoop, inFunction));
135
- }
136
- walk(body, false, false, false);
137
- return facts;
95
+ const facts = {
96
+ hasBreak: false,
97
+ hasContinue: false,
98
+ hasReturn: false,
99
+ hasAwait: false,
100
+ hasYield: false,
101
+ assignsBinding: false,
102
+ hasLabeledJump: false
103
+ };
104
+ function walk(node, inNestedBreakable, inNestedLoop, inFunction) {
105
+ if (!node || typeof node !== "object") return;
106
+ if (FUNCTION_TYPES.has(node.type)) {
107
+ eachChild(node, (c) => walk(c, inNestedBreakable, inNestedLoop, true));
108
+ return;
109
+ }
110
+ switch (node.type) {
111
+ case "BreakStatement":
112
+ if (node.label) facts.hasLabeledJump = true;
113
+ else if (!inNestedBreakable) facts.hasBreak = true;
114
+ break;
115
+ case "ContinueStatement":
116
+ if (node.label) facts.hasLabeledJump = true;
117
+ else if (!inNestedLoop) facts.hasContinue = true;
118
+ break;
119
+ case "ReturnStatement":
120
+ if (!inFunction) facts.hasReturn = true;
121
+ break;
122
+ case "AwaitExpression":
123
+ if (!inFunction) facts.hasAwait = true;
124
+ break;
125
+ case "YieldExpression":
126
+ if (!inFunction) facts.hasYield = true;
127
+ break;
128
+ case "AssignmentExpression":
129
+ if (node.left?.type === "Identifier" && names.has(node.left.name)) {
130
+ facts.assignsBinding = true;
131
+ }
132
+ break;
133
+ case "UpdateExpression":
134
+ if (node.argument?.type === "Identifier" && names.has(node.argument.name)) {
135
+ facts.assignsBinding = true;
136
+ }
137
+ break;
138
+ }
139
+ const isLoop = node.type === "ForStatement" || node.type === "ForOfStatement" || node.type === "ForInStatement" || node.type === "WhileStatement" || node.type === "DoWhileStatement";
140
+ const isBreakable = isLoop || node.type === "SwitchStatement";
141
+ eachChild(node, (c) => walk(c, inNestedBreakable || isBreakable, inNestedLoop || isLoop, inFunction));
142
+ }
143
+ walk(body, false, false, false);
144
+ return facts;
138
145
  }
139
146
  function collectBodyLexicalNames(node, out) {
140
- if (!node || typeof node !== "object" || typeof node.type !== "string") return;
141
- if (FUNCTION_TYPES.has(node.type) || node.type === "ClassBody") return;
142
- if (node.type === "VariableDeclaration") {
143
- if (node.kind === "let" || node.kind === "const") {
144
- for (const d of node.declarations || []) collectPatternNames(d.id, out);
145
- }
146
- return;
147
- }
148
- if (node.type === "ClassDeclaration") {
149
- if (node.id?.name) out.push(node.id.name);
150
- return;
151
- }
152
- eachChild(node, c => collectBodyLexicalNames(c, out));
147
+ if (!node || typeof node !== "object" || typeof node.type !== "string") return;
148
+ if (FUNCTION_TYPES.has(node.type) || node.type === "ClassBody") return;
149
+ if (node.type === "VariableDeclaration") {
150
+ if (node.kind === "let" || node.kind === "const") {
151
+ for (const d of node.declarations || []) collectPatternNames(d.id, out);
152
+ }
153
+ return;
154
+ }
155
+ if (node.type === "ClassDeclaration") {
156
+ if (node.id?.name) out.push(node.id.name);
157
+ return;
158
+ }
159
+ eachChild(node, (c) => collectBodyLexicalNames(c, out));
153
160
  }
154
- const LOOP_TYPES = /* @__PURE__ */new Set(["ForStatement", "ForOfStatement", "ForInStatement", "WhileStatement", "DoWhileStatement"]);
161
+ const LOOP_TYPES = /* @__PURE__ */ new Set([
162
+ "ForStatement",
163
+ "ForOfStatement",
164
+ "ForInStatement",
165
+ "WhileStatement",
166
+ "DoWhileStatement"
167
+ ]);
155
168
  function headDeclaration(node) {
156
- if (node.type === "ForStatement") return node.init;
157
- if (node.type === "ForOfStatement" || node.type === "ForInStatement") return node.left;
158
- return null;
169
+ if (node.type === "ForStatement") return node.init;
170
+ if (node.type === "ForOfStatement" || node.type === "ForInStatement") return node.left;
171
+ return null;
159
172
  }
160
173
  function transformOnce(code, filename) {
161
- const parsed = parseSync(filename, code, {
162
- lang: langFor(filename)
163
- });
164
- if (!parsed?.program || parsed.errors?.length) return null;
165
- const candidates = [];
166
- function findLoops(node, insideCandidate) {
167
- if (!node || typeof node !== "object") return;
168
- let isCandidate = false;
169
- if (LOOP_TYPES.has(node.type) && node.body) {
170
- const names = [];
171
- const decl = headDeclaration(node);
172
- if (decl?.type === "VariableDeclaration" && (decl.kind === "let" || decl.kind === "const")) {
173
- for (const d of decl.declarations || []) collectPatternNames(d.id, names);
174
- }
175
- const shared = [...names];
176
- collectBodyLexicalNames(node.body, shared);
177
- if (shared.length && capturesInClosure(node.body, new Set(shared))) {
178
- isCandidate = true;
179
- if (!insideCandidate) candidates.push({
180
- node,
181
- names
182
- });
183
- }
184
- }
185
- eachChild(node, c => findLoops(c, insideCandidate || isCandidate));
186
- }
187
- findLoops(parsed.program, false);
188
- if (!candidates.length) return null;
189
- const s = new MagicString(code);
190
- let counter = 0;
191
- let changed = false;
192
- for (const {
193
- node,
194
- names
195
- } of candidates) {
196
- const nameSet = new Set(names);
197
- const facts = analyzeBody(node.body, nameSet);
198
- if (facts.hasYield || facts.assignsBinding || facts.hasLabeledJump) continue;
199
- const fnName = `_hermesLoop${counter++}`;
200
- const params = names.join(", ");
201
- let bodyText = code.slice(node.body.start, node.body.end);
202
- if (node.body.type !== "BlockStatement") {
203
- bodyText = `{ ${bodyText} }`;
204
- }
205
- if (facts.hasBreak || facts.hasReturn || facts.hasContinue) {
206
- bodyText = rewriteJumps(bodyText, node.body, code, nameSet);
207
- }
208
- const asyncKw = facts.hasAwait ? "async " : "";
209
- const awaitKw = facts.hasAwait ? "await " : "";
210
- let call = `${awaitKw}${fnName}(${params})`;
211
- if (facts.hasBreak || facts.hasReturn) {
212
- const checks = [];
213
- if (facts.hasBreak) checks.push("if (_r === 1) break;");
214
- if (facts.hasReturn) checks.push("if (_r) return _r.v;");
215
- call = `{ var _r = ${call}; ${checks.join(" ")} }`;
216
- } else {
217
- call = `{ ${call}; }`;
218
- }
219
- s.overwrite(node.body.start, node.body.end, call);
220
- s.appendLeft(node.start, `{
174
+ const parsed = parseSync(filename, code, { lang: langFor(filename) });
175
+ if (!parsed?.program || parsed.errors?.length) return null;
176
+ const candidates = [];
177
+ function findLoops(node, insideCandidate) {
178
+ if (!node || typeof node !== "object") return;
179
+ let isCandidate = false;
180
+ if (LOOP_TYPES.has(node.type) && node.body) {
181
+ const names = [];
182
+ const decl = headDeclaration(node);
183
+ if (decl?.type === "VariableDeclaration" && (decl.kind === "let" || decl.kind === "const")) {
184
+ for (const d of decl.declarations || []) collectPatternNames(d.id, names);
185
+ }
186
+ const shared = [...names];
187
+ collectBodyLexicalNames(node.body, shared);
188
+ if (shared.length && capturesInClosure(node.body, new Set(shared))) {
189
+ isCandidate = true;
190
+ if (!insideCandidate) candidates.push({
191
+ node,
192
+ names
193
+ });
194
+ }
195
+ }
196
+ eachChild(node, (c) => findLoops(c, insideCandidate || isCandidate));
197
+ }
198
+ findLoops(parsed.program, false);
199
+ if (!candidates.length) return null;
200
+ const s = new MagicString(code);
201
+ let counter = 0;
202
+ let changed = false;
203
+ for (const { node, names } of candidates) {
204
+ const nameSet = new Set(names);
205
+ const facts = analyzeBody(node.body, nameSet);
206
+ if (facts.hasYield || facts.assignsBinding || facts.hasLabeledJump) continue;
207
+ const fnName = `_hermesLoop${counter++}`;
208
+ const params = names.join(", ");
209
+ let bodyText = code.slice(node.body.start, node.body.end);
210
+ if (node.body.type !== "BlockStatement") {
211
+ bodyText = `{ ${bodyText} }`;
212
+ }
213
+ if (facts.hasBreak || facts.hasReturn || facts.hasContinue) {
214
+ bodyText = rewriteJumps(bodyText, node.body, code, nameSet);
215
+ }
216
+ const asyncKw = facts.hasAwait ? "async " : "";
217
+ const awaitKw = facts.hasAwait ? "await " : "";
218
+ let call = `${awaitKw}${fnName}(${params})`;
219
+ if (facts.hasBreak || facts.hasReturn) {
220
+ const checks = [];
221
+ if (facts.hasBreak) checks.push("if (_r === 1) break;");
222
+ if (facts.hasReturn) checks.push("if (_r) return _r.v;");
223
+ call = `{ var _r = ${call}; ${checks.join(" ")} }`;
224
+ } else {
225
+ call = `{ ${call}; }`;
226
+ }
227
+ s.overwrite(node.body.start, node.body.end, call);
228
+ s.appendLeft(node.start, `{
221
229
  var ${fnName} = ${asyncKw}(${params}) => ${bodyText};
222
230
  `);
223
- s.appendLeft(node.end, "\n}");
224
- changed = true;
225
- }
226
- if (!changed) return null;
227
- return {
228
- code: s.toString(),
229
- map: s.generateMap({
230
- hires: true,
231
- source: filename,
232
- includeContent: false
233
- })
234
- };
231
+ s.appendLeft(node.end, "\n}");
232
+ changed = true;
233
+ }
234
+ if (!changed) return null;
235
+ return {
236
+ code: s.toString(),
237
+ map: s.generateMap({
238
+ hires: true,
239
+ source: filename,
240
+ includeContent: false
241
+ })
242
+ };
235
243
  }
236
244
  function rewriteJumps(bodyText, bodyNode, code, names) {
237
- const offset = bodyNode.start;
238
- const s = new MagicString(bodyText);
239
- const pad = bodyNode.type === "BlockStatement" ? 0 : 2;
240
- function walk(node, inNestedBreakable, inNestedLoop, inFunction) {
241
- if (!node || typeof node !== "object") return;
242
- if (FUNCTION_TYPES.has(node.type)) {
243
- eachChild(node, c => walk(c, inNestedBreakable, inNestedLoop, true));
244
- return;
245
- }
246
- if (node.type === "BreakStatement" && !node.label && !inNestedBreakable) {
247
- s.overwrite(node.start - offset + pad, node.end - offset + pad, "return 1;");
248
- return;
249
- }
250
- if (node.type === "ContinueStatement" && !node.label && !inNestedLoop) {
251
- s.overwrite(node.start - offset + pad, node.end - offset + pad, "return;");
252
- return;
253
- }
254
- if (node.type === "ReturnStatement" && !inFunction) {
255
- const arg = node.argument;
256
- const replacement = arg ? `return { v: ${code.slice(arg.start, arg.end)} };` : "return { v: undefined };";
257
- s.overwrite(node.start - offset + pad, node.end - offset + pad, replacement);
258
- return;
259
- }
260
- const isLoop = node.type === "ForStatement" || node.type === "ForOfStatement" || node.type === "ForInStatement" || node.type === "WhileStatement" || node.type === "DoWhileStatement";
261
- const isBreakable = isLoop || node.type === "SwitchStatement";
262
- eachChild(node, c => walk(c, inNestedBreakable || isBreakable, inNestedLoop || isLoop, inFunction));
263
- }
264
- walk(bodyNode, false, false, false);
265
- return s.toString();
245
+ const offset = bodyNode.start;
246
+ const s = new MagicString(bodyText);
247
+ const pad = bodyNode.type === "BlockStatement" ? 0 : 2;
248
+ function walk(node, inNestedBreakable, inNestedLoop, inFunction) {
249
+ if (!node || typeof node !== "object") return;
250
+ if (FUNCTION_TYPES.has(node.type)) {
251
+ eachChild(node, (c) => walk(c, inNestedBreakable, inNestedLoop, true));
252
+ return;
253
+ }
254
+ if (node.type === "BreakStatement" && !node.label && !inNestedBreakable) {
255
+ s.overwrite(node.start - offset + pad, node.end - offset + pad, "return 1;");
256
+ return;
257
+ }
258
+ if (node.type === "ContinueStatement" && !node.label && !inNestedLoop) {
259
+ s.overwrite(node.start - offset + pad, node.end - offset + pad, "return;");
260
+ return;
261
+ }
262
+ if (node.type === "ReturnStatement" && !inFunction) {
263
+ const arg = node.argument;
264
+ const replacement = arg ? `return { v: ${code.slice(arg.start, arg.end)} };` : "return { v: undefined };";
265
+ s.overwrite(node.start - offset + pad, node.end - offset + pad, replacement);
266
+ return;
267
+ }
268
+ const isLoop = node.type === "ForStatement" || node.type === "ForOfStatement" || node.type === "ForInStatement" || node.type === "WhileStatement" || node.type === "DoWhileStatement";
269
+ const isBreakable = isLoop || node.type === "SwitchStatement";
270
+ eachChild(node, (c) => walk(c, inNestedBreakable || isBreakable, inNestedLoop || isLoop, inFunction));
271
+ }
272
+ walk(bodyNode, false, false, false);
273
+ return s.toString();
266
274
  }
267
275
  function transformHermesLoops(code, filename) {
268
- if (!LOOP_RE.test(code) || !LEXICAL_RE.test(code)) return null;
269
- let current = code;
270
- const maps = [];
271
- for (let i = 0; i < 10; i++) {
272
- const next = transformOnce(current, filename);
273
- if (!next) break;
274
- current = next.code;
275
- maps.push(next.map);
276
- }
277
- return maps.length ? {
278
- code: current,
279
- maps
280
- } : null;
276
+ if (!LOOP_RE.test(code) || !LEXICAL_RE.test(code)) return null;
277
+ let current = code;
278
+ const maps = [];
279
+ for (let i = 0; i < 10; i++) {
280
+ const next = transformOnce(current, filename);
281
+ if (!next) break;
282
+ current = next.code;
283
+ maps.push(next.map);
284
+ }
285
+ return maps.length ? {
286
+ code: current,
287
+ maps
288
+ } : null;
281
289
  }
290
+
282
291
  export { transformHermesLoops };
283
292
  //# sourceMappingURL=transformHermesLoops.mjs.map