@scriptc/compiler 0.0.4 → 0.0.6

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 (74) hide show
  1. package/dist/backend/cc.d.ts +16 -0
  2. package/dist/backend/cc.js +88 -0
  3. package/dist/backend/cc.js.map +1 -1
  4. package/dist/backend/emission/emit-async.js +2 -2
  5. package/dist/backend/emission/emit-async.js.map +1 -1
  6. package/dist/backend/emission/emit-exprs.js +27 -4
  7. package/dist/backend/emission/emit-exprs.js.map +1 -1
  8. package/dist/backend/emission/emit-shapes.js +2 -2
  9. package/dist/backend/emission/emit-shapes.js.map +1 -1
  10. package/dist/backend/emission/emit-walkers.js +54 -8
  11. package/dist/backend/emission/emit-walkers.js.map +1 -1
  12. package/dist/backend/emission/emitter.d.ts +1 -0
  13. package/dist/backend/emission/emitter.js +108 -0
  14. package/dist/backend/emission/emitter.js.map +1 -1
  15. package/dist/backend/emission/may-throw.js +12 -0
  16. package/dist/backend/emission/may-throw.js.map +1 -1
  17. package/dist/backend/llvm/dyn.js +23 -1
  18. package/dist/backend/llvm/dyn.js.map +1 -1
  19. package/dist/backend/llvm/emitter.js +150 -6
  20. package/dist/backend/llvm/emitter.js.map +1 -1
  21. package/dist/backend/llvm/walkers.d.ts +5 -0
  22. package/dist/backend/llvm/walkers.js +65 -5
  23. package/dist/backend/llvm/walkers.js.map +1 -1
  24. package/dist/diagnostics/diagnostic.d.ts +25 -0
  25. package/dist/diagnostics/diagnostic.js +86 -0
  26. package/dist/diagnostics/diagnostic.js.map +1 -1
  27. package/dist/frontend/lib-exports.d.ts +16 -0
  28. package/dist/frontend/lib-exports.js +35 -0
  29. package/dist/frontend/lib-exports.js.map +1 -0
  30. package/dist/frontend/lowering/lower-assert.js +41 -1
  31. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  32. package/dist/frontend/lowering/lower-calls.js +2 -2
  33. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  34. package/dist/frontend/lowering/lower-classes.js +1 -1
  35. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  36. package/dist/frontend/lowering/lower-exprs.js +1 -1
  37. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  38. package/dist/frontend/lowering/lower-inspect.d.ts +7 -0
  39. package/dist/frontend/lowering/lower-inspect.js +130 -28
  40. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  41. package/dist/frontend/lowering/lower-island.js +1 -1
  42. package/dist/frontend/lowering/lower-island.js.map +1 -1
  43. package/dist/frontend/lowering/lower-mixins.js +4 -2
  44. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  45. package/dist/frontend/lowering/lower-stmts.js +107 -0
  46. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  47. package/dist/frontend/lowering/lowerer.d.ts +16 -2
  48. package/dist/frontend/lowering/lowerer.js +64 -15
  49. package/dist/frontend/lowering/lowerer.js.map +1 -1
  50. package/dist/frontend/npm-static-rewrite.d.ts +3 -0
  51. package/dist/frontend/npm-static-rewrite.js +677 -0
  52. package/dist/frontend/npm-static-rewrite.js.map +1 -0
  53. package/dist/frontend/npm-static.d.ts +8 -1
  54. package/dist/frontend/npm-static.js +159 -18
  55. package/dist/frontend/npm-static.js.map +1 -1
  56. package/dist/frontend/program.d.ts +6 -0
  57. package/dist/frontend/program.js +51 -14
  58. package/dist/frontend/program.js.map +1 -1
  59. package/dist/frontend/types.d.ts +68 -6
  60. package/dist/frontend/types.js +285 -57
  61. package/dist/frontend/types.js.map +1 -1
  62. package/dist/index.d.ts +22 -0
  63. package/dist/index.js +253 -17
  64. package/dist/index.js.map +1 -1
  65. package/dist/ir/nodes.d.ts +50 -4
  66. package/dist/ir/nodes.js +179 -13
  67. package/dist/ir/nodes.js.map +1 -1
  68. package/dist/ir/validate.js +61 -0
  69. package/dist/ir/validate.js.map +1 -1
  70. package/dist/library/profile.d.ts +52 -0
  71. package/dist/library/profile.js +232 -0
  72. package/dist/library/profile.js.map +1 -0
  73. package/package.json +2 -2
  74. package/surface-manifest.json +1 -1
@@ -195,6 +195,12 @@ export interface LowerOptions {
195
195
  * resolution walk and CJS named-import link check): the program
196
196
  * compiles to that startup crash. */
197
197
  startupCrash?: StartupCrash | null;
198
+ /** LIBRARY mode's reachability roots: the profile-mapped exports of the
199
+ * entry module. Executable builds root at the entry's top level alone
200
+ * (an unreferenced export dead-strips); a library's exports are called from
201
+ * OUTSIDE the graph, so discovery seeds them alongside the init
202
+ * bodies. Names are the entry file's unqualified declaration names. */
203
+ libRoots?: readonly string[];
198
204
  }
199
205
  /** The Lowerer's pass configuration (see lowerToIr). */
200
206
  export interface LowererMode {
@@ -786,7 +792,7 @@ export declare class Lowerer {
786
792
  * demand-driven) and lifted lambdas lower inline with their enclosing
787
793
  * body; both fire edges through the same hooks and are not units
788
794
  * themselves. */
789
- discover(): Set<string>;
795
+ discover(extraRoots?: readonly string[]): Set<string>;
790
796
  /** Discovery hook (see discover): fires when lowering resolves a
791
797
  * reference to a lowerable body. Inert in the emit pass. */
792
798
  noteEdge(name: string): void;
@@ -1210,7 +1216,7 @@ export declare class Lowerer {
1210
1216
  * which have no JSON serialization (a handle isn't JSON) but an honest
1211
1217
  * per-field construction. Recursion terminates: recursive shapes are
1212
1218
  * rejected at mapping time. */
1213
- jsvalLiftable(t: IrType): boolean;
1219
+ jsvalLiftable(t: IrType, visiting?: Set<string>): boolean;
1214
1220
  /** A jsval-typed expression carrying `e`'s value into the island —
1215
1221
  * jsvalLiftable's constructive side. Primitives and JSON-safe composites
1216
1222
  * keep the jsMarshal deep copy; jsval-bearing records and arrays go
@@ -1523,6 +1529,14 @@ export declare class Lowerer {
1523
1529
  * through arrows (function expressions/declarations reset `this` in JS;
1524
1530
  * their bodies never see an enclosing method's binding). */
1525
1531
  resolveThis(): IrLocal | null;
1532
+ /** READ-ONLY twin of resolveLocal for PROBES (isIslandExpr): answers
1533
+ * the nearest binding entry without boxing, threading, or predeclaring.
1534
+ * resolveKey mutates capture state as a side effect, and a speculative
1535
+ * island-ness query through a context that takes no captures (a plain
1536
+ * declared function between the origin and the reference) was an ICE —
1537
+ * the REAL lowering path still resolves (and diagnoses) the reference
1538
+ * itself. */
1539
+ peekLocal(ident: ts.Identifier): IrLocal | null;
1526
1540
  resolveKey(symbol: ts.Symbol, blame?: ts.Node): IrLocal | null;
1527
1541
  isSelfReference(ident: ts.Identifier): boolean;
1528
1542
  lowerStmts(stmts: readonly ts.Statement[]): IrStmt[];
@@ -17,7 +17,7 @@ import * as ts from "../ts7/adapter.js";
17
17
  import { anyOpRequiresDynamicDiag, blockedBindingUseDiag, checkerPanicDiag, isCheckerPanic, genericSignatureTypeDiag, indexSignatureTypeDiag, noLoweringDiag, recordShapeMismatchDiag, requiresDynamicApiDiag, requiresDynamicPackageDiag, requiresDynamicTypeDiag, unionMismatchDiag, unsupportedDiag, unsupportedTypeDiag, } from "../../diagnostics/diagnostic.js";
18
18
  import { arrayOf, BOOL, canAdaptDynFuncTo, canConvertToDyn, canCrossIslandBoundary, canExitIslandToType, canMarshalTypedFuncIntoIsland, DYN, F64, isJsonSafeType, isUndefinedArmedUnion, isUnitType, JSVAL, RUNTIME_ERROR_CLASSES, STRING, typeEquals, UNDEFINED_T, VOID } from "../../ir/nodes.js";
19
19
  import { provenanceActive } from "../provenance-registry.js";
20
- import { ambientDtsPath, canonicalBuiltinModule, cjsExportAssignmentOf, cjsExportDiscardReason, fallbackDtsPath, isCjsExportTableLiteral, isJsSourceFile, isNodeEsmFile, isNodeTypesPath, locOf, overridesDtsPath, requireSpecOf, resolveImport, workspacePackageOfPath, } from "../program.js";
20
+ import { ambientDtsPath, canonicalBuiltinModule, cjsExportAssignmentOf, cjsExportDiscardReason, fallbackDtsPath, isCjsExportTableLiteral, isJsSourceFile, isNodeEsmFile, isNodeTypesPath, locOf, overridesDtsPath, npmStaticDepSf7, requireSpecOf, resolveImport, workspacePackageOfPath, } from "../program.js";
21
21
  import { containsRecord, containsUnion, formatIrType, ISLAND_AMBIENT_TYPES, isUnitOnlyTsType, mapType, ShapeRegistry, typeKey, UnionRegistry, withUndefinedArm as withUndefinedArmCanonical, } from "../types.js";
22
22
  import { boundaryIntoIslandMsg, boundaryOutOfIslandMsg, builtinConstLit, builtinModuleConstOf, builtinFenceHintOf, builtinModuleFnOf, stdlibMemberFence, isStdlibMember, isStdlibSymbol, isStdlibGlobal, stdlibGlobalMember, nodeTypesOnlySymbol } from "./surfaces.js";
23
23
  import { splitFiles, collectProgram, collectNpmImports, collectJsonImports, moduleArtifacts, collectGlobals, declSymbolOf, defaultExportSymbolOf, lowerFileInit, lowerDefaultExport, buildMain, appendDynamicImportModules } from "./lower-modules.js";
@@ -148,7 +148,7 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
148
148
  const dynamic = options.dynamic ?? false;
149
149
  const targetPlatform = options.targetPlatform ?? process.platform;
150
150
  const startupCrash = options.startupCrash ?? null;
151
- const reachable = new Lowerer(program, entry, moduleOrder, dynamic, { targetPlatform }).discover();
151
+ const reachable = new Lowerer(program, entry, moduleOrder, dynamic, { targetPlatform }).discover(options.libRoots);
152
152
  const emit = new Lowerer(program, entry, moduleOrder, dynamic, { reachable, targetPlatform, startupCrash });
153
153
  const result = emit.run();
154
154
  if (options.coverage !== true)
@@ -1079,9 +1079,13 @@ export class Lowerer {
1079
1079
  return null;
1080
1080
  }
1081
1081
  const spec = importDecl.moduleSpecifier.text;
1082
- if (!isRelativeSpecifier(spec))
1083
- return null;
1084
- const dep = resolveImport(this.program, importDecl.getSourceFile(), spec);
1082
+ // Bare specifiers resolve only for opted-in --npm-static packages —
1083
+ // their CJS entries take the same default-binding interop as a
1084
+ // relative require; every other bare import answers null and keeps
1085
+ // its own machinery.
1086
+ const dep = isRelativeSpecifier(spec)
1087
+ ? resolveImport(this.program, importDecl.getSourceFile(), spec)
1088
+ : npmStaticDepSf7(this.program, importDecl.getSourceFile(), spec);
1085
1089
  if (!dep || !isJsSourceFile(dep) || isNodeEsmFile(dep))
1086
1090
  return null;
1087
1091
  return dep;
@@ -1575,7 +1579,7 @@ export class Lowerer {
1575
1579
  * demand-driven) and lifted lambdas lower inline with their enclosing
1576
1580
  * body; both fire edges through the same hooks and are not units
1577
1581
  * themselves. */
1578
- discover() {
1582
+ discover(extraRoots) {
1579
1583
  const parts = this.splitFiles();
1580
1584
  this.collectProgram(parts);
1581
1585
  // Decorated classes analyze post-collection here too: the %init seeds
@@ -1683,6 +1687,12 @@ export class Lowerer {
1683
1687
  this.lowerFileInit(fp.sf, fp.topStmts, this.initNameOf.get(fp.sf));
1684
1688
  drainInstances();
1685
1689
  });
1690
+ // LIBRARY mode's extra reachability roots (LowerOptions.libRoots): the
1691
+ // profile-mapped exports are called from outside the graph, so they
1692
+ // seed the worklist beside the init bodies. Unknown names are inert
1693
+ // (the export-map resolution reports them as SC4002 later).
1694
+ for (const root of extraRoots ?? [])
1695
+ this.onEdge?.(root);
1686
1696
  while (queue.length > 0) {
1687
1697
  // A body-level poison outside the per-statement catches (a fenced
1688
1698
  // constructor/method parameter default lowered by declareParams):
@@ -4222,7 +4232,7 @@ export class Lowerer {
4222
4232
  * which have no JSON serialization (a handle isn't JSON) but an honest
4223
4233
  * per-field construction. Recursion terminates: recursive shapes are
4224
4234
  * rejected at mapping time. */
4225
- jsvalLiftable(t) {
4235
+ jsvalLiftable(t, visiting = new Set()) {
4226
4236
  if (t.kind === "jsval")
4227
4237
  return true;
4228
4238
  if (this.boundarySafe(t))
@@ -4246,22 +4256,32 @@ export class Lowerer {
4246
4256
  const shape = this.shapes.get(t.shapeId);
4247
4257
  if (!shape || shape.tuple)
4248
4258
  return false;
4259
+ // Recursive shapes reaching here answer FALSE: this branch is the
4260
+ // per-field island lift (jsval/bytes-bearing composites — the
4261
+ // JSON-safe ones already answered true through boundarySafe, where
4262
+ // a cyclic value throws the circular TypeError at the marshal), and
4263
+ // the lift helpers walk values with no circular guard — fencing the
4264
+ // TYPE is the honest answer.
4265
+ if (visiting.has(t.shapeId))
4266
+ return false;
4267
+ visiting.add(t.shapeId);
4249
4268
  // An INDEX-SIGNATURE record lifts when its value slot does (dyn
4250
4269
  // included): declared fields write first, then the overflow keys.
4251
- if (shape.indexValue && !this.jsvalLiftable(shape.indexValue))
4270
+ if (shape.indexValue && !this.jsvalLiftable(shape.indexValue, visiting))
4252
4271
  return false;
4253
- return shape.fields.every((f) => !f.name.startsWith("%") && this.jsvalLiftable(f.type));
4272
+ return shape.fields.every((f) => !f.name.startsWith("%") && this.jsvalLiftable(f.type, visiting));
4254
4273
  }
4255
4274
  if (t.kind === "array")
4256
- return this.jsvalLiftable(t.elem);
4275
+ return this.jsvalLiftable(t.elem, visiting);
4257
4276
  // A union crossing IN lifts arm by arm (a runtime tag switch — see
4258
4277
  // unionToJsvalHelper) when every arm does: unit arms become the
4259
4278
  // engine's own undefined/null (which is why bare undefined-armed
4260
4279
  // unions lift here despite being JSON-unsafe), the rest lift as
4261
- // themselves. Arms never nest unions, so this terminates.
4280
+ // themselves. Arms never nest unions, so this terminates (recursive
4281
+ // knots pass through records, guarded above).
4262
4282
  if (t.kind === "union") {
4263
4283
  const def = this.unions.get(t.unionId);
4264
- return !!def && def.arms.every((a) => isUnitType(a) || this.jsvalLiftable(a));
4284
+ return !!def && def.arms.every((a) => isUnitType(a) || this.jsvalLiftable(a, visiting));
4265
4285
  }
4266
4286
  return false;
4267
4287
  }
@@ -5473,6 +5493,27 @@ export class Lowerer {
5473
5493
  resolveThis() {
5474
5494
  return this.resolveKey(THIS_BINDING);
5475
5495
  }
5496
+ /** READ-ONLY twin of resolveLocal for PROBES (isIslandExpr): answers
5497
+ * the nearest binding entry without boxing, threading, or predeclaring.
5498
+ * resolveKey mutates capture state as a side effect, and a speculative
5499
+ * island-ness query through a context that takes no captures (a plain
5500
+ * declared function between the origin and the reference) was an ICE —
5501
+ * the REAL lowering path still resolves (and diagnoses) the reference
5502
+ * itself. */
5503
+ peekLocal(ident) {
5504
+ let symbol = this.checker.getSymbolAtLocation(ident);
5505
+ if (ident.parent && ts.isShorthandPropertyAssignment(ident.parent) && ident.parent.name === ident) {
5506
+ symbol = this.checker.getShorthandAssignmentValueSymbol(ident.parent) ?? symbol;
5507
+ }
5508
+ if (!symbol)
5509
+ return null;
5510
+ for (let depth = this.fnStack.length - 1; depth >= 0; depth--) {
5511
+ const hit = this.bindingIn(this.fnStack[depth], symbol);
5512
+ if (hit)
5513
+ return hit;
5514
+ }
5515
+ return null;
5516
+ }
5476
5517
  resolveKey(symbol, blame) {
5477
5518
  const direct = this.bindingIn(this.ctx, symbol);
5478
5519
  if (direct)
@@ -5506,6 +5547,17 @@ export class Lowerer {
5506
5547
  const ctx = this.fnStack[j];
5507
5548
  let entry = ctx.captureBySymbol.get(symbol);
5508
5549
  if (!entry) {
5550
+ // A context that takes NO captures (a plain declared function —
5551
+ // monomorphized/implicit instances lower this way) cannot carry
5552
+ // the binding through: the shape is a module binding whose only
5553
+ // storage is the init function's LOCAL (a typed-but-unmappable
5554
+ // const — the file-scope `new Map()` ledger idiom) read from
5555
+ // inside a nested instance. Fence it — in JS the statement
5556
+ // defers to its runtime trap like every collection failure;
5557
+ // asserting here was an ICE on ordinary npm-static JS.
5558
+ if (ctx.captures === null) {
5559
+ this.unsupported("SC1090", blame ?? this.checker.declarationsOf(symbol)[0] ?? this.entry, `the binding '${origin.name}' captured through a plain nested function (the declaration has no static storage a capture can thread — bind the value through a typed const, or read it in the declaring scope)`);
5560
+ }
5509
5561
  const count = ctx.localCounters.get(origin.name) ?? 0;
5510
5562
  ctx.localCounters.set(origin.name, count + 1);
5511
5563
  entry = {
@@ -5520,9 +5572,6 @@ export class Lowerer {
5520
5572
  };
5521
5573
  ctx.locals.push(entry);
5522
5574
  ctx.captureBySymbol.set(symbol, entry);
5523
- if (ctx.captures === null) {
5524
- throw new Error("lowerer bug: capture threading through a non-lifted function");
5525
- }
5526
5575
  ctx.captures.push({ localId: entry.id, name: entry.name, type: entry.type });
5527
5576
  ctx.captureSources.push(parentEntry.id);
5528
5577
  }