@scriptc/compiler 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/backend/emission/emit-exprs.js +136 -12
  2. package/dist/backend/emission/emit-exprs.js.map +1 -1
  3. package/dist/backend/emission/emit-walkers.js +29 -2
  4. package/dist/backend/emission/emit-walkers.js.map +1 -1
  5. package/dist/backend/llvm/dyn.d.ts +1 -0
  6. package/dist/backend/llvm/dyn.js +83 -1
  7. package/dist/backend/llvm/dyn.js.map +1 -1
  8. package/dist/backend/llvm/emitter.js +151 -9
  9. package/dist/backend/llvm/emitter.js.map +1 -1
  10. package/dist/diagnostics/diagnostic.d.ts +21 -7
  11. package/dist/diagnostics/diagnostic.js +35 -16
  12. package/dist/diagnostics/diagnostic.js.map +1 -1
  13. package/dist/diagnostics/render.js +8 -0
  14. package/dist/diagnostics/render.js.map +1 -1
  15. package/dist/frontend/lowering/lib-boundary.js +11 -1
  16. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  17. package/dist/frontend/lowering/lower-builtins.d.ts +13 -0
  18. package/dist/frontend/lowering/lower-builtins.js +146 -1
  19. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  20. package/dist/frontend/lowering/lower-calls.d.ts +41 -0
  21. package/dist/frontend/lowering/lower-calls.js +524 -10
  22. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  23. package/dist/frontend/lowering/lower-containers.d.ts +17 -0
  24. package/dist/frontend/lowering/lower-containers.js +193 -10
  25. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  26. package/dist/frontend/lowering/lower-dgram.js +92 -17
  27. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  28. package/dist/frontend/lowering/lower-exprs.js +179 -10
  29. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  30. package/dist/frontend/lowering/lower-modules.js +33 -2
  31. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  32. package/dist/frontend/lowering/lower-namespaces.d.ts +25 -11
  33. package/dist/frontend/lowering/lower-namespaces.js +50 -15
  34. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  35. package/dist/frontend/lowering/lower-server.js +211 -4
  36. package/dist/frontend/lowering/lower-server.js.map +1 -1
  37. package/dist/frontend/lowering/lower-stmts.d.ts +1 -5
  38. package/dist/frontend/lowering/lower-stmts.js +216 -7
  39. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  40. package/dist/frontend/lowering/lower-stream.js +65 -4
  41. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  42. package/dist/frontend/lowering/lowerer.d.ts +36 -1
  43. package/dist/frontend/lowering/lowerer.js +106 -3
  44. package/dist/frontend/lowering/lowerer.js.map +1 -1
  45. package/dist/frontend/types.d.ts +13 -0
  46. package/dist/frontend/types.js +84 -7
  47. package/dist/frontend/types.js.map +1 -1
  48. package/dist/index.js +20 -8
  49. package/dist/index.js.map +1 -1
  50. package/dist/ir/nodes.d.ts +99 -5
  51. package/dist/ir/nodes.js +44 -3
  52. package/dist/ir/nodes.js.map +1 -1
  53. package/dist/ir/validate.js +53 -3
  54. package/dist/ir/validate.js.map +1 -1
  55. package/dist/library/fence-eval.d.ts +77 -0
  56. package/dist/library/fence-eval.js +385 -0
  57. package/dist/library/fence-eval.js.map +1 -0
  58. package/dist/library/profile.d.ts +11 -1
  59. package/dist/library/profile.js +102 -18
  60. package/dist/library/profile.js.map +1 -1
  61. package/package.json +2 -2
  62. package/surface-manifest.json +1 -1
@@ -489,6 +489,28 @@ export function emitExpr(E, e) {
489
489
  E.currentFrame().push({ name, type: e.type });
490
490
  return { name, type: e.type };
491
491
  }
492
+ if (e.left.type.kind === "dyn") {
493
+ // `a ?? b` on a checked-dynamic left: the runtime kind decides
494
+ // (UNDEF/NULL take the default; a wrapped island value asks the
495
+ // engine); the right runs lazily in its branch (already dyn).
496
+ const l = E.emitExpr(e.left);
497
+ E.moveTemp(l);
498
+ const name = `sc_t${E.tempCounter++}`;
499
+ E.line(`${cDecl(e.type, name)};`);
500
+ E.line(`if (scr_dyn_is_nullish(${l.name})) {`);
501
+ E.indent++;
502
+ E.releaseValue(l.name, e.left.type);
503
+ E.emitBranchInto(name, e.right);
504
+ E.indent--;
505
+ E.line(`} else {`);
506
+ E.indent++;
507
+ E.line(`${name} = ${l.name};`);
508
+ E.indent--;
509
+ E.line(`}`);
510
+ if (isRefCounted(e.type))
511
+ E.currentFrame().push({ name, type: e.type });
512
+ return { name, type: e.type };
513
+ }
492
514
  if (e.left.type.kind !== "union")
493
515
  throw new Error("emitter bug: nullish left is not a union");
494
516
  const def = E.unionsById.get(e.left.type.unionId);
@@ -1589,6 +1611,13 @@ export function emitExpr(E, e) {
1589
1611
  }
1590
1612
  return E.newTemp(e.type, `${E.toDynHelper(v.type)}(${v.name})`);
1591
1613
  }
1614
+ case "dynFromJsval": {
1615
+ // Island value → DOM: the by-reference wrap (scr_dyn_from_jsval
1616
+ // retains the cell in; engine scalars normalize to native DOM
1617
+ // kinds at wrap time). Operand borrowed, result +1, never throws.
1618
+ const v = E.emitExpr(e.value);
1619
+ return E.newTemp(e.type, `scr_dyn_from_jsval(${v.name})`);
1620
+ }
1592
1621
  case "dynCall": {
1593
1622
  // Calling a dyn value: args are already dyn (the lowering boxed or
1594
1623
  // converted them); everything is BORROWED by scr_dyn_call — the
@@ -1867,6 +1896,9 @@ export function emitExpr(E, e) {
1867
1896
  case "dynHasKey": {
1868
1897
  // `"k" in pkg`: a kind-guarded presence answer, computed against
1869
1898
  // the literal key at compile time — no allocation, borrowed box.
1899
+ // An ISLAND-held receiver fences loudly (Node asks the real
1900
+ // engine object — `false` would be a silent wrong answer), so
1901
+ // the temp rides the fallible path.
1870
1902
  const d = E.emitExpr(e.value);
1871
1903
  const keyBytes = Buffer.from(e.key, "utf8");
1872
1904
  const keyLit = cStringLiteral(keyBytes);
@@ -1876,8 +1908,8 @@ export function emitExpr(E, e) {
1876
1908
  : /^(0|[1-9][0-9]*)$/.test(e.key) && Number(e.key) <= Number.MAX_SAFE_INTEGER
1877
1909
  ? `${d.name}->v.arr.len > ${e.key}`
1878
1910
  : "false";
1879
- const test = `(${d.name}->kind == SCR_DYN_OBJ ? (${objTest}) : ${d.name}->kind == SCR_DYN_ARR ? (${arrTest}) : false)`;
1880
- return E.newTemp(e.type, e.negated ? `!${test}` : test);
1911
+ const test = `(${d.name}->kind == SCR_DYN_OBJ ? (${objTest}) : ${d.name}->kind == SCR_DYN_ARR ? (${arrTest}) : scr_dyn_isl_fence(${d.name}, "'in'"))`;
1912
+ return E.fallibleTemp(e.type, e.negated ? `!${test}` : test);
1881
1913
  }
1882
1914
  case "dynScalarEq": {
1883
1915
  // dyn vs scalar strict equality: kind test + payload compare.
@@ -1899,26 +1931,40 @@ export function emitExpr(E, e) {
1899
1931
  }
1900
1932
  case "dynTest": {
1901
1933
  // A pure kind compare on the DOM node — borrowed; only the truthy
1902
- // form also reads a scalar payload.
1934
+ // form also reads a scalar payload. ISLAND-held nodes (the jsval
1935
+ // kind — engine objects/arrays/functions only, scalars normalize
1936
+ // at wrap time) route the tests that depend on the engine's
1937
+ // answer through the scr_dyn_isl_* helpers (false on every other
1938
+ // kind, so the calls stay unconditional); narrowing never changes
1939
+ // representation (SEMANTICS.md).
1903
1940
  const d = E.emitExpr(e.value);
1904
1941
  const test = e.test === "nullish"
1905
1942
  ? `(${d.name}->kind == SCR_DYN_UNDEF || ${d.name}->kind == SCR_DYN_NULL)`
1906
1943
  : e.test === "object"
1907
1944
  ? // `typeof v === "object"`: objects, arrays, bytes, native
1908
- // handles, promises, AND null.
1909
- `(${d.name}->kind == SCR_DYN_OBJ || ${d.name}->kind == SCR_DYN_ARR || ${d.name}->kind == SCR_DYN_BYTES || ${d.name}->kind == SCR_DYN_HANDLE || ${d.name}->kind == SCR_DYN_PROMISE || ${d.name}->kind == SCR_DYN_NULL)`
1945
+ // handles, promises, AND null — engine-held objects by the
1946
+ // engine's own typeof.
1947
+ `(${d.name}->kind == SCR_DYN_OBJ || ${d.name}->kind == SCR_DYN_ARR || ${d.name}->kind == SCR_DYN_BYTES || ${d.name}->kind == SCR_DYN_HANDLE || ${d.name}->kind == SCR_DYN_PROMISE || ${d.name}->kind == SCR_DYN_NULL || scr_dyn_isl_typeof_is(${d.name}, "object"))`
1910
1948
  : e.test === "truthy"
1911
1949
  ? // ToBoolean over the DOM: bool by value; number falsy for
1912
1950
  // 0, -0 (== 0 in C), and NaN (self-inequality); string
1913
1951
  // falsy when empty; obj/arr/bytes/func/handle always true;
1914
- // the remaining kinds (undefined, null) always false.
1915
- `(${d.name}->kind == SCR_DYN_BOOL ? ${d.name}->v.b : ${d.name}->kind == SCR_DYN_NUM ? (${d.name}->v.num == ${d.name}->v.num && ${d.name}->v.num != 0) : ${d.name}->kind == SCR_DYN_STR ? ${d.name}->v.str->len != 0 : (${d.name}->kind == SCR_DYN_OBJ || ${d.name}->kind == SCR_DYN_ARR || ${d.name}->kind == SCR_DYN_BYTES || ${d.name}->kind == SCR_DYN_FUNC || ${d.name}->kind == SCR_DYN_HANDLE || ${d.name}->kind == SCR_DYN_PROMISE))`
1952
+ // JSVAL through the runtime's routed arm (the bigint 0n
1953
+ // edge); the remaining kinds (undefined, null) always false.
1954
+ `(${d.name}->kind == SCR_DYN_BOOL ? ${d.name}->v.b : ${d.name}->kind == SCR_DYN_NUM ? (${d.name}->v.num == ${d.name}->v.num && ${d.name}->v.num != 0) : ${d.name}->kind == SCR_DYN_STR ? ${d.name}->v.str->len != 0 : ${d.name}->kind == SCR_DYN_JSVAL ? scr_dyn_truthy(${d.name}) : (${d.name}->kind == SCR_DYN_OBJ || ${d.name}->kind == SCR_DYN_ARR || ${d.name}->kind == SCR_DYN_BYTES || ${d.name}->kind == SCR_DYN_FUNC || ${d.name}->kind == SCR_DYN_HANDLE || ${d.name}->kind == SCR_DYN_PROMISE))`
1916
1955
  : e.test === "error"
1917
1956
  ? // `u instanceof Error`: the DOM's error encoding — an
1918
1957
  // object carrying the reserved "%error" marker key
1919
- // (built by caughtToDyn for Error payloads).
1920
- `(${d.name}->kind == SCR_DYN_OBJ && scr_dyn_obj_get(${d.name}, "%error", 6) != NULL)`
1921
- : `${d.name}->kind == ${{ string: "SCR_DYN_STR", number: "SCR_DYN_NUM", boolean: "SCR_DYN_BOOL", undefined: "SCR_DYN_UNDEF", null: "SCR_DYN_NULL", bytes: "SCR_DYN_BYTES", array: "SCR_DYN_ARR", function: "SCR_DYN_FUNC" }[e.test]}`;
1958
+ // (built by caughtToDyn for Error payloads) — or a real
1959
+ // engine Error held by reference.
1960
+ `((${d.name}->kind == SCR_DYN_OBJ && scr_dyn_obj_get(${d.name}, "%error", 6) != NULL) || scr_dyn_isl_is_error(${d.name}))`
1961
+ : e.test === "array"
1962
+ ? // Array.isArray: the DOM's array kind, or the engine's
1963
+ // own answer for an engine-held value.
1964
+ `(${d.name}->kind == SCR_DYN_ARR || scr_dyn_isl_is_array(${d.name}))`
1965
+ : e.test === "function"
1966
+ ? `(${d.name}->kind == SCR_DYN_FUNC || scr_dyn_isl_typeof_is(${d.name}, "function"))`
1967
+ : `${d.name}->kind == ${{ string: "SCR_DYN_STR", number: "SCR_DYN_NUM", boolean: "SCR_DYN_BOOL", undefined: "SCR_DYN_UNDEF", null: "SCR_DYN_NULL", bytes: "SCR_DYN_BYTES" }[e.test]}`;
1922
1968
  return E.newTemp(e.type, e.negated ? `!(${test})` : test);
1923
1969
  }
1924
1970
  case "unionEq": {
@@ -2188,13 +2234,20 @@ export function emitExpr(E, e) {
2188
2234
  // member retains the value in); throws Node's TypeErrors on
2189
2235
  // non-object receivers (may-throw seed set).
2190
2236
  return finish(`scr_dyn_key_set(${arg(0)}, ${arg(1)}, ${arg(2)})`);
2237
+ case "dyn.iterPack":
2238
+ // Destructuring pack over a dyn source: both borrowed, fresh
2239
+ // array +1; throws V8's destructuring TypeError on
2240
+ // non-iterable DOM kinds (may-throw seed set).
2241
+ return finish(`scr_dyn_iter_pack(${arg(0)}, ${arg(1)})`);
2191
2242
  case "dyn.typeof":
2192
2243
  // Bare typeof on a dyn value: the DOM kind's JS answer (+1).
2193
2244
  return finish(`scr_dyn_typeof(${arg(0)})`);
2194
2245
  case "dyn.toString":
2195
2246
  // Receiver-kind-dispatched toString (+1); throws Node's
2196
- // TypeError on undefined/null (may-throw seed set).
2197
- return finish(`scr_dyn_to_string(${arg(0)}, ${arg(1)})`);
2247
+ // TypeError on undefined/null and the "is not a function"
2248
+ // TypeError on null-prototype dictionaries (may-throw seed
2249
+ // set) — args[2] carries the call's source spelling.
2250
+ return finish(`scr_dyn_to_string_method(${arg(0)}, ${arg(1)}, ${arg(2)})`);
2198
2251
  case "fs.readFileSync":
2199
2252
  // args[1] is the (always-"utf8") encoding: evaluated for
2200
2253
  // JS-exact side-effect order, ignored by the runtime.
@@ -3041,6 +3094,15 @@ export function emitExpr(E, e) {
3041
3094
  case "net.connect":
3042
3095
  E.usesTimers = true; // a connecting/open socket holds the loop open
3043
3096
  return finish(`scr_net_connect(${arg(0)}, ${arg(1)}, NULL)`);
3097
+ case "net.connectAttempt":
3098
+ // The validated autoSelectFamilyAttemptTimeout form: Node's
3099
+ // range ladder runs first, the dial follows.
3100
+ E.usesTimers = true;
3101
+ return finish(`scr_net_connect_attempt(${arg(0)}, ${arg(1)}, ${arg(2)})`);
3102
+ case "net.connectOptsChk":
3103
+ // The runtime option-bag ladder (always throws — a validation
3104
+ // error or the trailing fence; the error.nodeThrow dummy).
3105
+ return finish(`(scr_net_connect_opts_chk(${arg(0)}, ${arg(1)}), ${isRefCounted(e.type) ? `(${cType(e.type).trim()})NULL` : "0"})`);
3044
3106
  case "net.connectCb": {
3045
3107
  E.usesTimers = true;
3046
3108
  const cb = args[2];
@@ -3143,6 +3205,9 @@ export function emitExpr(E, e) {
3143
3205
  case "dgram.sendBytes":
3144
3206
  E.usesTimers = true;
3145
3207
  return finish(`scr_dgram_send_bytes(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)})`);
3208
+ case "dgram.sendChk":
3209
+ E.usesTimers = true; // a validated send implicit-binds
3210
+ return finish(`scr_dgram_send_chk(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)}, ${arg(5)}, ${arg(6)})`);
3146
3211
  case "dgram.address": {
3147
3212
  // The AddressInfo record, built here from runtime parts (the
3148
3213
  // frontend pinned the {address, family, port} shape). The
@@ -3850,6 +3915,13 @@ export function emitExpr(E, e) {
3850
3915
  // SNI answer serves; bad material is the construction-time
3851
3916
  // print-and-die trap, like createServer's.
3852
3917
  return finish(`scr_tls_create_secure_context((const char *)${arg(0)}->data, ${arg(0)}->len, (const char *)${arg(1)}->data, ${arg(1)}->len)`);
3918
+ case "tls.createSecureContextDyn":
3919
+ // The runtime option-bag form: Node's typed validations, then
3920
+ // the pem walk (throws catchably on both ladders).
3921
+ return finish(`scr_tls_create_secure_context_dyn(${arg(0)})`);
3922
+ case "tls.caCertsChk":
3923
+ // Always throws (validation error or the trailing fence).
3924
+ return finish(`(scr_tls_ca_certs_chk(${arg(0)}, ${arg(1)}), ${isRefCounted(e.type) ? `(${cType(e.type).trim()})NULL` : "0"})`);
3853
3925
  case "http.serverOnRequest": {
3854
3926
  const cbT = e.args[1].type;
3855
3927
  if (cbT.kind !== "func")
@@ -4278,10 +4350,41 @@ export function emitExpr(E, e) {
4278
4350
  return finish(`scr_buffer_new_string_fail(${arg(0)})`);
4279
4351
  case "fs.toUnixTimestamp":
4280
4352
  return finish(`scr_fs_to_unix_timestamp(${arg(0)})`);
4353
+ // The fs argument-validation ladders: the always-throw Chk
4354
+ // forms (validation error or the trailing fence) take the
4355
+ // error.nodeThrow dummy pattern; mkdtempSyncChk and the lchmod
4356
+ // pair answer real results on a validated pass.
4357
+ case "fs.existsChk":
4358
+ E.usesTimers = true; // the scheduled answer holds the loop open
4359
+ return finish(`scr_fs_exists_async(${arg(0)}, ${arg(1)})`);
4360
+ case "fs.mkdtempChk":
4361
+ return finish(`(scr_fs_mkdtemp_chk(${arg(0)}, ${arg(1)}, ${arg(2)}), ${isRefCounted(e.type) ? `(${cType(e.type).trim()})NULL` : "0"})`);
4362
+ case "fs.mkdtempSyncChk":
4363
+ return finish(`scr_fs_mkdtemp_sync_chk(${arg(0)}, ${arg(1)}, ${arg(2)})`);
4364
+ case "fs.readFileChk":
4365
+ return finish(`(scr_fs_read_file_chk(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}), ${isRefCounted(e.type) ? `(${cType(e.type).trim()})NULL` : "0"})`);
4366
+ case "fs.opendirChk":
4367
+ return finish(`(scr_fs_opendir_chk(${arg(0)}, ${arg(1)}, ${arg(2)}), ${isRefCounted(e.type) ? `(${cType(e.type).trim()})NULL` : "0"})`);
4368
+ case "fs.watchFileChk":
4369
+ return finish(`(scr_fs_watch_file_chk(${arg(0)}, ${arg(1)}, ${arg(2)}), ${isRefCounted(e.type) ? `(${cType(e.type).trim()})NULL` : "0"})`);
4370
+ case "fs.lchmodChk":
4371
+ return finish(`(scr_fs_lchmod_chk(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}), ${isRefCounted(e.type) ? `(${cType(e.type).trim()})NULL` : "0"})`);
4372
+ case "fs.lchmodSyncChk":
4373
+ return finish(`scr_fs_lchmod_sync_chk(${arg(0)}, ${arg(1)})`);
4374
+ case "fsp.lchmodChk":
4375
+ return finish(`scr_fsp_lchmod_chk(${arg(0)}, ${arg(1)})`);
4376
+ case "fs.readChk":
4377
+ return finish(`(scr_fs_read_chk(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)}, ${arg(5)}), ${isRefCounted(e.type) ? `(${cType(e.type).trim()})NULL` : "0"})`);
4378
+ case "fs.streamOptsChk":
4379
+ return finish(`(scr_fs_stream_opts_chk(${arg(0)}, ${arg(1)}, ${arg(2)}), ${isRefCounted(e.type) ? `(${cType(e.type).trim()})NULL` : "0"})`);
4281
4380
  case "error.argTypeThrow":
4282
4381
  // Always throws with the runtime-rendered Received tail (the
4283
4382
  // error.nodeThrow dummy pattern). Borrows all three.
4284
4383
  return finish(`(scr_throw_arg_type(${arg(0)}, ${arg(1)}, ${arg(2)}), ${isRefCounted(e.type) ? `(${cType(e.type).trim()})NULL` : "0"})`);
4384
+ case "error.propTypeThrow":
4385
+ // The property flavor ("The \"options.x\" property must be
4386
+ // ...") — same always-throw dummy pattern.
4387
+ return finish(`(scr_throw_prop_type(${arg(0)}, ${arg(1)}, ${arg(2)}), ${isRefCounted(e.type) ? `(${cType(e.type).trim()})NULL` : "0"})`);
4285
4388
  // The fs Buffer forms (scr_bytes_io.c): the sync pair throws
4286
4389
  // like the utf8 forms (may-throw seed set); the promise form
4287
4390
  // rejects instead.
@@ -4706,6 +4809,27 @@ export function emitExpr(E, e) {
4706
4809
  // Object.assign over DOM values: own members copy, the target
4707
4810
  // returns (+1); non-object receivers throw like Node.
4708
4811
  return finish(`scr_dyn_assign(${arg(0)}, ${arg(1)})`);
4812
+ case "dyn.packPush":
4813
+ // Variadic Object.assign's source pack: a plain source
4814
+ // retains in (both args borrowed). Never throws.
4815
+ return finish(`scr_dyn_pack_push(${arg(0)}, ${arg(1)})`);
4816
+ case "dyn.packPushSpread":
4817
+ // A spread source flattens through the spread-call walk —
4818
+ // V8's exact TypeError texts (may-throw seed set); the string
4819
+ // spells the spread expression for the nullish form.
4820
+ return finish(`scr_dyn_pack_push_spread(${arg(0)}, ${arg(1)}, ${arg(2)})`);
4821
+ case "dyn.packPushSpreadIter":
4822
+ // The non-last/multi-spread positions: V8's iterator-protocol
4823
+ // failure texts describe the value (may-throw seed set).
4824
+ return finish(`scr_dyn_pack_push_spread_iter(${arg(0)}, ${arg(1)})`);
4825
+ case "dyn.assignAll":
4826
+ // The flattened pack copies onto the target left to right;
4827
+ // the target returns (+1). Nullish targets throw like Node.
4828
+ return finish(`scr_dyn_assign_all(${arg(0)}, ${arg(1)})`);
4829
+ case "dyn.objCreateNullProto":
4830
+ // Object.create(null): the fresh null-prototype dictionary
4831
+ // (+1). Never throws.
4832
+ return finish(`scr_dyn_new_obj_null_proto()`);
4709
4833
  case "dyn.hasOwn":
4710
4834
  // Object.hasOwn over a DOM receiver (throws on nullish, like
4711
4835
  // Node's ToObject).