@scriptc/cli-darwin-x64 0.2.4 → 0.2.5

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 (123) 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 +915 -215
  5. package/dist/lib/declarations/scriptc-overrides.d.ts +5 -1
  6. package/dist/lib/declarations/scriptc.d.ts +22 -2
  7. package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
  8. package/dist/lib/llvm/package.json +1 -1
  9. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_array.o +0 -0
  10. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes.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_copying.o +0 -0
  13. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_json.o +0 -0
  14. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_lib.o +0 -0
  15. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_map.o +0 -0
  16. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_number.o +0 -0
  17. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_regex.o +0 -0
  18. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_string.o +0 -0
  19. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_util_compare.o +0 -0
  20. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_array.o +0 -0
  21. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
  22. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
  23. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_copying.o +0 -0
  24. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
  25. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
  26. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_map.o +0 -0
  27. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_number.o +0 -0
  28. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
  29. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_string.o +0 -0
  30. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_util_compare.o +0 -0
  31. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  32. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  33. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_array.o +0 -0
  34. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
  35. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
  36. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_copying.o +0 -0
  37. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
  38. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
  39. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_map.o +0 -0
  40. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_number.o +0 -0
  41. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
  42. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_string.o +0 -0
  43. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  44. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_array.o +0 -0
  45. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
  46. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
  47. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_copying.o +0 -0
  48. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_json.o +0 -0
  49. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
  50. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_map.o +0 -0
  51. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_number.o +0 -0
  52. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
  53. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_string.o +0 -0
  54. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  55. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_array.o +0 -0
  56. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
  57. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
  58. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_copying.o +0 -0
  59. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
  60. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
  61. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_map.o +0 -0
  62. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_number.o +0 -0
  63. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
  64. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_string.o +0 -0
  65. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  66. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_array.o +0 -0
  67. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
  68. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
  69. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_copying.o +0 -0
  70. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
  71. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
  72. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_map.o +0 -0
  73. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_number.o +0 -0
  74. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
  75. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_string.o +0 -0
  76. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  77. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_array.o +0 -0
  78. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes.o +0 -0
  79. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
  80. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_copying.o +0 -0
  81. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_json.o +0 -0
  82. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_lib.o +0 -0
  83. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_map.o +0 -0
  84. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_number.o +0 -0
  85. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_regex.o +0 -0
  86. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_string.o +0 -0
  87. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_util_compare.o +0 -0
  88. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_array.o +0 -0
  89. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
  90. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
  91. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_copying.o +0 -0
  92. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
  93. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
  94. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_map.o +0 -0
  95. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_number.o +0 -0
  96. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
  97. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_string.o +0 -0
  98. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_util_compare.o +0 -0
  99. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  100. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  101. package/dist/lib/runtime-darwin-x64/package.json +1 -1
  102. package/dist/lib/runtime-darwin-x64/runtime-pack.json +183 -183
  103. package/dist/lib/runtime-sources/package.json +1 -1
  104. package/dist/lib/runtime-sources/src/scr_array.c +267 -6
  105. package/dist/lib/runtime-sources/src/scr_async.test.ts +16 -6
  106. package/dist/lib/runtime-sources/src/scr_bytes.c +437 -216
  107. package/dist/lib/runtime-sources/src/scr_bytes.test.c +85 -0
  108. package/dist/lib/runtime-sources/src/scr_bytes_io.c +0 -34
  109. package/dist/lib/runtime-sources/src/scr_copying.c +12 -2
  110. package/dist/lib/runtime-sources/src/scr_json.c +479 -150
  111. package/dist/lib/runtime-sources/src/scr_json.test.c +323 -1
  112. package/dist/lib/runtime-sources/src/scr_json.test.ts +58 -25
  113. package/dist/lib/runtime-sources/src/scr_key.h +68 -0
  114. package/dist/lib/runtime-sources/src/scr_lib.c +132 -73
  115. package/dist/lib/runtime-sources/src/scr_map.c +50 -66
  116. package/dist/lib/runtime-sources/src/scr_number.c +2 -4
  117. package/dist/lib/runtime-sources/src/scr_numeric.h +25 -0
  118. package/dist/lib/runtime-sources/src/scr_numeric.test.c +37 -0
  119. package/dist/lib/runtime-sources/src/scr_numeric.test.ts +33 -0
  120. package/dist/lib/runtime-sources/src/scr_regex.c +238 -167
  121. package/dist/lib/runtime-sources/src/scr_runtime.h +37 -6
  122. package/dist/lib/runtime-sources/src/scr_string.c +155 -42
  123. package/package.json +1 -1
@@ -1032,7 +1032,7 @@ typedef struct ScrArr {
1032
1032
  void (*elem_release)(void *);
1033
1033
  ScrTraceFn elem_trace;
1034
1034
  uint64_t *data;
1035
- uint8_t *present; /* one ScrArrState per dense slot */
1035
+ uint8_t *present; /* one state per dense slot; heap arrays share data allocation */
1036
1036
  struct ScrArrSparseSlot *sparse;
1037
1037
  size_t sparse_len;
1038
1038
  size_t sparse_cap;
@@ -1111,6 +1111,13 @@ void scr_arr_copy_range(ScrArr *dst, size_t dst_start, const ScrArr *src,
1111
1111
  void scr_arr_copy_range_ex(ScrArr *dst, size_t dst_start, const ScrArr *src,
1112
1112
  size_t src_start, size_t count, bool reverse,
1113
1113
  bool materialize_holes);
1114
+ /* Mutating indexed operations borrow the receiver and value, preserve
1115
+ * sparse presence, and return the receiver retained. */
1116
+ ScrArr *scr_arr_copy_within(ScrArr *a, double target, double start, double end);
1117
+ ScrArr *scr_arr_fill_f64(ScrArr *a, double value, double start, double end);
1118
+ ScrArr *scr_arr_fill_bool(ScrArr *a, bool value, double start, double end);
1119
+ ScrArr *scr_arr_fill_ref(ScrArr *a, void *value, double start, double end);
1120
+ ScrArr *scr_arr_fill_undefined(ScrArr *a, double start, double end);
1114
1121
  /* Math.max(...xs) / Math.min(...xs) over an f64-element array: the JS
1115
1122
  * fold (NaN poisons, ±0 by the JS preferences, empty → ∓Infinity). */
1116
1123
  double scr_math_max_arr(ScrArr *a);
@@ -1170,6 +1177,10 @@ ScrArr *scr_arr_with_undefined(ScrArr *a, double index);
1170
1177
  double scr_arr_push_f64(ScrArr *a, double v);
1171
1178
  double scr_arr_push_bool(ScrArr *a, bool v);
1172
1179
  double scr_arr_push_ref(ScrArr *a, void *v);
1180
+ /* Compiler-built slot buffers do not alias array storage. Both operations
1181
+ * move ownership of every slot and preserve the evaluated argument order. */
1182
+ double scr_arr_push_many(ScrArr *a, size_t count, const uint64_t *slots);
1183
+ double scr_arr_unshift_many(ScrArr *a, size_t count, const uint64_t *slots);
1173
1184
  /* Append a same-element-kind array through the JS iterator contract: holes
1174
1185
  * become present undefined states. The source is borrowed and self-spread
1175
1186
  * duplicates the original indexed state. */
@@ -1394,7 +1405,7 @@ typedef struct ScrMap {
1394
1405
  size_t nlive; /* live entries (Map.size) */
1395
1406
  size_t ecap; /* entries capacity */
1396
1407
  ScrMapEntry *entries;
1397
- size_t nbuckets; /* power of two; >= 2 * ecap so probes terminate */
1408
+ size_t nbuckets; /* zero for small linear maps; otherwise power of two >= 2 * nentries */
1398
1409
  size_t *buckets; /* entry indices; SIZE_MAX = empty */
1399
1410
  size_t iter_depth; /* > 0: an iteration is active — no compaction */
1400
1411
  const ScrMapDynOps *dyn_ops;
@@ -3681,7 +3692,7 @@ typedef struct ScrJsval ScrJsval; /* opaque island cell (C11 repeat; the
3681
3692
  * result as an owned (+1) dyn value. `args` entries are BORROWED. */
3682
3693
  typedef ScrDyn *(*ScrDynThunk)(ScrClosure *clo, ScrDyn *const *args, size_t argc);
3683
3694
 
3684
- /* Object member. Keys are malloc'd UTF-8 bytes (NUL-terminated for
3695
+ /* Object member. Keys own shared immutable UTF-8 bytes (NUL-terminated for
3685
3696
  * convenience; key_len excludes the NUL) — duplicate keys were already
3686
3697
  * collapsed at parse time (later wins, like JS JSON.parse). */
3687
3698
  typedef struct {
@@ -3690,13 +3701,22 @@ typedef struct {
3690
3701
  ScrDyn *value; /* owned */
3691
3702
  ScrDyn *getter; /* owned when this is an accessor property */
3692
3703
  ScrDyn *setter; /* owned when this is an accessor property */
3693
- bool accessor;
3704
+ bool accessor : 1;
3705
+ /* Snapshot written by trace before visiting children. Collected teardown
3706
+ * must not inspect the value: an earlier cycle member may already be freed.
3707
+ * Ordinary mutations need not maintain this collector-only decision. */
3708
+ bool value_traced : 1;
3694
3709
  /* Ordinary object insertion sets all three attributes true. */
3695
3710
  bool writable;
3696
3711
  bool enumerable;
3697
3712
  bool configurable;
3698
3713
  } ScrDynEntry;
3699
3714
 
3715
+ _Static_assert(sizeof(ScrDynEntry) == (sizeof(void *) == 8 ? 48 : 24),
3716
+ "LLVM checked-object readers use the target entry stride");
3717
+ _Static_assert(offsetof(ScrDynEntry, value) == 2 * sizeof(void *),
3718
+ "LLVM checked-object readers use the third pointer-sized field");
3719
+
3700
3720
  struct ScrDyn {
3701
3721
  size_t rc; /* SIZE_MAX = immortal (unused for dyn; kept per convention) */
3702
3722
  ScrDynKind kind;
@@ -3739,6 +3759,7 @@ struct ScrDyn {
3739
3759
  * interfaces may request a fresh snapshot with the true arm. */
3740
3760
  void *source_identity;
3741
3761
  ScrDyn *(*source_access)(void *, bool materialize);
3762
+ struct ScrDynObjectIndex *index; /* optional wide-object lookup; owns no values */
3742
3763
  } obj; /* owned */
3743
3764
  /* SCR_DYN_FUNC: the boxed closure (owned) + its call descriptor. `sig`
3744
3765
  * and `name` are static compiler-emitted literals (never freed); name
@@ -3925,6 +3946,12 @@ void scr_dyn_install_async_iterator_symbol(ScrDyn *key);
3925
3946
  ScrDyn *scr_dyn_array_values_function(void);
3926
3947
  ScrDyn *scr_dyn_array_from_iterator(const ScrDyn *value);
3927
3948
  ScrDyn *scr_dyn_iterator_result(ScrDyn *value);
3949
+ /* Internal consumption of a captured builtin next method. Check can_step
3950
+ * once before entering the loop. step returns an owned ordinary value;
3951
+ * read step_done immediately afterward, before running any user code. */
3952
+ bool scr_dyn_iterator_can_step(const ScrDyn *iterator, const ScrDyn *next);
3953
+ ScrDyn *scr_dyn_iterator_step(const ScrDyn *iterator);
3954
+ bool scr_dyn_iterator_step_done(const ScrDyn *iterator);
3928
3955
  /* The ordinary object snapshot plus a retained typed source. source_access
3929
3956
  * releases that source when materialize=false and returns a fresh snapshot
3930
3957
  * when true. */
@@ -4524,6 +4551,8 @@ typedef struct {
4524
4551
  } ScrJsonBuf;
4525
4552
 
4526
4553
  void scr_jb_init(ScrJsonBuf *b);
4554
+ /* Append a borrowed byte span verbatim, including embedded NUL bytes. */
4555
+ void scr_jb_write(ScrJsonBuf *b, const char *s, size_t n);
4527
4556
  /* Append one borrowed runtime string verbatim (no JSON quoting). */
4528
4557
  void scr_jb_put_str(ScrJsonBuf *b, const ScrStr *s);
4529
4558
  /* Push a container onto the circular-detection stack before serializing
@@ -5819,9 +5848,10 @@ ScrBytes *scr_array_buffer_view_dv(ScrDyn *, ScrDyn *, ScrDyn *);
5819
5848
  /* Native callback boundary: exact owned u8 copy. NULL with len == 0 is an
5820
5849
  * empty span. */
5821
5850
  ScrBytes *scr_bytes_from_data(const uint8_t *data, size_t len); /* +1 */
5851
+ ScrBytes *scr_bytes_take_data(uint8_t *data, size_t len); /* +1, consumes malloc storage */
5822
5852
 
5823
- /* `new Uint8Array(src)` / Buffer.from(u8): a same-elem-kind copy (the
5824
- * compiler fences cross-kind construction). Borrows src. Never throws. */
5853
+ /* Same-element-kind copy, preserving the raw representation. Cross-kind
5854
+ * construction uses scr_bytes_convert. Borrows src. Never throws. */
5825
5855
  ScrBytes *scr_bytes_copy(const ScrBytes *src); /* +1 */
5826
5856
 
5827
5857
  /* `new Uint8Array([1, 2, 3])` / Buffer.from(number[]): each f64 element
@@ -5985,6 +6015,7 @@ ScrStr *scr_text_decode_legacy(const ScrBytes *b, double encoding);
5985
6015
  * "utf16le" writes LE code units, surrogate pairs included. Borrows
5986
6016
  * both; +1 u8 result. Never throws. */
5987
6017
  ScrBytes *scr_bytes_from_str(const ScrStr *s, const ScrStr *enc);
6018
+ ScrBytes *scr_bytes_from_str_checked(const ScrStr *s, const ScrStr *enc);
5988
6019
 
5989
6020
  /* Buffer.byteLength(string, enc) — enc NORMALIZED like from_str — and
5990
6021
  * Buffer.isEncoding(name) (case-insensitive over Node's alias set).
@@ -72,6 +72,7 @@ typedef struct ScrSidx {
72
72
  const ScrStr *s; /* NULL = empty slot */
73
73
  size_t u16len; /* SCR_U16_UNKNOWN until the whole current string */
74
74
  size_t cu, cb; /* hot cursor: cb starts the char at unit cu */
75
+ size_t ascii_cu, ascii_cb, ascii_end; /* bounded, proven identity span */
75
76
  ScrSidxPoint *points; /* sparse, ordered code-point-boundary anchors */
76
77
  size_t npoints, cap; /* owned points length/capacity */
77
78
  size_t indexed_cu; /* exact contiguous prefix indexed from byte zero */
@@ -112,8 +113,13 @@ static void scr_sidx_register_cleanup(void) {
112
113
 
113
114
  #ifdef SCR_SIDX_TEST
114
115
  static SCR_TL size_t scr_sidx_walk_steps;
115
- void scr_sidx_test_reset_steps(void) { scr_sidx_walk_steps = 0; }
116
+ static SCR_TL size_t scr_sidx_searches;
117
+ void scr_sidx_test_reset_steps(void) {
118
+ scr_sidx_walk_steps = 0;
119
+ scr_sidx_searches = 0;
120
+ }
116
121
  size_t scr_sidx_test_walk_steps(void) { return scr_sidx_walk_steps; }
122
+ size_t scr_sidx_test_searches(void) { return scr_sidx_searches; }
117
123
  void scr_sidx_test_reset_cache(void) { scr_sidx_reset_all(); }
118
124
  size_t scr_sidx_test_entries(void) {
119
125
  size_t n = 0;
@@ -128,8 +134,10 @@ size_t scr_sidx_test_points(void) {
128
134
  return n;
129
135
  }
130
136
  #define SCR_SIDX_STEP() (scr_sidx_walk_steps++)
137
+ #define SCR_SIDX_SEARCH() (scr_sidx_searches++)
131
138
  #else
132
139
  #define SCR_SIDX_STEP() ((void)0)
140
+ #define SCR_SIDX_SEARCH() ((void)0)
133
141
  #endif
134
142
 
135
143
  static void scr_sidx_purge(const ScrStr *s) {
@@ -779,9 +787,14 @@ static size_t scr_sidx_abs_diff(size_t a, size_t b) {
779
787
  * sufficient; the hot cursor retains sequential-access locality. */
780
788
  static ScrSidxPoint scr_sidx_near_u16(const ScrStr *s, const ScrSidx *e,
781
789
  size_t u16) {
790
+ /* A nearby cursor already bounds the walk. Searching the complete index
791
+ * first would make each sequential read depend on the receiver's size. */
792
+ if (e->cb <= s->len && scr_sidx_abs_diff(e->cu, u16) <= 16)
793
+ return (ScrSidxPoint){e->cu, e->cb};
782
794
  ScrSidxPoint best = {0, 0};
783
795
  size_t best_dist = u16;
784
796
  if (e->npoints != 0) {
797
+ SCR_SIDX_SEARCH();
785
798
  size_t lo = 0, hi = e->npoints;
786
799
  while (lo < hi) {
787
800
  size_t m = lo + (hi - lo) / 2;
@@ -812,9 +825,12 @@ static ScrSidxPoint scr_sidx_near_u16(const ScrStr *s, const ScrSidx *e,
812
825
 
813
826
  static ScrSidxPoint scr_sidx_near_byte(const ScrStr *s, const ScrSidx *e,
814
827
  size_t byte_off) {
828
+ if (e->cb <= s->len && scr_sidx_abs_diff(e->cb, byte_off) <= 16)
829
+ return (ScrSidxPoint){e->cu, e->cb};
815
830
  ScrSidxPoint best = {0, 0};
816
831
  size_t best_dist = byte_off;
817
832
  if (e->npoints != 0) {
833
+ SCR_SIDX_SEARCH();
818
834
  size_t lo = 0, hi = e->npoints;
819
835
  while (lo < hi) {
820
836
  size_t m = lo + (hi - lo) / 2;
@@ -843,6 +859,36 @@ static ScrSidxPoint scr_sidx_near_byte(const ScrStr *s, const ScrSidx *e,
843
859
  return best;
844
860
  }
845
861
 
862
+ /* Cache only a bounded ASCII run at a resolved boundary. Local scans then
863
+ * use arithmetic even inside a mixed string. The bytes are immutable except
864
+ * for append, which preserves this prefix; eviction/reallocation clears the
865
+ * whole entry. No scan reads outside the receiver or allocates metadata. */
866
+ static void scr_sidx_ascii_run(const ScrStr *s, ScrSidx *e) {
867
+ size_t start = e->cb, end = start;
868
+ /* Center the window on the access so reverse scans reuse it too. A
869
+ * forward-only window would rescan its full width on every backward read. */
870
+ size_t lower = start < 128 ? 0 : start - 128;
871
+ while (start - lower >= 8) {
872
+ uint64_t word;
873
+ memcpy(&word, s->data + start - 8, 8);
874
+ if (word & UINT64_C(0x8080808080808080)) break;
875
+ start -= 8;
876
+ }
877
+ while (start > lower && (unsigned char)s->data[start - 1] < 0x80) start--;
878
+ size_t remaining = s->len - end;
879
+ size_t limit = end + (remaining < 128 ? remaining : 128);
880
+ while (limit - end >= 8) {
881
+ uint64_t word;
882
+ memcpy(&word, s->data + end, 8);
883
+ if (word & UINT64_C(0x8080808080808080)) break;
884
+ end += 8;
885
+ }
886
+ while (end < limit && (unsigned char)s->data[end] < 0x80) end++;
887
+ e->ascii_cu = e->cu - (e->cb - start);
888
+ e->ascii_cb = start;
889
+ e->ascii_end = end;
890
+ }
891
+
846
892
  /* Convert a UTF-16 index to a byte offset from the closest sparse anchor or
847
893
  * hot cursor. If u16 addresses the second (low-surrogate) unit of
848
894
  * an astral char, *mid is set and the returned offset is the START of that
@@ -854,6 +900,12 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
854
900
  *mid = false;
855
901
  return u16 < s->len ? u16 : s->len;
856
902
  }
903
+ if (u16 >= e->ascii_cu && u16 - e->ascii_cu < e->ascii_end - e->ascii_cb) {
904
+ e->cb = e->ascii_cb + (u16 - e->ascii_cu);
905
+ e->cu = u16;
906
+ *mid = false;
907
+ return e->cb;
908
+ }
857
909
  scr_sidx_extend_to_u16(s, e, u16);
858
910
  /* Extending a far-end lookup can just have proved identity. Do not
859
911
  * materialize an index that the identity fast path will never consult. */
@@ -864,9 +916,31 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
864
916
  scr_sidx_materialize_identity_prefix(s, e);
865
917
  ScrSidxPoint near = scr_sidx_near_u16(s, e, u16);
866
918
  size_t cu = near.cu, cb = near.cb;
867
- while (cu > u16) scr_sidx_back(s, &cu, &cb);
919
+ while (cu > u16) {
920
+ /* Eight bytes starting inside a sequence can reach back at most three
921
+ * more bytes to its lead. Such a span contains at most nine UTF-16
922
+ * units (seven ASCII bytes plus an astral pair), so it cannot overshoot
923
+ * a target at least nine units away. */
924
+ if (cu - u16 >= 9 && cb >= 8) {
925
+ size_t start = cb - 8;
926
+ while (start > 0 && ((unsigned char)s->data[start] & 0xC0) == 0x80)
927
+ start--;
928
+ cu -= scr_utf16_units_span(s->data + start, cb - start, NULL);
929
+ cb = start;
930
+ } else {
931
+ scr_sidx_back(s, &cu, &cb);
932
+ }
933
+ }
868
934
  bool m = false;
869
935
  while (cu < u16 && cb < s->len) {
936
+ if (u16 - cu >= 9 && s->len - cb >= 8) {
937
+ size_t end = cb + 8;
938
+ while (end < s->len && ((unsigned char)s->data[end] & 0xC0) == 0x80)
939
+ end++;
940
+ cu += scr_utf16_units_span(s->data + cb, end - cb, NULL);
941
+ cb = end;
942
+ continue;
943
+ }
870
944
  SCR_SIDX_STEP();
871
945
  size_t seq = scr_utf8_seq_len((unsigned char)s->data[cb]);
872
946
  size_t w = seq == 4 ? 2 : 1;
@@ -879,6 +953,8 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
879
953
  }
880
954
  e->cu = cu;
881
955
  e->cb = cb;
956
+ if (cb < s->len && (unsigned char)s->data[cb] < 0x80)
957
+ scr_sidx_ascii_run(s, e);
882
958
  *mid = m;
883
959
  return cb;
884
960
  }
@@ -888,6 +964,11 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
888
964
  static size_t scr_byte_to_u16_c(const ScrStr *s, ScrSidx *e,
889
965
  size_t byte_off) {
890
966
  if (e->u16len == s->len) return byte_off; /* all ASCII */
967
+ if (byte_off >= e->ascii_cb && byte_off < e->ascii_end) {
968
+ e->cu = e->ascii_cu + (byte_off - e->ascii_cb);
969
+ e->cb = byte_off;
970
+ return e->cu;
971
+ }
891
972
  /* A byte search result may be far beyond the existing prefix. Build the
892
973
  * same sparse intervals first, then choose the closest boundary anchor. */
893
974
  if (byte_off > e->indexed_cb) {
@@ -900,15 +981,17 @@ static size_t scr_byte_to_u16_c(const ScrStr *s, ScrSidx *e,
900
981
  scr_sidx_materialize_identity_prefix(s, e);
901
982
  ScrSidxPoint near = scr_sidx_near_byte(s, e, byte_off);
902
983
  size_t cu = near.cu, cb = near.cb;
903
- while (cb > byte_off) scr_sidx_back(s, &cu, &cb);
904
- while (cb < byte_off) {
905
- SCR_SIDX_STEP();
906
- size_t seq = scr_utf8_seq_len((unsigned char)s->data[cb]);
907
- cu += seq == 4 ? 2 : 1;
908
- cb += seq;
909
- }
984
+ /* Unlike unit-to-byte conversion, both endpoints are already exact byte
985
+ * boundaries. Count the whole span with the shared word-wise classifier. */
986
+ if (cb > byte_off)
987
+ cu -= scr_utf16_units_span(s->data + byte_off, cb - byte_off, NULL);
988
+ else
989
+ cu += scr_utf16_units_span(s->data + cb, byte_off - cb, NULL);
990
+ cb = byte_off;
910
991
  e->cu = cu;
911
992
  e->cb = cb;
993
+ if (cb < s->len && (unsigned char)s->data[cb] < 0x80)
994
+ scr_sidx_ascii_run(s, e);
912
995
  return cu;
913
996
  }
914
997
 
@@ -919,16 +1002,21 @@ static double scr_to_integer_or_infinity(double x) {
919
1002
  return trunc(x);
920
1003
  }
921
1004
 
922
- /* Naive byte substring search (needle and hay are both well-formed UTF-8,
1005
+ /* Byte substring search (needle and hay are both well-formed UTF-8,
923
1006
  * so any byte-level match starts on a char boundary — UTF-8 is
924
1007
  * self-synchronizing). Empty needle matches at hay. */
925
1008
  static const char *scr_byte_find(const char *hay, size_t hay_len,
926
1009
  const char *nee, size_t nee_len) {
927
1010
  if (nee_len == 0) return hay;
928
1011
  if (nee_len > hay_len) return NULL;
929
- for (size_t i = 0; i + nee_len <= hay_len; i++) {
930
- if (hay[i] == nee[0] && memcmp(hay + i, nee, nee_len) == 0)
931
- return hay + i;
1012
+ if (nee_len == 1) return memchr(hay, (unsigned char)nee[0], hay_len);
1013
+ size_t remaining = hay_len - nee_len + 1;
1014
+ while (remaining) {
1015
+ const char *found = memchr(hay, (unsigned char)nee[0], remaining);
1016
+ if (!found) return NULL;
1017
+ if (memcmp(found + 1, nee + 1, nee_len - 1) == 0) return found;
1018
+ remaining -= (size_t)(found - hay) + 1;
1019
+ hay = found + 1;
932
1020
  }
933
1021
  return NULL;
934
1022
  }
@@ -981,14 +1069,18 @@ double scr_str_char_code_at(ScrStr *s, double i) {
981
1069
 
982
1070
  double scr_str_index_of(ScrStr *s, ScrStr *needle, double fromIndex) {
983
1071
  double pos = scr_to_integer_or_infinity(fromIndex);
1072
+ if (needle->len > s->len) return -1.0;
984
1073
  ScrSidx *e = scr_sidx(s);
985
- size_t len16 = scr_sidx_len(s, e);
986
- size_t start16 = pos <= 0 ? 0
987
- : pos >= (double)len16 ? len16
988
- : (size_t)pos;
989
1074
  /* Per spec, the empty needle is found at the clamped fromIndex itself —
990
1075
  * even when that index is between the halves of an astral pair. */
991
- if (needle->len == 0) return (double)start16;
1076
+ if (needle->len == 0) {
1077
+ size_t len16 = scr_sidx_len(s, e);
1078
+ return pos <= 0 ? 0 : pos >= (double)len16 ? (double)len16 : pos;
1079
+ }
1080
+ /* Byte length bounds UTF-16 length and fences the cast. Let the mapper
1081
+ * extend only as far as needed instead of indexing an unsearched suffix. */
1082
+ if (pos >= (double)s->len) return -1.0;
1083
+ size_t start16 = pos <= 0 ? 0 : (size_t)pos;
992
1084
  bool mid;
993
1085
  size_t start_b = scr_u16_to_byte_c(s, e, start16, &mid);
994
1086
  /* A match can't begin on a low-surrogate half (needles are well-formed),
@@ -1001,11 +1093,11 @@ double scr_str_index_of(ScrStr *s, ScrStr *needle, double fromIndex) {
1001
1093
  return (double)scr_byte_to_u16_c(s, e, (size_t)(found - s->data));
1002
1094
  }
1003
1095
 
1004
- /* substring: slice's clamp-and-swap sibling — ToIntegerOrInfinity both
1005
- * boundaries (NaN → 0), clamp each to [0, len16] (negatives clamp to 0,
1006
- * NOT relative like slice's), swap when start > end, then extract exactly
1007
- * like slice (whose relative/negative handling is inert on the
1008
- * already-clamped values — delegation is exact). */
1096
+ static ScrStr *scr_str_slice_units(ScrStr *s, ScrSidx *e,
1097
+ size_t from, size_t to);
1098
+
1099
+ /* Normalize once, then share slice's extraction without another cache
1100
+ * lookup, length query or floating-point boundary conversion. */
1009
1101
  ScrStr *scr_str_substring(ScrStr *s, double start, double end) {
1010
1102
  ScrSidx *e = scr_sidx(s);
1011
1103
  double len16 = (double)scr_sidx_len(s, e);
@@ -1013,7 +1105,8 @@ ScrStr *scr_str_substring(ScrStr *s, double start, double end) {
1013
1105
  double b = scr_to_integer_or_infinity(end);
1014
1106
  double fa = a < 0 ? 0 : a > len16 ? len16 : a;
1015
1107
  double fb = b < 0 ? 0 : b > len16 ? len16 : b;
1016
- return fa < fb ? scr_str_slice(s, fa, fb) : scr_str_slice(s, fb, fa);
1108
+ return fa < fb ? scr_str_slice_units(s, e, (size_t)fa, (size_t)fb)
1109
+ : scr_str_slice_units(s, e, (size_t)fb, (size_t)fa);
1017
1110
  }
1018
1111
 
1019
1112
  bool scr_str_includes(ScrStr *s, ScrStr *needle) {
@@ -1037,22 +1130,27 @@ static size_t scr_str_clamp_u16_position(double position, size_t len16) {
1037
1130
  }
1038
1131
 
1039
1132
  bool scr_str_starts_with_from(ScrStr *s, ScrStr *needle, double position) {
1040
- ScrSidx *e = scr_sidx(s);
1041
- size_t len16 = scr_sidx_len(s, e);
1042
- size_t start16 = scr_str_clamp_u16_position(position, len16);
1043
1133
  if (needle->len == 0) return true;
1134
+ double pos = scr_to_integer_or_infinity(position);
1135
+ if (pos <= 0) return scr_str_starts_with(s, needle);
1136
+ if (pos >= (double)s->len || needle->len > s->len) return false;
1137
+ ScrSidx *e = scr_sidx(s);
1044
1138
  bool mid;
1045
- size_t start_byte = scr_u16_to_byte_c(s, e, start16, &mid);
1139
+ size_t start_byte = scr_u16_to_byte_c(s, e, (size_t)pos, &mid);
1046
1140
  return !mid && needle->len <= s->len - start_byte &&
1047
1141
  memcmp(s->data + start_byte, needle->data, needle->len) == 0;
1048
1142
  }
1049
1143
 
1050
1144
  bool scr_str_ends_with_from(ScrStr *s, ScrStr *needle, double end_position) {
1145
+ if (needle->len == 0) return true;
1146
+ if (needle->len > s->len) return false;
1147
+ if (end_position >= (double)s->len) return scr_str_ends_with(s, needle);
1148
+ /* A second receiver lookup can evict the first receiver's entry. Resolve
1149
+ * the needle before borrowing the haystack entry for both conversions. */
1150
+ size_t needle16 = scr_sidx_len(needle, scr_sidx(needle));
1051
1151
  ScrSidx *e = scr_sidx(s);
1052
1152
  size_t len16 = scr_sidx_len(s, e);
1053
1153
  size_t end16 = scr_str_clamp_u16_position(end_position, len16);
1054
- size_t needle16 = scr_sidx_len(needle, scr_sidx(needle));
1055
- if (needle16 == 0) return true;
1056
1154
  if (needle16 > end16) return false;
1057
1155
  bool start_mid, end_mid;
1058
1156
  size_t start_byte = scr_u16_to_byte_c(s, e, end16 - needle16, &start_mid);
@@ -1077,6 +1175,11 @@ ScrStr *scr_str_slice(ScrStr *s, double start, double end) {
1077
1175
  size_t len16 = scr_sidx_len(s, e);
1078
1176
  size_t from = scr_slice_boundary(scr_to_integer_or_infinity(start), len16);
1079
1177
  size_t to = scr_slice_boundary(scr_to_integer_or_infinity(end), len16);
1178
+ return scr_str_slice_units(s, e, from, to);
1179
+ }
1180
+
1181
+ static ScrStr *scr_str_slice_units(ScrStr *s, ScrSidx *e,
1182
+ size_t from, size_t to) {
1080
1183
  if (from >= to) return scr_str_empty();
1081
1184
 
1082
1185
  bool from_mid, to_mid;
@@ -1093,18 +1196,16 @@ ScrStr *scr_str_slice(ScrStr *s, double start, double end) {
1093
1196
  /* Divergence: JS would emit the lone surrogate half; we emit U+FFFD. */
1094
1197
  size_t total = content_len + (from_mid ? SCR_REPLACEMENT_LEN : 0) +
1095
1198
  (to_mid ? SCR_REPLACEMENT_LEN : 0);
1096
- char *tmp = malloc(total);
1097
- if (!tmp) scr_oom();
1199
+ ScrStr *r = scr_str_alloc(total, total);
1098
1200
  size_t o = 0;
1099
1201
  if (from_mid) {
1100
- memcpy(tmp + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
1202
+ memcpy(r->data + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
1101
1203
  o += SCR_REPLACEMENT_LEN;
1102
1204
  }
1103
- memcpy(tmp + o, s->data + content_b, content_len);
1205
+ memcpy(r->data + o, s->data + content_b, content_len);
1104
1206
  o += content_len;
1105
- if (to_mid) memcpy(tmp + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
1106
- ScrStr *r = scr_str_new(tmp, total);
1107
- free(tmp);
1207
+ if (to_mid) memcpy(r->data + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
1208
+ r->data[total] = '\0';
1108
1209
  return r;
1109
1210
  }
1110
1211
 
@@ -1213,6 +1314,18 @@ ScrStr *scr_str_trim_end(ScrStr *s) {
1213
1314
  static const struct { size_t rc; size_t len; size_t cap; char data[4]; }
1214
1315
  scr_lit_fffd = {SIZE_MAX, 3, 3, "\xEF\xBF\xBD"};
1215
1316
 
1317
+ /* Split owns a fresh array and appends only present string values. Fill an
1318
+ * available dense slot directly; ordinary push handles growth and the sparse
1319
+ * boundary. The array remains valid after every append, including RC audit. */
1320
+ static void scr_str_split_append(ScrArr *out, ScrStr *value) {
1321
+ if (out->len < out->cap) {
1322
+ out->data[out->len] = (uint64_t)(uintptr_t)value;
1323
+ out->present[out->len++] = SCR_ARR_VALUE;
1324
+ } else {
1325
+ scr_arr_push_ref(out, value);
1326
+ }
1327
+ }
1328
+
1216
1329
  /* split(separator, limit) with a STRING separator (ECMA-262 22.1.3.23):
1217
1330
  * limit is ToUint32'd; zero returns [] and reaching the limit stops before
1218
1331
  * any later separator probes. The no-limit wrapper supplies 2^32-1.
@@ -1235,11 +1348,11 @@ ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit_num) {
1235
1348
  size_t adv;
1236
1349
  uint32_t cp = scr_utf8_decode(s->data + i, &adv);
1237
1350
  if (cp >= 0x10000) { /* two units in JS: both halves become U+FFFD */
1238
- scr_arr_push_ref(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
1351
+ scr_str_split_append(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
1239
1352
  if (out->len == limit) return out;
1240
- scr_arr_push_ref(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
1353
+ scr_str_split_append(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
1241
1354
  } else {
1242
- scr_arr_push_ref(out, scr_str_from_span(s->data + i, adv));
1355
+ scr_str_split_append(out, scr_str_from_span(s->data + i, adv));
1243
1356
  }
1244
1357
  if (out->len == limit) return out;
1245
1358
  i += adv;
@@ -1252,11 +1365,11 @@ ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit_num) {
1252
1365
  sep->data, sep->len);
1253
1366
  if (!found) break;
1254
1367
  size_t at = (size_t)(found - s->data);
1255
- scr_arr_push_ref(out, scr_str_from_span(s->data + start, at - start));
1368
+ scr_str_split_append(out, scr_str_from_span(s->data + start, at - start));
1256
1369
  if (out->len == limit) return out;
1257
1370
  start = at + sep->len;
1258
1371
  }
1259
- scr_arr_push_ref(out, scr_str_from_span(s->data + start, s->len - start));
1372
+ scr_str_split_append(out, scr_str_from_span(s->data + start, s->len - start));
1260
1373
  return out;
1261
1374
  }
1262
1375
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scriptc/cli-darwin-x64",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Native scriptc compiler for darwin-x64",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://scriptc.dev",