@scriptc/cli-darwin-x64 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.
Files changed (180) hide show
  1. package/dist/THIRD_PARTY_NOTICES +1 -1
  2. package/dist/bin/scriptc +0 -0
  3. package/dist/bin/scriptc.json +1 -1
  4. package/dist/lib/declarations/scriptc-node-fallback.d.ts +99 -27
  5. package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
  6. package/dist/lib/llvm/package.json +1 -1
  7. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_array.o +0 -0
  8. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_assert.o +0 -0
  9. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_async.o +0 -0
  10. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bigint.o +0 -0
  11. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
  12. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_cycle.o +0 -0
  13. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_events.o +0 -0
  14. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_exception.o +0 -0
  15. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_file_handle.o +0 -0
  16. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_json.o +0 -0
  17. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_lib.o +0 -0
  18. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_map.o +0 -0
  19. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_node_builtin.o +0 -0
  20. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_regex.o +0 -0
  21. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_string.o +0 -0
  22. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_symbol.o +0 -0
  23. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_url.o +0 -0
  24. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_url_params.o +0 -0
  25. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_util_compare.o +0 -0
  26. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_util_style.o +0 -0
  27. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_array.o +0 -0
  28. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_assert.o +0 -0
  29. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_async.o +0 -0
  30. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bigint.o +0 -0
  31. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
  32. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_cycle.o +0 -0
  33. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_events.o +0 -0
  34. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_exception.o +0 -0
  35. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_file_handle.o +0 -0
  36. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_island.o +0 -0
  37. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
  38. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
  39. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_map.o +0 -0
  40. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_node_builtin.o +0 -0
  41. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
  42. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_string.o +0 -0
  43. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_symbol.o +0 -0
  44. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_url.o +0 -0
  45. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_url_params.o +0 -0
  46. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_util_compare.o +0 -0
  47. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_util_style.o +0 -0
  48. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_web.o +0 -0
  49. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_array.o +0 -0
  50. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_assert.o +0 -0
  51. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bigint.o +0 -0
  52. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
  53. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_cycle.o +0 -0
  54. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_exception.o +0 -0
  55. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
  56. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
  57. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_map.o +0 -0
  58. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_node_builtin.o +0 -0
  59. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
  60. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_string.o +0 -0
  61. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_symbol.o +0 -0
  62. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_url.o +0 -0
  63. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_url_params.o +0 -0
  64. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_array.o +0 -0
  65. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_assert.o +0 -0
  66. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bigint.o +0 -0
  67. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
  68. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_cycle.o +0 -0
  69. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_exception.o +0 -0
  70. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_json.o +0 -0
  71. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
  72. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_map.o +0 -0
  73. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_node_builtin.o +0 -0
  74. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
  75. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_string.o +0 -0
  76. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_symbol.o +0 -0
  77. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_url.o +0 -0
  78. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_url_params.o +0 -0
  79. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_array.o +0 -0
  80. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_assert.o +0 -0
  81. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bigint.o +0 -0
  82. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
  83. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_cycle.o +0 -0
  84. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_exception.o +0 -0
  85. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
  86. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
  87. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_map.o +0 -0
  88. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_node_builtin.o +0 -0
  89. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
  90. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_string.o +0 -0
  91. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_symbol.o +0 -0
  92. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_url.o +0 -0
  93. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_url_params.o +0 -0
  94. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_array.o +0 -0
  95. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_assert.o +0 -0
  96. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bigint.o +0 -0
  97. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
  98. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_cycle.o +0 -0
  99. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_exception.o +0 -0
  100. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
  101. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
  102. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_map.o +0 -0
  103. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_node_builtin.o +0 -0
  104. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
  105. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_string.o +0 -0
  106. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_symbol.o +0 -0
  107. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_url.o +0 -0
  108. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_url_params.o +0 -0
  109. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_array.o +0 -0
  110. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_assert.o +0 -0
  111. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_async.o +0 -0
  112. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bigint.o +0 -0
  113. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
  114. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_cycle.o +0 -0
  115. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_events.o +0 -0
  116. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_exception.o +0 -0
  117. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_file_handle.o +0 -0
  118. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_json.o +0 -0
  119. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_lib.o +0 -0
  120. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_map.o +0 -0
  121. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_node_builtin.o +0 -0
  122. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_regex.o +0 -0
  123. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_string.o +0 -0
  124. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_symbol.o +0 -0
  125. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_url.o +0 -0
  126. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_url_params.o +0 -0
  127. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_util_compare.o +0 -0
  128. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_util_style.o +0 -0
  129. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_array.o +0 -0
  130. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_assert.o +0 -0
  131. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_async.o +0 -0
  132. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bigint.o +0 -0
  133. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
  134. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_cycle.o +0 -0
  135. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_events.o +0 -0
  136. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_exception.o +0 -0
  137. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_file_handle.o +0 -0
  138. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_island.o +0 -0
  139. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
  140. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
  141. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_map.o +0 -0
  142. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_node_builtin.o +0 -0
  143. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
  144. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_string.o +0 -0
  145. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_symbol.o +0 -0
  146. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_url.o +0 -0
  147. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_url_params.o +0 -0
  148. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_util_compare.o +0 -0
  149. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_util_style.o +0 -0
  150. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_web.o +0 -0
  151. package/dist/lib/runtime-darwin-x64/package.json +1 -1
  152. package/dist/lib/runtime-darwin-x64/runtime-pack.json +399 -273
  153. package/dist/lib/runtime-sources/package.json +1 -1
  154. package/dist/lib/runtime-sources/src/scr_array.c +55 -34
  155. package/dist/lib/runtime-sources/src/scr_assert.c +26 -0
  156. package/dist/lib/runtime-sources/src/scr_async.c +44 -0
  157. package/dist/lib/runtime-sources/src/scr_bigint.c +15 -0
  158. package/dist/lib/runtime-sources/src/scr_bytes_io.c +305 -48
  159. package/dist/lib/runtime-sources/src/scr_cycle.c +84 -60
  160. package/dist/lib/runtime-sources/src/scr_events.c +9 -0
  161. package/dist/lib/runtime-sources/src/scr_exception.c +1 -0
  162. package/dist/lib/runtime-sources/src/scr_file_handle.c +11 -0
  163. package/dist/lib/runtime-sources/src/scr_island.c +1001 -417
  164. package/dist/lib/runtime-sources/src/scr_island_manifest.h +11 -7
  165. package/dist/lib/runtime-sources/src/scr_json.c +150 -13
  166. package/dist/lib/runtime-sources/src/scr_lib.c +424 -28
  167. package/dist/lib/runtime-sources/src/scr_map.c +236 -40
  168. package/dist/lib/runtime-sources/src/scr_node_builtin.c +78 -0
  169. package/dist/lib/runtime-sources/src/scr_regex.c +112 -8
  170. package/dist/lib/runtime-sources/src/scr_runtime.h +108 -14
  171. package/dist/lib/runtime-sources/src/scr_string.c +29 -0
  172. package/dist/lib/runtime-sources/src/scr_symbol.c +5 -0
  173. package/dist/lib/runtime-sources/src/scr_system_errors.h +573 -0
  174. package/dist/lib/runtime-sources/src/scr_url.c +515 -59
  175. package/dist/lib/runtime-sources/src/scr_url_internal.h +6 -0
  176. package/dist/lib/runtime-sources/src/scr_url_params.c +10 -0
  177. package/dist/lib/runtime-sources/src/scr_util_compare.c +222 -0
  178. package/dist/lib/runtime-sources/src/scr_util_style.c +337 -0
  179. package/dist/lib/runtime-sources/src/scr_web.c +720 -238
  180. package/package.json +1 -1
@@ -420,13 +420,6 @@ void scr_regex_reset_last_index(ScrRegex *re, double index) {
420
420
  re->last_index = index;
421
421
  }
422
422
 
423
- bool scr_regex_test(ScrRegex *re, ScrStr *s) {
424
- ScrArr *result = scr_regex_exec(s, re);
425
- bool matched = result != NULL;
426
- scr_arr_release(result);
427
- return matched;
428
- }
429
-
430
423
  static int scr_regex_start(ScrRegex *re, int len) {
431
424
  double index = re->last_index;
432
425
  if (isnan(index) || index <= 0) return 0;
@@ -434,6 +427,43 @@ static int scr_regex_start(ScrRegex *re, int len) {
434
427
  return (int)floor(index);
435
428
  }
436
429
 
430
+ /* A predicate needs only the match boundary, not the captured strings or
431
+ * result metadata. Short ASCII subjects already have the engine's one-byte
432
+ * representation. Bound that scan so a long mixed-text subject does not
433
+ * traverse an ASCII prefix twice before matching. Other subjects use exec's
434
+ * UTF-16 conversion. Register storage is bounded by alloc_count, not captures. */
435
+ bool scr_regex_test(ScrRegex *re, ScrStr *s) {
436
+ uint8_t *bc = scr_regex_bc(re);
437
+ bool ascii = s->len <= 256;
438
+ size_t i = 0;
439
+ for (; ascii && s->len - i >= sizeof(uint64_t); i += sizeof(uint64_t)) {
440
+ uint64_t word;
441
+ memcpy(&word, s->data + i, sizeof word);
442
+ if (word & UINT64_C(0x8080808080808080)) ascii = false;
443
+ }
444
+ for (; ascii && i < s->len; i++) {
445
+ if ((unsigned char)s->data[i] >= 0x80) ascii = false;
446
+ }
447
+ int len;
448
+ uint16_t *converted = ascii ? NULL : scr_to_utf16(s, &len);
449
+ const uint8_t *subject = ascii ? (const uint8_t *)s->data : (const uint8_t *)converted;
450
+ if (ascii) len = (int)s->len;
451
+ uint8_t *registers[32];
452
+ uint8_t **capture = lre_get_alloc_count(bc) <= 32 ? registers : scr_capture_alloc(bc);
453
+ bool stateful = (lre_get_flags(bc) & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) != 0;
454
+ int pos = stateful ? scr_regex_start(re, len) : 0;
455
+ int rc = pos < 0 ? 0 : lre_exec(capture, bc, subject, pos, len, ascii ? 0 : 1, lre_opaque());
456
+ if (rc < 0) {
457
+ fflush(stdout);
458
+ scr_trap("scriptc: regular expression execution failed\n");
459
+ }
460
+ if (stateful) re->last_index = rc == 1
461
+ ? (double)((capture[1] - subject) >> (ascii ? 0 : 1)) : 0;
462
+ if (capture != registers) free(capture);
463
+ free(converted);
464
+ return rc == 1;
465
+ }
466
+
437
467
  /* ── match ────────────────────────────────────────────────────────────── */
438
468
 
439
469
  /* re.exec(s): a fresh string[] of [whole match, ...captures], or NULL
@@ -719,6 +749,60 @@ ScrStr *scr_regex_replace(ScrStr *s, ScrRegex *re, ScrStr *rep) {
719
749
  return scr_replace_impl(s, re, rep);
720
750
  }
721
751
 
752
+
753
+ /* The pinned Node ANSI matcher derives from ansi-regex, copyright (c)
754
+ * Sindre Sorhus <sindresorhus@gmail.com>, used under the MIT license:
755
+ * Permission is hereby granted, free of charge, to any person obtaining a
756
+ * copy of this software and associated documentation files (the "Software"),
757
+ * to deal in the Software without restriction, including without limitation
758
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
759
+ * and/or sell copies of the Software, and to permit persons to whom the
760
+ * Software is furnished to do so, subject to the following conditions:
761
+ * The above copyright notice and this permission notice shall be included
762
+ * in all copies or substantial portions of the Software.
763
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
764
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
765
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
766
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
767
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
768
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
769
+ * DEALINGS IN THE SOFTWARE.
770
+ * Keep the pattern equivalent to Node v24.15.0 internal/util/inspect.js. */
771
+ #define SCR_VT_PATTERN "[\\u001B\\u009B][[\\]()#;?]*" \
772
+ "(?:(?:(?:(?:;[-a-zA-Z\\d\\/\\#&.:=?%@~_]+)*" \
773
+ "|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/\\#&.:=?%@~_]*)*)?" \
774
+ "(?:\\u0007|\\u001B\\u005C|\\u009C))" \
775
+ "|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"
776
+
777
+ ScrStr *scr_util_strip_vt(const ScrDyn *input) {
778
+ if (!input || input->kind != SCR_DYN_STR) {
779
+ scr_dyn_arg_type_fail("str", "of type string", input ? input : scr_dyn_undefined());
780
+ return NULL;
781
+ }
782
+ ScrStr *subject = input->v.str;
783
+ bool escape = false;
784
+ for (size_t i = 0; i < subject->len; i++) {
785
+ if (subject->data[i] == '\x1b' || ((unsigned char)subject->data[i] == 0xc2 &&
786
+ i + 1 < subject->len && (unsigned char)subject->data[i + 1] == 0x9b)) {
787
+ escape = true;
788
+ break;
789
+ }
790
+ }
791
+ if (!escape) return scr_str_retain(subject);
792
+ static const struct { size_t rc, len, cap; char data[sizeof SCR_VT_PATTERN]; }
793
+ source = { SIZE_MAX, sizeof SCR_VT_PATTERN - 1, sizeof SCR_VT_PATTERN - 1, SCR_VT_PATTERN };
794
+ static const struct { size_t rc, len, cap; char data[2]; }
795
+ flags = { SIZE_MAX, 1, 1, "g" };
796
+ static SCR_TL ScrRegex template = { SIZE_MAX, (ScrStr *)&source, (ScrStr *)&flags, NULL, 0, NULL };
797
+ ScrRegex *regex = scr_regex_literal(&template);
798
+ ScrStr *empty = scr_str_new("", 0);
799
+ ScrStr *result = scr_regex_replace(subject, regex, empty);
800
+ scr_str_release(empty);
801
+ scr_regex_release(regex);
802
+ return result;
803
+ }
804
+ #undef SCR_VT_PATTERN
805
+
722
806
  ScrStr *scr_regex_replace_all(ScrStr *s, ScrRegex *re, ScrStr *rep) {
723
807
  if (!(lre_get_flags(scr_regex_bc(re)) & LRE_FLAG_GLOBAL)) {
724
808
  /* Node's exact TypeError — a real instance now: catch bindings narrow
@@ -1058,6 +1142,17 @@ bool scr_assert_regex_err_test(ScrRegex *re, ScrError *err) {
1058
1142
  return matched;
1059
1143
  }
1060
1144
 
1145
+ bool scr_assert_regex_dyn_test(ScrRegex *re, ScrDyn *actual) {
1146
+ // String(symbol) accepts a direct Symbol; object conversion uses the
1147
+ // string hint, including Symbol.toPrimitive and custom Error formatters.
1148
+ ScrStr *str = actual->kind == SCR_DYN_SYMBOL
1149
+ ? scr_dyn_string_constructor(actual) : scr_util_to_usv_string(actual);
1150
+ if (!str) return false;
1151
+ bool matched = scr_assert_regex_hits(re, str);
1152
+ scr_str_release(str);
1153
+ return matched;
1154
+ }
1155
+
1061
1156
  /* The regex-valued shape slot (assert.throws(fn, {message: /re/})):
1062
1157
  * test the stashed actual key eagerly and store verdict + rendering, so
1063
1158
  * scr_assert.c's comparison and diff stay libregexp-free. An absent
@@ -1105,7 +1200,16 @@ ScrRegex *scr_regex_new(ScrStr *pattern, ScrStr *flags) {
1105
1200
  }
1106
1201
  re->rc = 1;
1107
1202
  re->source = pattern->len > 0 ? scr_str_retain(pattern) : scr_str_new("(?:)", 4);
1108
- re->flags = scr_str_retain(flags);
1203
+ /* Public flags use getter order, independently of constructor spelling.
1204
+ * Validate first so duplicates and invalid flags retain their errors. */
1205
+ char canonical[6];
1206
+ size_t flag_count = 0;
1207
+ const char *order = "gimsuy";
1208
+ for (unsigned i = 0; i < 6; i++) {
1209
+ if (seen_flags & (1u << i)) canonical[flag_count++] = order[i];
1210
+ }
1211
+ re->flags = flag_count == flags->len && memcmp(canonical, flags->data, flag_count) == 0
1212
+ ? scr_str_retain(flags) : scr_str_new(canonical, flag_count);
1109
1213
  /* Eager compile — the literal path stays lazy (its failure is an
1110
1214
  * abort; tsc already parsed those patterns). */
1111
1215
  int lre_flags = scr_lre_flags(re->flags);
@@ -297,7 +297,7 @@ void scr_library_bytes_out(ScrBytes *b, const uint8_t **out, size_t *out_len);
297
297
  * The collector is synchronous Bacon–Rajan trial deletion: a release that
298
298
  * leaves a candidate's rc above zero buffers it as a possible cycle root;
299
299
  * collection walks the buffer (markGray: trial-decrement internal edges;
300
- * scan: restore externally-referenced subgraphs; collectWhite: free the
300
+ * scan: restore externally-referenced subgraphs; gather: free the
301
301
  * dead cycle members, releasing only edges that LEAVE the white set).
302
302
  * It is GENERATIONAL: each header carries a generation, a pass names the
303
303
  * oldest one it will walk, and objects that survive a pass are promoted out
@@ -322,9 +322,9 @@ typedef void (*ScrTraceVisit)(void *child, void *ctx);
322
322
  typedef void (*ScrTraceFn)(void *obj, ScrTraceVisit visit, void *ctx);
323
323
  typedef void (*ScrCycFreeFn)(void *obj);
324
324
 
325
- /* DOOMED is WHITE that collectWhite has already gathered: it stops the
326
- * gather recursing twice, and distinguishes "about to be freed" from a
327
- * survivor for the re-buffering step (see scr_cycle.c). */
325
+ /* DOOMED identifies the gathered dead set during re-buffering and weak
326
+ * observer teardown. WHITE candidates may still become black when a later
327
+ * outside root restores them; only the settled white set becomes DOOMED. */
328
328
  enum {
329
329
  SCR_CYC_BLACK = 0, SCR_CYC_PURPLE = 1, SCR_CYC_GRAY = 2, SCR_CYC_WHITE = 3,
330
330
  SCR_CYC_DOOMED = 4
@@ -437,7 +437,7 @@ typedef struct ScrVt {
437
437
  *
438
438
  * cap is the usable byte capacity of data[] excluding the NUL (allocation
439
439
  * is sizeof(ScrStr) + cap + 1); cap == len for interned literals and plain
440
- * allocations. Spare capacity (cap > len) exists only on concat results so
440
+ * allocations. Builders and concat results may have spare capacity so
441
441
  * scr_str_concat can append in place when the left operand is uniquely
442
442
  * owned (rc == 1) — observable immutability is preserved: a string with
443
443
  * rc > 1 or rc == SIZE_MAX is never mutated.
@@ -454,7 +454,7 @@ ScrStr *scr_str_new(const char *bytes, size_t len); /* returns +1 */
454
454
  * malformed subsequences with U+FFFD. NULL with len == 0 is an empty span. */
455
455
  ScrStr *scr_str_from_utf8_lossy(const uint8_t *bytes, size_t len); /* +1 */
456
456
 
457
- /* Internal allocators for buffer builders (scr_json.c): a +1 string with
457
+ /* Internal allocators for buffer builders: a +1 string with
458
458
  * UNINITIALIZED data (the builder fills bytes, then len and the NUL), and
459
459
  * an rc==1-only realloc that grows capacity in place. Both keep the RC
460
460
  * audit's live count exact. */
@@ -470,6 +470,8 @@ void scr_str_release(ScrStr *s); /* NULL-tolerant (uninitialized locals) */
470
470
 
471
471
  /* Borrow both args, return +1. */
472
472
  ScrStr *scr_str_concat(ScrStr *a, ScrStr *b);
473
+ /* Borrow each part without mutation; return one independently owned result. */
474
+ ScrStr *scr_str_concat_parts(ScrStr *const *parts, size_t count);
473
475
 
474
476
  bool scr_str_eq(ScrStr *a, ScrStr *b);
475
477
 
@@ -818,6 +820,11 @@ ScrStr *scr_str_pad_end(ScrStr *s, double maxLength, ScrStr *fill);
818
820
  * both are no-ops on well-formed input). Borrow s; toWellFormed +1. */
819
821
  bool scr_str_is_well_formed(ScrStr *s);
820
822
  ScrStr *scr_str_to_well_formed(ScrStr *s);
823
+ /* Node text utilities: borrowed input, +1 result or NULL+pending. The VT
824
+ * helper lives in the optional regex unit; USV conversion uses native strings. */
825
+ ScrStr *scr_util_strip_vt(const struct ScrDyn *input);
826
+ ScrStr *scr_util_to_usv_string(const struct ScrDyn *input);
827
+ void scr_dyn_install_to_primitive_symbol(struct ScrDyn *key);
821
828
 
822
829
  /* RegExp.escape(s) — ES2025 EncodeForRegExpEscape per code point: leading
823
830
  * ASCII alphanumeric hex-escapes, SyntaxCharacters and '/' take a
@@ -911,11 +918,22 @@ void scr_qs_parse_into(ScrMap *out, const ScrStr *qs, const ScrStr *sep,
911
918
  * a fresh ParsedResults object whose `values` child has null prototype.
912
919
  * Borrows config; returns +1, or NULL with a Node-coded TypeError pending. */
913
920
  struct ScrDyn *scr_util_parse_args(const struct ScrDyn *config);
921
+ ScrStr *scr_util_style_text(const struct ScrDyn *format, const struct ScrDyn *text, const struct ScrDyn *options);
922
+
923
+ /* Node/libuv system error utilities. Arguments are checked without coercion;
924
+ * entries is a fresh array of [number, [name, message]] pairs (+1). */
925
+ ScrStr *scr_util_system_error_name(const struct ScrDyn *error);
926
+ ScrStr *scr_util_system_error_message(const struct ScrDyn *error);
927
+ struct ScrDyn *scr_util_system_error_entries(void);
914
928
 
915
929
  /* Node 24's dotenv grammar, shared by util.parseEnv and process.loadEnvFile.
916
930
  * Arguments are borrowed; parseEnv returns a fresh ordinary object (+1).
917
931
  * Validation and file failures leave a coded exception pending. */
918
932
  struct ScrDyn *scr_util_parse_env(const struct ScrDyn *content);
933
+ /* Checked primitives, ordinary records/arrays and byte views. Opaque native
934
+ * objects and accessor descriptors retain explicit catchable refusals. */
935
+ bool scr_util_is_deep_strict_equal(const struct ScrDyn *a, const struct ScrDyn *b,
936
+ const struct ScrDyn *skip_prototype);
919
937
  void scr_process_load_env_file(const struct ScrDyn *path);
920
938
 
921
939
  /* querystring.stringify — Node's stringify over a borrowed dyn value (the
@@ -1119,6 +1137,10 @@ double scr_arr_get_number(const ScrArr *a, double i);
1119
1137
  bool scr_arr_index_eq(const ScrArr *a, double i, const ScrArr *b, double j);
1120
1138
  bool scr_arr_get_bool(ScrArr *a, double i); /* trap missing/hole */
1121
1139
  void *scr_arr_get_ref(ScrArr *a, double i); /* trap missing/hole; +1 */
1140
+ /* Borrow a non-null reference element, or NULL for a hole/undefined/missing
1141
+ * property. Keep the array alive and retain before removing its element.
1142
+ * This read does not invoke retain callbacks or mutate runtime state. */
1143
+ void *scr_arr_peek_ref(const ScrArr *a, double i);
1122
1144
 
1123
1145
  /* i == len appends; the _ref variant releases the old element (when
1124
1146
  * replacing) and takes ownership of the new one. */
@@ -1301,10 +1323,10 @@ ScrArr *scr_regex_match_all_into(ScrStr *s, ScrRegex *re, ScrArr *indices);
1301
1323
  * are visited (they append), deleted entries are skipped (tombstones), and
1302
1324
  * a delete + re-add moves the key to the end (Node-verified).
1303
1325
  *
1304
- * Keys are identity references, string (content), or number with SameValueZero: NaN equals NaN
1305
- * (canonicalized before hashing) and -0 is normalized to +0 at insertion,
1306
- * exactly like JS (a stored -0 key reads back as +0). Hash is FNV-1a over
1307
- * the reference address, string bytes, or canonicalized f64 bit pattern.
1326
+ * Primitive keys compare by value and reference keys by identity. Numbers
1327
+ * use SameValueZero: NaN equals NaN and -0 is stored as +0. Union wrappers
1328
+ * are representations, never identities; their arm descriptors select
1329
+ * the primitive or reference comparison, including null and undefined.
1308
1330
  *
1309
1331
  * Values are one uniform kind per map (like ScrArr elements): f64, bool, or
1310
1332
  * a refcounted pointer whose RC entry points arrive as function pointers at
@@ -1331,13 +1353,17 @@ ScrArr *scr_regex_match_all_into(ScrStr *s, ScrRegex *re, ScrArr *indices);
1331
1353
  * DYN owns a checked-value box and compares its JavaScript value using
1332
1354
  * SameValueZero, including reference identity for object payloads.
1333
1355
  * These key kinds serve both Maps and Sets. */
1334
- typedef enum { SCR_MAP_KEY_F64, SCR_MAP_KEY_STR, SCR_MAP_KEY_REF, SCR_MAP_KEY_UNION_REF, SCR_MAP_KEY_DYN } ScrMapKeyKind;
1356
+ typedef enum {
1357
+ SCR_MAP_KEY_F64, SCR_MAP_KEY_STR, SCR_MAP_KEY_REF, SCR_MAP_KEY_UNION_REF, SCR_MAP_KEY_DYN,
1358
+ SCR_MAP_KEY_BIGINT, SCR_MAP_KEY_BOOL, SCR_MAP_KEY_UNION_VALUE,
1359
+ SCR_MAP_KEY_NULL, SCR_MAP_KEY_UNDEFINED /* tag-only union arms */
1360
+ } ScrMapKeyKind;
1335
1361
  typedef enum { SCR_MAP_VAL_F64, SCR_MAP_VAL_BOOL, SCR_MAP_VAL_REF } ScrMapValKind;
1336
1362
 
1337
1363
  typedef struct {
1338
1364
  uint64_t key; /* double bits (normalized), ScrStr* (owned), or ref ptr (owned) */
1339
1365
  uint64_t val; /* double bits, bool, or owned pointer */
1340
- bool live; /* false = tombstone (key/val already released) */
1366
+ uint64_t hash; /* nonzero cached hash; zero = tombstone (key/val released) */
1341
1367
  } ScrMapEntry;
1342
1368
 
1343
1369
  /* Checked views use the original storage. Slot converters borrow on reads
@@ -1360,7 +1386,7 @@ typedef struct ScrMap {
1360
1386
  void *(*val_retain)(void *);
1361
1387
  void (*val_release)(void *);
1362
1388
  ScrTraceFn val_trace;
1363
- /* SCR_MAP_KEY_REF, SCR_MAP_KEY_UNION_REF and SCR_MAP_KEY_DYN only. */
1389
+ /* Reference-represented keys, including bigint and union values. */
1364
1390
  void *(*key_retain)(void *);
1365
1391
  void (*key_release)(void *);
1366
1392
  ScrTraceFn key_trace;
@@ -1372,8 +1398,17 @@ typedef struct ScrMap {
1372
1398
  size_t *buckets; /* entry indices; SIZE_MAX = empty */
1373
1399
  size_t iter_depth; /* > 0: an iteration is active — no compaction */
1374
1400
  const ScrMapDynOps *dyn_ops;
1401
+ const uint8_t *union_keys; /* immutable key-kind table indexed by union tag */
1375
1402
  } ScrMap;
1376
1403
 
1404
+ /* Called once on a fresh UNION_VALUE collection, before its first insert. */
1405
+ void scr_map_union_keys(ScrMap *map, const uint8_t *kinds);
1406
+ /* Fresh shallow copies with compact storage and independent mutation.
1407
+ * keys_only selects a Set; checked views materialize their boxed values. */
1408
+ ScrMap *scr_map_clone(const ScrMap *source, bool keys_only);
1409
+ ScrMap *scr_map_clone_dyn(const ScrMap *source, bool keys_only);
1410
+ void scr_map_values_into(ScrMap *set, const ScrMap *source, bool checked);
1411
+
1377
1412
  void scr_map_dyn_attach(ScrMap *map, const ScrMapDynOps *ops);
1378
1413
  struct ScrDyn *scr_map_dyn_key(const ScrMap *map, double index);
1379
1414
  struct ScrDyn *scr_map_dyn_value(const ScrMap *map, double index);
@@ -1406,9 +1441,11 @@ double scr_map_size(const ScrMap *m); /* live entries (Map.size) */
1406
1441
  void scr_map_clear(ScrMap *m);
1407
1442
 
1408
1443
  bool scr_map_has_f64(const ScrMap *m, double key);
1444
+ bool scr_map_has_bool(const ScrMap *m, bool key);
1409
1445
  bool scr_map_has_str(const ScrMap *m, const ScrStr *key);
1410
1446
  bool scr_map_has_ref(const ScrMap *m, const void *key);
1411
1447
  bool scr_map_delete_f64(ScrMap *m, double key);
1448
+ bool scr_map_delete_bool(ScrMap *m, bool key);
1412
1449
  bool scr_map_delete_str(ScrMap *m, const ScrStr *key);
1413
1450
  bool scr_map_delete_ref(ScrMap *m, const void *key);
1414
1451
 
@@ -1418,6 +1455,9 @@ bool scr_map_delete_ref(ScrMap *m, const void *key);
1418
1455
  void scr_map_set_f64_f64(ScrMap *m, double key, double v);
1419
1456
  void scr_map_set_f64_bool(ScrMap *m, double key, bool v);
1420
1457
  void scr_map_set_f64_ref(ScrMap *m, double key, void *v);
1458
+ void scr_map_set_bool_f64(ScrMap *m, bool key, double v);
1459
+ void scr_map_set_bool_bool(ScrMap *m, bool key, bool v);
1460
+ void scr_map_set_bool_ref(ScrMap *m, bool key, void *v);
1421
1461
  void scr_map_set_str_f64(ScrMap *m, ScrStr *key, double v);
1422
1462
  void scr_map_set_str_bool(ScrMap *m, ScrStr *key, bool v);
1423
1463
  void scr_map_set_str_ref(ScrMap *m, ScrStr *key, void *v);
@@ -1432,6 +1472,9 @@ void scr_map_set_ref_ref(ScrMap *m, void *key, void *v);
1432
1472
  bool scr_map_get_f64_f64(const ScrMap *m, double key, double *out);
1433
1473
  bool scr_map_get_f64_bool(const ScrMap *m, double key, bool *out);
1434
1474
  void *scr_map_get_f64_ref(const ScrMap *m, double key);
1475
+ bool scr_map_get_bool_f64(const ScrMap *m, bool key, double *out);
1476
+ bool scr_map_get_bool_bool(const ScrMap *m, bool key, bool *out);
1477
+ void *scr_map_get_bool_ref(const ScrMap *m, bool key);
1435
1478
  bool scr_map_get_str_f64(const ScrMap *m, const ScrStr *key, double *out);
1436
1479
  bool scr_map_get_str_bool(const ScrMap *m, const ScrStr *key, bool *out);
1437
1480
  void *scr_map_get_str_ref(const ScrMap *m, const ScrStr *key);
@@ -1447,6 +1490,7 @@ void *scr_map_get_ref_ref(const ScrMap *m, const void *key);
1447
1490
  double scr_map_iter_count(const ScrMap *m); /* entries incl. tombstones */
1448
1491
  bool scr_map_iter_live(const ScrMap *m, double i);
1449
1492
  double scr_map_iter_key_f64(const ScrMap *m, double i);
1493
+ bool scr_map_iter_key_bool(const ScrMap *m, double i);
1450
1494
  ScrStr *scr_map_iter_key_str(const ScrMap *m, double i); /* +1 */
1451
1495
  void *scr_map_iter_key_ref(const ScrMap *m, double i); /* +1 */
1452
1496
  double scr_map_iter_val_f64(const ScrMap *m, double i);
@@ -1464,8 +1508,10 @@ void scr_set_add_all(ScrMap *set, ScrArr *values);
1464
1508
  /* `[...set]` (scr_lib.c): the live entries drained into a fresh +1 elem[]
1465
1509
  * in insertion order. Borrows the set; string elements retained in. */
1466
1510
  ScrArr *scr_set_to_arr_f64(const ScrMap *s);
1511
+ ScrArr *scr_set_to_arr_bool(const ScrMap *s);
1467
1512
  ScrArr *scr_set_to_arr_str(const ScrMap *s);
1468
1513
  ScrArr *scr_set_to_arr_ref(const ScrMap *s);
1514
+ ScrArr *scr_set_to_arr_dyn(const ScrMap *s);
1469
1515
 
1470
1516
  /* REF-element Set construction: a set-shaped map whose keys are refcounted
1471
1517
  * pointers under identity hashing (see SCR_MAP_KEY_REF above). The element
@@ -2615,7 +2661,29 @@ void scr_fs_fchmod(double fd, double mode);
2615
2661
  void scr_fs_fsync(double fd);
2616
2662
  void scr_fs_fdatasync(double fd);
2617
2663
  void scr_fs_ftruncate(double fd, double length);
2664
+ void scr_fs_utimes(ScrStr *path, double atime, double mtime, bool nofollow);
2665
+ void scr_fs_invalid_path(const ScrDyn *value, const ScrStr *path);
2666
+ void scr_fs_invalid_named_path(const ScrDyn *value, const ScrStr *path, const char *name);
2667
+ void scr_fs_futimes(double fd, double atime, double mtime);
2618
2668
  void scr_fs_link(ScrStr *source, ScrStr *dest);
2669
+ void scr_fs_symlink(ScrStr *target, ScrStr *destination, int kind);
2670
+ int scr_fs_symlink_infer(ScrStr *absolute);
2671
+ ScrBytes *scr_fs_readlink_bytes(ScrStr *path);
2672
+ void scr_fs_link_checked(const ScrDyn *existing, const ScrDyn *destination);
2673
+ void scr_fs_symlink_checked(const ScrDyn *target, const ScrDyn *destination, const ScrDyn *type);
2674
+ void scr_fs_symlink_promise_checked(const ScrDyn *target, const ScrDyn *destination, const ScrDyn *type);
2675
+ ScrDyn *scr_fs_readlink_checked(const ScrDyn *path, const ScrDyn *options, bool promise);
2676
+ ScrDyn *scr_fs_readlink_dyn(const ScrDyn *path, const ScrDyn *options);
2677
+ ScrDyn *scr_fs_statfs(ScrStr *path, bool bigint);
2678
+ ScrDyn *scr_fs_statfs_checked(const ScrDyn *path, const ScrDyn *options);
2679
+ ScrPromise *scr_fsp_statfs(const ScrDyn *path, const ScrDyn *options);
2680
+ ScrStr *scr_fs_readlink_str(const ScrDyn *path, const ScrDyn *options);
2681
+ ScrBytes *scr_fs_readlink_buffer(const ScrDyn *path, const ScrDyn *options);
2682
+ ScrPromise *scr_fsp_link(const ScrDyn *existing, const ScrDyn *destination);
2683
+ ScrPromise *scr_fsp_symlink(const ScrDyn *target, const ScrDyn *destination, const ScrDyn *type);
2684
+ ScrPromise *scr_fsp_readlink_dyn(const ScrDyn *path, const ScrDyn *options);
2685
+ ScrPromise *scr_fsp_readlink_str(const ScrDyn *path, const ScrDyn *options);
2686
+ ScrPromise *scr_fsp_readlink_buffer(const ScrDyn *path, const ScrDyn *options);
2619
2687
  ScrStats *scr_stats_retain(ScrStats *s);
2620
2688
  void scr_stats_release(ScrStats *s);
2621
2689
  void *scr_stats_retain_v(void *p);
@@ -2647,6 +2715,8 @@ ScrPromise *scr_fsp_mkdir_recursive(ScrStr *path);
2647
2715
  ScrPromise *scr_fsp_mkdir_recursive_mode(ScrStr *path, double mode);
2648
2716
  ScrPromise *scr_fsp_unlink(ScrStr *path);
2649
2717
  ScrPromise *scr_fsp_chmod(ScrStr *path, double mode);
2718
+ ScrPromise *scr_fsp_utimes(const ScrDyn *path, const ScrDyn *atime, const ScrDyn *mtime);
2719
+ ScrPromise *scr_fsp_lutimes(const ScrDyn *path, const ScrDyn *atime, const ScrDyn *mtime);
2650
2720
  ScrPromise *scr_fsp_readdir(ScrStr *path);
2651
2721
  ScrPromise *scr_fsp_rm(ScrStr *path);
2652
2722
  ScrPromise *scr_fsp_stat(ScrStr *path);
@@ -2655,6 +2725,7 @@ ScrPromise *scr_fsp_lstat(ScrStr *path);
2655
2725
  ScrPromise *scr_fsp_rename(ScrStr *oldpath, ScrStr *newpath);
2656
2726
  ScrPromise *scr_fsp_open(ScrStr *path, ScrStr *flags, double mode);
2657
2727
  ScrPromise *scr_file_handle_close_promise(ScrFileHandle *h);
2728
+ ScrPromise *scr_file_handle_utimes_promise(ScrFileHandle *h, const ScrDyn *atime, const ScrDyn *mtime);
2658
2729
  ScrPromise *scr_file_handle_read_file_promise(ScrFileHandle *h, ScrStr *encoding);
2659
2730
  ScrPromise *scr_file_handle_read_file_bytes_promise(ScrFileHandle *h, ScrStr *encoding);
2660
2731
  ScrPromise *scr_file_handle_write_file_promise(ScrFileHandle *h, ScrStr *data, ScrStr *encoding);
@@ -3203,7 +3274,7 @@ double scr_fs_read_zero(double fd, double position);
3203
3274
  void scr_fs_close(double fd);
3204
3275
 
3205
3276
  /* ── WHATWG URL (scr_url.c) ──────────────────────────────────────────
3206
- * An immutable, refcounted URL value, parsed once at construction. The
3277
+ * A mutable, refcounted URL value with selected component setters. The
3207
3278
  * parser covers the WHATWG algorithm's common ground exactly (see
3208
3279
  * scr_url.c's header comment for the covered surface and the documented
3209
3280
  * divergences: no IDNA, no IPv6, opaque paths verbatim).
@@ -3235,6 +3306,9 @@ ScrStr *scr_url_hostname(ScrUrl *u); /* +1 port-less host ("" when none) */
3235
3306
  ScrStr *scr_url_port(ScrUrl *u); /* +1 "" or normalized non-default port */
3236
3307
  ScrStr *scr_url_pathname(ScrUrl *u); /* +1 */
3237
3308
  ScrStr *scr_url_href(ScrUrl *u); /* +1; also toString() */
3309
+ void scr_url_set(ScrUrl *u, ScrStr *field, ScrStr *value); /* borrowed; href may throw */
3310
+ bool scr_url_set_component(ScrUrl *u, ScrStr *field, ScrStr *value); /* borrowed; false for ignored writes */
3311
+ void scr_url_set_checked(ScrUrl *u, ScrStr *field, const ScrDyn *value); /* borrowed; conversion may throw */
3238
3312
  ScrStr *scr_url_to_path(ScrUrl *u); /* +1, or throws */
3239
3313
  ScrStr *scr_url_str_to_path(ScrStr *s); /* +1, or throws */
3240
3314
  ScrUrl *scr_url_from_path(ScrStr *path); /* +1; throws on win32 UNC malformations only */
@@ -3348,6 +3422,7 @@ ScrBigInt *scr_bigint_xor(ScrBigInt *a, ScrBigInt *b);
3348
3422
  ScrBigInt *scr_bigint_shl(ScrBigInt *a, ScrBigInt *count);
3349
3423
  ScrBigInt *scr_bigint_shr(ScrBigInt *a, ScrBigInt *count);
3350
3424
  bool scr_bigint_eq(ScrBigInt *a, ScrBigInt *b);
3425
+ uint64_t scr_bigint_hash(const ScrBigInt *value); /* normalized value, no allocation */
3351
3426
  bool scr_bigint_eq_string(ScrBigInt *a, ScrStr *b); /* StringToBigInt failure is false */
3352
3427
  double scr_bigint_cmp_string(ScrBigInt *a, ScrStr *b); /* 2 = invalid StringToBigInt */
3353
3428
  double scr_bigint_cmp_f64(ScrBigInt *a, ScrBigInt *b); /* -1, 0, 1 */
@@ -3928,6 +4003,8 @@ ScrBytes *scr_dyn_bytes_unbox(const ScrDyn *d);
3928
4003
  /* Exact numeric typed-array brand; elem is a ScrBytesElem tag. */
3929
4004
  bool scr_dyn_bytes_is(const ScrDyn *d, int elem);
3930
4005
  bool scr_dyn_typed_array_is(const ScrDyn *d, int elem);
4006
+ bool scr_dyn_util_type_is(const ScrDyn *value, const ScrStr *probe);
4007
+ ScrDyn *scr_dyn_util_type_value(const ScrDyn *value, const ScrStr *probe);
3931
4008
  void scr_dyn_arr_push(ScrDyn *arr, ScrDyn *item);
3932
4009
  /* Spread completion for a runtime-arity argument list (`f(...xs)` in the
3933
4010
  * checked-dynamic tier): flattens `src` into `arr` per JS's spread over the
@@ -4133,6 +4210,9 @@ ScrMap *scr_dyn_native_map_check(const ScrDyn *value, const ScrDynPath *path);
4133
4210
  bool scr_dyn_native_collection_is(const ScrDyn *value, int map, const char *type);
4134
4211
  ScrMap *scr_dyn_native_collection_check(const ScrDyn *value, int map, const char *type, const ScrDynPath *path);
4135
4212
  ScrStr *scr_url_checked_to_path(const ScrDyn *value);
4213
+ ScrStr *scr_url_checked_to_path_options(const ScrDyn *value, const ScrDyn *options);
4214
+ ScrBytes *scr_url_checked_to_path_buffer(const ScrDyn *value, const ScrDyn *options);
4215
+ ScrUrl *scr_url_checked_from_path(const ScrDyn *value, const ScrDyn *options);
4136
4216
  ScrUrl *scr_dyn_native_url_check(const ScrDyn *value, const ScrDynPath *path);
4137
4217
  ScrRegex *scr_dyn_native_regex_check(const ScrDyn *value, const ScrDynPath *path);
4138
4218
  ScrClassObj *scr_dyn_class_check(const ScrDyn *value, const char *type_key, const ScrDynPath *path);
@@ -4194,6 +4274,8 @@ ScrDyn *scr_global_native(ScrArr *known);
4194
4274
  ScrDyn *scr_global_native_init(ScrArr *known, ScrDyn *(*console_get)(void));
4195
4275
  ScrDyn *scr_console_native(void);
4196
4276
  ScrDyn *scr_process_stdio(double fd);
4277
+ bool scr_dyn_process_stdio_is(const ScrDyn *value);
4278
+ double scr_dyn_process_stdio_fd(const ScrDyn *value, const ScrDynPath *path);
4197
4279
 
4198
4280
  void scr_dyn_handle_install(ScrDynHandleTag tag, const ScrDynHandleOps *ops);
4199
4281
  void scr_file_handle_dyn_install(void);
@@ -4298,6 +4380,7 @@ typedef struct ScrDynJsvalOps {
4298
4380
  ScrDyn *(*iter_drain)(ScrJsval *cell, bool spread, const ScrStr *spell);
4299
4381
  ScrDyn *(*iterator)(ScrJsval *cell, const ScrStr *spell, bool array_from);
4300
4382
  ScrDyn *(*iter_n)(ScrJsval *cell, double count);
4383
+ bool (*type_probe)(ScrJsval *cell, const ScrStr *probe); /* internal brand; no property access */
4301
4384
  } ScrDynJsvalOps;
4302
4385
 
4303
4386
  /* The allocator view the gated constructor uses (installs the ops);
@@ -5151,6 +5234,8 @@ typedef struct ScrIslandEdge {
5151
5234
  * after scr_lib_init. */
5152
5235
  void scr_island_modules(const ScrIslandModule *mods, size_t nmods,
5153
5236
  const ScrIslandEdge *edges, size_t nedges);
5237
+ /* The logical source entry, independent of the installed binary path. */
5238
+ void scr_island_entry_module(const char *filename);
5154
5239
 
5155
5240
  /* The inflater for compressed embedded module text (raw DEFLATE, exact
5156
5241
  * inflated size known from the table row). The emitted main installs
@@ -5950,6 +6035,10 @@ ScrBytes *scr_buffer_new_string_fail(const ScrDyn *got);
5950
6035
  * numbers coerce (negatives answer now/1000), the rest throw Node's
5951
6036
  * ERR_INVALID_ARG_TYPE. Borrowed. */
5952
6037
  double scr_fs_to_unix_timestamp(const ScrDyn *t);
6038
+ double scr_fs_timestamp_value(const ScrDyn *t, const char *name);
6039
+ void scr_fs_utimes_checked(const ScrDyn *path, const ScrDyn *atime, const ScrDyn *mtime);
6040
+ void scr_fs_lutimes_checked(const ScrDyn *path, const ScrDyn *atime, const ScrDyn *mtime);
6041
+ void scr_fs_futimes_checked(const ScrDyn *fd, const ScrDyn *atime, const ScrDyn *mtime);
5953
6042
  /* The fs argument-validation ladders (the fs.*Chk libCalls): Node-order
5954
6043
  * validation over dyn values with Node's exact typed errors; a pass
5955
6044
  * meets the real operation where one exists (mkdtempSync, macOS
@@ -7364,6 +7453,11 @@ void scr_assert_shape_end(ScrStr *msg, bool has_msg);
7364
7453
  /* assert.doesNotReject whose rejection MATCHED (or had no expected):
7365
7454
  * "Got unwanted rejection[: message].\nActual message: \"...\"". */
7366
7455
  void scr_assert_unwanted_rejection(ScrError *err, ScrStr *msg, bool has_msg);
7456
+ /* No-error assertions share Node's unwanted-exception/rejection message.
7457
+ * The frontend reads and coerces actual?.message, preserving getter throws. */
7458
+ void scr_assert_unwanted_error(ScrStr *actual_message, bool rejection, ScrStr *msg, bool has_msg);
7459
+ bool scr_assert_no_error_predicate(ScrDyn *predicate, ScrDyn *actual);
7460
+ bool scr_assert_regex_dyn_test(ScrRegex *re, ScrDyn *actual);
7367
7461
  /* assert.ifError over the static surface: throws for ANY value the
7368
7462
  * frontend routes here (Node: everything but null/undefined, falsy
7369
7463
  * included) — "ifError got unwanted exception: " + the error's message
@@ -271,6 +271,7 @@ ScrStr *scr_str_alloc_raw(size_t len, size_t cap) {
271
271
  }
272
272
 
273
273
  ScrStr *scr_str_regrow(ScrStr *s, size_t newcap) {
274
+ if (newcap < s->len || newcap > SIZE_MAX - sizeof(ScrStr) - 1) scr_oom();
274
275
  scr_short_forget(s);
275
276
  scr_sidx_purge(s); /* realloc may move; the old address may be recycled */
276
277
  ScrStr *r = realloc(s, sizeof(ScrStr) + newcap + 1);
@@ -300,6 +301,8 @@ void scr_str_release(ScrStr *s) {
300
301
  }
301
302
 
302
303
  ScrStr *scr_str_concat(ScrStr *a, ScrStr *b) {
304
+ if (a->len == 0) return scr_str_retain(b);
305
+ if (b->len == 0) return scr_str_retain(a);
303
306
  if (a->len > SIZE_MAX - b->len - sizeof(ScrStr) - 1) scr_oom();
304
307
  size_t newlen = a->len + b->len;
305
308
  /* In-place append: a is uniquely owned by the caller's borrow (rc == 1 —
@@ -343,6 +346,32 @@ ScrStr *scr_str_concat(ScrStr *a, ScrStr *b) {
343
346
  return s;
344
347
  }
345
348
 
349
+ ScrStr *scr_str_concat_parts(ScrStr *const *parts, size_t count) {
350
+ const size_t limit = SIZE_MAX - sizeof(ScrStr) - 1;
351
+ size_t len = 0;
352
+ ScrStr *only = NULL;
353
+ size_t nonempty = 0;
354
+ for (size_t i = 0; i < count; i++) {
355
+ const size_t n = parts[i]->len;
356
+ if (n > limit - len) scr_oom();
357
+ len += n;
358
+ if (n != 0) {
359
+ only = parts[i];
360
+ nonempty++;
361
+ }
362
+ }
363
+ if (nonempty == 1) return scr_str_retain(only);
364
+ ScrStr *out = scr_str_alloc_raw(len, len);
365
+ size_t offset = 0;
366
+ for (size_t i = 0; i < count; i++) {
367
+ const ScrStr *part = parts[i];
368
+ memcpy(out->data + offset, part->data, part->len);
369
+ offset += part->len;
370
+ }
371
+ out->data[len] = '\0';
372
+ return out;
373
+ }
374
+
346
375
  bool scr_str_eq(ScrStr *a, ScrStr *b) {
347
376
  return a == b || (a->len == b->len && memcmp(a->data, b->data, a->len) == 0);
348
377
  }
@@ -90,6 +90,11 @@ ScrSym *scr_sym_well_known(ScrStr *name) {
90
90
  scr_dyn_install_async_iterator_symbol(key);
91
91
  scr_dyn_release(key);
92
92
  }
93
+ if (name->len == 11 && !memcmp(name->data, "toPrimitive", 11)) {
94
+ ScrDyn *key = scr_dyn_new_symbol(symbol);
95
+ scr_dyn_install_to_primitive_symbol(key);
96
+ scr_dyn_release(key);
97
+ }
93
98
  return symbol;
94
99
  }
95
100