@scriptc/compiler 0.0.3 → 0.0.5

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 (92) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +145 -9
  2. package/dist/backend/cc.d.ts +23 -0
  3. package/dist/backend/cc.js +89 -0
  4. package/dist/backend/cc.js.map +1 -1
  5. package/dist/backend/emission/emit-async.js +2 -2
  6. package/dist/backend/emission/emit-async.js.map +1 -1
  7. package/dist/backend/emission/emit-exprs.js +37 -2
  8. package/dist/backend/emission/emit-exprs.js.map +1 -1
  9. package/dist/backend/emission/emit-shapes.js +3 -2
  10. package/dist/backend/emission/emit-shapes.js.map +1 -1
  11. package/dist/backend/emission/emit-walkers.js +7 -8
  12. package/dist/backend/emission/emit-walkers.js.map +1 -1
  13. package/dist/backend/emission/emitter.d.ts +1 -0
  14. package/dist/backend/emission/emitter.js +123 -3
  15. package/dist/backend/emission/emitter.js.map +1 -1
  16. package/dist/backend/llvm/emitter.js +198 -15
  17. package/dist/backend/llvm/emitter.js.map +1 -1
  18. package/dist/backend/llvm/shapes.js +1 -0
  19. package/dist/backend/llvm/shapes.js.map +1 -1
  20. package/dist/diagnostics/diagnostic.d.ts +25 -0
  21. package/dist/diagnostics/diagnostic.js +88 -2
  22. package/dist/diagnostics/diagnostic.js.map +1 -1
  23. package/dist/frontend/lib-exports.d.ts +16 -0
  24. package/dist/frontend/lib-exports.js +35 -0
  25. package/dist/frontend/lib-exports.js.map +1 -0
  26. package/dist/frontend/lowering/lib-boundary.js +76 -6
  27. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  28. package/dist/frontend/lowering/lower-builtins.d.ts +37 -4
  29. package/dist/frontend/lowering/lower-builtins.js +240 -6
  30. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  31. package/dist/frontend/lowering/lower-calls.js +124 -34
  32. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  33. package/dist/frontend/lowering/lower-classes.d.ts +34 -2
  34. package/dist/frontend/lowering/lower-classes.js +257 -34
  35. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  36. package/dist/frontend/lowering/lower-containers.js +25 -3
  37. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  38. package/dist/frontend/lowering/lower-exprs.d.ts +10 -0
  39. package/dist/frontend/lowering/lower-exprs.js +411 -10
  40. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  41. package/dist/frontend/lowering/lower-inspect.d.ts +16 -1
  42. package/dist/frontend/lowering/lower-inspect.js +132 -5
  43. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  44. package/dist/frontend/lowering/lower-island.js +25 -4
  45. package/dist/frontend/lowering/lower-island.js.map +1 -1
  46. package/dist/frontend/lowering/lower-mixins.js +4 -2
  47. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  48. package/dist/frontend/lowering/lower-modules.d.ts +6 -5
  49. package/dist/frontend/lowering/lower-modules.js +56 -18
  50. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  51. package/dist/frontend/lowering/lower-stmts.js +163 -0
  52. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  53. package/dist/frontend/lowering/lowerer.d.ts +72 -2
  54. package/dist/frontend/lowering/lowerer.js +339 -19
  55. package/dist/frontend/lowering/lowerer.js.map +1 -1
  56. package/dist/frontend/lowering/surfaces.d.ts +9 -2
  57. package/dist/frontend/lowering/surfaces.js +44 -7
  58. package/dist/frontend/lowering/surfaces.js.map +1 -1
  59. package/dist/frontend/npm-static-rewrite.d.ts +3 -0
  60. package/dist/frontend/npm-static-rewrite.js +677 -0
  61. package/dist/frontend/npm-static-rewrite.js.map +1 -0
  62. package/dist/frontend/npm-static.d.ts +8 -1
  63. package/dist/frontend/npm-static.js +159 -18
  64. package/dist/frontend/npm-static.js.map +1 -1
  65. package/dist/frontend/npm.js +2 -2
  66. package/dist/frontend/npm.js.map +1 -1
  67. package/dist/frontend/program.d.ts +6 -0
  68. package/dist/frontend/program.js +110 -22
  69. package/dist/frontend/program.js.map +1 -1
  70. package/dist/frontend/resolve.js +120 -5
  71. package/dist/frontend/resolve.js.map +1 -1
  72. package/dist/frontend/shared.d.ts +8 -2
  73. package/dist/frontend/shared.js +22 -6
  74. package/dist/frontend/shared.js.map +1 -1
  75. package/dist/frontend/ts7/checker.js +1 -1
  76. package/dist/frontend/ts7/checker.js.map +1 -1
  77. package/dist/frontend/types.d.ts +25 -1
  78. package/dist/frontend/types.js +121 -7
  79. package/dist/frontend/types.js.map +1 -1
  80. package/dist/index.d.ts +22 -0
  81. package/dist/index.js +256 -17
  82. package/dist/index.js.map +1 -1
  83. package/dist/ir/nodes.d.ts +86 -1
  84. package/dist/ir/nodes.js +183 -0
  85. package/dist/ir/nodes.js.map +1 -1
  86. package/dist/ir/validate.js +89 -6
  87. package/dist/ir/validate.js.map +1 -1
  88. package/dist/library/profile.d.ts +52 -0
  89. package/dist/library/profile.js +232 -0
  90. package/dist/library/profile.js.map +1 -0
  91. package/package.json +2 -2
  92. package/surface-manifest.json +67 -2
@@ -0,0 +1,677 @@
1
+ /* --npm-static's bundler-emitted-CJS export surface: the getter-table
2
+ * shapes. A bundler-emitted CJS dist exports through runtime plumbing the
3
+ * checker cannot model — the `__export(target, { name: () => value, ... })`
4
+ * getter table behind `module.exports = __toCommonJS(target)`, the
5
+ * `Object.defineProperty(exports, 'n', { get })` family, and the
6
+ * transpiler star re-exports (`__exportStar(require('./x'), exports)`,
7
+ * `__reExport(target, require('./x'), module.exports)`). Node's CJS lexer
8
+ * SEES those named exports (cjs-lexer.ts mirrors it exactly), so named
9
+ * imports link under Node — but the inferred surface the opted-in
10
+ * resolution feeds the checker is an opaque object, and every import site
11
+ * reports "X has no exported member" (the SC0001 storm that used to gate
12
+ * the whole build).
13
+ *
14
+ * THE REWRITE. For an opted-in package's CJS file whose exports come from
15
+ * these shapes, the fs shadow (npm-static.ts) serves BOTH worlds — the
16
+ * checker and the lowering ride one program — a text rewrite that spells
17
+ * the same export surface in the plain CJS the whole existing machinery
18
+ * already models:
19
+ *
20
+ * - the recognized plumbing statements are SPACE-PADDED in place
21
+ * (newlines kept, so every original line/offset survives): the
22
+ * `module.exports = __toCommonJS(target)` assignment, the
23
+ * `__export(target, {...})` call, the star-pattern calls, the
24
+ * recognized defineProperty exports, and the dead esbuild annotation
25
+ * `0 && (module.exports = {...})` (left live it poisons the checker's
26
+ * alias resolution — multiple module.exports assignments make import
27
+ * aliases land on properties no lowering path resolves);
28
+ * - one canonical export table is APPENDED at the tail:
29
+ * `module.exports = { ...require("./star"), own: local, ... };`
30
+ * Each getter body the chase can follow types the export by its
31
+ * resolved VALUE (`() => localBinding` resolves to the binding's
32
+ * inferred type; member chains and scalar literals hoist to a tail
33
+ * const first), and every lexer-visible name the chase cannot follow
34
+ * falls back to a checked-dynamic `any` binding (value undefined —
35
+ * exactly what Node's import binds for a lexer-visible name the
36
+ * runtime export object never carries).
37
+ *
38
+ * LEXER PARITY IS THE CONTRACT: the rewritten text must answer the SAME
39
+ * name set to cjs-lexer.ts that the original answers to Node — named
40
+ * imports must link exactly where Node's would. The table is formatted
41
+ * for merve's byte rules (`name: IDENT,` — value ident runs directly
42
+ * followed by ','), star re-exports ride spread entries (recorded as
43
+ * reexports and resolved recursively, exactly Node's union), and the
44
+ * esbuild `__esModule: !0` marker is spelled as a deliberate SCAN STOPPER
45
+ * so it stays lexer-invisible (Node never lexes __esModule out of
46
+ * __toCommonJS) while member-access star entries after it are covered by
47
+ * the spread records.
48
+ *
49
+ * SNAPSHOT SEMANTICS (the documented divergence): the getter table reads
50
+ * its locals LIVE at every access; the canonical table captures values
51
+ * ONCE, at module tail — after every top-level statement ran, so ordinary
52
+ * modules see identical values, and only post-evaluation reassignment of
53
+ * an exported local (the lazy-cache counter idiom) can diverge. Star
54
+ * re-export targets load at module tail instead of their original
55
+ * statement positions (visible only to load-order-sensitive side
56
+ * effects). Node's __esModule marker survives on the rewritten object.
57
+ *
58
+ * Everything here is SYNTACTIC (typescript5 world, the cjs-lexer's
59
+ * sanctioned island): the chase decides only what TEXT to emit — the
60
+ * checker then infers the types from the emitted spellings. A file whose
61
+ * export mechanism the recognizers cannot fully account for is left
62
+ * untouched (null): its import-site errors stay, and the frontend's
63
+ * offender attribution degrades the PACKAGE to the island with a note. */
64
+ import { existsSync, readFileSync, statSync } from "node:fs";
65
+ import { dirname, resolve as resolvePath } from "node:path";
66
+ import ts from "typescript5";
67
+ import { cjsLexedExportsOf, cjsLexerVisibleNames } from "./cjs-lexer.js";
68
+ /** True when `e` is exactly the `exports` identifier. */
69
+ function isExportsIdent(e) {
70
+ return ts.isIdentifier(e) && e.text === "exports";
71
+ }
72
+ /** True when `e` is exactly `module.exports`. */
73
+ function isModuleExports(e) {
74
+ return (ts.isPropertyAccessExpression(e) &&
75
+ e.questionDotToken === undefined &&
76
+ ts.isIdentifier(e.expression) &&
77
+ e.expression.text === "module" &&
78
+ ts.isIdentifier(e.name) &&
79
+ e.name.text === "exports");
80
+ }
81
+ /** The bare `require('spec')` call (identifier callee, one string arg). */
82
+ function bareRequireSpecOf(e) {
83
+ if (!ts.isCallExpression(e) || e.questionDotToken !== undefined)
84
+ return null;
85
+ if (!ts.isIdentifier(e.expression) || e.expression.text !== "require")
86
+ return null;
87
+ if (e.arguments.length !== 1)
88
+ return null;
89
+ const arg = e.arguments[0];
90
+ return ts.isStringLiteral(arg) ? arg.text : null;
91
+ }
92
+ /** The last NAME of a callee: bare identifier or any member chain's final
93
+ * name (`tslib_1.__exportStar` → "__exportStar"). */
94
+ function calleeNameOf(call) {
95
+ const callee = call.expression;
96
+ if (ts.isIdentifier(callee))
97
+ return callee.text;
98
+ if (ts.isPropertyAccessExpression(callee) && ts.isIdentifier(callee.name))
99
+ return callee.name.text;
100
+ return null;
101
+ }
102
+ /** A chaseable getter/descriptor VALUE: a plain identifier, an
103
+ * identifier-rooted member/element chain (string keys only), or a scalar
104
+ * literal. Answers the classification or null (not chaseable). */
105
+ function chaseValue(e) {
106
+ let cur = e;
107
+ while (ts.isParenthesizedExpression(cur))
108
+ cur = cur.expression;
109
+ if (ts.isIdentifier(cur))
110
+ return { kind: "ident", text: cur.text };
111
+ if (ts.isNumericLiteral(cur) ||
112
+ ts.isStringLiteral(cur) ||
113
+ ts.isNoSubstitutionTemplateLiteral(cur) ||
114
+ cur.kind === ts.SyntaxKind.TrueKeyword ||
115
+ cur.kind === ts.SyntaxKind.FalseKeyword ||
116
+ cur.kind === ts.SyntaxKind.NullKeyword) {
117
+ return { kind: "hoist", text: cur.getText() };
118
+ }
119
+ // ident-rooted member chains: this.x / a.b.c / a["k"].d — side-effect
120
+ // free reads the tail const can evaluate once.
121
+ let walk = cur;
122
+ while ((ts.isPropertyAccessExpression(walk) && walk.questionDotToken === undefined && ts.isIdentifier(walk.name)) ||
123
+ (ts.isElementAccessExpression(walk) && walk.questionDotToken === undefined && ts.isStringLiteral(walk.argumentExpression))) {
124
+ walk = walk.expression;
125
+ }
126
+ if (ts.isIdentifier(walk))
127
+ return { kind: "hoist", text: cur.getText() };
128
+ return null;
129
+ }
130
+ /** The getter body's returned expression for the two descriptor getter
131
+ * spellings (`get() { return X }` / `get: function () { return X }`) and
132
+ * the arrow forms the esbuild table uses (`() => X`, `() => { return X }`). */
133
+ function getterReturnOf(fn) {
134
+ let body;
135
+ if (ts.isArrowFunction(fn) && fn.parameters.length === 0)
136
+ body = fn.body;
137
+ else if (ts.isFunctionExpression(fn) && fn.parameters.length === 0)
138
+ body = fn.body;
139
+ else if (ts.isMethodDeclaration(fn) && fn.parameters.length === 0 && fn.body !== undefined)
140
+ body = fn.body;
141
+ else
142
+ return null;
143
+ if (body === undefined)
144
+ return null;
145
+ if (!ts.isBlock(body))
146
+ return body; // expression-bodied arrow
147
+ if (body.statements.length !== 1)
148
+ return null;
149
+ const ret = body.statements[0];
150
+ return ts.isReturnStatement(ret) && ret.expression !== undefined ? ret.expression : null;
151
+ }
152
+ /** The `__export(IDENT, { name: () => value, ... })` call's parts, or null.
153
+ * Every property must be a `name: <function>` assignment (identifier or
154
+ * string-literal name) — anything else is not the esbuild table. */
155
+ function exportCallOf(call) {
156
+ if (calleeNameOf(call) !== "__export")
157
+ return null;
158
+ if (call.arguments.length !== 2)
159
+ return null;
160
+ const [target, table] = call.arguments;
161
+ if (!ts.isIdentifier(target) || !ts.isObjectLiteralExpression(table))
162
+ return null;
163
+ const entries = [];
164
+ for (const prop of table.properties) {
165
+ if (!ts.isPropertyAssignment(prop))
166
+ return null;
167
+ let name;
168
+ if (ts.isIdentifier(prop.name))
169
+ name = prop.name.text;
170
+ else if (ts.isStringLiteral(prop.name))
171
+ name = prop.name.text;
172
+ else
173
+ return null;
174
+ entries.push([name, getterReturnOf(prop.initializer)]);
175
+ }
176
+ return { target: target.text, entries };
177
+ }
178
+ /** `Object.defineProperty(exports|module.exports, 'name', {...})` — the
179
+ * name plus the chased descriptor value (getter return or `value:`), or
180
+ * null when the statement is not that shape at all. `value: null` means
181
+ * recognized but unchaseable. */
182
+ function definePropertyExportOf(call) {
183
+ const callee = call.expression;
184
+ if (!ts.isPropertyAccessExpression(callee) ||
185
+ !ts.isIdentifier(callee.expression) ||
186
+ callee.expression.text !== "Object" ||
187
+ !ts.isIdentifier(callee.name) ||
188
+ callee.name.text !== "defineProperty") {
189
+ return null;
190
+ }
191
+ if (call.arguments.length !== 3)
192
+ return null;
193
+ const [recv, nameArg, desc] = call.arguments;
194
+ if (!isExportsIdent(recv) && !isModuleExports(recv))
195
+ return null;
196
+ if (!ts.isStringLiteral(nameArg) || !ts.isObjectLiteralExpression(desc))
197
+ return null;
198
+ const name = nameArg.text;
199
+ let value = null;
200
+ for (const p of desc.properties) {
201
+ if (ts.isPropertyAssignment(p) && ts.isIdentifier(p.name)) {
202
+ if (p.name.text === "value")
203
+ value = p.initializer;
204
+ else if (p.name.text === "get")
205
+ value = getterReturnOf(p.initializer);
206
+ }
207
+ else if (ts.isMethodDeclaration(p) && ts.isIdentifier(p.name) && p.name.text === "get") {
208
+ value = getterReturnOf(p);
209
+ }
210
+ }
211
+ const esModuleStamp = name === "__esModule" && value !== null && value.kind === ts.SyntaxKind.TrueKeyword;
212
+ return { name, value, esModuleStamp };
213
+ }
214
+ /** Resolves a RELATIVE CJS require target with Node's file-first probes
215
+ * (the dist-tree subset: exact, .js/.cjs, /index.js, package.json "main"
216
+ * for directories). Bare specifiers answer null — their names ride the
217
+ * spread entry and the program resolver. */
218
+ function resolveRelativeCjs(fromFile, spec) {
219
+ if (!spec.startsWith("./") && !spec.startsWith("../"))
220
+ return null;
221
+ const base = resolvePath(dirname(fromFile), spec);
222
+ const candidates = [base, `${base}.js`, `${base}.cjs`];
223
+ for (const c of candidates) {
224
+ try {
225
+ if (existsSync(c) && statSync(c).isFile() && /\.(js|cjs)$/.test(c))
226
+ return c;
227
+ }
228
+ catch {
229
+ /* keep probing */
230
+ }
231
+ }
232
+ try {
233
+ if (existsSync(base) && statSync(base).isDirectory()) {
234
+ const pkgPath = resolvePath(base, "package.json");
235
+ if (existsSync(pkgPath)) {
236
+ const main = JSON.parse(readFileSync(pkgPath, "utf8")).main;
237
+ if (typeof main === "string") {
238
+ const m = resolvePath(base, main);
239
+ for (const c of [m, `${m}.js`, `${m}.cjs`, resolvePath(m, "index.js")]) {
240
+ if (existsSync(c) && statSync(c).isFile() && /\.(js|cjs)$/.test(c))
241
+ return c;
242
+ }
243
+ }
244
+ }
245
+ const idx = resolvePath(base, "index.js");
246
+ if (existsSync(idx))
247
+ return idx;
248
+ }
249
+ }
250
+ catch {
251
+ /* unresolved */
252
+ }
253
+ return null;
254
+ }
255
+ /** The Node-visible named-export set of a star-re-export TARGET file:
256
+ * its recursive lexer-visible names (relative edges only — exactly what
257
+ * the emitted member entries must enumerate). */
258
+ function starTargetNames(file) {
259
+ try {
260
+ return cjsLexerVisibleNames(file, (f) => readFileSync(f, "utf8"), (from, spec) => resolveRelativeCjs(from, spec));
261
+ }
262
+ catch {
263
+ return new Set();
264
+ }
265
+ }
266
+ /** Space-pads [start, end) of `text` preserving newlines — the recognized
267
+ * statement disappears while every original offset survives. */
268
+ function padSpan(text, start, end) {
269
+ let pad = "";
270
+ for (let i = start; i < end; i++)
271
+ pad += text[i] === "\n" ? "\n" : " ";
272
+ return text.slice(0, start) + pad + text.slice(end);
273
+ }
274
+ /** A valid identifier-run export name (the table can spell it bare). */
275
+ function isPlainName(name) {
276
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
277
+ }
278
+ const RESERVED_KEYS = new Set(["__proto__"]);
279
+ /** The rewrite (see the header). Null = not a recognized bundle shape (or
280
+ * nothing to fix) — serve the file untouched. */
281
+ export function rewriteBundlerCjsExports(source, filePath) {
282
+ // Cheap gates before any parse: CJS bundle plumbing leaves textual
283
+ // fingerprints; files without any are never candidates.
284
+ if (!source.includes("__toCommonJS") &&
285
+ !source.includes("__exportStar") &&
286
+ !source.includes("__reExport") &&
287
+ !(source.includes("Object.defineProperty(exports") && source.includes("get"))) {
288
+ return null;
289
+ }
290
+ // parents ON: the helper sweep excludes declarator-name self references
291
+ // and the chase reads expression text through the tree
292
+ const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
293
+ // ESM syntax → not CJS; leave alone.
294
+ for (const stmt of sf.statements) {
295
+ if (ts.isImportDeclaration(stmt) || ts.isExportDeclaration(stmt) || ts.isExportAssignment(stmt))
296
+ return null;
297
+ }
298
+ const neutralize = [];
299
+ const exportTables = [];
300
+ const definePropEntries = [];
301
+ const memberStmts = [];
302
+ /** Star spec → require-load emission order (statement order). */
303
+ const starSpecsInOrder = [];
304
+ let esbuildMainTarget = null;
305
+ let tablePos = null;
306
+ let sawBundleShape = false;
307
+ const addStarSpec = (spec) => {
308
+ if (!starSpecsInOrder.includes(spec))
309
+ starSpecsInOrder.push(spec);
310
+ };
311
+ for (const stmt of sf.statements) {
312
+ if (!ts.isExpressionStatement(stmt))
313
+ continue;
314
+ const e = stmt.expression;
315
+ // `module.exports = <rhs>`
316
+ if (ts.isBinaryExpression(e) && e.operatorToken.kind === ts.SyntaxKind.EqualsToken && isModuleExports(e.left)) {
317
+ const rhs = e.right;
318
+ if (ts.isCallExpression(rhs) && calleeNameOf(rhs) === "__toCommonJS" && rhs.arguments.length === 1 && ts.isIdentifier(rhs.arguments[0])) {
319
+ esbuildMainTarget = rhs.arguments[0].text;
320
+ tablePos = stmt.getStart(sf);
321
+ neutralize.push({ start: stmt.getStart(sf), end: stmt.getEnd() });
322
+ sawBundleShape = true;
323
+ continue;
324
+ }
325
+ // Any other real module.exports assignment: the file has an export
326
+ // mechanism the checker already models (or a shape outside the
327
+ // recognizers) — not ours to rewrite.
328
+ return null;
329
+ }
330
+ // member exports — `exports.N = RHS;` / `module.exports.N = RHS;`,
331
+ // chains included (`exports.a = exports.b = void 0;` — the tsc
332
+ // void-init preamble collects every name with the chain's final RHS).
333
+ {
334
+ let cur = e;
335
+ const names = [];
336
+ let viaBareExports = false;
337
+ while (ts.isBinaryExpression(cur) &&
338
+ cur.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
339
+ ts.isPropertyAccessExpression(cur.left) &&
340
+ cur.left.questionDotToken === undefined &&
341
+ ts.isIdentifier(cur.left.name) &&
342
+ (isExportsIdent(cur.left.expression) || isModuleExports(cur.left.expression))) {
343
+ names.push(cur.left.name.text);
344
+ if (isExportsIdent(cur.left.expression))
345
+ viaBareExports = true;
346
+ cur = cur.right;
347
+ }
348
+ if (names.length > 0) {
349
+ memberStmts.push({
350
+ names,
351
+ finalRhs: cur,
352
+ viaBareExports,
353
+ pos: stmt.getStart(sf),
354
+ start: stmt.getStart(sf),
355
+ end: stmt.getEnd(),
356
+ });
357
+ continue; // classified later (only when a rewrite actually happens)
358
+ }
359
+ }
360
+ // the dead esbuild annotation: `0 && (module.exports = { ... });`
361
+ if (ts.isBinaryExpression(e) &&
362
+ e.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken &&
363
+ ts.isNumericLiteral(e.left) &&
364
+ e.left.text === "0") {
365
+ let inner = e.right;
366
+ while (ts.isParenthesizedExpression(inner))
367
+ inner = inner.expression;
368
+ if (ts.isBinaryExpression(inner) &&
369
+ inner.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
370
+ isModuleExports(inner.left) &&
371
+ ts.isObjectLiteralExpression(inner.right)) {
372
+ neutralize.push({ start: stmt.getStart(sf), end: stmt.getEnd() });
373
+ sawBundleShape = true;
374
+ continue;
375
+ }
376
+ }
377
+ if (!ts.isCallExpression(e))
378
+ continue;
379
+ const name = calleeNameOf(e);
380
+ // `__export(TARGET, { getter table });`
381
+ const table = exportCallOf(e);
382
+ if (table !== null) {
383
+ exportTables.push(table);
384
+ neutralize.push({ start: stmt.getStart(sf), end: stmt.getEnd() });
385
+ sawBundleShape = true;
386
+ continue;
387
+ }
388
+ // `__exportStar(require('spec'), exports);` — the tsc/tslib spelling —
389
+ // and `__export(require('spec'))`, the legacy twin.
390
+ if ((name === "__exportStar" || name === "__export") && e.arguments.length >= 1) {
391
+ const spec = bareRequireSpecOf(e.arguments[0]);
392
+ if (spec !== null) {
393
+ addStarSpec(spec);
394
+ neutralize.push({ start: stmt.getStart(sf), end: stmt.getEnd() });
395
+ sawBundleShape = true;
396
+ continue;
397
+ }
398
+ }
399
+ // `__reExport(TARGET, require('spec')[, module.exports]);` — esbuild's
400
+ // `export * from` plumbing.
401
+ if (name === "__reExport" && e.arguments.length >= 2) {
402
+ const spec = bareRequireSpecOf(e.arguments[1]);
403
+ if (spec !== null) {
404
+ addStarSpec(spec);
405
+ neutralize.push({ start: stmt.getStart(sf), end: stmt.getEnd() });
406
+ sawBundleShape = true;
407
+ continue;
408
+ }
409
+ }
410
+ // Object.defineProperty(exports, 'n', {...})
411
+ const def = definePropertyExportOf(e);
412
+ if (def !== null) {
413
+ if (def.esModuleStamp) {
414
+ neutralize.push({ start: stmt.getStart(sf), end: stmt.getEnd() });
415
+ // the canonical table re-stamps it (lexer-visibly — merve detects
416
+ // this defineProperty form, so parity wants a visible entry)
417
+ continue;
418
+ }
419
+ const chased = def.value !== null ? chaseValue(def.value) : null;
420
+ if (chased !== null) {
421
+ definePropEntries.push({ name: def.name, value: def.value });
422
+ neutralize.push({ start: stmt.getStart(sf), end: stmt.getEnd() });
423
+ sawBundleShape = true;
424
+ }
425
+ // unchaseable descriptor: LEAVE the statement (its runtime fence is
426
+ // loud where an undefined-valued entry would be a silent lie); the
427
+ // name still types through the any-fallback below.
428
+ continue;
429
+ }
430
+ }
431
+ if (!sawBundleShape)
432
+ return null;
433
+ const lexed = cjsLexedExportsOf(source, filePath);
434
+ if (lexed.exports.size === 0 && lexed.reexports.length === 0)
435
+ return null;
436
+ /* Star specs Node actually honors are the lexer's SURVIVING reexports
437
+ * (annotation spreads for esbuild bundles, star-pattern calls for tsc
438
+ * output). The statements walked above contribute load order; specs the
439
+ * lexer dropped (cleared by a later module.exports=) drop here too. */
440
+ const lexerSpecs = new Set(lexed.reexports);
441
+ const starSpecs = starSpecsInOrder.filter((s) => lexerSpecs.has(s));
442
+ for (const s of lexed.reexports) {
443
+ if (!starSpecs.includes(s))
444
+ starSpecs.push(s);
445
+ }
446
+ /* The entry list, first-wins per name: own getter-table entries, then
447
+ * defineProperty entries, then surviving top-level member exports, then
448
+ * (for names still uncovered) star enumerations in spec order, then the
449
+ * any fallback for every remaining lexer-visible name. */
450
+ const entries = new Map();
451
+ const claim = (name, spec) => {
452
+ if (name === "__esModule" || RESERVED_KEYS.has(name))
453
+ return;
454
+ if (!entries.has(name))
455
+ entries.set(name, spec);
456
+ };
457
+ const classify = (name, value) => {
458
+ const chased = value !== null ? chaseValue(value) : null;
459
+ if (chased === null)
460
+ return { name, kind: "any" };
461
+ if (chased.kind === "ident")
462
+ return { name, kind: "ident", value: chased.text };
463
+ return { name, kind: "hoist", value: chased.text };
464
+ };
465
+ // Own names: the getter table(s) — the one feeding module.exports first.
466
+ const tablesOrdered = [
467
+ ...exportTables.filter((t) => t.target === esbuildMainTarget),
468
+ ...exportTables.filter((t) => t.target !== esbuildMainTarget),
469
+ ];
470
+ for (const t of tablesOrdered) {
471
+ for (const [name, value] of t.entries)
472
+ claim(name, classify(name, value));
473
+ }
474
+ for (const d of definePropEntries)
475
+ claim(d.name, classify(d.name, d.value));
476
+ /* Top-level member exports. Node's export-object identity rules decide
477
+ * each statement's fate against the ORIGINAL table (esbuildMainTarget's
478
+ * assignment): a member attached BEFORE it was discarded (the table
479
+ * replaced the object), a bare `exports.N =` AFTER it wrote the stale
480
+ * object — both keep only their lexer-visible NAME (value undefined,
481
+ * exactly Node's link answer: the any fallback below). A surviving
482
+ * member (`module.exports.N =` after the table, or any spelling when no
483
+ * table exists) re-emits its VALUE as a canonical entry — identifier
484
+ * RHS only; any other RHS would need a second evaluation, so the file
485
+ * is left alone (the offender path owns it). Every member statement is
486
+ * then NEUTRALIZED: the canonical tail table replaces the object, and
487
+ * a stray earlier attach would meet the lowering's discard fence. */
488
+ for (const m of memberStmts) {
489
+ let cur = m.finalRhs;
490
+ while (ts.isParenthesizedExpression(cur))
491
+ cur = cur.expression;
492
+ const isVoidInit = cur.kind === ts.SyntaxKind.VoidExpression || (ts.isIdentifier(cur) && cur.text === "undefined");
493
+ const discarded = tablePos !== null && (m.pos < tablePos || m.viaBareExports);
494
+ if (!isVoidInit) {
495
+ // Only side-effect-free RHS shapes may be neutralized (identifiers,
496
+ // scalar literals, ident-rooted member chains — chaseValue's set);
497
+ // anything else keeps the file untouched (the offender path owns
498
+ // it: neutralizing would drop an evaluation, keeping it meets the
499
+ // lowering's discard fence at load).
500
+ const chased = chaseValue(cur);
501
+ if (chased === null)
502
+ return null;
503
+ if (!discarded) {
504
+ for (const name of m.names)
505
+ claim(name, { name, kind: chased.kind, value: chased.text });
506
+ }
507
+ // discarded members keep only their lexer-visible NAME (the any
508
+ // fallback below) — value undefined, exactly Node's link answer
509
+ }
510
+ neutralize.push({ start: m.start, end: m.end });
511
+ }
512
+ /* Direct-vs-hoist for ident entries: only bindings declared by a
513
+ * top-level const/function/class may be spelled directly (alias
514
+ * plumbing needs an immutable target — a `var`/`let` in the table would
515
+ * fence the whole statement). Everything else snapshots via a tail
516
+ * const. */
517
+ const immutableTopLevel = new Set();
518
+ for (const stmt of sf.statements) {
519
+ if (ts.isFunctionDeclaration(stmt) && stmt.name !== undefined)
520
+ immutableTopLevel.add(stmt.name.text);
521
+ else if (ts.isClassDeclaration(stmt) && stmt.name !== undefined)
522
+ immutableTopLevel.add(stmt.name.text);
523
+ else if (ts.isVariableStatement(stmt) && (stmt.declarationList.flags & ts.NodeFlags.Const) !== 0) {
524
+ for (const d of stmt.declarationList.declarations) {
525
+ if (ts.isIdentifier(d.name))
526
+ immutableTopLevel.add(d.name.text);
527
+ }
528
+ }
529
+ }
530
+ for (const spec of entries.values()) {
531
+ if (spec.kind === "ident" && !immutableTopLevel.has(spec.value))
532
+ spec.kind = "hoist";
533
+ }
534
+ // Star enumerations for names the own entries left uncovered.
535
+ const starMembers = [];
536
+ const requireConsts = [];
537
+ starSpecs.forEach((spec, i) => {
538
+ const target = resolveRelativeCjs(filePath, spec);
539
+ if (target === null)
540
+ return; // bare/unresolved: the spread entry carries it
541
+ const names = starTargetNames(target);
542
+ let refVar = null;
543
+ for (const n of names) {
544
+ if (n === "default" || n === "__esModule" || entries.has(n) || RESERVED_KEYS.has(n))
545
+ continue;
546
+ if (starMembers.some((m) => m.name === n))
547
+ continue; // earlier spec wins
548
+ if (refVar === null) {
549
+ refVar = `__scriptc_r${i}`;
550
+ requireConsts.push(`const ${refVar} = require(${JSON.stringify(spec)});`);
551
+ }
552
+ starMembers.push({ name: n, ref: refVar });
553
+ }
554
+ });
555
+ // The any fallback: every lexer-visible name nothing above covered.
556
+ for (const n of lexed.exports)
557
+ claim(n, { name: n, kind: "any" });
558
+ if (entries.size === 0 && starSpecs.length === 0)
559
+ return null;
560
+ /* Bundler HELPPER declarations left unused once the plumbing statements
561
+ * are gone would still fence at module load (`var __defProp =
562
+ * Object.defineProperty;` — a stdlib generic method as a value has no
563
+ * lowering, and a top-level declaration's fence throws when init runs
564
+ * it). Mark-and-sweep the RECOGNIZED helper names: a helper whose every
565
+ * reference lies inside an already-neutralized span (the plumbing
566
+ * calls, or another swept helper's declaration) is neutralized too.
567
+ * Helpers live code still calls (__toESM interop wrappers, __commonJS
568
+ * chunk factories) stay — their declarations are plain function values
569
+ * whose bodies defer per the JS function-poison rule. */
570
+ {
571
+ const HELPER_NAMES = new Set([
572
+ "__create", "__defProp", "__defProps", "__getOwnPropDesc", "__getOwnPropDescs",
573
+ "__getOwnPropNames", "__getOwnPropSymbols", "__getProtoOf", "__hasOwnProp",
574
+ "__propIsEnum", "__export", "__copyProps", "__reExport", "__toESM", "__toCommonJS",
575
+ "__exportStar", "__createBinding", "__setModuleDefault", "__importStar", "__importDefault",
576
+ ]);
577
+ const helperDecls = new Map();
578
+ for (const stmt of sf.statements) {
579
+ if (!ts.isVariableStatement(stmt))
580
+ continue;
581
+ const decls = stmt.declarationList.declarations;
582
+ if (decls.length !== 1)
583
+ continue;
584
+ const d = decls[0];
585
+ if (ts.isIdentifier(d.name) && HELPER_NAMES.has(d.name.text)) {
586
+ helperDecls.set(d.name.text, { start: stmt.getStart(sf), end: stmt.getEnd() });
587
+ }
588
+ }
589
+ // every identifier occurrence of a helper name outside its own
590
+ // declarator name node, position-recorded for the span test
591
+ const refs = new Map();
592
+ const record = (node) => {
593
+ ts.forEachChild(node, record);
594
+ if (ts.isIdentifier(node) && helperDecls.has(node.text)) {
595
+ const parent = node.parent;
596
+ if (parent !== undefined && ts.isVariableDeclaration(parent) && parent.name === node)
597
+ return;
598
+ const list = refs.get(node.text);
599
+ if (list === undefined)
600
+ refs.set(node.text, [node.getStart(sf)]);
601
+ else
602
+ list.push(node.getStart(sf));
603
+ }
604
+ };
605
+ record(sf);
606
+ const dead = [...neutralize];
607
+ const inDead = (pos) => dead.some((s) => pos >= s.start && pos < s.end);
608
+ const removed = new Set();
609
+ for (let changed = true; changed;) {
610
+ changed = false;
611
+ for (const [name, span] of helperDecls) {
612
+ if (removed.has(name))
613
+ continue;
614
+ // SELF-references inside the candidate's own declaration don't
615
+ // keep it alive (`var __createBinding = (this && this.__createBinding)
616
+ // || ...` — the tsc helper's UMD-style self probe).
617
+ const live = (refs.get(name) ?? []).filter((p) => p < span.start || p >= span.end);
618
+ if (live.every(inDead)) {
619
+ removed.add(name);
620
+ dead.push(span);
621
+ changed = true;
622
+ }
623
+ }
624
+ }
625
+ neutralize.length = 0;
626
+ neutralize.push(...dead);
627
+ }
628
+ /* ── emission ─────────────────────────────────────────────────────── */
629
+ let text = source;
630
+ // pad from the END so earlier spans' offsets stay valid
631
+ for (const n of [...neutralize].sort((a, b) => b.start - a.start)) {
632
+ text = padSpan(text, n.start, n.end);
633
+ }
634
+ const lines = [""];
635
+ const hasAnyFallback = [...entries.values()].some((s) => s.kind === "any");
636
+ if (hasAnyFallback) {
637
+ // checked-dynamic undefined: an implicit-any IIFE result registers a
638
+ // dyn module global the table's alias plumbing can resolve.
639
+ lines.push("const __scriptc_any = (() => { let u; return u; })();");
640
+ }
641
+ lines.push(...requireConsts);
642
+ const hoists = [];
643
+ let hoistN = 0;
644
+ const keyOf = (name) => (isPlainName(name) ? name : JSON.stringify(name));
645
+ const plainParts = [];
646
+ for (const spec of entries.values()) {
647
+ if (spec.kind === "ident") {
648
+ plainParts.push(`${keyOf(spec.name)}: ${spec.value},`);
649
+ }
650
+ else if (spec.kind === "hoist") {
651
+ const v = `__scriptc_e${hoistN++}`;
652
+ hoists.push(`const ${v} = ${spec.value};`);
653
+ plainParts.push(`${keyOf(spec.name)}: ${v},`);
654
+ }
655
+ else {
656
+ plainParts.push(`${keyOf(spec.name)}: __scriptc_any,`);
657
+ }
658
+ }
659
+ lines.push(...hoists);
660
+ /* The table. Spread entries first (REVERSED: Node's star copies are
661
+ * first-wins, an object literal's later-wins — reversing makes them
662
+ * agree), then the scan-visible plain entries, then — only where the
663
+ * original stamped it LEXER-DETECTABLY (the tsc defineProperty form;
664
+ * Node links `import { __esModule }` there) — the `__esModule: true`
665
+ * entry, then the member-access star entries whose names the spread
666
+ * records already cover. esbuild's marker lives inside __toCommonJS
667
+ * where Node's lexer never saw it, and spelling it here would flip the
668
+ * checker's default-import interop (an __esModule-stamped surface binds
669
+ * `import def` to exports.default) away from Node's CJS answer — so it
670
+ * is deliberately OMITTED from the canonical table. */
671
+ const spreadParts = [...starSpecs].reverse().map((s) => `...require(${JSON.stringify(s)}),`);
672
+ const esModulePart = lexed.exports.has("__esModule") ? "__esModule: true," : "";
673
+ const memberParts = starMembers.map((m) => `${keyOf(m.name)}: ${m.ref}${isPlainName(m.name) ? `.${m.name}` : `[${JSON.stringify(m.name)}]`},`);
674
+ lines.push(`module.exports = {${spreadParts.join("")}${plainParts.join("")}${esModulePart}${memberParts.join("")}};`);
675
+ return text + lines.join("\n") + "\n";
676
+ }
677
+ //# sourceMappingURL=npm-static-rewrite.js.map