@scriptc/cli-darwin-arm64 0.2.3 → 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 (139) 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-arm64/artifacts/dev/runtime/default/scr_array.o +0 -0
  10. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bigint.o +0 -0
  11. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes.o +0 -0
  12. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
  13. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_copying.o +0 -0
  14. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_cycle.o +0 -0
  15. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_json.o +0 -0
  16. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_lib.o +0 -0
  17. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_map.o +0 -0
  18. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_number.o +0 -0
  19. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_regex.o +0 -0
  20. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_string.o +0 -0
  21. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_array.o +0 -0
  22. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bigint.o +0 -0
  23. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
  24. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
  25. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_copying.o +0 -0
  26. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_cycle.o +0 -0
  27. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
  28. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
  29. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_map.o +0 -0
  30. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_number.o +0 -0
  31. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
  32. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_string.o +0 -0
  33. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  34. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  35. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_array.o +0 -0
  36. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bigint.o +0 -0
  37. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
  38. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
  39. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_copying.o +0 -0
  40. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_cycle.o +0 -0
  41. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
  42. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
  43. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_map.o +0 -0
  44. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_number.o +0 -0
  45. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
  46. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_string.o +0 -0
  47. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  48. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_array.o +0 -0
  49. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bigint.o +0 -0
  50. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
  51. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
  52. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_copying.o +0 -0
  53. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_cycle.o +0 -0
  54. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_json.o +0 -0
  55. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
  56. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_map.o +0 -0
  57. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_number.o +0 -0
  58. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
  59. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_string.o +0 -0
  60. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  61. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_array.o +0 -0
  62. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bigint.o +0 -0
  63. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
  64. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
  65. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_copying.o +0 -0
  66. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_cycle.o +0 -0
  67. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
  68. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
  69. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_map.o +0 -0
  70. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_number.o +0 -0
  71. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
  72. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_string.o +0 -0
  73. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  74. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_array.o +0 -0
  75. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bigint.o +0 -0
  76. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
  77. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
  78. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_copying.o +0 -0
  79. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_cycle.o +0 -0
  80. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
  81. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
  82. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_map.o +0 -0
  83. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_number.o +0 -0
  84. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
  85. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_string.o +0 -0
  86. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  87. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_array.o +0 -0
  88. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bigint.o +0 -0
  89. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes.o +0 -0
  90. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
  91. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_copying.o +0 -0
  92. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_cycle.o +0 -0
  93. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_json.o +0 -0
  94. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_lib.o +0 -0
  95. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_map.o +0 -0
  96. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_number.o +0 -0
  97. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_regex.o +0 -0
  98. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_string.o +0 -0
  99. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_util_compare.o +0 -0
  100. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_array.o +0 -0
  101. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bigint.o +0 -0
  102. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
  103. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
  104. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_copying.o +0 -0
  105. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_cycle.o +0 -0
  106. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
  107. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
  108. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_map.o +0 -0
  109. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_number.o +0 -0
  110. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
  111. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_string.o +0 -0
  112. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_util_compare.o +0 -0
  113. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  114. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  115. package/dist/lib/runtime-darwin-arm64/package.json +1 -1
  116. package/dist/lib/runtime-darwin-arm64/runtime-pack.json +213 -213
  117. package/dist/lib/runtime-sources/package.json +1 -1
  118. package/dist/lib/runtime-sources/src/scr_array.c +317 -40
  119. package/dist/lib/runtime-sources/src/scr_async.test.ts +16 -6
  120. package/dist/lib/runtime-sources/src/scr_bigint.c +15 -0
  121. package/dist/lib/runtime-sources/src/scr_bytes.c +437 -216
  122. package/dist/lib/runtime-sources/src/scr_bytes.test.c +85 -0
  123. package/dist/lib/runtime-sources/src/scr_bytes_io.c +0 -34
  124. package/dist/lib/runtime-sources/src/scr_copying.c +12 -2
  125. package/dist/lib/runtime-sources/src/scr_cycle.c +84 -60
  126. package/dist/lib/runtime-sources/src/scr_json.c +494 -161
  127. package/dist/lib/runtime-sources/src/scr_json.test.c +323 -1
  128. package/dist/lib/runtime-sources/src/scr_json.test.ts +58 -25
  129. package/dist/lib/runtime-sources/src/scr_key.h +68 -0
  130. package/dist/lib/runtime-sources/src/scr_lib.c +177 -89
  131. package/dist/lib/runtime-sources/src/scr_map.c +268 -96
  132. package/dist/lib/runtime-sources/src/scr_number.c +2 -4
  133. package/dist/lib/runtime-sources/src/scr_numeric.h +25 -0
  134. package/dist/lib/runtime-sources/src/scr_numeric.test.c +37 -0
  135. package/dist/lib/runtime-sources/src/scr_numeric.test.ts +33 -0
  136. package/dist/lib/runtime-sources/src/scr_regex.c +255 -145
  137. package/dist/lib/runtime-sources/src/scr_runtime.h +76 -19
  138. package/dist/lib/runtime-sources/src/scr_string.c +184 -42
  139. package/package.json +1 -1
@@ -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) {
@@ -271,6 +279,7 @@ ScrStr *scr_str_alloc_raw(size_t len, size_t cap) {
271
279
  }
272
280
 
273
281
  ScrStr *scr_str_regrow(ScrStr *s, size_t newcap) {
282
+ if (newcap < s->len || newcap > SIZE_MAX - sizeof(ScrStr) - 1) scr_oom();
274
283
  scr_short_forget(s);
275
284
  scr_sidx_purge(s); /* realloc may move; the old address may be recycled */
276
285
  ScrStr *r = realloc(s, sizeof(ScrStr) + newcap + 1);
@@ -300,6 +309,8 @@ void scr_str_release(ScrStr *s) {
300
309
  }
301
310
 
302
311
  ScrStr *scr_str_concat(ScrStr *a, ScrStr *b) {
312
+ if (a->len == 0) return scr_str_retain(b);
313
+ if (b->len == 0) return scr_str_retain(a);
303
314
  if (a->len > SIZE_MAX - b->len - sizeof(ScrStr) - 1) scr_oom();
304
315
  size_t newlen = a->len + b->len;
305
316
  /* In-place append: a is uniquely owned by the caller's borrow (rc == 1 —
@@ -343,6 +354,32 @@ ScrStr *scr_str_concat(ScrStr *a, ScrStr *b) {
343
354
  return s;
344
355
  }
345
356
 
357
+ ScrStr *scr_str_concat_parts(ScrStr *const *parts, size_t count) {
358
+ const size_t limit = SIZE_MAX - sizeof(ScrStr) - 1;
359
+ size_t len = 0;
360
+ ScrStr *only = NULL;
361
+ size_t nonempty = 0;
362
+ for (size_t i = 0; i < count; i++) {
363
+ const size_t n = parts[i]->len;
364
+ if (n > limit - len) scr_oom();
365
+ len += n;
366
+ if (n != 0) {
367
+ only = parts[i];
368
+ nonempty++;
369
+ }
370
+ }
371
+ if (nonempty == 1) return scr_str_retain(only);
372
+ ScrStr *out = scr_str_alloc_raw(len, len);
373
+ size_t offset = 0;
374
+ for (size_t i = 0; i < count; i++) {
375
+ const ScrStr *part = parts[i];
376
+ memcpy(out->data + offset, part->data, part->len);
377
+ offset += part->len;
378
+ }
379
+ out->data[len] = '\0';
380
+ return out;
381
+ }
382
+
346
383
  bool scr_str_eq(ScrStr *a, ScrStr *b) {
347
384
  return a == b || (a->len == b->len && memcmp(a->data, b->data, a->len) == 0);
348
385
  }
@@ -750,9 +787,14 @@ static size_t scr_sidx_abs_diff(size_t a, size_t b) {
750
787
  * sufficient; the hot cursor retains sequential-access locality. */
751
788
  static ScrSidxPoint scr_sidx_near_u16(const ScrStr *s, const ScrSidx *e,
752
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};
753
794
  ScrSidxPoint best = {0, 0};
754
795
  size_t best_dist = u16;
755
796
  if (e->npoints != 0) {
797
+ SCR_SIDX_SEARCH();
756
798
  size_t lo = 0, hi = e->npoints;
757
799
  while (lo < hi) {
758
800
  size_t m = lo + (hi - lo) / 2;
@@ -783,9 +825,12 @@ static ScrSidxPoint scr_sidx_near_u16(const ScrStr *s, const ScrSidx *e,
783
825
 
784
826
  static ScrSidxPoint scr_sidx_near_byte(const ScrStr *s, const ScrSidx *e,
785
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};
786
830
  ScrSidxPoint best = {0, 0};
787
831
  size_t best_dist = byte_off;
788
832
  if (e->npoints != 0) {
833
+ SCR_SIDX_SEARCH();
789
834
  size_t lo = 0, hi = e->npoints;
790
835
  while (lo < hi) {
791
836
  size_t m = lo + (hi - lo) / 2;
@@ -814,6 +859,36 @@ static ScrSidxPoint scr_sidx_near_byte(const ScrStr *s, const ScrSidx *e,
814
859
  return best;
815
860
  }
816
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
+
817
892
  /* Convert a UTF-16 index to a byte offset from the closest sparse anchor or
818
893
  * hot cursor. If u16 addresses the second (low-surrogate) unit of
819
894
  * an astral char, *mid is set and the returned offset is the START of that
@@ -825,6 +900,12 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
825
900
  *mid = false;
826
901
  return u16 < s->len ? u16 : s->len;
827
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
+ }
828
909
  scr_sidx_extend_to_u16(s, e, u16);
829
910
  /* Extending a far-end lookup can just have proved identity. Do not
830
911
  * materialize an index that the identity fast path will never consult. */
@@ -835,9 +916,31 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
835
916
  scr_sidx_materialize_identity_prefix(s, e);
836
917
  ScrSidxPoint near = scr_sidx_near_u16(s, e, u16);
837
918
  size_t cu = near.cu, cb = near.cb;
838
- 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
+ }
839
934
  bool m = false;
840
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
+ }
841
944
  SCR_SIDX_STEP();
842
945
  size_t seq = scr_utf8_seq_len((unsigned char)s->data[cb]);
843
946
  size_t w = seq == 4 ? 2 : 1;
@@ -850,6 +953,8 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
850
953
  }
851
954
  e->cu = cu;
852
955
  e->cb = cb;
956
+ if (cb < s->len && (unsigned char)s->data[cb] < 0x80)
957
+ scr_sidx_ascii_run(s, e);
853
958
  *mid = m;
854
959
  return cb;
855
960
  }
@@ -859,6 +964,11 @@ static size_t scr_u16_to_byte_c(const ScrStr *s, ScrSidx *e, size_t u16,
859
964
  static size_t scr_byte_to_u16_c(const ScrStr *s, ScrSidx *e,
860
965
  size_t byte_off) {
861
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
+ }
862
972
  /* A byte search result may be far beyond the existing prefix. Build the
863
973
  * same sparse intervals first, then choose the closest boundary anchor. */
864
974
  if (byte_off > e->indexed_cb) {
@@ -871,15 +981,17 @@ static size_t scr_byte_to_u16_c(const ScrStr *s, ScrSidx *e,
871
981
  scr_sidx_materialize_identity_prefix(s, e);
872
982
  ScrSidxPoint near = scr_sidx_near_byte(s, e, byte_off);
873
983
  size_t cu = near.cu, cb = near.cb;
874
- while (cb > byte_off) scr_sidx_back(s, &cu, &cb);
875
- while (cb < byte_off) {
876
- SCR_SIDX_STEP();
877
- size_t seq = scr_utf8_seq_len((unsigned char)s->data[cb]);
878
- cu += seq == 4 ? 2 : 1;
879
- cb += seq;
880
- }
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;
881
991
  e->cu = cu;
882
992
  e->cb = cb;
993
+ if (cb < s->len && (unsigned char)s->data[cb] < 0x80)
994
+ scr_sidx_ascii_run(s, e);
883
995
  return cu;
884
996
  }
885
997
 
@@ -890,16 +1002,21 @@ static double scr_to_integer_or_infinity(double x) {
890
1002
  return trunc(x);
891
1003
  }
892
1004
 
893
- /* 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,
894
1006
  * so any byte-level match starts on a char boundary — UTF-8 is
895
1007
  * self-synchronizing). Empty needle matches at hay. */
896
1008
  static const char *scr_byte_find(const char *hay, size_t hay_len,
897
1009
  const char *nee, size_t nee_len) {
898
1010
  if (nee_len == 0) return hay;
899
1011
  if (nee_len > hay_len) return NULL;
900
- for (size_t i = 0; i + nee_len <= hay_len; i++) {
901
- if (hay[i] == nee[0] && memcmp(hay + i, nee, nee_len) == 0)
902
- 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;
903
1020
  }
904
1021
  return NULL;
905
1022
  }
@@ -952,14 +1069,18 @@ double scr_str_char_code_at(ScrStr *s, double i) {
952
1069
 
953
1070
  double scr_str_index_of(ScrStr *s, ScrStr *needle, double fromIndex) {
954
1071
  double pos = scr_to_integer_or_infinity(fromIndex);
1072
+ if (needle->len > s->len) return -1.0;
955
1073
  ScrSidx *e = scr_sidx(s);
956
- size_t len16 = scr_sidx_len(s, e);
957
- size_t start16 = pos <= 0 ? 0
958
- : pos >= (double)len16 ? len16
959
- : (size_t)pos;
960
1074
  /* Per spec, the empty needle is found at the clamped fromIndex itself —
961
1075
  * even when that index is between the halves of an astral pair. */
962
- 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;
963
1084
  bool mid;
964
1085
  size_t start_b = scr_u16_to_byte_c(s, e, start16, &mid);
965
1086
  /* A match can't begin on a low-surrogate half (needles are well-formed),
@@ -972,11 +1093,11 @@ double scr_str_index_of(ScrStr *s, ScrStr *needle, double fromIndex) {
972
1093
  return (double)scr_byte_to_u16_c(s, e, (size_t)(found - s->data));
973
1094
  }
974
1095
 
975
- /* substring: slice's clamp-and-swap sibling — ToIntegerOrInfinity both
976
- * boundaries (NaN → 0), clamp each to [0, len16] (negatives clamp to 0,
977
- * NOT relative like slice's), swap when start > end, then extract exactly
978
- * like slice (whose relative/negative handling is inert on the
979
- * 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. */
980
1101
  ScrStr *scr_str_substring(ScrStr *s, double start, double end) {
981
1102
  ScrSidx *e = scr_sidx(s);
982
1103
  double len16 = (double)scr_sidx_len(s, e);
@@ -984,7 +1105,8 @@ ScrStr *scr_str_substring(ScrStr *s, double start, double end) {
984
1105
  double b = scr_to_integer_or_infinity(end);
985
1106
  double fa = a < 0 ? 0 : a > len16 ? len16 : a;
986
1107
  double fb = b < 0 ? 0 : b > len16 ? len16 : b;
987
- 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);
988
1110
  }
989
1111
 
990
1112
  bool scr_str_includes(ScrStr *s, ScrStr *needle) {
@@ -1008,22 +1130,27 @@ static size_t scr_str_clamp_u16_position(double position, size_t len16) {
1008
1130
  }
1009
1131
 
1010
1132
  bool scr_str_starts_with_from(ScrStr *s, ScrStr *needle, double position) {
1011
- ScrSidx *e = scr_sidx(s);
1012
- size_t len16 = scr_sidx_len(s, e);
1013
- size_t start16 = scr_str_clamp_u16_position(position, len16);
1014
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);
1015
1138
  bool mid;
1016
- 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);
1017
1140
  return !mid && needle->len <= s->len - start_byte &&
1018
1141
  memcmp(s->data + start_byte, needle->data, needle->len) == 0;
1019
1142
  }
1020
1143
 
1021
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));
1022
1151
  ScrSidx *e = scr_sidx(s);
1023
1152
  size_t len16 = scr_sidx_len(s, e);
1024
1153
  size_t end16 = scr_str_clamp_u16_position(end_position, len16);
1025
- size_t needle16 = scr_sidx_len(needle, scr_sidx(needle));
1026
- if (needle16 == 0) return true;
1027
1154
  if (needle16 > end16) return false;
1028
1155
  bool start_mid, end_mid;
1029
1156
  size_t start_byte = scr_u16_to_byte_c(s, e, end16 - needle16, &start_mid);
@@ -1048,6 +1175,11 @@ ScrStr *scr_str_slice(ScrStr *s, double start, double end) {
1048
1175
  size_t len16 = scr_sidx_len(s, e);
1049
1176
  size_t from = scr_slice_boundary(scr_to_integer_or_infinity(start), len16);
1050
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) {
1051
1183
  if (from >= to) return scr_str_empty();
1052
1184
 
1053
1185
  bool from_mid, to_mid;
@@ -1064,18 +1196,16 @@ ScrStr *scr_str_slice(ScrStr *s, double start, double end) {
1064
1196
  /* Divergence: JS would emit the lone surrogate half; we emit U+FFFD. */
1065
1197
  size_t total = content_len + (from_mid ? SCR_REPLACEMENT_LEN : 0) +
1066
1198
  (to_mid ? SCR_REPLACEMENT_LEN : 0);
1067
- char *tmp = malloc(total);
1068
- if (!tmp) scr_oom();
1199
+ ScrStr *r = scr_str_alloc(total, total);
1069
1200
  size_t o = 0;
1070
1201
  if (from_mid) {
1071
- memcpy(tmp + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
1202
+ memcpy(r->data + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
1072
1203
  o += SCR_REPLACEMENT_LEN;
1073
1204
  }
1074
- memcpy(tmp + o, s->data + content_b, content_len);
1205
+ memcpy(r->data + o, s->data + content_b, content_len);
1075
1206
  o += content_len;
1076
- if (to_mid) memcpy(tmp + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
1077
- ScrStr *r = scr_str_new(tmp, total);
1078
- free(tmp);
1207
+ if (to_mid) memcpy(r->data + o, SCR_REPLACEMENT, SCR_REPLACEMENT_LEN);
1208
+ r->data[total] = '\0';
1079
1209
  return r;
1080
1210
  }
1081
1211
 
@@ -1184,6 +1314,18 @@ ScrStr *scr_str_trim_end(ScrStr *s) {
1184
1314
  static const struct { size_t rc; size_t len; size_t cap; char data[4]; }
1185
1315
  scr_lit_fffd = {SIZE_MAX, 3, 3, "\xEF\xBF\xBD"};
1186
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
+
1187
1329
  /* split(separator, limit) with a STRING separator (ECMA-262 22.1.3.23):
1188
1330
  * limit is ToUint32'd; zero returns [] and reaching the limit stops before
1189
1331
  * any later separator probes. The no-limit wrapper supplies 2^32-1.
@@ -1206,11 +1348,11 @@ ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit_num) {
1206
1348
  size_t adv;
1207
1349
  uint32_t cp = scr_utf8_decode(s->data + i, &adv);
1208
1350
  if (cp >= 0x10000) { /* two units in JS: both halves become U+FFFD */
1209
- 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));
1210
1352
  if (out->len == limit) return out;
1211
- 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));
1212
1354
  } else {
1213
- 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));
1214
1356
  }
1215
1357
  if (out->len == limit) return out;
1216
1358
  i += adv;
@@ -1223,11 +1365,11 @@ ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit_num) {
1223
1365
  sep->data, sep->len);
1224
1366
  if (!found) break;
1225
1367
  size_t at = (size_t)(found - s->data);
1226
- 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));
1227
1369
  if (out->len == limit) return out;
1228
1370
  start = at + sep->len;
1229
1371
  }
1230
- 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));
1231
1373
  return out;
1232
1374
  }
1233
1375
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scriptc/cli-darwin-arm64",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Native scriptc compiler for darwin-arm64",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://scriptc.dev",