@scriptc/compiler 0.2.2 → 0.2.4
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 +99 -27
- package/dist/backend/cycle-analysis.js +63 -50
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +51 -0
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/llvm/borrowed-inputs.d.ts +15 -0
- package/dist/backend/llvm/borrowed-inputs.js +28 -0
- package/dist/backend/llvm/borrowed-inputs.js.map +1 -0
- package/dist/backend/llvm/borrowed-receivers.d.ts +9 -0
- package/dist/backend/llvm/borrowed-receivers.js +58 -0
- package/dist/backend/llvm/borrowed-receivers.js.map +1 -0
- package/dist/backend/llvm/byte-numbers.d.ts +10 -0
- package/dist/backend/llvm/byte-numbers.js +235 -0
- package/dist/backend/llvm/byte-numbers.js.map +1 -0
- package/dist/backend/llvm/bytes-bounds.d.ts +9 -0
- package/dist/backend/llvm/bytes-bounds.js +189 -0
- package/dist/backend/llvm/bytes-bounds.js.map +1 -0
- package/dist/backend/llvm/call-lifetimes.d.ts +27 -0
- package/dist/backend/llvm/call-lifetimes.js +199 -0
- package/dist/backend/llvm/call-lifetimes.js.map +1 -0
- package/dist/backend/llvm/call-lifetimes.test.d.ts +1 -0
- package/dist/backend/llvm/call-lifetimes.test.js +259 -0
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -0
- package/dist/backend/llvm/checked-value-lifetimes.d.ts +9 -0
- package/dist/backend/llvm/checked-value-lifetimes.js +35 -0
- package/dist/backend/llvm/checked-value-lifetimes.js.map +1 -0
- package/dist/backend/llvm/counted-loops.d.ts +6 -0
- package/dist/backend/llvm/counted-loops.js +28 -0
- package/dist/backend/llvm/counted-loops.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +2 -2
- package/dist/backend/llvm/dyn.js +79 -35
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +56 -7
- package/dist/backend/llvm/emitter.js +310 -37
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +24 -5
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +4 -3
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +4 -4
- package/dist/backend/llvm/expr-bytes.js +68 -35
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js +50 -5
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +2 -1
- package/dist/backend/llvm/expr-containers.js +136 -57
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +11 -0
- package/dist/backend/llvm/expr-control.js +26 -5
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +33 -31
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +61 -27
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-records.js +9 -3
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +5 -10
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/integer-values.d.ts +10 -0
- package/dist/backend/llvm/integer-values.js +41 -0
- package/dist/backend/llvm/integer-values.js.map +1 -0
- package/dist/backend/llvm/integer-views.d.ts +7 -0
- package/dist/backend/llvm/integer-views.js +67 -0
- package/dist/backend/llvm/integer-views.js.map +1 -0
- package/dist/backend/llvm/integer-views.test.d.ts +1 -0
- package/dist/backend/llvm/integer-views.test.js +34 -0
- package/dist/backend/llvm/integer-views.test.js.map +1 -0
- package/dist/backend/llvm/lib-dispatch.js +3 -1
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +5 -5
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +35 -1
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.d.ts +42 -0
- package/dist/backend/llvm/local-array-reads.js +226 -0
- package/dist/backend/llvm/local-array-reads.js.map +1 -0
- package/dist/backend/llvm/local-array-reads.test.d.ts +1 -0
- package/dist/backend/llvm/local-array-reads.test.js +446 -0
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.d.ts +36 -0
- package/dist/backend/llvm/map-read-lifetimes.js +128 -0
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.test.d.ts +1 -0
- package/dist/backend/llvm/map-read-lifetimes.test.js +127 -0
- package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -0
- package/dist/backend/llvm/reference-effects.d.ts +22 -0
- package/dist/backend/llvm/reference-effects.js +148 -0
- package/dist/backend/llvm/reference-effects.js.map +1 -0
- package/dist/backend/llvm/reference-effects.test.d.ts +1 -0
- package/dist/backend/llvm/reference-effects.test.js +74 -0
- package/dist/backend/llvm/reference-effects.test.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +7 -4
- package/dist/backend/llvm/shapes.js +24 -6
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/split.js +15 -5
- package/dist/backend/llvm/split.js.map +1 -1
- package/dist/backend/llvm/split.test.js +17 -0
- package/dist/backend/llvm/split.test.js.map +1 -1
- package/dist/backend/llvm/stack-unions.d.ts +20 -0
- package/dist/backend/llvm/stack-unions.js +61 -0
- package/dist/backend/llvm/stack-unions.js.map +1 -0
- package/dist/backend/llvm/stack-unions.test.d.ts +1 -0
- package/dist/backend/llvm/stack-unions.test.js +262 -0
- package/dist/backend/llvm/stack-unions.test.js.map +1 -0
- package/dist/backend/llvm/string-construction.d.ts +10 -0
- package/dist/backend/llvm/string-construction.js +38 -0
- package/dist/backend/llvm/string-construction.js.map +1 -0
- package/dist/backend/llvm/string-construction.test.d.ts +1 -0
- package/dist/backend/llvm/string-construction.test.js +65 -0
- package/dist/backend/llvm/string-construction.test.js.map +1 -0
- package/dist/backend/llvm/string-lifetimes.d.ts +12 -0
- package/dist/backend/llvm/string-lifetimes.js +72 -0
- package/dist/backend/llvm/string-lifetimes.js.map +1 -0
- package/dist/backend/llvm/string-lifetimes.test.d.ts +1 -0
- package/dist/backend/llvm/string-lifetimes.test.js +239 -0
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -0
- package/dist/backend/mangle.d.ts +2 -0
- package/dist/backend/mangle.js +4 -0
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/may-throw.js +67 -29
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +104 -1
- package/dist/backend/may-throw.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +2 -2
- package/dist/backend/native-toolchain.js +2 -0
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/frontend/input-tracker.js +3 -3
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +38 -2
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lowering/collection-ingestion.d.ts +31 -0
- package/dist/frontend/lowering/collection-ingestion.js +224 -0
- package/dist/frontend/lowering/collection-ingestion.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.js +2 -0
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +6 -0
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/import-meta.d.ts +10 -0
- package/dist/frontend/lowering/import-meta.js +52 -0
- package/dist/frontend/lowering/import-meta.js.map +1 -0
- package/dist/frontend/lowering/lower-assert.js +105 -41
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +2 -0
- package/dist/frontend/lowering/lower-builtin-values.js +22 -1
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +3 -13
- package/dist/frontend/lowering/lower-builtins.js +152 -46
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +6 -3
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +7 -7
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +5 -1
- package/dist/frontend/lowering/lower-containers.js +52 -37
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +47 -43
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +43 -0
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +72 -68
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-system-errors.d.ts +6 -0
- package/dist/frontend/lowering/lower-system-errors.js +29 -0
- package/dist/frontend/lowering/lower-system-errors.js.map +1 -0
- package/dist/frontend/lowering/lowerer.d.ts +4 -3
- package/dist/frontend/lowering/lowerer.js +60 -25
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +2 -2
- package/dist/frontend/lowering/surfaces.js +69 -21
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/module-syntax.d.ts +1 -1
- package/dist/frontend/module-syntax.js +8 -1
- package/dist/frontend/module-syntax.js.map +1 -1
- package/dist/frontend/module-syntax.test.js +10 -0
- package/dist/frontend/module-syntax.test.js.map +1 -1
- package/dist/frontend/npm.d.ts +4 -0
- package/dist/frontend/npm.js +86 -33
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +103 -0
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/pipeline-native.js +2 -1
- package/dist/frontend/pipeline-native.js.map +1 -1
- package/dist/frontend/services-node.js +3 -2
- package/dist/frontend/services-node.js.map +1 -1
- package/dist/frontend/services.d.ts +5 -1
- package/dist/frontend/services.js +9 -1
- package/dist/frontend/services.js.map +1 -1
- package/dist/frontend/services.test.js +21 -0
- package/dist/frontend/services.test.js.map +1 -1
- package/dist/frontend/ts7/ast-node.d.ts +2 -0
- package/dist/frontend/ts7/ast-node.js +30 -4
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +60 -1
- package/dist/frontend/ts7/ast-node.test.js.map +1 -1
- package/dist/frontend/type-mapper.js +8 -2
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js +4 -1
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/byte-numbers.d.ts +20 -0
- package/dist/ir/byte-numbers.js +65 -0
- package/dist/ir/byte-numbers.js.map +1 -0
- package/dist/ir/byte-numbers.test.d.ts +1 -0
- package/dist/ir/byte-numbers.test.js +42 -0
- package/dist/ir/byte-numbers.test.js.map +1 -0
- package/dist/ir/integer-loops.d.ts +26 -0
- package/dist/ir/integer-loops.js +130 -1
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-loops.test.d.ts +1 -0
- package/dist/ir/integer-loops.test.js +91 -0
- package/dist/ir/integer-loops.test.js.map +1 -0
- package/dist/ir/integer-ranges.d.ts +8 -6
- package/dist/ir/integer-ranges.js +343 -89
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +54 -3
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/ir.d.ts +29 -22
- package/dist/ir/ir.js +59 -14
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +18 -0
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/validate.js +208 -105
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +247 -0
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/fence-eval.js +9 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/fence-eval.test.d.ts +1 -0
- package/dist/library/fence-eval.test.js +21 -0
- package/dist/library/fence-eval.test.js.map +1 -0
- package/dist/native/runtime-typescript.d.ts +4 -0
- package/dist/native/runtime-typescript.js +61 -0
- package/dist/native/runtime-typescript.js.map +1 -0
- package/dist/native/runtime-typescript.test.d.ts +1 -0
- package/dist/native/runtime-typescript.test.js +41 -0
- package/dist/native/runtime-typescript.test.js.map +1 -0
- package/dist/native/toolchain.js +6 -3
- package/dist/native/toolchain.js.map +1 -1
- package/dist/native/toolchain.test.js +43 -5
- package/dist/native/toolchain.test.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +271 -17
package/dist/ir/validate.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/* IR validation — runs on every compile as the backstop for frontend bugs.
|
|
2
|
+
* A violation is an internal compiler error (the frontend should never
|
|
3
|
+
* produce invalid IR), but it still carries the user's source location:
|
|
4
|
+
* an ICE that points at source is a gift to whoever debugs it.
|
|
5
|
+
*/
|
|
6
|
+
import { validByteNumberToken } from "./byte-numbers.js";
|
|
1
7
|
import { arrayOf, BYTES_ELEMENT_NAME, BOOL, BYTES_U8, bytesOf, canAdaptDynFuncTo, canDynCheckTo, canConvertToDyn, canExitIslandToType, canMarshalIntoIsland, canMarshalTypedFuncIntoIsland, CHILD_T, CHILDSTREAM_T, CHILDWRITER_T, CRYPTOHASH_T, CRYPTOHMAC_T, DATE_T, DGRAMSOCK_T, DYN, DYN_HANDLE_KINDS, F64, ffiClassType, ffiSourceParamTypes, FILEHANDLE_T, FSWATCHER_T, HTTP2SESSION_T, HTTP2STREAM_T, HTTPCLIENTREQ_T, HTTPREQ_T, HTTPRES_T, islandPromisePayloadTag, isDynTypedRefType, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isJsonSafeType, isJsonStringifySafeType, isRefCounted, isSupportedArrayElem, isSupportedIndexValue, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, jsOpResultKind, JSVAL, NETSERVER_T, NETSOCKET_T, PROCSTREAM_T, REF_TRUTHY_KINDS, REGEX, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, SEARCH_PARAMS_T, SECURECTX_T, shapeHasAccessorSlots, SPAWNRES_T, STATS_T, STRING, SYMBOL_T, TESTCTX_T, typeEquals, typeKey, unionContainerArmsOk, URL_T, VOID } from "./ir.js";
|
|
2
8
|
import { BIGINT_T, DYN_CLASS_PROPERTIES } from "./ir.js";
|
|
3
9
|
import { unionWideningTags } from "./analysis.js";
|
|
@@ -358,8 +364,13 @@ export const LIB_FN_SIGS = {
|
|
|
358
364
|
"url.port": { argTypes: [URL_T], result: STRING },
|
|
359
365
|
"url.pathname": { argTypes: [URL_T], result: STRING },
|
|
360
366
|
"url.href": { argTypes: [URL_T], result: STRING },
|
|
367
|
+
"url.set": { argTypes: [URL_T, STRING, STRING], result: VOID },
|
|
368
|
+
"url.setChecked": { argTypes: [URL_T, STRING, DYN], result: VOID },
|
|
361
369
|
"url.fileURLToPathUrl": { argTypes: [URL_T], result: STRING },
|
|
362
370
|
"url.fileURLToPathChecked": { argTypes: [DYN], result: STRING },
|
|
371
|
+
"url.fileURLToPathOptions": { argTypes: [DYN, DYN], result: STRING },
|
|
372
|
+
"url.fileURLToPathBuffer": { argTypes: [DYN, DYN], result: BYTES_U8 },
|
|
373
|
+
"url.pathToFileURLChecked": { argTypes: [DYN, DYN], result: URL_T },
|
|
363
374
|
"url.fileURLToPathStr": { argTypes: [STRING], result: STRING },
|
|
364
375
|
"url.pathToFileURL": { argTypes: [STRING], result: URL_T },
|
|
365
376
|
"url.pathToFileURLPlatform": { argTypes: [STRING, BOOL], result: URL_T },
|
|
@@ -400,6 +411,15 @@ export const LIB_FN_SIGS = {
|
|
|
400
411
|
"qs.unescape": { argTypes: [STRING], result: STRING },
|
|
401
412
|
"util.parseArgs": { argTypes: [DYN], result: DYN },
|
|
402
413
|
"util.parseEnv": { argTypes: [DYN], result: DYN },
|
|
414
|
+
"util.getSystemErrorName": { argTypes: [DYN], result: STRING },
|
|
415
|
+
"util.getSystemErrorMessage": { argTypes: [DYN], result: STRING },
|
|
416
|
+
"util.systemErrorEntries": { argTypes: [], result: DYN },
|
|
417
|
+
"util.stripVTControlCharacters": { argTypes: [DYN], result: STRING },
|
|
418
|
+
"util.toUSVString": { argTypes: [DYN], result: STRING },
|
|
419
|
+
"util.isDeepStrictEqual": { argTypes: [DYN, DYN, DYN], result: BOOL },
|
|
420
|
+
"util.styleText": { argTypes: [DYN, DYN, DYN], result: STRING },
|
|
421
|
+
"util.typeIs": { argTypes: [DYN, STRING], result: BOOL },
|
|
422
|
+
"util.typeValue": { argTypes: [DYN, STRING], result: DYN },
|
|
403
423
|
"fs.statSync": { argTypes: [STRING], result: STATS_T },
|
|
404
424
|
"fs.lstatSync": { argTypes: [STRING], result: STATS_T },
|
|
405
425
|
"fs.fstatSync": { argTypes: [F64], result: STATS_T },
|
|
@@ -407,9 +427,17 @@ export const LIB_FN_SIGS = {
|
|
|
407
427
|
"fs.fsyncSync": { argTypes: [F64], result: VOID },
|
|
408
428
|
"fs.fdatasyncSync": { argTypes: [F64], result: VOID },
|
|
409
429
|
"fs.ftruncateSync": { argTypes: [F64, F64], result: VOID },
|
|
430
|
+
"fs.utimesSync": { argTypes: [DYN, DYN, DYN], result: VOID },
|
|
431
|
+
"fs.futimesSync": { argTypes: [DYN, DYN, DYN], result: VOID },
|
|
432
|
+
"fs.lutimesSync": { argTypes: [DYN, DYN, DYN], result: VOID },
|
|
410
433
|
"fs.readvSync": { argTypes: [F64, arrayOf(BYTES_U8), F64], result: F64 },
|
|
411
434
|
"fs.writevSync": { argTypes: [F64, arrayOf(BYTES_U8), F64], result: F64 },
|
|
412
|
-
"fs.linkSync": { argTypes: [
|
|
435
|
+
"fs.linkSync": { argTypes: [DYN, DYN], result: VOID },
|
|
436
|
+
"fs.symlinkSync": { argTypes: [DYN, DYN, DYN], result: VOID },
|
|
437
|
+
"fs.readlinkSync": { argTypes: [DYN, DYN], result: DYN },
|
|
438
|
+
"fs.statfsSync": { argTypes: [DYN, DYN], result: DYN },
|
|
439
|
+
"fs.readlinkSyncStr": { argTypes: [DYN, DYN], result: STRING },
|
|
440
|
+
"fs.readlinkSyncBuffer": { argTypes: [DYN, DYN], result: BYTES_U8 },
|
|
413
441
|
"fs.openSync": { argTypes: [STRING, STRING], result: F64 },
|
|
414
442
|
"fs.openNumericSync": { argTypes: [STRING, F64, F64], result: F64 },
|
|
415
443
|
"fs.readSync": { argTypes: [F64, BYTES_U8, F64, F64, F64], result: F64 },
|
|
@@ -1051,6 +1079,14 @@ export const LIB_FN_SIGS = {
|
|
|
1051
1079
|
"fsp.mkdirRecursiveMode": { argTypes: [STRING, F64], result: { kind: "promise", inner: VOID } },
|
|
1052
1080
|
"fsp.unlink": { argTypes: [STRING], result: { kind: "promise", inner: VOID } },
|
|
1053
1081
|
"fsp.chmod": { argTypes: [STRING, F64], result: { kind: "promise", inner: VOID } },
|
|
1082
|
+
"fsp.link": { argTypes: [DYN, DYN], result: { kind: "promise", inner: VOID } },
|
|
1083
|
+
"fsp.symlink": { argTypes: [DYN, DYN, DYN], result: { kind: "promise", inner: VOID } },
|
|
1084
|
+
"fsp.readlink": { argTypes: [DYN, DYN], result: { kind: "promise", inner: DYN } },
|
|
1085
|
+
"fsp.statfs": { argTypes: [DYN, DYN], result: { kind: "promise", inner: DYN } },
|
|
1086
|
+
"fsp.readlinkStr": { argTypes: [DYN, DYN], result: { kind: "promise", inner: STRING } },
|
|
1087
|
+
"fsp.readlinkBuffer": { argTypes: [DYN, DYN], result: { kind: "promise", inner: BYTES_U8 } },
|
|
1088
|
+
"fsp.utimes": { argTypes: [DYN, DYN, DYN], result: { kind: "promise", inner: VOID } },
|
|
1089
|
+
"fsp.lutimes": { argTypes: [DYN, DYN, DYN], result: { kind: "promise", inner: VOID } },
|
|
1054
1090
|
"fsp.rename": { argTypes: [STRING, STRING], result: { kind: "promise", inner: VOID } },
|
|
1055
1091
|
"fsp.readdir": { argTypes: [STRING], result: { kind: "promise", inner: arrayOf(STRING) } },
|
|
1056
1092
|
// Result is promise<call-site Dirent record array>; the libCall case
|
|
@@ -1067,6 +1103,7 @@ export const LIB_FN_SIGS = {
|
|
|
1067
1103
|
"fileHandle.datasync": { argTypes: [FILEHANDLE_T], result: { kind: "promise", inner: VOID } },
|
|
1068
1104
|
"fileHandle.truncate": { argTypes: [FILEHANDLE_T, F64], result: { kind: "promise", inner: VOID } },
|
|
1069
1105
|
"fileHandle.chmod": { argTypes: [FILEHANDLE_T, F64], result: { kind: "promise", inner: VOID } },
|
|
1106
|
+
"fileHandle.utimes": { argTypes: [FILEHANDLE_T, DYN, DYN], result: { kind: "promise", inner: VOID } },
|
|
1070
1107
|
"fileHandle.readv": { argTypes: [FILEHANDLE_T, arrayOf(BYTES_U8), F64], result: { kind: "promise", inner: VOID } },
|
|
1071
1108
|
"fileHandle.writev": { argTypes: [FILEHANDLE_T, arrayOf(BYTES_U8), F64], result: { kind: "promise", inner: VOID } },
|
|
1072
1109
|
// read/write carry call-site result record shapes; the validator checks
|
|
@@ -1390,6 +1427,9 @@ export const LIB_FN_SIGS = {
|
|
|
1390
1427
|
"assert.shapeEnd": { argTypes: [STRING, BOOL], result: VOID },
|
|
1391
1428
|
"assert.regexErrTest": { argTypes: [REGEX, { kind: "object", className: "%Error" }], result: BOOL },
|
|
1392
1429
|
"assert.unwantedRejection": { argTypes: [{ kind: "object", className: "%Error" }, STRING, BOOL], result: VOID },
|
|
1430
|
+
"assert.unwantedError": { argTypes: [STRING, BOOL, STRING, BOOL], result: VOID },
|
|
1431
|
+
"assert.noErrorPredicate": { argTypes: [DYN, DYN], result: BOOL },
|
|
1432
|
+
"assert.regexDynTest": { argTypes: [REGEX, DYN], result: BOOL },
|
|
1393
1433
|
"assert.expectsErrDyn": { argTypes: [DYN, DYN, STRING, BOOL], result: VOID },
|
|
1394
1434
|
// assert.ifError's typed entries (always throw; unit args never
|
|
1395
1435
|
// lower). The error slot is program-dependent — any %Error-hierarchy
|
|
@@ -1761,6 +1801,7 @@ export function validateModule(mod) {
|
|
|
1761
1801
|
});
|
|
1762
1802
|
}
|
|
1763
1803
|
const classesByName = new Map();
|
|
1804
|
+
const classFields = new Map();
|
|
1764
1805
|
for (const cls of mod.classes ?? []) {
|
|
1765
1806
|
if (classesByName.has(cls.name)) {
|
|
1766
1807
|
errors.push({ message: `duplicate class "${cls.name}"`, loc: cls.loc });
|
|
@@ -1813,16 +1854,24 @@ export function validateModule(mod) {
|
|
|
1813
1854
|
errors.push({ message: `class ${cls.name}: invalid symbol field metadata`, loc: cls.loc });
|
|
1814
1855
|
}
|
|
1815
1856
|
}
|
|
1816
|
-
|
|
1857
|
+
// Reuse duplicate detection as the field index for function validation.
|
|
1858
|
+
// Array.find selected the first field, even in an invalid duplicate layout.
|
|
1859
|
+
const seen = new Map();
|
|
1817
1860
|
for (const f of cls.fields) {
|
|
1818
1861
|
if (seen.has(f.name)) {
|
|
1819
1862
|
errors.push({ message: `class ${cls.name}: duplicate field "${f.name}"`, loc: cls.loc });
|
|
1820
1863
|
}
|
|
1821
|
-
|
|
1864
|
+
else
|
|
1865
|
+
seen.set(f.name, f.type);
|
|
1822
1866
|
if (isUnitType(f.type)) {
|
|
1823
1867
|
errors.push({ message: `class ${cls.name}: field "${f.name}" is ${f.type.kind}`, loc: cls.loc });
|
|
1824
1868
|
}
|
|
1825
1869
|
}
|
|
1870
|
+
// Duplicate class names, like classesByName, select the last declaration.
|
|
1871
|
+
if (seen.size > 0)
|
|
1872
|
+
classFields.set(cls.name, seen);
|
|
1873
|
+
else
|
|
1874
|
+
classFields.delete(cls.name);
|
|
1826
1875
|
// Constructor presence is checked at `new` sites (below): a class kept
|
|
1827
1876
|
// only for its layout/type (reachability never constructs it) carries
|
|
1828
1877
|
// no constructor function, and that is fine — nothing calls it.
|
|
@@ -1899,30 +1948,41 @@ export function validateModule(mod) {
|
|
|
1899
1948
|
}
|
|
1900
1949
|
const noLoc = { file: mod.sourceFile, start: 0, end: 0 };
|
|
1901
1950
|
const recordsById = new Map();
|
|
1951
|
+
const recordIds = new Set((mod.records ?? []).map((record) => record.id));
|
|
1952
|
+
const recordValidation = new Map();
|
|
1902
1953
|
for (const rec of mod.records ?? []) {
|
|
1903
1954
|
if (recordsById.has(rec.id)) {
|
|
1904
1955
|
errors.push({ message: `duplicate record shape "${rec.id}"`, loc: noLoc });
|
|
1905
1956
|
}
|
|
1906
1957
|
recordsById.set(rec.id, rec);
|
|
1907
|
-
const
|
|
1958
|
+
const fields = new Map();
|
|
1908
1959
|
for (const f of rec.fields) {
|
|
1909
|
-
if (
|
|
1960
|
+
if (fields.has(f.name)) {
|
|
1910
1961
|
errors.push({ message: `record ${rec.id}: duplicate field "${f.name}"`, loc: noLoc });
|
|
1911
1962
|
}
|
|
1912
|
-
|
|
1963
|
+
else
|
|
1964
|
+
fields.set(f.name, f.type);
|
|
1913
1965
|
// Unit kinds (undefinedT/nullT) exist only as union arms — a BARE
|
|
1914
1966
|
// unit field is as malformed as a void one. dyn and jsval slots
|
|
1915
1967
|
// are valid; both are refcounted values held by the record shape.
|
|
1916
1968
|
if (f.type.kind === "void" || isUnitType(f.type)) {
|
|
1917
1969
|
errors.push({ message: `record ${rec.id}: field "${f.name}" is ${f.type.kind}`, loc: noLoc });
|
|
1918
1970
|
}
|
|
1919
|
-
if (f.type.kind === "record" && !
|
|
1971
|
+
if (f.type.kind === "record" && !recordIds.has(f.type.shapeId)) {
|
|
1920
1972
|
errors.push({
|
|
1921
1973
|
message: `record ${rec.id}: field "${f.name}" references undeclared shape "${f.type.shapeId}"`,
|
|
1922
1974
|
loc: noLoc,
|
|
1923
1975
|
});
|
|
1924
1976
|
}
|
|
1925
1977
|
}
|
|
1978
|
+
// Reads historically use the first duplicate field, while literal and
|
|
1979
|
+
// clone checks use the last. Preserve both on malformed shapes; valid
|
|
1980
|
+
// shapes share one index. All indexes belong to this validation call.
|
|
1981
|
+
recordValidation.set(rec.id, {
|
|
1982
|
+
fields,
|
|
1983
|
+
initializationFields: fields.size === rec.fields.length ? fields : new Map(rec.fields.map((field) => [field.name, field.type])),
|
|
1984
|
+
hasAccessorSlots: shapeHasAccessorSlots(rec),
|
|
1985
|
+
});
|
|
1926
1986
|
// Canonical order is the shape's identity — enforce it.
|
|
1927
1987
|
const sorted = [...rec.fields].map((f) => f.name).sort();
|
|
1928
1988
|
if (rec.fields.some((f, i) => f.name !== sorted[i])) {
|
|
@@ -1975,7 +2035,7 @@ export function validateModule(mod) {
|
|
|
1975
2035
|
for (const candidate of cases) {
|
|
1976
2036
|
const arm = u.arms[candidate.tag];
|
|
1977
2037
|
const record = arm?.kind === "record" ? recordsById.get(arm.shapeId) : undefined;
|
|
1978
|
-
const member = record?.fields.
|
|
2038
|
+
const member = record ? recordValidation.get(record.id)?.fields.get(field) : undefined;
|
|
1979
2039
|
if (!Number.isInteger(candidate.tag) || candidate.tag < 0 || !member || tags.has(candidate.tag)) {
|
|
1980
2040
|
errors.push({ message: `union ${u.id}: invalid discriminant tag ${candidate.tag}`, loc: noLoc });
|
|
1981
2041
|
}
|
|
@@ -1988,8 +2048,8 @@ export function validateModule(mod) {
|
|
|
1988
2048
|
errors.push({ message: `union ${u.id}: undefined discriminant value`, loc: noLoc });
|
|
1989
2049
|
continue;
|
|
1990
2050
|
}
|
|
1991
|
-
const fieldTypes = member?.
|
|
1992
|
-
? unionsById.get(member.
|
|
2051
|
+
const fieldTypes = member?.kind === "union"
|
|
2052
|
+
? unionsById.get(member.unionId)?.arms ?? [] : member ? [member] : [];
|
|
1993
2053
|
const valid = fieldTypes.some((type) => typeof value === "string" ? type.kind === "string"
|
|
1994
2054
|
: typeof value === "boolean" ? type.kind === "bool"
|
|
1995
2055
|
: typeof value === "number" && Number.isFinite(value) && type.kind === "f64");
|
|
@@ -2152,12 +2212,34 @@ export function validateModule(mod) {
|
|
|
2152
2212
|
}
|
|
2153
2213
|
}
|
|
2154
2214
|
}
|
|
2215
|
+
// Class metadata is invariant across functions. Keep field lookup, hierarchy
|
|
2216
|
+
// membership, and virtual-call resolution local to this validation invocation.
|
|
2217
|
+
const classValidation = {
|
|
2218
|
+
fields: classFields,
|
|
2219
|
+
hierarchy: new Set(), implementations: new Map(), virtualCalls: new Map(),
|
|
2220
|
+
};
|
|
2221
|
+
for (const cls of classesByName.values()) {
|
|
2222
|
+
if (cls.base !== undefined) {
|
|
2223
|
+
classValidation.hierarchy.add(cls.name);
|
|
2224
|
+
classValidation.hierarchy.add(cls.base);
|
|
2225
|
+
}
|
|
2226
|
+
if (cls.name === RUNTIME_EMITTER_CLASS)
|
|
2227
|
+
classValidation.hierarchy.add(cls.name);
|
|
2228
|
+
for (const method of new Set(cls.methods ?? [])) {
|
|
2229
|
+
if (cls.abstractMethods?.includes(method))
|
|
2230
|
+
continue;
|
|
2231
|
+
let implementations = classValidation.implementations.get(method);
|
|
2232
|
+
if (!implementations)
|
|
2233
|
+
classValidation.implementations.set(method, (implementations = []));
|
|
2234
|
+
implementations.push(cls);
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2155
2237
|
for (const fn of mod.functions) {
|
|
2156
|
-
validateFunction(fn, functionsByName, ffiByName, classesByName, recordsById, unionsById, globalsById, errors);
|
|
2238
|
+
validateFunction(fn, functionsByName, ffiByName, classesByName, recordsById, recordValidation, unionsById, globalsById, classValidation, errors);
|
|
2157
2239
|
}
|
|
2158
2240
|
return errors;
|
|
2159
2241
|
}
|
|
2160
|
-
function validateFunction(fn, functions, ffiByName, classes, records, unions, globals, errors) {
|
|
2242
|
+
function validateFunction(fn, functions, ffiByName, classes, records, recordValidation, unions, globals, classValidation, errors) {
|
|
2161
2243
|
const locals = new Map(fn.locals.map((l) => [l.id, l]));
|
|
2162
2244
|
const err = (message, loc) => errors.push({ message: `in ${fn.name}: ${message}`, loc });
|
|
2163
2245
|
const asyncCaches = [
|
|
@@ -2200,17 +2282,41 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2200
2282
|
}
|
|
2201
2283
|
return false;
|
|
2202
2284
|
};
|
|
2203
|
-
const hierarchy =
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2285
|
+
const hierarchy = classValidation.hierarchy;
|
|
2286
|
+
const virtualCallInfo = (className, method) => {
|
|
2287
|
+
let methods = classValidation.virtualCalls.get(className);
|
|
2288
|
+
const cached = methods?.get(method);
|
|
2289
|
+
if (cached)
|
|
2290
|
+
return cached;
|
|
2291
|
+
if (!methods)
|
|
2292
|
+
classValidation.virtualCalls.set(className, (methods = new Map()));
|
|
2293
|
+
let declared = false;
|
|
2294
|
+
let implementation;
|
|
2295
|
+
for (let c = classes.get(className); c; c = c.base !== undefined ? classes.get(c.base) : undefined) {
|
|
2296
|
+
if (c.methods?.includes(method)) {
|
|
2297
|
+
declared = true;
|
|
2298
|
+
if (!c.abstractMethods?.includes(method)) {
|
|
2299
|
+
implementation = functions.get(`%${c.name}.${method}`);
|
|
2300
|
+
break;
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
}
|
|
2304
|
+
let hasOverride = false;
|
|
2305
|
+
if (declared) {
|
|
2306
|
+
// Preserve class-table order when choosing an abstract slot's ABI.
|
|
2307
|
+
for (const c of classValidation.implementations.get(method) ?? []) {
|
|
2308
|
+
if (!isStrictSubclass(c.name, className))
|
|
2309
|
+
continue;
|
|
2310
|
+
hasOverride = true;
|
|
2311
|
+
implementation ??= functions.get(`%${c.name}.${method}`);
|
|
2312
|
+
if (implementation)
|
|
2313
|
+
break;
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
const result = { declared, hasOverride, implementation };
|
|
2317
|
+
methods.set(method, result);
|
|
2318
|
+
return result;
|
|
2319
|
+
};
|
|
2214
2320
|
// Unit kinds live only inside unions: a bare-unit local, param, or
|
|
2215
2321
|
// return type is frontend breakage (mapType never produces them).
|
|
2216
2322
|
for (const l of fn.locals) {
|
|
@@ -2636,15 +2742,15 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2636
2742
|
// dyn field with fieldDyn set (validated numeric read-modify-write).
|
|
2637
2743
|
checkExpr(e.obj);
|
|
2638
2744
|
const cls = classes.get(e.className);
|
|
2639
|
-
const
|
|
2745
|
+
const fieldType = classValidation.fields.get(e.className)?.get(e.field);
|
|
2640
2746
|
if (!cls)
|
|
2641
2747
|
err(`fieldIncDec on undeclared class "${e.className}"`, e.loc);
|
|
2642
|
-
else if (!
|
|
2748
|
+
else if (!fieldType)
|
|
2643
2749
|
err(`class ${e.className} has no field "${e.field}"`, e.loc);
|
|
2644
2750
|
else {
|
|
2645
2751
|
expectType(e.obj, { kind: "object", className: e.className }, "fieldIncDec receiver");
|
|
2646
|
-
if (e.fieldDyn ?
|
|
2647
|
-
err(`fieldIncDec ${e.className}.${e.field} field/flag mismatch (${
|
|
2752
|
+
if (e.fieldDyn ? fieldType.kind !== "dyn" : fieldType.kind !== "f64") {
|
|
2753
|
+
err(`fieldIncDec ${e.className}.${e.field} field/flag mismatch (${fieldType.kind})`, e.loc);
|
|
2648
2754
|
}
|
|
2649
2755
|
}
|
|
2650
2756
|
if (e.type.kind !== "f64")
|
|
@@ -3140,17 +3246,17 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3140
3246
|
break;
|
|
3141
3247
|
}
|
|
3142
3248
|
const recv = e.receiver.type;
|
|
3143
|
-
// The
|
|
3249
|
+
// The DataView getters and setters use a bytes<u8>
|
|
3144
3250
|
// view; dataViewNew and byteOffset take ANY elem kind (views form
|
|
3145
3251
|
// over any typed array's storage, owners answer byteOffset 0).
|
|
3146
|
-
const
|
|
3252
|
+
const isDv = e.method.startsWith("dvGet") || e.method.startsWith("dvSet");
|
|
3147
3253
|
const isNum = e.method === "readNum" || e.method === "writeNum" || e.method === "readNumVar" || e.method === "writeNumVar";
|
|
3148
3254
|
const U8_ONLY_EXTRA = new Set([
|
|
3149
3255
|
"toString", "toStringVar", "equals", "compareBuf", "indexOf", "lastIndexOf", "includes",
|
|
3150
3256
|
"indexOfNum", "lastIndexOfNum", "includesNum", "fill", "fillNum", "fillStr",
|
|
3151
3257
|
"copy", "swap16", "swap32", "swap64", "writeStr",
|
|
3152
3258
|
]);
|
|
3153
|
-
const u8Only = U8_ONLY_EXTRA.has(e.method) || isNum ||
|
|
3259
|
+
const u8Only = U8_ONLY_EXTRA.has(e.method) || isNum || isDv;
|
|
3154
3260
|
if (u8Only && recv.elem !== "u8") {
|
|
3155
3261
|
err(`bytesIntrinsic ${e.method} on a ${recv.elem} receiver (u8 only)`, e.loc);
|
|
3156
3262
|
}
|
|
@@ -3160,6 +3266,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3160
3266
|
if (isNum && e.args[0]?.kind !== "strLit") {
|
|
3161
3267
|
err(`bytesIntrinsic ${e.method} args[0] must be a strLit kind token`, e.loc);
|
|
3162
3268
|
}
|
|
3269
|
+
else if (isNum && e.args[0]?.kind === "strLit" && !validByteNumberToken(e.method, e.args[0].value)) {
|
|
3270
|
+
err(`bytesIntrinsic ${e.method} invalid kind token '${e.args[0].value}'`, e.loc);
|
|
3271
|
+
}
|
|
3163
3272
|
// fillStr/writeStr carry their NORMALIZED encoding as args[1],
|
|
3164
3273
|
// always a strLit (the frontend folds the aliases).
|
|
3165
3274
|
if ((e.method === "fillStr" || e.method === "writeStr") && e.args[1]?.kind !== "strLit") {
|
|
@@ -3414,19 +3523,26 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3414
3523
|
}
|
|
3415
3524
|
break;
|
|
3416
3525
|
}
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3526
|
+
if (e.method === "valueSet" && !isSupportedSetElem(value, value.kind === "union" ? unions.get(value.unionId)?.arms : undefined)) {
|
|
3527
|
+
err(`mapIntrinsic valueSet element kind ${value.kind} (frontend must fence)`, e.loc);
|
|
3528
|
+
}
|
|
3529
|
+
const sig = e.method === "clone"
|
|
3530
|
+
? { argTypes: [], result: e.receiver.type }
|
|
3531
|
+
: e.method === "keySet" || e.method === "valueSet"
|
|
3532
|
+
? { argTypes: [], result: { kind: "set", elem: e.method === "keySet" ? key : value } }
|
|
3533
|
+
: e.method === "set"
|
|
3534
|
+
? { argTypes: [key, value], result: VOID }
|
|
3535
|
+
: e.method === "has" || e.method === "delete"
|
|
3536
|
+
? { argTypes: [key], result: BOOL }
|
|
3537
|
+
: e.method === "clear" || e.method === "iterEnter" || e.method === "iterExit"
|
|
3538
|
+
? { argTypes: [], result: VOID }
|
|
3539
|
+
: e.method === "iterLive"
|
|
3540
|
+
? { argTypes: [F64], result: BOOL }
|
|
3541
|
+
: e.method === "iterKey"
|
|
3542
|
+
? { argTypes: [F64], result: key }
|
|
3543
|
+
: e.method === "iterValue"
|
|
3544
|
+
? { argTypes: [F64], result: value }
|
|
3545
|
+
: { argTypes: [], result: F64 }; // size / iterCount
|
|
3430
3546
|
if (e.args.length !== sig.argTypes.length) {
|
|
3431
3547
|
err(`mapIntrinsic ${e.method}: ${e.args.length} args, expected ${sig.argTypes.length}`, e.loc);
|
|
3432
3548
|
}
|
|
@@ -3463,19 +3579,21 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3463
3579
|
break;
|
|
3464
3580
|
}
|
|
3465
3581
|
const { elem } = e.receiver.type;
|
|
3466
|
-
const sig = e.method === "
|
|
3467
|
-
? { argTypes: [
|
|
3468
|
-
: e.method === "
|
|
3469
|
-
? { argTypes: [elem], result:
|
|
3470
|
-
: e.method === "
|
|
3471
|
-
? { argTypes: [], result:
|
|
3472
|
-
: e.method === "
|
|
3473
|
-
? { argTypes: [
|
|
3474
|
-
: e.method === "
|
|
3475
|
-
? { argTypes: [F64], result:
|
|
3476
|
-
: e.method === "
|
|
3477
|
-
? { argTypes: [], result:
|
|
3478
|
-
:
|
|
3582
|
+
const sig = e.method === "clone"
|
|
3583
|
+
? { argTypes: [], result: e.receiver.type }
|
|
3584
|
+
: e.method === "add"
|
|
3585
|
+
? { argTypes: [elem], result: VOID }
|
|
3586
|
+
: e.method === "has" || e.method === "delete"
|
|
3587
|
+
? { argTypes: [elem], result: BOOL }
|
|
3588
|
+
: e.method === "clear" || e.method === "iterEnter" || e.method === "iterExit"
|
|
3589
|
+
? { argTypes: [], result: VOID }
|
|
3590
|
+
: e.method === "iterLive"
|
|
3591
|
+
? { argTypes: [F64], result: BOOL }
|
|
3592
|
+
: e.method === "iterKey"
|
|
3593
|
+
? { argTypes: [F64], result: elem }
|
|
3594
|
+
: e.method === "toArray"
|
|
3595
|
+
? { argTypes: [], result: arrayOf(elem) }
|
|
3596
|
+
: { argTypes: [], result: F64 }; // size / iterCount
|
|
3479
3597
|
if (e.args.length !== sig.argTypes.length) {
|
|
3480
3598
|
err(`setIntrinsic ${e.method}: ${e.args.length} args, expected ${sig.argTypes.length}`, e.loc);
|
|
3481
3599
|
}
|
|
@@ -3668,14 +3786,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3668
3786
|
case "fieldGet": {
|
|
3669
3787
|
checkExpr(e.obj);
|
|
3670
3788
|
const cls = classes.get(e.className);
|
|
3671
|
-
const
|
|
3789
|
+
const fieldType = classValidation.fields.get(e.className)?.get(e.field);
|
|
3672
3790
|
if (!cls)
|
|
3673
3791
|
err(`fieldGet on undeclared class "${e.className}"`, e.loc);
|
|
3674
|
-
else if (!
|
|
3792
|
+
else if (!fieldType)
|
|
3675
3793
|
err(`class ${e.className} has no field "${e.field}"`, e.loc);
|
|
3676
3794
|
else {
|
|
3677
3795
|
expectType(e.obj, { kind: "object", className: e.className }, "fieldGet receiver");
|
|
3678
|
-
if (!typeEquals(e.type,
|
|
3796
|
+
if (!typeEquals(e.type, fieldType)) {
|
|
3679
3797
|
err(`fieldGet ${e.className}.${e.field} type mismatch`, e.loc);
|
|
3680
3798
|
}
|
|
3681
3799
|
}
|
|
@@ -3849,30 +3967,15 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3849
3967
|
// is then well-formed against any concrete override below — the
|
|
3850
3968
|
// frontend's override-exactness rule makes every implementation
|
|
3851
3969
|
// ABI-identical, so any one of them carries the slot's signature.
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
for (let c = classes.get(e.className); c; c = c.base !== undefined ? classes.get(c.base) : undefined) {
|
|
3855
|
-
if (c.methods?.includes(e.method)) {
|
|
3856
|
-
declared = true;
|
|
3857
|
-
if (!c.abstractMethods?.includes(e.method)) {
|
|
3858
|
-
impl = functions.get(`%${c.name}.${e.method}`);
|
|
3859
|
-
break;
|
|
3860
|
-
}
|
|
3861
|
-
}
|
|
3862
|
-
}
|
|
3863
|
-
if (!declared) {
|
|
3970
|
+
const info = virtualCallInfo(e.className, e.method);
|
|
3971
|
+
if (!info.declared) {
|
|
3864
3972
|
err(`virtualCall ${e.className}.${e.method}: no declaration on the base chain`, e.loc);
|
|
3865
3973
|
break;
|
|
3866
3974
|
}
|
|
3867
|
-
|
|
3868
|
-
!c.abstractMethods?.includes(e.method) &&
|
|
3869
|
-
isStrictSubclass(c.name, e.className));
|
|
3870
|
-
if (concreteBelow.length === 0) {
|
|
3975
|
+
if (!info.hasOverride) {
|
|
3871
3976
|
err(`virtualCall ${e.className}.${e.method}: no concrete override below the static class`, e.loc);
|
|
3872
3977
|
}
|
|
3873
|
-
impl
|
|
3874
|
-
.map((c) => functions.get(`%${c.name}.${e.method}`))
|
|
3875
|
-
.find((f) => f !== undefined);
|
|
3978
|
+
const impl = info.implementation;
|
|
3876
3979
|
if (!impl) {
|
|
3877
3980
|
err(`virtualCall ${e.className}.${e.method}: no implementation function exists`, e.loc);
|
|
3878
3981
|
break;
|
|
@@ -3908,7 +4011,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3908
4011
|
err(`recordLit of undeclared shape "${e.type.shapeId}"`, e.loc);
|
|
3909
4012
|
break;
|
|
3910
4013
|
}
|
|
3911
|
-
const want =
|
|
4014
|
+
const want = recordValidation.get(shape.id).initializationFields;
|
|
3912
4015
|
const seen = new Set();
|
|
3913
4016
|
for (const f of e.fields) {
|
|
3914
4017
|
checkExpr(f.value);
|
|
@@ -3964,11 +4067,11 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3964
4067
|
err(`recordClone of undeclared shape "${e.type.shapeId}"`, e.loc);
|
|
3965
4068
|
break;
|
|
3966
4069
|
}
|
|
3967
|
-
if (shape.tuple || shape.indexValue ||
|
|
4070
|
+
if (shape.tuple || shape.indexValue || recordValidation.get(shape.id).hasAccessorSlots) {
|
|
3968
4071
|
err(`recordClone requires a plain declared-field shape, got ${shape.id}`, e.loc);
|
|
3969
4072
|
}
|
|
3970
4073
|
expectType(e.source, e.type, "recordClone source");
|
|
3971
|
-
const want =
|
|
4074
|
+
const want = recordValidation.get(shape.id).initializationFields;
|
|
3972
4075
|
const seen = new Set();
|
|
3973
4076
|
for (const f of e.overrides) {
|
|
3974
4077
|
checkExpr(f.value);
|
|
@@ -3986,14 +4089,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3986
4089
|
case "recordGet": {
|
|
3987
4090
|
checkExpr(e.obj);
|
|
3988
4091
|
const shape = records.get(e.shapeId);
|
|
3989
|
-
const field =
|
|
4092
|
+
const field = recordValidation.get(e.shapeId)?.fields.get(e.field);
|
|
3990
4093
|
if (!shape)
|
|
3991
4094
|
err(`recordGet on undeclared shape "${e.shapeId}"`, e.loc);
|
|
3992
4095
|
else if (!field)
|
|
3993
4096
|
err(`shape ${e.shapeId} has no field "${e.field}"`, e.loc);
|
|
3994
4097
|
else {
|
|
3995
4098
|
expectType(e.obj, { kind: "record", shapeId: e.shapeId }, "recordGet receiver");
|
|
3996
|
-
if (!typeEquals(e.type, field
|
|
4099
|
+
if (!typeEquals(e.type, field)) {
|
|
3997
4100
|
err(`recordGet ${e.shapeId}.${e.field} type mismatch`, e.loc);
|
|
3998
4101
|
}
|
|
3999
4102
|
}
|
|
@@ -4365,9 +4468,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
4365
4468
|
}
|
|
4366
4469
|
def.arms.forEach((arm, i) => {
|
|
4367
4470
|
const fieldType = arm.kind === "record"
|
|
4368
|
-
?
|
|
4471
|
+
? recordValidation.get(arm.shapeId)?.fields.get(e.field)
|
|
4369
4472
|
: arm.kind === "object"
|
|
4370
|
-
?
|
|
4473
|
+
? classValidation.fields.get(arm.className)?.get(e.field)
|
|
4371
4474
|
: undefined;
|
|
4372
4475
|
if (!fieldType) {
|
|
4373
4476
|
err(`unionDisc: arm ${i} of ${e.unionId} has no field "${e.field}"`, e.loc);
|
|
@@ -4430,7 +4533,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
4430
4533
|
return;
|
|
4431
4534
|
}
|
|
4432
4535
|
const literal = e.key.kind === "strLit" ? e.key.value : null;
|
|
4433
|
-
const declared = literal !== null ? shape.fields.
|
|
4536
|
+
const declared = literal !== null ? recordValidation.get(shape.id)?.fields.get(literal) : undefined;
|
|
4434
4537
|
if (declared) {
|
|
4435
4538
|
if (!surfaces(declared)) {
|
|
4436
4539
|
err(`unionKeyGet: arm ${i} field "${literal}" of type ${declared.kind} cannot surface as the result`, e.loc);
|
|
@@ -4651,11 +4754,11 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
4651
4754
|
const countName = e.fn === "fileHandle.read" || e.fn === "fileHandle.readv" ? "bytesRead" : "bytesWritten";
|
|
4652
4755
|
const payloadName = e.fn === "fileHandle.readv" || e.fn === "fileHandle.writev" ? "buffers" : "buffer";
|
|
4653
4756
|
const payload = e.args[1]?.type;
|
|
4654
|
-
const count = shape?.fields.
|
|
4655
|
-
const buffer = shape?.fields.
|
|
4757
|
+
const count = shape ? recordValidation.get(shape.id)?.fields.get(countName) : undefined;
|
|
4758
|
+
const buffer = shape ? recordValidation.get(shape.id)?.fields.get(payloadName) : undefined;
|
|
4656
4759
|
const ok = shape !== undefined && !shape.tuple && shape.indexValue === undefined && shape.fields.length === 2 &&
|
|
4657
|
-
count?.
|
|
4658
|
-
typeEquals(buffer
|
|
4760
|
+
count?.kind === "f64" && payload !== undefined && buffer !== undefined &&
|
|
4761
|
+
typeEquals(buffer, payload);
|
|
4659
4762
|
if (!ok) {
|
|
4660
4763
|
err(`libCall ${e.fn} must return a promise of { ${countName}: number, ${payloadName} }`, e.loc);
|
|
4661
4764
|
}
|
|
@@ -5948,17 +6051,17 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5948
6051
|
break;
|
|
5949
6052
|
}
|
|
5950
6053
|
const rec = records.get(resultT.shapeId);
|
|
5951
|
-
const doneF = rec?.fields.
|
|
5952
|
-
const valueF = rec?.fields.
|
|
5953
|
-
if (!rec || rec.fields.length !== 2 || doneF?.
|
|
6054
|
+
const doneF = rec ? recordValidation.get(rec.id)?.fields.get("done") : undefined;
|
|
6055
|
+
const valueF = rec ? recordValidation.get(rec.id)?.fields.get("value") : undefined;
|
|
6056
|
+
if (!rec || rec.fields.length !== 2 || doneF?.kind !== "bool" || valueF === undefined) {
|
|
5954
6057
|
err(`genResume result record ${resultT.shapeId} is not { done: bool, value: V }`, e.loc);
|
|
5955
6058
|
break;
|
|
5956
6059
|
}
|
|
5957
|
-
if (valueF.
|
|
6060
|
+
if (valueF.kind === "dyn")
|
|
5958
6061
|
break;
|
|
5959
|
-
const vdef = valueF.
|
|
6062
|
+
const vdef = valueF.kind === "union" ? unions.get(valueF.unionId) : undefined;
|
|
5960
6063
|
if (!vdef || !vdef.arms.some((a) => a.kind === "undefinedT")) {
|
|
5961
|
-
err(`genResume value slot ${typeKey(valueF
|
|
6064
|
+
err(`genResume value slot ${typeKey(valueF)} is neither dyn nor an undefined-armed union`, e.loc);
|
|
5962
6065
|
}
|
|
5963
6066
|
break;
|
|
5964
6067
|
}
|
|
@@ -6042,10 +6145,10 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
6042
6145
|
break;
|
|
6043
6146
|
}
|
|
6044
6147
|
const shape = records.get(e.type.shapeId);
|
|
6045
|
-
const fields =
|
|
6046
|
-
const prom = fields
|
|
6047
|
-
const resolve = fields
|
|
6048
|
-
const reject = fields
|
|
6148
|
+
const fields = recordValidation.get(e.type.shapeId)?.initializationFields;
|
|
6149
|
+
const prom = fields?.get("promise");
|
|
6150
|
+
const resolve = fields?.get("resolve");
|
|
6151
|
+
const reject = fields?.get("reject");
|
|
6049
6152
|
if (!shape || shape.fields.length !== 3 || !prom || !resolve || !reject) {
|
|
6050
6153
|
err("promiseWithResolvers record must be { promise, resolve, reject }", e.loc);
|
|
6051
6154
|
break;
|
|
@@ -6357,14 +6460,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
6357
6460
|
checkExpr(s.obj);
|
|
6358
6461
|
checkExpr(s.value);
|
|
6359
6462
|
const cls = classes.get(s.className);
|
|
6360
|
-
const
|
|
6463
|
+
const fieldType = classValidation.fields.get(s.className)?.get(s.field);
|
|
6361
6464
|
if (!cls)
|
|
6362
6465
|
err(`fieldSet on undeclared class "${s.className}"`, s.loc);
|
|
6363
|
-
else if (!
|
|
6466
|
+
else if (!fieldType)
|
|
6364
6467
|
err(`class ${s.className} has no field "${s.field}"`, s.loc);
|
|
6365
6468
|
else {
|
|
6366
6469
|
expectType(s.obj, { kind: "object", className: s.className }, "fieldSet receiver");
|
|
6367
|
-
expectType(s.value,
|
|
6470
|
+
expectType(s.value, fieldType, `fieldSet ${s.className}.${s.field}`);
|
|
6368
6471
|
}
|
|
6369
6472
|
break;
|
|
6370
6473
|
}
|
|
@@ -6372,14 +6475,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
6372
6475
|
checkExpr(s.obj);
|
|
6373
6476
|
checkExpr(s.value);
|
|
6374
6477
|
const shape = records.get(s.shapeId);
|
|
6375
|
-
const field =
|
|
6478
|
+
const field = recordValidation.get(s.shapeId)?.fields.get(s.field);
|
|
6376
6479
|
if (!shape)
|
|
6377
6480
|
err(`recordSet on undeclared shape "${s.shapeId}"`, s.loc);
|
|
6378
6481
|
else if (!field)
|
|
6379
6482
|
err(`shape ${s.shapeId} has no field "${s.field}"`, s.loc);
|
|
6380
6483
|
else {
|
|
6381
6484
|
expectType(s.obj, { kind: "record", shapeId: s.shapeId }, "recordSet receiver");
|
|
6382
|
-
expectType(s.value, field
|
|
6485
|
+
expectType(s.value, field, `recordSet ${s.shapeId}.${s.field}`);
|
|
6383
6486
|
}
|
|
6384
6487
|
break;
|
|
6385
6488
|
}
|