@scriptc/compiler 0.0.7 → 0.0.9
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/ambient/scriptc-node-fallback.d.ts +13 -0
- package/dist/backend/cc.js +14 -0
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +155 -6
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-island.js +9 -1
- package/dist/backend/emission/emit-island.js.map +1 -1
- package/dist/backend/emission/emit-stmts.js +3 -1
- package/dist/backend/emission/emit-stmts.js.map +1 -1
- package/dist/backend/emission/emit-types.d.ts +3 -0
- package/dist/backend/emission/emit-types.js +12 -0
- package/dist/backend/emission/emit-types.js.map +1 -1
- package/dist/backend/emission/emit-walkers.d.ts +7 -5
- package/dist/backend/emission/emit-walkers.js +45 -18
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +1 -1
- package/dist/backend/emission/emitter.js +35 -10
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/emission/may-throw.js +4 -3
- package/dist/backend/emission/may-throw.js.map +1 -1
- package/dist/backend/llvm/emitter.js +300 -18
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +98 -11
- package/dist/diagnostics/diagnostic.js +185 -25
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lib-contract.d.ts +24 -6
- package/dist/frontend/lib-contract.js +125 -44
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +16 -0
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +11 -0
- package/dist/frontend/lowering/lower-builtins.js +127 -4
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +77 -18
- package/dist/frontend/lowering/lower-calls.js +978 -44
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +14 -1
- package/dist/frontend/lowering/lower-classes.js +112 -16
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +4 -2
- package/dist/frontend/lowering/lower-containers.js +236 -44
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-emitter.js +55 -1
- package/dist/frontend/lowering/lower-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +26 -3
- package/dist/frontend/lowering/lower-exprs.js +507 -47
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +7 -0
- package/dist/frontend/lowering/lower-island.js +71 -10
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +1 -1
- package/dist/frontend/lowering/lower-mixins.js +1 -1
- package/dist/frontend/lowering/lower-modules.js +95 -4
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +866 -56
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +28 -2
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +85 -17
- package/dist/frontend/lowering/lowerer.js +459 -37
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +20 -3
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm-static-rewrite.d.ts +7 -2
- package/dist/frontend/npm-static-rewrite.js +566 -138
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static.js +11 -2
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/program.js +5 -5
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/shared.d.ts +6 -1
- package/dist/frontend/shared.js +46 -1
- package/dist/frontend/shared.js.map +1 -1
- package/dist/frontend/types.d.ts +28 -1
- package/dist/frontend/types.js +304 -10
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +181 -26
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +159 -9
- package/dist/ir/nodes.js +76 -6
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +93 -14
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/profile.d.ts +17 -3
- package/dist/library/profile.js +38 -9
- package/dist/library/profile.js.map +1 -1
- package/dist/library/sidecar.js +162 -43
- package/dist/library/sidecar.js.map +1 -1
- package/dist/library/trap-teaching.d.ts +11 -0
- package/dist/library/trap-teaching.js +49 -0
- package/dist/library/trap-teaching.js.map +1 -0
- package/package.json +2 -2
- package/surface-manifest.json +46 -4
package/dist/ir/nodes.d.ts
CHANGED
|
@@ -243,6 +243,7 @@ export type IrType = {
|
|
|
243
243
|
params: IrType[];
|
|
244
244
|
ret: IrType;
|
|
245
245
|
rest?: true;
|
|
246
|
+
restAbi?: "jsval";
|
|
246
247
|
} | {
|
|
247
248
|
kind: "object";
|
|
248
249
|
className: string;
|
|
@@ -436,8 +437,16 @@ export declare function isSupportedMapValue(t: IrType): boolean;
|
|
|
436
437
|
/** The INDEX-SIGNATURE value fence (`{ [k: string]: V }` shapes): the map
|
|
437
438
|
* VALUE kinds — the overflow portion IS a string-keyed map — plus dyn
|
|
438
439
|
* (`unknown`, an unknown-valued pricing-table shape: overflow reads surface ordinary
|
|
439
|
-
* dyn values validated by the usual checked casts)
|
|
440
|
-
*
|
|
440
|
+
* dyn values validated by the usual checked casts) and three kinds the
|
|
441
|
+
* overflow store carries that user Maps don't admit yet:
|
|
442
|
+
* func — `Record<string, () => void>`, the command-registry pattern
|
|
443
|
+
* (scr_closure adapters; closures are cycle-headered and traced,
|
|
444
|
+
* so a handler capturing its own registry collects)
|
|
445
|
+
* map/set — `Record<string, Map<K, V>>`/`Record<string, Set<T>>`
|
|
446
|
+
* nested-container tables (scr_map adapters; a map value's own
|
|
447
|
+
* cycle capability propagates through the trace fixpoint)
|
|
448
|
+
* Nested index-signature RECORDS ride the record kind like any other.
|
|
449
|
+
* Shared frontend (mapType) / validator. */
|
|
441
450
|
export declare function isSupportedIndexValue(t: IrType): boolean;
|
|
442
451
|
export declare function funcOf(params: IrType[], ret: IrType): IrType;
|
|
443
452
|
/** The union FUNC/SET-arm sibling rule, shared by the frontend's union
|
|
@@ -542,6 +551,24 @@ export interface IrLibExport {
|
|
|
542
551
|
fnName: string;
|
|
543
552
|
params: ("f64" | "bool" | "string" | "bytes" | "u8" | "u32" | "i32")[];
|
|
544
553
|
returns: "f64" | "bool" | "string" | "bytes" | "void";
|
|
554
|
+
/** The exact sink-message bytes this wrapper passes to the inbound-bytes
|
|
555
|
+
* marshalling helper's trap — present exactly when a parameter is
|
|
556
|
+
* bytes-classed. Already the assembled structured trap-teaching form
|
|
557
|
+
* (library/trap-teaching.ts): 0x01, teaching text, 0x1F, SC4012, 0x1F,
|
|
558
|
+
* this export's C symbol, and the profile's remediation behind one more
|
|
559
|
+
* 0x1F when supplied. Assembled ONCE at export resolution so both
|
|
560
|
+
* backends emit identical bytes by construction. */
|
|
561
|
+
inboundBytesTrap?: string;
|
|
562
|
+
}
|
|
563
|
+
/** One runtime-trap overlay row: the profile's teaching (replaces the
|
|
564
|
+
* baseline human line as field 0) and/or remediation (the optional fourth
|
|
565
|
+
* field) for one runtime detected-trap code. At least one of the two is
|
|
566
|
+
* present, or the row is not emitted. Text is profile-validated free of
|
|
567
|
+
* the encoding's reserved bytes (SC4001). */
|
|
568
|
+
export interface IrLibTrapOverlay {
|
|
569
|
+
code: string;
|
|
570
|
+
teaching?: string;
|
|
571
|
+
remediation?: string;
|
|
545
572
|
}
|
|
546
573
|
export interface IrLibSection {
|
|
547
574
|
/** The profile's identity string (artifact header comments only). */
|
|
@@ -557,6 +584,15 @@ export interface IrLibSection {
|
|
|
557
584
|
* posture (every entry prologue resets the arena). */
|
|
558
585
|
resultResetSymbol: string | null;
|
|
559
586
|
exports: IrLibExport[];
|
|
587
|
+
/** Profile-declared teaching/remediation overlays for the runtime
|
|
588
|
+
* detected-trap code family (SC4013–SC4019, diagnostics registry): both
|
|
589
|
+
* backends emit these as the program TU's overlay table
|
|
590
|
+
* (scr_library_trap_overlays — flat code/teaching/remediation triples)
|
|
591
|
+
* that the library trap funnel consults when it assembles a detected
|
|
592
|
+
* trap's structured sink message. Only declared codes appear, in the
|
|
593
|
+
* registry family's order, so the two emissions' data is identical by
|
|
594
|
+
* construction. */
|
|
595
|
+
trapOverlays: IrLibTrapOverlay[];
|
|
560
596
|
/** The ask-2 identity getters (present exactly when the profile
|
|
561
597
|
* declares a sidecar): pure data returns emitted with NO entry
|
|
562
598
|
* prologue — exempt from the poisoned guard and every runtime touch
|
|
@@ -1162,7 +1198,12 @@ export type IrStrIntrinsicMethod = "length" | "charCodeAt" | "charAt" | "indexOf
|
|
|
1162
1198
|
* DataView" RangeError on any bad offset. `dvGetBigUint64Number`/
|
|
1163
1199
|
* `dvGetBigInt64Number` are the COMPOSED `Number(view.getBigUint64(...))`
|
|
1164
1200
|
* lowerings — the bare bigint-returning calls are fenced, the wrapped
|
|
1165
|
-
* form converts the 8-byte integer to double exactly as Number(bigint).
|
|
1201
|
+
* form converts the 8-byte integer to double exactly as Number(bigint).
|
|
1202
|
+
* The `dvSet*` setters mirror the getters: [offset, value] plus the
|
|
1203
|
+
* optional bool littleEndian on the multi-byte kinds → void, the same
|
|
1204
|
+
* constant RangeError on any bad offset; values coerce JS-exactly
|
|
1205
|
+
* (integer kinds by modular truncation, Float32 by double→float
|
|
1206
|
+
* rounding). No BIG setters exist — bigint arguments never lower. */
|
|
1166
1207
|
export type IrBytesIntrinsicMethod = "length" | "byteLength" | "get" | "slice" | "setFrom" | "toString" | "readNum" | "writeNum" | "readNumVar" | "writeNumVar"
|
|
1167
1208
|
/** The comparison/search/mutation surface (u8 receivers only; see the
|
|
1168
1209
|
* runtime contract): `equals` [bytes] → bool (never throws);
|
|
@@ -1178,7 +1219,7 @@ export type IrBytesIntrinsicMethod = "length" | "byteLength" | "get" | "slice" |
|
|
|
1178
1219
|
* f64 copied count, THROWS; `swap16/32/64` [] → the receiver (+1,
|
|
1179
1220
|
* in-place), THROW; `writeStr` [string, strLit enc, f64 offset, f64
|
|
1180
1221
|
* length?] → f64 bytes written, THROWS. */
|
|
1181
|
-
| "equals" | "compareBuf" | "indexOf" | "lastIndexOf" | "includes" | "indexOfNum" | "lastIndexOfNum" | "includesNum" | "fill" | "fillNum" | "fillStr" | "copy" | "swap16" | "swap32" | "swap64" | "writeStr" | "byteOffset" | "dataViewNew" | "dvGetUint8" | "dvGetInt8" | "dvGetUint16" | "dvGetInt16" | "dvGetUint32" | "dvGetInt32" | "dvGetFloat32" | "dvGetFloat64" | "dvGetBigUint64Number" | "dvGetBigInt64Number";
|
|
1222
|
+
| "equals" | "compareBuf" | "indexOf" | "lastIndexOf" | "includes" | "indexOfNum" | "lastIndexOfNum" | "includesNum" | "fill" | "fillNum" | "fillStr" | "copy" | "swap16" | "swap32" | "swap64" | "writeStr" | "byteOffset" | "dataViewNew" | "dvGetUint8" | "dvGetInt8" | "dvGetUint16" | "dvGetInt16" | "dvGetUint32" | "dvGetInt32" | "dvGetFloat32" | "dvGetFloat64" | "dvGetBigUint64Number" | "dvGetBigInt64Number" | "dvSetUint8" | "dvSetInt8" | "dvSetUint16" | "dvSetInt16" | "dvSetUint32" | "dvSetInt32" | "dvSetFloat32" | "dvSetFloat64";
|
|
1182
1223
|
/** The bytesIntrinsic methods that can raise a catchable error — backends'
|
|
1183
1224
|
* may-throw analyses seed on these exactly like MAY_THROW_LIB_FNS. */
|
|
1184
1225
|
export declare const MAY_THROW_BYTES_METHODS: ReadonlySet<IrBytesIntrinsicMethod>;
|
|
@@ -1425,6 +1466,20 @@ export type IrLibFn = "island.eval"
|
|
|
1425
1466
|
* result for negative fractions rounding to zero. The explicit-digits
|
|
1426
1467
|
* forms keep their island lowering. Results +1; never throw. */
|
|
1427
1468
|
| "num.toExponential" | "num.toFixed0"
|
|
1469
|
+
/** Object.is over two numbers — the spec's SameValue on doubles: NaN
|
|
1470
|
+
* equals NaN, +0 differs from -0, everything else is `===`. Plain bool
|
|
1471
|
+
* result; never throws. (Union-armed operands take unionEq's sameValue
|
|
1472
|
+
* flag instead — this is the both-f64 fast path.) */
|
|
1473
|
+
| "num.sameValue"
|
|
1474
|
+
/** `new Intl.NumberFormat("en-US").format(x)` and
|
|
1475
|
+
* `x.toLocaleString("en-US")` with DEFAULT options — the one locale
|
|
1476
|
+
* whose data the runtime embeds (Node's default-build locale): decimal
|
|
1477
|
+
* notation, 0–3 fraction digits rounded half-up on the SHORTEST
|
|
1478
|
+
* round-tripping decimal (ICU's rounding input, probed vs Node —
|
|
1479
|
+
* format(1.0005) is "1.001" though toFixed(3) answers "1.000"), ","
|
|
1480
|
+
* grouping every three integer digits, "∞"/"NaN" texts, and "-0" for
|
|
1481
|
+
* negative inputs rounding to zero. Result +1; never throws. */
|
|
1482
|
+
| "intl.numFormatEnUs"
|
|
1428
1483
|
/** `delete process.env[NAME]` — unsetenv(3): the mutation is visible to
|
|
1429
1484
|
* every later read (process.envGet asks getenv fresh) and inherited by
|
|
1430
1485
|
* spawned children, exactly Node. Statement position only (JS's boolean
|
|
@@ -1952,6 +2007,37 @@ export type IrLibFn = "island.eval"
|
|
|
1952
2007
|
* zero-padded to the total. THROWS Node's 'length' RangeError on a
|
|
1953
2008
|
* negative/non-integer total (may-throw seed). */
|
|
1954
2009
|
| "buffer.concatLen"
|
|
2010
|
+
/** The checked-dynamic compare/equals validators (scr_bytes_io.c) —
|
|
2011
|
+
* the lowered form when an argument is NOT statically bytes<u8> (the
|
|
2012
|
+
* invalid-input probes; a dyn from an untyped JS helper): Node's own
|
|
2013
|
+
* argument ladders run at runtime — ERR_INVALID_ARG_TYPE with the
|
|
2014
|
+
* API's argument name ("buf1"/"buf2", "otherBuffer", "target"; offsets
|
|
2015
|
+
* "of type number"), validateOffset's ERR_OUT_OF_RANGE for bad
|
|
2016
|
+
* numbers, undefined offsets taking their Node defaults — and a
|
|
2017
|
+
* well-typed value still computes the real answer. All args borrowed
|
|
2018
|
+
* dyn; compareChk's four offset slots pass the undefined dyn when
|
|
2019
|
+
* syntactically absent. May-throw seeds. */
|
|
2020
|
+
| "buffer.compareChk" | "bytes.equalsChk" | "bytes.compareChk"
|
|
2021
|
+
/** The deprecated `new Buffer(number, 'enc')` string-arm rejection:
|
|
2022
|
+
* always throws Node's ERR_INVALID_ARG_TYPE ("The \"string\" argument
|
|
2023
|
+
* must be of type string. Received ..."). Borrowed dyn; may-throw. */
|
|
2024
|
+
| "buffer.newStringFail"
|
|
2025
|
+
/** fs._toUnixTimestamp(time) over a DOM value: numeric strings and
|
|
2026
|
+
* finite numbers coerce (negatives answer now/1000, Node's shape);
|
|
2027
|
+
* everything else throws Node's ERR_INVALID_ARG_TYPE. May-throw. */
|
|
2028
|
+
| "fs.toUnixTimestamp"
|
|
2029
|
+
/** The compiler-resolved ERR_INVALID_ARG_TYPE throw with a RUNTIME-
|
|
2030
|
+
* rendered Received tail: args [argname, "of type ..." clause, the
|
|
2031
|
+
* offending DOM value]. ALWAYS THROWS; polymorphic result (the
|
|
2032
|
+
* error.nodeThrow pattern). May-throw seed. */
|
|
2033
|
+
| "error.argTypeThrow"
|
|
2034
|
+
/** The checked-dynamic max-listeners ladders: setMaxChk is the
|
|
2035
|
+
* instance form over a DOM n (non-numbers ERR_INVALID_ARG_TYPE,
|
|
2036
|
+
* negatives/NaN ERR_OUT_OF_RANGE; +1 receiver back — chaining);
|
|
2037
|
+
* setDefaultMaxChk is the static/property form, its second argument
|
|
2038
|
+
* naming the message slot ("setMaxListeners" for the static call,
|
|
2039
|
+
* "defaultMaxListeners" for the module-property assignment). */
|
|
2040
|
+
| "emitter.setMaxChk" | "emitter.setDefaultMaxChk"
|
|
1955
2041
|
/** The Buffer forms of the fs quartet: readFileSync(path) with NO
|
|
1956
2042
|
* encoding → bytes<u8> (+1), writeFileSync(path, bytes), and the
|
|
1957
2043
|
* fs/promises readFile(path) no-encoding form (an already-settled
|
|
@@ -2176,6 +2262,20 @@ export type IrLibFn = "island.eval"
|
|
|
2176
2262
|
* field to stamp. error.toString: borrowed `%Error`-typed receiver, +1
|
|
2177
2263
|
* string in Node's "name: message" shape. None of the three throws. */
|
|
2178
2264
|
| "error.new"
|
|
2265
|
+
/** The compiler-resolved Node-parity throw for always-throwing lowered
|
|
2266
|
+
* arms (ERR_INVALID_THIS receivers, ERR_MISSING_ARGS arity ladders,
|
|
2267
|
+
* the symbol-to-string TypeError): args are [error-kind f64 (the
|
|
2268
|
+
* SCR_ERR_* index: 0 Error, 1 TypeError, 2 RangeError), code (empty =
|
|
2269
|
+
* no code slot), message]. ALWAYS THROWS catchably; the result type is
|
|
2270
|
+
* the replaced expression's own (never materialized — the
|
|
2271
|
+
* global.undefRead pattern). May-throw seed. */
|
|
2272
|
+
| "error.nodeThrow"
|
|
2273
|
+
/** JS ToString over a DOM value WITH the object protocol (a user
|
|
2274
|
+
* toString/valueOf member is CALLED and its throw propagates;
|
|
2275
|
+
* exhaustion throws "Cannot convert object to primitive value"; units
|
|
2276
|
+
* render "null"/"undefined") — the WHATWG USVString conversions
|
|
2277
|
+
* (URLSearchParams names/values). Borrowed dyn; +1 string. May-throw. */
|
|
2278
|
+
| "dyn.toStringCoerce"
|
|
2179
2279
|
/** A read of a `declare`d const NOTHING defines (the bundler-define
|
|
2180
2280
|
* pattern — __VERSION__): always throws the catchable ReferenceError
|
|
2181
2281
|
* Node raises at the access ("<name> is not defined"). args[0] is the
|
|
@@ -2230,7 +2330,7 @@ export type IrLibFn = "island.eval"
|
|
|
2230
2330
|
* JS). Strings/arrays/bytes answer their index keys; other scalars an
|
|
2231
2331
|
* empty array; null/undefined throw Node's catchable TypeError
|
|
2232
2332
|
* ("Cannot convert undefined or null to object"). */
|
|
2233
|
-
| "dyn.objKeys" | "dyn.objValues" | "dyn.objEntries"
|
|
2333
|
+
| "dyn.objKeys" | "dyn.hasOwn" | "dyn.assign" | "dyn.objValues" | "dyn.objEntries"
|
|
2234
2334
|
/** structuredClone over the DOM (scr_json.c): the JSON-safe subset plus
|
|
2235
2335
|
* bytes (a fresh copy — a Buffer clones as a plain Uint8Array, like
|
|
2236
2336
|
* Node), deep. Functions and handle kinds throw the spec's catchable
|
|
@@ -2334,7 +2434,13 @@ export type IrLibFn = "island.eval"
|
|
|
2334
2434
|
* propagates the first error by destroying the rest, calls cb after the
|
|
2335
2435
|
* last 'close'; answers the destination +1. The Dyn twins take the
|
|
2336
2436
|
* callback as a checked-dynamic VALUE (mustCall wrappers). */
|
|
2337
|
-
| "stream.finished" | "stream.finishedDyn" | "stream.pipeline" | "stream.pipelineDyn"
|
|
2437
|
+
| "stream.finished" | "stream.finishedDyn" | "stream.pipeline" | "stream.pipelineDyn"
|
|
2438
|
+
/** node:stream/promises — the promise forms over the same machinery:
|
|
2439
|
+
* sp.finished: (s) → a pending void promise the terminal watcher
|
|
2440
|
+
* settles; sp.pipeline: (count, s1..sn) → the callback pipeline's
|
|
2441
|
+
* chaining/destroyer semantics settling a void promise (fulfilled on a
|
|
2442
|
+
* clean finish, rejected with the finish status otherwise). */
|
|
2443
|
+
| "sp.finished" | "sp.pipeline" | "readable.newDyn" | "writable.newDyn" | "duplex.newDyn" | "transform.newDyn" | "passthrough.newDyn" | "readable.initDyn" | "writable.initDyn" | "duplex.initDyn" | "transform.initDyn" | "passthrough.initDyn" | "readable.push" | "readable.pushStr" | "readable.pushNull" | "readable.pushU" | "readable.pushDyn" | "readable.unshift" | "readable.unshiftStr" | "readable.read" | "readable.pause" | "readable.resume" | "readable.setEncoding"
|
|
2338
2444
|
/** for-await over a readable (the desugared loop's per-pass promise):
|
|
2339
2445
|
* +1 promise of the next chunk — buffered content, the EOF sentinel
|
|
2340
2446
|
* (empty Buffer / dyn undefined), or a rejection with the stream's
|
|
@@ -3558,12 +3664,26 @@ export type IrExpr = {
|
|
|
3558
3664
|
* message exactly). A function callee calls through the boxed thunk:
|
|
3559
3665
|
* per-arg validation against the boxed signature (mismatches throw the
|
|
3560
3666
|
* path-annotated TypeError), result converted back to dyn. Callee and
|
|
3561
|
-
* args are borrowed; the result is owned (+1). MAY THROW.
|
|
3667
|
+
* args are borrowed; the result is owned (+1). MAY THROW.
|
|
3668
|
+
*
|
|
3669
|
+
* `spreads` (the runtime-arity form — `f(...args)`, the rest-forwarding
|
|
3670
|
+
* idiom): entries name indices into `args` whose DOM values FLATTEN into
|
|
3671
|
+
* the argument vector at the call — JS's spread over the DOM's iterable
|
|
3672
|
+
* kinds (arrays element-by-element, strings by code point, bytes by
|
|
3673
|
+
* byte; every other kind throws V8's exact spread-call TypeError,
|
|
3674
|
+
* catchably — `what` is the spread expression's source spelling, which
|
|
3675
|
+
* the nullish text spells), evaluated and flattened left-to-right (JS's
|
|
3676
|
+
* ArgumentListEvaluation). The emitters build one fresh argument array
|
|
3677
|
+
* and apply through it. */
|
|
3562
3678
|
| {
|
|
3563
3679
|
kind: "dynCall";
|
|
3564
3680
|
callee: IrExpr;
|
|
3565
3681
|
calleeName: string;
|
|
3566
3682
|
args: IrExpr[];
|
|
3683
|
+
spreads?: {
|
|
3684
|
+
arg: number;
|
|
3685
|
+
what: string;
|
|
3686
|
+
}[];
|
|
3567
3687
|
type: IrType;
|
|
3568
3688
|
loc: SrcLoc;
|
|
3569
3689
|
}
|
|
@@ -3932,11 +4052,15 @@ export type IrExpr = {
|
|
|
3932
4052
|
* comparison (`u === "text"`) arrives here after the frontend wraps the
|
|
3933
4053
|
* plain side (payload identity is preserved by the wrap, so ref-arm
|
|
3934
4054
|
* semantics stay JS-exact). Operands are borrowed; result is a plain
|
|
3935
|
-
* bool. `negated` is the `!==` spelling.
|
|
4055
|
+
* bool. `negated` is the `!==` spelling. `sameValue` upgrades the f64
|
|
4056
|
+
* arm's compare from `===` to SameValue (NaN equals NaN, +0 differs
|
|
4057
|
+
* from -0) — the Object.is lowering; every other arm's compare is
|
|
4058
|
+
* shared between the two semantics. */
|
|
3936
4059
|
| {
|
|
3937
4060
|
kind: "unionEq";
|
|
3938
4061
|
unionId: string;
|
|
3939
4062
|
negated: boolean;
|
|
4063
|
+
sameValue: boolean;
|
|
3940
4064
|
left: IrExpr;
|
|
3941
4065
|
right: IrExpr;
|
|
3942
4066
|
type: IrType;
|
|
@@ -4108,6 +4232,15 @@ export type IrJsOp = "add" | "sub" | "mul" | "div" | "mod" | "pow" | "neg" | "pl
|
|
|
4108
4232
|
* engine, Symbol.hasInstance included; a non-object RHS throws the
|
|
4109
4233
|
* engine's own TypeError, bridged catchably. */
|
|
4110
4234
|
| "instanceOf" | "truthy" | "not" | "typeof" | "toStr" | "getProp" | "setProp" | "getIdx" | "setIdx" | "callMethod" | "callFn"
|
|
4235
|
+
/** Spread application on an island callee — `f(...pre, ...s)`, the
|
|
4236
|
+
* rest-forwarding idiom (`(...args) => g(...args)` under --dynamic).
|
|
4237
|
+
* Args are exactly (callee, pre, spread): `pre` is the engine array of
|
|
4238
|
+
* leading fixed arguments (jsOp arrLit), `spread` the spread source;
|
|
4239
|
+
* `name` carries the spread expression's source spelling (V8's nullish
|
|
4240
|
+
* spread-call TypeError spells it). The prelude helper uses REAL spread
|
|
4241
|
+
* syntax, so iterator protocols are the engine's own, with guards
|
|
4242
|
+
* front-running V8's exact spread-call TypeError texts. May throw. */
|
|
4243
|
+
| "callSpread"
|
|
4111
4244
|
/** `new X(...)` where X is jsval-typed (package-declared classes):
|
|
4112
4245
|
* JS_CallConstructor — args are the callee then the constructor
|
|
4113
4246
|
* arguments, mirroring callFn. */
|
|
@@ -4122,6 +4255,23 @@ export type IrJsOp = "add" | "sub" | "mul" | "div" | "mod" | "pow" | "neg" | "pl
|
|
|
4122
4255
|
* are alternating key/value jsvals (keys are marshaled strings), arrLit
|
|
4123
4256
|
* args are the elements. Never throw. */
|
|
4124
4257
|
| "objLit" | "arrLit"
|
|
4258
|
+
/** The engine-native TemplateStringsArray for an ISLAND TAG call: args
|
|
4259
|
+
* are 2n marshaled strings — n cooked then n raw — building a fresh
|
|
4260
|
+
* engine array whose `.raw` carries the raw spellings (tags dispatch on
|
|
4261
|
+
* it). Never throws. */
|
|
4262
|
+
| "tplStrings"
|
|
4263
|
+
/** Spread completion for an island-native object literal: copies
|
|
4264
|
+
* args[1]'s own enumerable properties onto args[0] (the spec's
|
|
4265
|
+
* CopyDataProperties — the engine's own Object.assign; null/undefined
|
|
4266
|
+
* sources spread nothing) and answers args[0] for chaining. May throw
|
|
4267
|
+
* (getters run). */
|
|
4268
|
+
| "objSpread"
|
|
4269
|
+
/** Accessor completion for an island-native object literal: defines a
|
|
4270
|
+
* GETTER property on args[0] (the object) — args are (obj, key string
|
|
4271
|
+
* marshal, getter function handle) — and answers the same object (the
|
|
4272
|
+
* chainable spelling: `defineGetter(objLit(...), k, f)`). The
|
|
4273
|
+
* self-referential doc-printer root-indent shape. Never throws. */
|
|
4274
|
+
| "defineGetter"
|
|
4125
4275
|
/** The engine's own undefined / null as island values (zero args, never
|
|
4126
4276
|
* throw): the unit arms of a union marshaling IN (`string | undefined`
|
|
4127
4277
|
* into an 'any' slot — the undefined arm IS the engine undefined), and
|
|
@@ -4202,7 +4352,7 @@ export declare function isIslandCallbackParamType(t: IrType, getRecord: (shapeId
|
|
|
4202
4352
|
* composites: still fenced). */
|
|
4203
4353
|
export declare function islandCallbackRet(t: IrType, getRecord: (shapeId: string) => IrRecordShape | undefined, getUnion: (unionId: string) => IrUnionDef | undefined): {
|
|
4204
4354
|
async: boolean;
|
|
4205
|
-
tag: "void" | "jsval" | "f64" | "bool" | "string" | "json";
|
|
4355
|
+
tag: "void" | "jsval" | "f64" | "bool" | "string" | "json" | "dyn";
|
|
4206
4356
|
} | null;
|
|
4207
4357
|
/** The TYPED extension of canMarshalFuncIntoIsland (a strict superset):
|
|
4208
4358
|
* closures whose params are per-argument-convertible at call time
|
package/dist/ir/nodes.js
CHANGED
|
@@ -143,6 +143,11 @@ export function isSupportedMapValue(t) {
|
|
|
143
143
|
// references at all, so no trace, no cycles, ever.
|
|
144
144
|
case "classval":
|
|
145
145
|
return true;
|
|
146
|
+
// A regex (Map<string, RegExp> — the per-EOL pattern table): the
|
|
147
|
+
// array-element story (scr_regex retain/release adapters, no trace —
|
|
148
|
+
// a regex holds no references), map form.
|
|
149
|
+
case "regex":
|
|
150
|
+
return true;
|
|
146
151
|
default:
|
|
147
152
|
return false;
|
|
148
153
|
}
|
|
@@ -150,10 +155,22 @@ export function isSupportedMapValue(t) {
|
|
|
150
155
|
/** The INDEX-SIGNATURE value fence (`{ [k: string]: V }` shapes): the map
|
|
151
156
|
* VALUE kinds — the overflow portion IS a string-keyed map — plus dyn
|
|
152
157
|
* (`unknown`, an unknown-valued pricing-table shape: overflow reads surface ordinary
|
|
153
|
-
* dyn values validated by the usual checked casts)
|
|
154
|
-
*
|
|
158
|
+
* dyn values validated by the usual checked casts) and three kinds the
|
|
159
|
+
* overflow store carries that user Maps don't admit yet:
|
|
160
|
+
* func — `Record<string, () => void>`, the command-registry pattern
|
|
161
|
+
* (scr_closure adapters; closures are cycle-headered and traced,
|
|
162
|
+
* so a handler capturing its own registry collects)
|
|
163
|
+
* map/set — `Record<string, Map<K, V>>`/`Record<string, Set<T>>`
|
|
164
|
+
* nested-container tables (scr_map adapters; a map value's own
|
|
165
|
+
* cycle capability propagates through the trace fixpoint)
|
|
166
|
+
* Nested index-signature RECORDS ride the record kind like any other.
|
|
167
|
+
* Shared frontend (mapType) / validator. */
|
|
155
168
|
export function isSupportedIndexValue(t) {
|
|
156
|
-
return t.kind === "dyn" ||
|
|
169
|
+
return (t.kind === "dyn" ||
|
|
170
|
+
t.kind === "func" ||
|
|
171
|
+
t.kind === "map" ||
|
|
172
|
+
t.kind === "set" ||
|
|
173
|
+
isSupportedMapValue(t));
|
|
157
174
|
}
|
|
158
175
|
export function funcOf(params, ret) {
|
|
159
176
|
return { kind: "func", params, ret };
|
|
@@ -219,7 +236,7 @@ export function typeKey(t) {
|
|
|
219
236
|
case "set":
|
|
220
237
|
return `set<${typeKey(t.elem)}>`;
|
|
221
238
|
case "func":
|
|
222
|
-
return `func(${[...t.params.map(typeKey), ...(t.rest ? ["...dyn[]"] : [])].join(",")})=>${typeKey(t.ret)}`;
|
|
239
|
+
return `func(${[...t.params.map(typeKey), ...(t.rest ? [t.restAbi === "jsval" ? "...jsval[]" : "...dyn[]"] : [])].join(",")})=>${typeKey(t.ret)}`;
|
|
223
240
|
case "object":
|
|
224
241
|
return `object:${t.className}`;
|
|
225
242
|
case "classval":
|
|
@@ -456,6 +473,14 @@ export const MAY_THROW_BYTES_METHODS = new Set([
|
|
|
456
473
|
"dvGetFloat64",
|
|
457
474
|
"dvGetBigUint64Number",
|
|
458
475
|
"dvGetBigInt64Number",
|
|
476
|
+
"dvSetUint8",
|
|
477
|
+
"dvSetInt8",
|
|
478
|
+
"dvSetUint16",
|
|
479
|
+
"dvSetInt16",
|
|
480
|
+
"dvSetUint32",
|
|
481
|
+
"dvSetInt32",
|
|
482
|
+
"dvSetFloat32",
|
|
483
|
+
"dvSetFloat64",
|
|
459
484
|
]);
|
|
460
485
|
/** Result-type rule for each island op (the validator enforces it; the
|
|
461
486
|
* frontend constructs nodes with exactly these). */
|
|
@@ -473,10 +498,14 @@ export function jsOpResultKind(op) {
|
|
|
473
498
|
case "getIdx":
|
|
474
499
|
case "callMethod":
|
|
475
500
|
case "callFn":
|
|
501
|
+
case "callSpread":
|
|
476
502
|
case "construct":
|
|
477
503
|
case "globalGet":
|
|
478
504
|
case "objLit":
|
|
479
505
|
case "arrLit":
|
|
506
|
+
case "defineGetter":
|
|
507
|
+
case "tplStrings":
|
|
508
|
+
case "objSpread":
|
|
480
509
|
case "undefLit":
|
|
481
510
|
case "nullLit":
|
|
482
511
|
case "iterNew":
|
|
@@ -672,6 +701,7 @@ export function canCrossIslandBoundary(t, getRecord, getUnion) {
|
|
|
672
701
|
export const MAX_ISLAND_CALLBACK_ARITY = 16;
|
|
673
702
|
export function canMarshalFuncIntoIsland(t) {
|
|
674
703
|
return (t.kind === "func" &&
|
|
704
|
+
t.rest !== true &&
|
|
675
705
|
t.params.length <= MAX_ISLAND_CALLBACK_ARITY &&
|
|
676
706
|
t.params.every((p) => p.kind === "jsval") &&
|
|
677
707
|
(t.ret.kind === "jsval" || t.ret.kind === "void" ||
|
|
@@ -720,6 +750,13 @@ export function islandCallbackRet(t, getRecord, getUnion) {
|
|
|
720
750
|
const tag = tagOf(t);
|
|
721
751
|
if (tag)
|
|
722
752
|
return { async: false, tag };
|
|
753
|
+
// A CHECKED-DYNAMIC result (a JS getter/callback whose inferred return
|
|
754
|
+
// degraded — the doc-printer root-indent getter): the DOM value deep-
|
|
755
|
+
// copies into the engine on return, exactly the jsMarshal dyn rule
|
|
756
|
+
// (data kinds only; boxed functions/handles throw the catchable
|
|
757
|
+
// TypeError). Sync only — no engine-promise tag exists for DOM values.
|
|
758
|
+
if (t.kind === "dyn")
|
|
759
|
+
return { async: false, tag: "dyn" };
|
|
723
760
|
return isJsonSafeType(t, getRecord, getUnion) ? { async: false, tag: "json" } : null;
|
|
724
761
|
}
|
|
725
762
|
/** The TYPED extension of canMarshalFuncIntoIsland (a strict superset):
|
|
@@ -729,8 +766,22 @@ export function islandCallbackRet(t, getRecord, getUnion) {
|
|
|
729
766
|
* buffer. Closures taking closures and 'unknown'-typed params stay fenced
|
|
730
767
|
* (no per-type extraction exists for them inside a host call). */
|
|
731
768
|
export function canMarshalTypedFuncIntoIsland(t, getRecord, getUnion) {
|
|
732
|
-
|
|
733
|
-
|
|
769
|
+
if (t.kind !== "func")
|
|
770
|
+
return false;
|
|
771
|
+
// The ISLAND-REST form (`async (...args) =>` in JS under --dynamic —
|
|
772
|
+
// the withPlugins wrapper): the trailing ABI param is the ENGINE array
|
|
773
|
+
// of the call's surplus arguments; leading params convert per argument
|
|
774
|
+
// like any typed callback. Plain rest signatures (dynRest, typed
|
|
775
|
+
// rests) stay out — no completed-ABI spelling exists for them here.
|
|
776
|
+
if (t.rest === true) {
|
|
777
|
+
return (t.restAbi === "jsval" &&
|
|
778
|
+
t.params.length >= 1 &&
|
|
779
|
+
t.params.length <= MAX_ISLAND_CALLBACK_ARITY &&
|
|
780
|
+
t.params[t.params.length - 1].kind === "jsval" &&
|
|
781
|
+
t.params.slice(0, -1).every((p) => isIslandCallbackParamType(p, getRecord, getUnion)) &&
|
|
782
|
+
islandCallbackRet(t.ret, getRecord, getUnion) !== null);
|
|
783
|
+
}
|
|
784
|
+
return (t.params.length <= MAX_ISLAND_CALLBACK_ARITY &&
|
|
734
785
|
t.params.every((p) => isIslandCallbackParamType(p, getRecord, getUnion)) &&
|
|
735
786
|
islandCallbackRet(t.ret, getRecord, getUnion) !== null);
|
|
736
787
|
}
|
|
@@ -1119,6 +1170,7 @@ export function moduleUsesStream(mod) {
|
|
|
1119
1170
|
node.fn.startsWith("passthrough.") ||
|
|
1120
1171
|
node.fn === "stream.destroy" || node.fn === "stream.destroyErr" ||
|
|
1121
1172
|
node.fn === "stream.prop" || node.fn === "stream.errored" ||
|
|
1173
|
+
node.fn === "sp.finished" || node.fn === "sp.pipeline" ||
|
|
1122
1174
|
node.fn.startsWith("stream.set"))) {
|
|
1123
1175
|
found = true;
|
|
1124
1176
|
return;
|
|
@@ -1977,6 +2029,8 @@ export const MAY_THROW_LIB_FNS = new Set([
|
|
|
1977
2029
|
"stream.finishedDyn",
|
|
1978
2030
|
"stream.pipeline",
|
|
1979
2031
|
"stream.pipelineDyn",
|
|
2032
|
+
"sp.finished",
|
|
2033
|
+
"sp.pipeline",
|
|
1980
2034
|
"readable.newDyn",
|
|
1981
2035
|
"writable.newDyn",
|
|
1982
2036
|
"duplex.newDyn",
|
|
@@ -2028,6 +2082,10 @@ export const MAY_THROW_LIB_FNS = new Set([
|
|
|
2028
2082
|
// A read of a declare-d const nothing defines: always throws Node's
|
|
2029
2083
|
// catchable ReferenceError.
|
|
2030
2084
|
"global.undefRead",
|
|
2085
|
+
// The compiler-resolved Node-parity throw: always throws, catchably.
|
|
2086
|
+
"error.nodeThrow",
|
|
2087
|
+
// USVString coercion runs user toString/valueOf — throws propagate.
|
|
2088
|
+
"dyn.toStringCoerce",
|
|
2031
2089
|
"child.kill",
|
|
2032
2090
|
// The caller's lookup runs synchronously inside the connect call — a
|
|
2033
2091
|
// throw there propagates like Node's.
|
|
@@ -2072,6 +2130,8 @@ export const MAY_THROW_LIB_FNS = new Set([
|
|
|
2072
2130
|
"dyn.cloneTransferFail",
|
|
2073
2131
|
// the dyn Object walks throw on null/undefined receivers
|
|
2074
2132
|
"dyn.objKeys",
|
|
2133
|
+
"dyn.hasOwn",
|
|
2134
|
+
"dyn.assign",
|
|
2075
2135
|
"dyn.objValues",
|
|
2076
2136
|
"dyn.objEntries",
|
|
2077
2137
|
"error.domClone",
|
|
@@ -2107,6 +2167,16 @@ export const MAY_THROW_LIB_FNS = new Set([
|
|
|
2107
2167
|
"crypto.randomBytesToString",
|
|
2108
2168
|
"crypto.randomBytes",
|
|
2109
2169
|
"buffer.concatLen",
|
|
2170
|
+
// The checked-dynamic compare/equals validators: Node's argument
|
|
2171
|
+
// ladders throw ERR_INVALID_ARG_TYPE / ERR_OUT_OF_RANGE catchably.
|
|
2172
|
+
"buffer.compareChk",
|
|
2173
|
+
"bytes.equalsChk",
|
|
2174
|
+
"bytes.compareChk",
|
|
2175
|
+
"buffer.newStringFail",
|
|
2176
|
+
"fs.toUnixTimestamp",
|
|
2177
|
+
"error.argTypeThrow",
|
|
2178
|
+
"emitter.setMaxChk",
|
|
2179
|
+
"emitter.setDefaultMaxChk",
|
|
2110
2180
|
"fs.readFileSyncBytes",
|
|
2111
2181
|
"fs.writeFileSyncBytes",
|
|
2112
2182
|
"zlib.inflateSync",
|