@scriptc/compiler 0.0.11 → 0.0.13
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 +153 -24
- package/ambient/scriptc.d.ts +2 -2
- package/dist/backend/cc.d.ts +10 -2
- package/dist/backend/cc.js +12 -0
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-async.js +1 -1
- package/dist/backend/emission/emit-exprs.js +235 -64
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-island.js +1 -1
- package/dist/backend/emission/emit-shapes.js +1 -1
- package/dist/backend/emission/emit-walkers.d.ts +14 -14
- package/dist/backend/emission/emit-walkers.js +44 -44
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +3 -3
- package/dist/backend/emission/emitter.js +8 -8
- package/dist/backend/emission/may-throw.js +1 -1
- package/dist/backend/llvm/dyn.d.ts +10 -10
- package/dist/backend/llvm/dyn.js +26 -26
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +140 -49
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.js +1 -1
- package/dist/backend/llvm/walkers.js +2 -2
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +1 -1
- package/dist/diagnostics/diagnostic.js +4 -3
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lowering/crypto-tables.d.ts +7 -0
- package/dist/frontend/lowering/crypto-tables.js +139 -0
- package/dist/frontend/lowering/crypto-tables.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.js +5 -5
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +12 -12
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +45 -27
- package/dist/frontend/lowering/lower-builtins.js +203 -70
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +4 -4
- package/dist/frontend/lowering/lower-calls.js +74 -66
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +41 -7
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +5 -5
- package/dist/frontend/lowering/lower-containers.js +19 -19
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-emitter.js +2 -2
- package/dist/frontend/lowering/lower-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +7 -7
- package/dist/frontend/lowering/lower-exprs.js +227 -119
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +5 -5
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +12 -3
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +17 -17
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +11 -1
- package/dist/frontend/lowering/lower-namespaces.js +41 -6
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +21 -0
- package/dist/frontend/lowering/lower-server.js +278 -23
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +1 -1
- package/dist/frontend/lowering/lower-stmts.js +195 -34
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +67 -23
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +31 -13
- package/dist/frontend/lowering/lowerer.js +99 -45
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +6 -0
- package/dist/frontend/lowering/surfaces.js +78 -2
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/program.js +1 -1
- package/dist/frontend/shared.js +7 -7
- package/dist/frontend/shared.js.map +1 -1
- package/dist/frontend/types.d.ts +2 -2
- package/dist/frontend/types.js +27 -15
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.js +44 -8
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +208 -106
- package/dist/ir/nodes.js +100 -22
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +96 -38
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/int-infer.js +13 -0
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/profile.d.ts +8 -6
- package/dist/library/profile.js.map +1 -1
- package/dist/library/sidecar-validate.js +1 -1
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +1 -1
- package/dist/library/sidecar.js +20 -7
- package/dist/library/sidecar.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +289 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { canMarshalFuncIntoIsland, CAUGHT, DYN, F64, islandCallbackRet, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, moduleUsesDynInvoke, moduleUsesFetch, moduleUsesFsWatch, moduleUsesHttpServer, moduleUsesNet, moduleUsesProcessEvents, moduleUsesStream, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, STRING, typeEquals, typeKey, VOID } from "../../ir/nodes.js";
|
|
1
|
+
import { canMarshalFuncIntoIsland, CAUGHT, DYN, F64, islandCallbackRet, islandPromisePayloadTag, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, moduleUsesDynInvoke, moduleUsesFetch, moduleUsesFsWatch, moduleUsesHttpServer, moduleUsesNet, moduleUsesProcessEvents, moduleUsesStream, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, STRING, typeEquals, typeKey, VOID } from "../../ir/nodes.js";
|
|
2
2
|
import { computeMayThrow } from "../emission/may-throw.js";
|
|
3
3
|
import { mangleArgPack, mangleAsyncSpawn, mangleClassNew, mangleClassObj, mangleClassRetain, mangleFnClosure, mangleFunction, mangleGenDrop, mangleGenResThunk, mangleGenSpawn, mangleGlobal, mangleLocal, mangleRecordNew, mangleRecordStruct, mangleResolveThunk, mangleTrampoline, mangleVtStruct, mangleWrapper } from "../mangle.js";
|
|
4
4
|
import { BlockBuilder } from "./blocks.js";
|
|
@@ -226,6 +226,9 @@ const LIB_FN_SYMS = {
|
|
|
226
226
|
"text.decode": "scr_text_decode",
|
|
227
227
|
"zlib.deflateSync": "scr_zlib_deflate",
|
|
228
228
|
"zlib.inflateSync": "scr_zlib_inflate",
|
|
229
|
+
// The CA-store read (tlsca.get/set are may-throw seeds and refuse by
|
|
230
|
+
// omission — the C fallback carries them).
|
|
231
|
+
"tlsca.root": "scr_tls_ca_root",
|
|
229
232
|
"crypto.randomBytes": "scr_crypto_random_bytes",
|
|
230
233
|
"crypto.randomBytesToString": "scr_crypto_random_string",
|
|
231
234
|
"crypto.randomUUID": "scr_crypto_random_uuid",
|
|
@@ -340,7 +343,7 @@ const LIB_FN_SYMS = {
|
|
|
340
343
|
"sym.toString": "scr_sym_to_string",
|
|
341
344
|
"error.toString": "scr_error_to_string",
|
|
342
345
|
"class.name": "scr_classobj_name",
|
|
343
|
-
// The dyn (ScrDyn
|
|
346
|
+
// The dyn (ScrDyn dyn) surface (scr_json.c / scr_dyn_invoke.c):
|
|
344
347
|
// json.parse throws the catchable SyntaxError; keySet/toString/
|
|
345
348
|
// defineProps throw Node's TypeErrors (all in the may-throw seed set —
|
|
346
349
|
// the generic path emits the standard pending check). typeof and the
|
|
@@ -348,6 +351,9 @@ const LIB_FN_SYMS = {
|
|
|
348
351
|
"json.parse": "scr_json_parse",
|
|
349
352
|
"dyn.keySet": "scr_dyn_key_set",
|
|
350
353
|
"dyn.iterPack": "scr_dyn_iter_pack",
|
|
354
|
+
"dyn.arrLen": "scr_dyn_arr_len",
|
|
355
|
+
"dyn.arrAt": "scr_dyn_arr_at",
|
|
356
|
+
"dyn.hasKey": "scr_dyn_has_key",
|
|
351
357
|
"dyn.defineProps": "scr_dyn_define_props",
|
|
352
358
|
"dyn.typeof": "scr_dyn_typeof",
|
|
353
359
|
"dyn.toString": "scr_dyn_to_string_method",
|
|
@@ -444,6 +450,12 @@ const LIB_FN_SYMS = {
|
|
|
444
450
|
"net.sockSetEncoding": "scr_net_sock_set_encoding",
|
|
445
451
|
"net.sockSetTimeout": "scr_net_sock_set_timeout",
|
|
446
452
|
"net.sockUnshift": "scr_net_sock_unshift_bytes",
|
|
453
|
+
"net.sockPause": "scr_net_sock_pause",
|
|
454
|
+
"net.sockResume": "scr_net_sock_resume",
|
|
455
|
+
"net.sockSetNoDelay": "scr_net_sock_set_nodelay",
|
|
456
|
+
"net.sockDestroySoon": "scr_net_sock_destroy_soon",
|
|
457
|
+
"net.sockBytesWritten": "scr_net_sock_bytes_written",
|
|
458
|
+
"net.sockReadable": "scr_net_sock_readable",
|
|
447
459
|
"net.sockPipeRes": "scr_http_sock_pipe_res",
|
|
448
460
|
"net.serverEmitConnection": "scr_net_server_emit_connection",
|
|
449
461
|
"net.getAutoSelTimeout": "scr_net_get_autosel_timeout",
|
|
@@ -490,6 +502,7 @@ const LIB_FN_SYMS = {
|
|
|
490
502
|
"http.clientDestroy": "scr_http_client_destroy",
|
|
491
503
|
"http.clientDestroyed": "scr_http_client_destroyed",
|
|
492
504
|
"http2.streamUndefCall": "scr_http2_stream_undef_call",
|
|
505
|
+
"http.agentNew": "scr_http_agent_new",
|
|
493
506
|
// The island surface (--dynamic): eval/import bridge catchably (the
|
|
494
507
|
// may-throw seed's pending check); importDyn answers an engine promise
|
|
495
508
|
// and never throws itself. insp.jsval throws on composite island
|
|
@@ -535,7 +548,7 @@ const LIB_FN_SYMS = {
|
|
|
535
548
|
"dc.tcTraceCallback": "scr_dc_tc_trace_callback",
|
|
536
549
|
"dc.tcTracePromise": "scr_dc_tc_trace_promise",
|
|
537
550
|
// AsyncLocalStorage (scr_async_dyn.c): store ids are doubles, values
|
|
538
|
-
// ride the
|
|
551
|
+
// ride the checked-dynamic tree; run/exitRun dispatch user callbacks (may-throw).
|
|
539
552
|
// The dc bind-store trio shares the als id space.
|
|
540
553
|
"als.new": "scr_als_new",
|
|
541
554
|
"als.get": "scr_als_get",
|
|
@@ -547,13 +560,16 @@ const LIB_FN_SYMS = {
|
|
|
547
560
|
"dc.chanUnbindStore": "scr_dc_chan_unbind_store",
|
|
548
561
|
"dc.chanRunStores": "scr_dc_chan_run_stores",
|
|
549
562
|
// process warning/rejection events (scr_lib.c / scr_async_dyn.c):
|
|
550
|
-
//
|
|
563
|
+
// dyn listeners are borrowed (the runtime retains its copy);
|
|
551
564
|
// onUnhandledRejection marks the loop live (the loop-end report
|
|
552
565
|
// dispatches the listeners).
|
|
553
566
|
"process.onWarning": "scr_process_on_warning",
|
|
554
567
|
"process.offWarning": "scr_process_off_warning",
|
|
555
568
|
"process.emitWarning": "scr_process_emit_warning",
|
|
556
569
|
"process.onUnhandledRejection": "scr_process_on_unhandled_rejection",
|
|
570
|
+
"process.offUnhandledRejection": "scr_process_off_unhandled_rejection",
|
|
571
|
+
"process.onRejectionHandled": "scr_process_on_rejection_handled",
|
|
572
|
+
"process.offRejectionHandled": "scr_process_off_rejection_handled",
|
|
557
573
|
// The await lowering's loop hop and the dyn await (both park the
|
|
558
574
|
// current fiber — USES_TIMERS_LIB_FNS marks the loop live).
|
|
559
575
|
"async.hop": "scr_await_hop",
|
|
@@ -568,7 +584,7 @@ const LIB_FN_SYMS = {
|
|
|
568
584
|
"regexp.escape": "scr_regexp_escape",
|
|
569
585
|
// The dyn Object walks (throw on nullish receivers), structuredClone
|
|
570
586
|
// (option/DataClone/cycle errors), and new RegExp's eager compile
|
|
571
|
-
// (catchable SyntaxError) — all may-throw generics over the
|
|
587
|
+
// (catchable SyntaxError) — all may-throw generics over the checked-dynamic tree.
|
|
572
588
|
"dyn.objKeys": "scr_dyn_obj_keys",
|
|
573
589
|
"dyn.hasOwn": "scr_dyn_has_own",
|
|
574
590
|
"dyn.assign": "scr_dyn_assign",
|
|
@@ -631,12 +647,13 @@ const USES_TIMERS_LIB_FNS = new Set([
|
|
|
631
647
|
"http.createServer", "http.createServerEmpty",
|
|
632
648
|
"http.request", "http.requestCb", "http.requestUrl", "http.requestUrlCb",
|
|
633
649
|
"http.requestConn", "http.requestConnCb",
|
|
650
|
+
"http.agentNew", "http.requestAgent", "http.requestAgentCb",
|
|
634
651
|
// The dyn-async slice (emit-exprs.ts's markings): fiber parks, the
|
|
635
652
|
// microtask/immediate mints, the tracing-promise reaction fiber, and
|
|
636
653
|
// the loop-end unhandled-rejection report.
|
|
637
654
|
"async.hop", "async.awaitDyn",
|
|
638
655
|
"dc.tcTracePromise",
|
|
639
|
-
"process.onUnhandledRejection",
|
|
656
|
+
"process.onUnhandledRejection", "process.onRejectionHandled",
|
|
640
657
|
"timers.queueMicrotaskDyn", "timers.setImmediateFnValue", "timers.immediatePromise",
|
|
641
658
|
]);
|
|
642
659
|
/** ScrBytesElem (scr_runtime.h): U8, U32, F32, I32. */
|
|
@@ -719,7 +736,7 @@ class LlEmitter {
|
|
|
719
736
|
* rewriter, union ToString/join) — interned per typeKey/unionId, defs
|
|
720
737
|
* flushed with the shape helpers. */
|
|
721
738
|
walkers = new LlWalkers(this);
|
|
722
|
-
/** The dyn (ScrDyn
|
|
739
|
+
/** The dyn (ScrDyn dyn) helper registry — dyn.ts's interned ports of
|
|
723
740
|
* emit-walkers.ts's dyn slice. */
|
|
724
741
|
dyn = new LlDyn(this);
|
|
725
742
|
/** External declarations, in first-use order. */
|
|
@@ -2036,7 +2053,7 @@ class LlEmitter {
|
|
|
2036
2053
|
return t;
|
|
2037
2054
|
}
|
|
2038
2055
|
case "dyn": {
|
|
2039
|
-
// ToBoolean over the
|
|
2056
|
+
// ToBoolean over the dyn kind (scr_dyn_truthy — JS-exact for
|
|
2040
2057
|
// every kind; borrowed, never throws): `v || dflt` and condition
|
|
2041
2058
|
// descent on checked-dynamic values.
|
|
2042
2059
|
this.declare(`declare zeroext i1 @scr_dyn_truthy(ptr)`);
|
|
@@ -3714,7 +3731,7 @@ class LlEmitter {
|
|
|
3714
3731
|
return this.own({ name: t, type: e.type });
|
|
3715
3732
|
}
|
|
3716
3733
|
if (v.type.kind === "dyn") {
|
|
3717
|
-
// String(unknown): dispatch over the
|
|
3734
|
+
// String(unknown): dispatch over the dyn kind (dyn.ts's sc_ds —
|
|
3718
3735
|
// Node's String() incl. arrays-join and "[object Object]").
|
|
3719
3736
|
const helper = this.dyn.dynToStrHelper();
|
|
3720
3737
|
const t = B.tmp();
|
|
@@ -4015,7 +4032,7 @@ class LlEmitter {
|
|
|
4015
4032
|
this.unionTagSwitch(u.name, def, (arm) => {
|
|
4016
4033
|
if (isUnitType(arm)) {
|
|
4017
4034
|
if (e.type.kind === "dyn") {
|
|
4018
|
-
// A dyn-typed chain: the unit path is the undefined
|
|
4035
|
+
// A dyn-typed chain: the unit path is the undefined dyn
|
|
4019
4036
|
// value — dyn represents undefined directly.
|
|
4020
4037
|
this.declare(`declare ptr @scr_dyn_undefined()`);
|
|
4021
4038
|
this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
|
|
@@ -4197,8 +4214,21 @@ class LlEmitter {
|
|
|
4197
4214
|
const lj = B.newLabel("ord.j");
|
|
4198
4215
|
B.condBr(truthy, lt, lf);
|
|
4199
4216
|
B.startBlock(lt);
|
|
4200
|
-
|
|
4201
|
-
|
|
4217
|
+
if (e.retag !== undefined) {
|
|
4218
|
+
// Retagged shape: the whole box goes to the union→union helper,
|
|
4219
|
+
// which CONSUMES it (callees own their params) — no release on
|
|
4220
|
+
// this side. The store precedes the pending check so an unwind
|
|
4221
|
+
// leaves only the NULL dummy behind, in a slot nothing reads.
|
|
4222
|
+
const t = B.tmp();
|
|
4223
|
+
B.line(`${t} = call ${ty} @${this.callTarget(e.retag)}(${this.llType(e.left.type)} ${l.name})`);
|
|
4224
|
+
B.line(`store ${ty} ${t}, ptr ${slot}`);
|
|
4225
|
+
if (this.mayThrow.has(e.retag))
|
|
4226
|
+
this.emitPendingCheck();
|
|
4227
|
+
}
|
|
4228
|
+
else {
|
|
4229
|
+
B.line(`store ${ty} ${this.unionExtract(l.name, e.type)}, ptr ${slot}`);
|
|
4230
|
+
this.releaseValue(l.name, e.left.type);
|
|
4231
|
+
}
|
|
4202
4232
|
B.br(lj);
|
|
4203
4233
|
B.startBlock(lf);
|
|
4204
4234
|
this.releaseValue(l.name, e.left.type);
|
|
@@ -4311,9 +4341,9 @@ class LlEmitter {
|
|
|
4311
4341
|
// the frame's release is a no-op) and the body reads it through
|
|
4312
4342
|
// chainRecv.
|
|
4313
4343
|
if (e.receiver.type.kind === "dyn") {
|
|
4314
|
-
// A dyn (
|
|
4344
|
+
// A dyn (dyn) receiver — the `rawName?.match(re)` step: the
|
|
4315
4345
|
// nullish test reads the node's kind tag; the unit path is the
|
|
4316
|
-
// undefined
|
|
4346
|
+
// undefined dyn singleton (dyn results) or nothing (void
|
|
4317
4347
|
// bodies), the body runs over the bound receiver otherwise.
|
|
4318
4348
|
const r = this.emitExpr(e.receiver);
|
|
4319
4349
|
const kd = this.dynKind(r.name);
|
|
@@ -4465,7 +4495,7 @@ class LlEmitter {
|
|
|
4465
4495
|
}
|
|
4466
4496
|
if (e.type.kind === "dyn") {
|
|
4467
4497
|
// A dyn-typed chain (`pricing?.[key]` over an unknown-valued
|
|
4468
|
-
// index signature): the unit path is the undefined
|
|
4498
|
+
// index signature): the unit path is the undefined dyn value —
|
|
4469
4499
|
// dyn represents undefined directly, no union wrapper exists.
|
|
4470
4500
|
const slotD = B.slot();
|
|
4471
4501
|
B.entryAllocas.push(`${slotD} = alloca ptr`);
|
|
@@ -4912,14 +4942,14 @@ class LlEmitter {
|
|
|
4912
4942
|
}
|
|
4913
4943
|
case "jsonStringify": {
|
|
4914
4944
|
// Type-directed serialization: the STATIC type picks an emitted
|
|
4915
|
-
// serializer (interned per typeKey) — no
|
|
4945
|
+
// serializer (interned per typeKey) — no dyn, no runtime dispatch.
|
|
4916
4946
|
// The value temp is BORROWED (released with this statement's
|
|
4917
4947
|
// frame); the result string is owned (+1). Never throws — except
|
|
4918
4948
|
// the dyn root below.
|
|
4919
4949
|
const v = this.emitExpr(e.value);
|
|
4920
4950
|
let compact;
|
|
4921
4951
|
if (e.value.type.kind === "dyn") {
|
|
4922
|
-
// A dyn root: the runtime's
|
|
4952
|
+
// A dyn root: the runtime's dyn walker (scr_dyn_format_j — the
|
|
4923
4953
|
// C backend's dispatch exactly): number/string/bool/null/array/
|
|
4924
4954
|
// object exact, dropped members omitted, and a dropped ROOT
|
|
4925
4955
|
// becomes the TEXT "undefined" (JSON.stringify(undefined) is
|
|
@@ -5084,7 +5114,7 @@ class LlEmitter {
|
|
|
5084
5114
|
if (e.arg === null) {
|
|
5085
5115
|
if (genT.nextT.kind === "dyn") {
|
|
5086
5116
|
// Valueless resume on a dyn channel: JS's undefined — the
|
|
5087
|
-
//
|
|
5117
|
+
// dyn singleton rides the IN slot (+1 moves in).
|
|
5088
5118
|
this.declare(`declare ptr @scr_dyn_undefined()`);
|
|
5089
5119
|
this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
|
|
5090
5120
|
this.declare(`declare void @scr_dyn_release_v(ptr)`);
|
|
@@ -5552,10 +5582,10 @@ class LlEmitter {
|
|
|
5552
5582
|
return { name: "", type: e.type };
|
|
5553
5583
|
}
|
|
5554
5584
|
case "dynFrom": {
|
|
5555
|
-
// Static value → fresh
|
|
5585
|
+
// Static value → fresh dyn tree (+1) through the interned per-type
|
|
5556
5586
|
// converter; the operand stays borrowed (frame-released as usual).
|
|
5557
5587
|
// Bare unit literals (an `undefined`/`null` stored under an
|
|
5558
|
-
// `unknown` index signature) are the
|
|
5588
|
+
// `unknown` index signature) are the dyn unit values directly.
|
|
5559
5589
|
if (e.value.kind === "unitLit") {
|
|
5560
5590
|
const t = B.tmp();
|
|
5561
5591
|
if (e.value.unit === "undefined") {
|
|
@@ -5573,7 +5603,7 @@ class LlEmitter {
|
|
|
5573
5603
|
}
|
|
5574
5604
|
const v = this.emitExpr(e.value);
|
|
5575
5605
|
if (v.type.kind === "func") {
|
|
5576
|
-
// A closure boxes as the
|
|
5606
|
+
// A closure boxes as the checked-dynamic tree's function kind: retained closure +
|
|
5577
5607
|
// the per-signature call thunk + the interned signature key. The
|
|
5578
5608
|
// best-effort name rides along (null when the lowering had none).
|
|
5579
5609
|
const name = e.fnName !== undefined && e.fnName !== "" ? this.cstr(e.fnName) : "null";
|
|
@@ -5589,8 +5619,8 @@ class LlEmitter {
|
|
|
5589
5619
|
return this.own({ name: t, type: e.type });
|
|
5590
5620
|
}
|
|
5591
5621
|
case "dynFromJsval": {
|
|
5592
|
-
// Island value →
|
|
5593
|
-
// retains the cell in; engine scalars normalize to native
|
|
5622
|
+
// Island value → dyn: the by-reference wrap (scr_dyn_from_jsval
|
|
5623
|
+
// retains the cell in; engine scalars normalize to native dyn
|
|
5594
5624
|
// kinds at wrap time). Operand borrowed, result +1, never throws.
|
|
5595
5625
|
const v = this.emitExpr(e.value);
|
|
5596
5626
|
this.declare(`declare ptr @scr_dyn_from_jsval(ptr)`);
|
|
@@ -5609,7 +5639,7 @@ class LlEmitter {
|
|
|
5609
5639
|
return this.own({ name: t, type: e.type });
|
|
5610
5640
|
}
|
|
5611
5641
|
case "dynCheck": {
|
|
5612
|
-
// The dynamic boundary: validate the
|
|
5642
|
+
// The dynamic boundary: validate the checked-dynamic tree against the target type
|
|
5613
5643
|
// and BUILD the typed value (+1) — or throw the catchable
|
|
5614
5644
|
// path-annotated TypeError. The dyn temp is BORROWED; the result
|
|
5615
5645
|
// joins the frame BEFORE the pending check so an unwind releases
|
|
@@ -5630,11 +5660,11 @@ class LlEmitter {
|
|
|
5630
5660
|
// spelling rides along for Node's "<name> is not a function".
|
|
5631
5661
|
const callee = this.emitExpr(e.callee);
|
|
5632
5662
|
if (e.spreads !== undefined && e.spreads.length > 0) {
|
|
5633
|
-
// The RUNTIME-ARITY form (`f(...args)`): one fresh
|
|
5663
|
+
// The RUNTIME-ARITY form (`f(...args)`): one fresh dyn array
|
|
5634
5664
|
// collects the arguments left-to-right — plain args move in
|
|
5635
5665
|
// (push takes ownership), spread args FLATTEN (push_spread
|
|
5636
5666
|
// retains elements in and throws V8's spread-call TypeError for
|
|
5637
|
-
// non-iterable
|
|
5667
|
+
// non-iterable dyn kinds, checked per spread — JS's
|
|
5638
5668
|
// ArgumentListEvaluation order) — then apply calls through the
|
|
5639
5669
|
// array's elements (borrowed, exactly scr_dyn_call).
|
|
5640
5670
|
this.declare(`declare ptr @scr_dyn_new_arr()`);
|
|
@@ -5707,7 +5737,7 @@ class LlEmitter {
|
|
|
5707
5737
|
return out;
|
|
5708
5738
|
}
|
|
5709
5739
|
case "dynArrLit": {
|
|
5710
|
-
// A
|
|
5740
|
+
// A dyn array built element-by-element: ownership of each dyn
|
|
5711
5741
|
// element MOVES into the array (scr_dyn_arr_push's contract).
|
|
5712
5742
|
this.declare(`declare ptr @scr_dyn_new_arr()`);
|
|
5713
5743
|
this.declare(`declare void @scr_dyn_arr_push(ptr, ptr)`);
|
|
@@ -5722,7 +5752,7 @@ class LlEmitter {
|
|
|
5722
5752
|
return out;
|
|
5723
5753
|
}
|
|
5724
5754
|
case "dynObjLit": {
|
|
5725
|
-
// A
|
|
5755
|
+
// A dyn object built member-by-member: key then value, source
|
|
5726
5756
|
// order. scr_dyn_key_set BORROWS all three (the member retains the
|
|
5727
5757
|
// value in); the receiver is a fresh OBJ, so the non-object throw
|
|
5728
5758
|
// paths are unreachable here.
|
|
@@ -5739,7 +5769,7 @@ class LlEmitter {
|
|
|
5739
5769
|
return out;
|
|
5740
5770
|
}
|
|
5741
5771
|
case "dynKeyGet": {
|
|
5742
|
-
// Keyed read on the
|
|
5772
|
+
// Keyed read on the checked-dynamic tree through the one interned helper — the
|
|
5743
5773
|
// non-optional form throws JS's TypeError on an undefined/null
|
|
5744
5774
|
// receiver, and HANDLE receivers can throw the loud unmodeled-
|
|
5745
5775
|
// property ladder on EITHER form; the result is owned (+1).
|
|
@@ -5824,7 +5854,7 @@ class LlEmitter {
|
|
|
5824
5854
|
const [d, s, st] = e.left.type.kind === "dyn" ? [l, r, e.right.type] : [r, l, e.left.type];
|
|
5825
5855
|
let test;
|
|
5826
5856
|
if (st.kind === "dyn") {
|
|
5827
|
-
// dyn vs dyn: whole-
|
|
5857
|
+
// dyn vs dyn: whole-dyn strict equality.
|
|
5828
5858
|
this.declare(`declare zeroext i1 @scr_dyn_strict_eq(ptr, ptr)`);
|
|
5829
5859
|
test = B.tmp();
|
|
5830
5860
|
B.line(`${test} = call zeroext i1 @scr_dyn_strict_eq(ptr ${l.name}, ptr ${r.name})`);
|
|
@@ -5877,7 +5907,7 @@ class LlEmitter {
|
|
|
5877
5907
|
return { name: neg, type: e.type };
|
|
5878
5908
|
}
|
|
5879
5909
|
case "dynTest": {
|
|
5880
|
-
// A pure kind compare on the
|
|
5910
|
+
// A pure kind compare on the dyn node — borrowed; only the truthy
|
|
5881
5911
|
// form also reads a scalar payload (the runtime's ToBoolean).
|
|
5882
5912
|
const d = this.emitExpr(e.value);
|
|
5883
5913
|
let test;
|
|
@@ -5887,7 +5917,7 @@ class LlEmitter {
|
|
|
5887
5917
|
B.line(`${test} = call zeroext i1 @scr_dyn_truthy(ptr ${d.name})`);
|
|
5888
5918
|
}
|
|
5889
5919
|
else if (e.test === "error") {
|
|
5890
|
-
// `u instanceof Error`: the
|
|
5920
|
+
// `u instanceof Error`: the checked-dynamic tree's error encoding — an object
|
|
5891
5921
|
// carrying the reserved "%error" marker key — or a real engine
|
|
5892
5922
|
// Error held by reference (the isl helper answers false for
|
|
5893
5923
|
// every non-JSVAL kind, so the call is unconditional).
|
|
@@ -5954,7 +5984,7 @@ class LlEmitter {
|
|
|
5954
5984
|
test = orIsl(oneOf([DK.OBJ, DK.ARR, DK.BYTES, DK.HANDLE, DK.PROMISE, DK.NULL]), "scr_dyn_isl_typeof_is", this.cstr("object"));
|
|
5955
5985
|
}
|
|
5956
5986
|
else if (e.test === "array") {
|
|
5957
|
-
// Array.isArray: the
|
|
5987
|
+
// Array.isArray: the checked-dynamic tree's array kind, or the engine's own
|
|
5958
5988
|
// answer for an engine-held value.
|
|
5959
5989
|
test = orIsl(oneOf([DK.ARR]), "scr_dyn_isl_is_array");
|
|
5960
5990
|
}
|
|
@@ -5980,7 +6010,7 @@ class LlEmitter {
|
|
|
5980
6010
|
return { name: neg, type: e.type };
|
|
5981
6011
|
}
|
|
5982
6012
|
case "dynDestrCheck": {
|
|
5983
|
-
// RequireObjectCoercible with V8's destructuring TypeError.
|
|
6013
|
+
// RequireObjectCoercible with V8's destructuring TypeError. dyn
|
|
5984
6014
|
// values check in the runtime helper and pass through unchanged
|
|
5985
6015
|
// (same temp, same ownership); island values check in the engine
|
|
5986
6016
|
// (a fresh +1 cell for the same value comes back).
|
|
@@ -6001,7 +6031,7 @@ class LlEmitter {
|
|
|
6001
6031
|
}
|
|
6002
6032
|
case "dynIterN": {
|
|
6003
6033
|
// GetIterator + first-N steps as a fresh array (V8's exact
|
|
6004
|
-
// not-iterable TypeError on non-iterables): the
|
|
6034
|
+
// not-iterable TypeError on non-iterables): the dyn helper for
|
|
6005
6035
|
// dyn operands, the engine's real iterator protocol for island
|
|
6006
6036
|
// ones.
|
|
6007
6037
|
const v = this.emitExpr(e.value);
|
|
@@ -6033,7 +6063,9 @@ class LlEmitter {
|
|
|
6033
6063
|
const v = this.emitExpr(e.value);
|
|
6034
6064
|
const payload = e.type.kind === "promise" && e.type.inner.kind === "void"
|
|
6035
6065
|
? 0 // SCR_ISLP_VOID
|
|
6036
|
-
:
|
|
6066
|
+
: e.type.kind === "promise" && e.type.inner.kind === "array" && e.type.inner.elem.kind === "jsval"
|
|
6067
|
+
? 5 // SCR_ISLP_JSVAL_ARR: the Array.isArray-gated by-reference exit at settle
|
|
6068
|
+
: 4; // SCR_ISLP_JSVAL
|
|
6037
6069
|
this.declare(`declare ptr @scr_jsval_bridge_promise(ptr, i32)`);
|
|
6038
6070
|
const t = B.tmp();
|
|
6039
6071
|
B.line(`${t} = call ptr @scr_jsval_bridge_promise(ptr ${v.name}, i32 ${payload})`);
|
|
@@ -6081,7 +6113,7 @@ class LlEmitter {
|
|
|
6081
6113
|
case "string":
|
|
6082
6114
|
return simple("scr_jsval_from_str", "ptr", false);
|
|
6083
6115
|
case "dyn":
|
|
6084
|
-
// A CHECKED-DYNAMIC (
|
|
6116
|
+
// A CHECKED-DYNAMIC (dyn) value entering the island: deep copy,
|
|
6085
6117
|
// data kinds only — boxed functions/handles/promises throw the
|
|
6086
6118
|
// catchable TypeError in the runtime, and a wrapped island value
|
|
6087
6119
|
// unwraps to the SAME engine value (the identity round trip).
|
|
@@ -6093,6 +6125,25 @@ class LlEmitter {
|
|
|
6093
6125
|
case "url":
|
|
6094
6126
|
// A URL crossing IN: an engine URL instance built from href.
|
|
6095
6127
|
return simple("scr_jsval_from_url", "ptr", true);
|
|
6128
|
+
case "promise": {
|
|
6129
|
+
// A STATIC promise crossing IN: a real engine thenable settled
|
|
6130
|
+
// when the scriptc promise settles (the async-callback return
|
|
6131
|
+
// bridge). from_promise takes ownership of a +1 — retain past
|
|
6132
|
+
// the borrowed frame temp. The C emitter's rule, mirrored.
|
|
6133
|
+
const tag = islandPromisePayloadTag(e.value.type.inner);
|
|
6134
|
+
if (!tag)
|
|
6135
|
+
throw new Error("llvm emitter bug: jsMarshal of a promise outside the bridge payload domain");
|
|
6136
|
+
const tagN = { void: 0, f64: 1, bool: 2, string: 3, jsval: 4, jsvalArr: 5 }[tag];
|
|
6137
|
+
this.declare(`declare ptr @scr_promise_retain(ptr)`);
|
|
6138
|
+
this.declare(`declare ptr @scr_jsval_from_promise(ptr, i32)`);
|
|
6139
|
+
const pr = B.tmp();
|
|
6140
|
+
B.line(`${pr} = call ptr @scr_promise_retain(ptr ${v.name})`);
|
|
6141
|
+
const t = B.tmp();
|
|
6142
|
+
B.line(`${t} = call ptr @scr_jsval_from_promise(ptr ${pr}, i32 ${tagN})`);
|
|
6143
|
+
const out = this.own({ name: t, type: e.type });
|
|
6144
|
+
this.emitPendingCheck();
|
|
6145
|
+
return out;
|
|
6146
|
+
}
|
|
6096
6147
|
case "func": {
|
|
6097
6148
|
// A closure entering the island as a host function: from_closure
|
|
6098
6149
|
// retains it; the engine's finalizer releases it at teardown. The
|
|
@@ -6424,6 +6475,17 @@ class LlEmitter {
|
|
|
6424
6475
|
return out;
|
|
6425
6476
|
}
|
|
6426
6477
|
default: {
|
|
6478
|
+
// `any[]`-declared slot: Array.isArray-gated, elements BY
|
|
6479
|
+
// REFERENCE (identity crosses; the spine is a snapshot copy).
|
|
6480
|
+
// JSON-safe element types keep the round trip below.
|
|
6481
|
+
if (e.type.kind === "array" && e.type.elem.kind === "jsval") {
|
|
6482
|
+
this.declare(`declare ptr @scr_jsval_exit_jsval_arr(ptr)`);
|
|
6483
|
+
const t = B.tmp();
|
|
6484
|
+
B.line(`${t} = call ptr @scr_jsval_exit_jsval_arr(ptr ${v.name})`);
|
|
6485
|
+
const out = this.own({ name: t, type: e.type });
|
|
6486
|
+
this.emitPendingCheck();
|
|
6487
|
+
return out;
|
|
6488
|
+
}
|
|
6427
6489
|
// An undefined-armed union target: the engine's undefined takes
|
|
6428
6490
|
// the undefined arm FIRST (JSON cannot spell it); then null and
|
|
6429
6491
|
// data ride the round trip into the union's dynCheck like any
|
|
@@ -6460,11 +6522,31 @@ class LlEmitter {
|
|
|
6460
6522
|
B.br(lj);
|
|
6461
6523
|
B.startBlock(ld);
|
|
6462
6524
|
this.frames.push([]);
|
|
6463
|
-
const
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6525
|
+
const unionDef = this.unionsById.get(e.type.unionId);
|
|
6526
|
+
const dataArms = unionDef ? unionDef.arms.flatMap((a, i) => (isUnitType(a) ? [] : [{ a, i }])) : [];
|
|
6527
|
+
const jsvalArr = dataArms.length === 1 && dataArms[0].a.kind === "array" && dataArms[0].a.elem.kind === "jsval" ? dataArms[0] : null;
|
|
6528
|
+
let t;
|
|
6529
|
+
if (jsvalArr) {
|
|
6530
|
+
// The `any[] | undefined` defaulted-parameter spelling: the
|
|
6531
|
+
// engine array exits BY REFERENCE into the data arm.
|
|
6532
|
+
this.declare(`declare ptr @scr_jsval_exit_jsval_arr(ptr)`);
|
|
6533
|
+
this.declare(`declare ptr @scr_union_new_ref(i32, ptr, ptr, ptr, ptr)`);
|
|
6534
|
+
this.declare(`declare ptr @scr_arr_retain_v(ptr)`);
|
|
6535
|
+
this.declare(`declare void @scr_arr_release_v(ptr)`);
|
|
6536
|
+
const arr = B.tmp();
|
|
6537
|
+
B.line(`${arr} = call ptr @scr_jsval_exit_jsval_arr(ptr ${v.name})`);
|
|
6538
|
+
this.emitPendingCheck();
|
|
6539
|
+
t = B.tmp();
|
|
6540
|
+
B.line(`${t} = call ptr @scr_union_new_ref(i32 ${jsvalArr.i}, ptr ${arr}, ptr @scr_arr_retain_v, ptr @scr_arr_release_v, ptr null)`);
|
|
6541
|
+
B.line(`store ptr ${t}, ptr ${slot}`);
|
|
6542
|
+
}
|
|
6543
|
+
else {
|
|
6544
|
+
t = roundTrip();
|
|
6545
|
+
this.own({ name: t, type: e.type });
|
|
6546
|
+
this.emitPendingCheck();
|
|
6547
|
+
this.moveTemp({ name: t, type: e.type });
|
|
6548
|
+
B.line(`store ptr ${t}, ptr ${slot}`);
|
|
6549
|
+
}
|
|
6468
6550
|
this.releaseFrame(this.frames.pop());
|
|
6469
6551
|
B.br(lj);
|
|
6470
6552
|
B.startBlock(lj);
|
|
@@ -6677,7 +6759,7 @@ class LlEmitter {
|
|
|
6677
6759
|
d.push(` %r = call ptr %fn(${passed.join(", ")})`, ` %rn = icmp eq ptr %r, null`, ` br i1 %rn, label %snull, label %sok`, `snull:`, ` ret ptr null`, `sok:`, ` %j = call ptr @scr_jsval_from_str(ptr %r)`, ` call void @scr_str_release(ptr %r)`, ` ret ptr %j`);
|
|
6678
6760
|
break;
|
|
6679
6761
|
case "dyn":
|
|
6680
|
-
// A checked-dynamic (+1
|
|
6762
|
+
// A checked-dynamic (+1 dyn) result: deep copy into the engine
|
|
6681
6763
|
// (the jsMarshal dyn rule); NULL is the throw-path dummy.
|
|
6682
6764
|
this.declare(`declare ptr @scr_jsval_from_dyn(ptr)`);
|
|
6683
6765
|
this.declare(`declare void @scr_dyn_release(ptr)`);
|
|
@@ -6708,7 +6790,7 @@ class LlEmitter {
|
|
|
6708
6790
|
this.resolveThunkDefs.push(...d);
|
|
6709
6791
|
return sym;
|
|
6710
6792
|
}
|
|
6711
|
-
/** Loads a
|
|
6793
|
+
/** Loads a dyn node's kind tag (i32 at +8) — the dyn expression tests'
|
|
6712
6794
|
* shared read. */
|
|
6713
6795
|
dynKind(d) {
|
|
6714
6796
|
const B = this.B;
|
|
@@ -8537,7 +8619,7 @@ class LlEmitter {
|
|
|
8537
8619
|
// A dyn JOIN (the C helper's `surface` dyn arm): declared hits
|
|
8538
8620
|
// convert through the per-type toDyn walker (borrowed read → fresh
|
|
8539
8621
|
// +1 tree), a dyn-valued overflow hit passes through (+1 from the
|
|
8540
|
-
// map get), and a miss is JS's undefined — the
|
|
8622
|
+
// map get), and a miss is JS's undefined — the dyn singleton.
|
|
8541
8623
|
this.declare(`declare zeroext i1 @scr_str_eq(ptr, ptr)`);
|
|
8542
8624
|
for (const f of overflowOnly ? [] : shape.fields) {
|
|
8543
8625
|
const lit = this.internLiteral(f.name);
|
|
@@ -8615,7 +8697,7 @@ class LlEmitter {
|
|
|
8615
8697
|
B.br(join);
|
|
8616
8698
|
B.startBlock(ln);
|
|
8617
8699
|
}
|
|
8618
|
-
// The miss path: JS's undefined — the
|
|
8700
|
+
// The miss path: JS's undefined — the dyn singleton, retained.
|
|
8619
8701
|
this.declare(`declare ptr @scr_dyn_undefined()`);
|
|
8620
8702
|
this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
|
|
8621
8703
|
const u = B.tmp();
|
|
@@ -10544,9 +10626,11 @@ class LlEmitter {
|
|
|
10544
10626
|
B.line(`call void @${entry}(ptr ${args[0].name}, ptr ${args[1].name}, ptr @${adapter}, i1 ${args[2].name})`);
|
|
10545
10627
|
return { name: "", type: e.type };
|
|
10546
10628
|
}
|
|
10547
|
-
if (e.fn === "http.request" || e.fn === "http.requestCb" || e.fn === "http.requestUrl" || e.fn === "http.requestUrlCb"
|
|
10629
|
+
if (e.fn === "http.request" || e.fn === "http.requestCb" || e.fn === "http.requestUrl" || e.fn === "http.requestUrlCb" ||
|
|
10630
|
+
e.fn === "http.requestAgent" || e.fn === "http.requestAgentCb") {
|
|
10548
10631
|
const isUrl = e.fn.startsWith("http.requestUrl");
|
|
10549
|
-
const
|
|
10632
|
+
const isAgent = e.fn.startsWith("http.requestAgent");
|
|
10633
|
+
const cbIdx = isUrl ? 3 : isAgent ? 8 : 7;
|
|
10550
10634
|
const hasCb = e.fn.endsWith("Cb");
|
|
10551
10635
|
const args = e.args.map((a) => this.emitExpr(a));
|
|
10552
10636
|
let cb = "null";
|
|
@@ -10563,7 +10647,7 @@ class LlEmitter {
|
|
|
10563
10647
|
}
|
|
10564
10648
|
const head = args.slice(0, cbIdx);
|
|
10565
10649
|
const decls = head.map((a) => (this.llType(a.type) === "i1" ? "i1 zeroext" : this.llType(a.type)));
|
|
10566
|
-
const entry = isUrl ? "scr_http_request_url" : "scr_http_request";
|
|
10650
|
+
const entry = isUrl ? "scr_http_request_url" : isAgent ? "scr_http_request_agent" : "scr_http_request";
|
|
10567
10651
|
this.declare(`declare ptr @${entry}(${[...decls, "ptr", "ptr"].join(", ")})`);
|
|
10568
10652
|
const t = B.tmp();
|
|
10569
10653
|
B.line(`${t} = call ptr @${entry}(${[...head.map((a) => `${this.llType(a.type)} ${a.name}`), `ptr ${cb}`, `ptr ${adapter}`].join(", ")})`);
|
|
@@ -10598,6 +10682,13 @@ class LlEmitter {
|
|
|
10598
10682
|
B.line(`call void @scr_http_res_on_finish(ptr ${args[0].name}, ptr ${args[1].name})`);
|
|
10599
10683
|
return { name: "", type: e.type };
|
|
10600
10684
|
}
|
|
10685
|
+
if (e.fn === "net.sockOnFinish") {
|
|
10686
|
+
const args = e.args.map((a) => this.emitExpr(a));
|
|
10687
|
+
this.moveTemp(args[1]);
|
|
10688
|
+
this.declare(`declare void @scr_net_sock_on_finish(ptr, ptr)`);
|
|
10689
|
+
B.line(`call void @scr_net_sock_on_finish(ptr ${args[0].name}, ptr ${args[1].name})`);
|
|
10690
|
+
return { name: "", type: e.type };
|
|
10691
|
+
}
|
|
10601
10692
|
if (e.fn === "island.castFail") {
|
|
10602
10693
|
// The deferred boundary failure: the island value was evaluated
|
|
10603
10694
|
// (its side effects are real), the throw is unconditional
|