@scriptc/cli-darwin-arm64 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 (121) 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_bytes.o +0 -0
  11. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
  12. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_copying.o +0 -0
  13. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_json.o +0 -0
  14. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_lib.o +0 -0
  15. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_map.o +0 -0
  16. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_number.o +0 -0
  17. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_regex.o +0 -0
  18. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_string.o +0 -0
  19. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_array.o +0 -0
  20. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
  21. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
  22. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_copying.o +0 -0
  23. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
  24. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
  25. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_map.o +0 -0
  26. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_number.o +0 -0
  27. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
  28. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_string.o +0 -0
  29. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  30. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  31. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_array.o +0 -0
  32. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
  33. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
  34. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_copying.o +0 -0
  35. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
  36. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
  37. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_map.o +0 -0
  38. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_number.o +0 -0
  39. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
  40. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_string.o +0 -0
  41. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  42. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_array.o +0 -0
  43. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
  44. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
  45. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_copying.o +0 -0
  46. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_json.o +0 -0
  47. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
  48. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_map.o +0 -0
  49. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_number.o +0 -0
  50. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
  51. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_string.o +0 -0
  52. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  53. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_array.o +0 -0
  54. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
  55. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
  56. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_copying.o +0 -0
  57. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
  58. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
  59. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_map.o +0 -0
  60. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_number.o +0 -0
  61. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
  62. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_string.o +0 -0
  63. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  64. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_array.o +0 -0
  65. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
  66. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
  67. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_copying.o +0 -0
  68. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
  69. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
  70. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_map.o +0 -0
  71. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_number.o +0 -0
  72. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
  73. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_string.o +0 -0
  74. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  75. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_array.o +0 -0
  76. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes.o +0 -0
  77. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
  78. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_copying.o +0 -0
  79. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_json.o +0 -0
  80. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_lib.o +0 -0
  81. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_map.o +0 -0
  82. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_number.o +0 -0
  83. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_regex.o +0 -0
  84. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_string.o +0 -0
  85. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_util_compare.o +0 -0
  86. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_array.o +0 -0
  87. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
  88. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
  89. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_copying.o +0 -0
  90. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
  91. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
  92. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_map.o +0 -0
  93. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_number.o +0 -0
  94. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
  95. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_string.o +0 -0
  96. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_util_compare.o +0 -0
  97. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  98. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  99. package/dist/lib/runtime-darwin-arm64/package.json +1 -1
  100. package/dist/lib/runtime-darwin-arm64/runtime-pack.json +181 -181
  101. package/dist/lib/runtime-sources/package.json +1 -1
  102. package/dist/lib/runtime-sources/src/scr_array.c +267 -6
  103. package/dist/lib/runtime-sources/src/scr_async.test.ts +16 -6
  104. package/dist/lib/runtime-sources/src/scr_bytes.c +437 -216
  105. package/dist/lib/runtime-sources/src/scr_bytes.test.c +85 -0
  106. package/dist/lib/runtime-sources/src/scr_bytes_io.c +0 -34
  107. package/dist/lib/runtime-sources/src/scr_copying.c +12 -2
  108. package/dist/lib/runtime-sources/src/scr_json.c +479 -150
  109. package/dist/lib/runtime-sources/src/scr_json.test.c +323 -1
  110. package/dist/lib/runtime-sources/src/scr_json.test.ts +58 -25
  111. package/dist/lib/runtime-sources/src/scr_key.h +68 -0
  112. package/dist/lib/runtime-sources/src/scr_lib.c +132 -73
  113. package/dist/lib/runtime-sources/src/scr_map.c +50 -66
  114. package/dist/lib/runtime-sources/src/scr_number.c +2 -4
  115. package/dist/lib/runtime-sources/src/scr_numeric.h +25 -0
  116. package/dist/lib/runtime-sources/src/scr_numeric.test.c +37 -0
  117. package/dist/lib/runtime-sources/src/scr_numeric.test.ts +33 -0
  118. package/dist/lib/runtime-sources/src/scr_regex.c +238 -167
  119. package/dist/lib/runtime-sources/src/scr_runtime.h +37 -6
  120. package/dist/lib/runtime-sources/src/scr_string.c +155 -42
  121. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scriptc/runtime",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "scriptc native runtime sources and vendored dependencies",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://scriptc.dev",
@@ -147,10 +147,14 @@ static void scr_arr_grow_dense(ScrArr *a, size_t need) {
147
147
  cap *= 2;
148
148
  }
149
149
  if (cap > SCR_ARR_DENSE_LIMIT) cap = SCR_ARR_DENSE_LIMIT;
150
- uint64_t *data = realloc(a->data, cap * sizeof(uint64_t));
150
+ /* Values and states share one allocation. Move the old states before
151
+ * publishing the larger capacity: their previous location is now part
152
+ * of the value area. Existing data and state pointers keep their ABI. */
153
+ if (cap > SIZE_MAX / (sizeof(uint64_t) + sizeof(uint8_t))) scr_arr_oom();
154
+ uint64_t *data = realloc(a->data, cap * (sizeof(uint64_t) + sizeof(uint8_t)));
151
155
  if (!data) scr_arr_oom();
152
- uint8_t *present = realloc(a->present, cap);
153
- if (!present) scr_arr_oom();
156
+ uint8_t *present = (uint8_t *)(data + cap);
157
+ if (a->cap) memmove(present, (uint8_t *)(data + a->cap), a->cap);
154
158
  memset(present + a->cap, 0, cap - a->cap);
155
159
  a->data = data;
156
160
  a->present = present;
@@ -397,11 +401,58 @@ static ScrArrStorage scr_arr_take_storage(ScrArr *a) {
397
401
 
398
402
  static void scr_arr_free_storage(ScrArrStorage *s) {
399
403
  free(s->data);
400
- free(s->present);
401
404
  free(s->sparse);
402
405
  memset(s, 0, sizeof(*s));
403
406
  }
404
407
 
408
+ /* Dense storage may still contain holes and explicit undefined. These
409
+ * operations move ownership with the slots and move the states alongside
410
+ * them; they never inspect an uninitialized hole payload. */
411
+ static bool scr_arr_is_dense(const ScrArr *a) {
412
+ return a->len <= a->cap && a->sparse_len == 0;
413
+ }
414
+
415
+ static void scr_arr_move_dense(ScrArr *a, size_t to, size_t from, size_t count) {
416
+ if (count == 0) return;
417
+ memmove(a->data + to, a->data + from, count * sizeof(*a->data));
418
+ memmove(a->present + to, a->present + from, count);
419
+ }
420
+
421
+ static void scr_arr_clear_dense(ScrArr *a, size_t from, size_t count) {
422
+ if (count == 0) return;
423
+ memset(a->present + from, SCR_ARR_HOLE, count);
424
+ memset(a->data + from, 0, count * sizeof(*a->data));
425
+ }
426
+
427
+ /* The destination owns no values in this range. Only retain adapters run
428
+ * while copying references: no release can collect an intermediate copy.
429
+ * Self-appends use disjoint ranges after reserving capacity. */
430
+ static void scr_arr_copy_dense(ScrArr *dst, size_t to, const ScrArr *src,
431
+ size_t from, size_t count, bool reverse,
432
+ bool materialize_holes) {
433
+ if (count == 0) return;
434
+ if (!reverse) {
435
+ memcpy(dst->data + to, src->data + from, count * sizeof(*dst->data));
436
+ memcpy(dst->present + to, src->present + from, count);
437
+ } else {
438
+ for (size_t i = 0; i < count; i++) {
439
+ size_t source = from + count - i - 1;
440
+ memcpy(dst->data + to + i, src->data + source, sizeof(*dst->data));
441
+ dst->present[to + i] = src->present[source];
442
+ }
443
+ }
444
+ bool refs = scr_elem_is_ref(src->elem);
445
+ if (!refs && !materialize_holes) return;
446
+ for (size_t i = to; i < to + count; i++) {
447
+ if (dst->present[i] == SCR_ARR_VALUE) {
448
+ if (refs) dst->data[i] = scr_elem_retain_slot(src, dst->data[i]);
449
+ } else if (materialize_holes && dst->present[i] == SCR_ARR_HOLE) {
450
+ dst->data[i] = 0;
451
+ dst->present[i] = SCR_ARR_UNDEFINED;
452
+ }
453
+ }
454
+ }
455
+
405
456
  ScrArr *scr_arr_new(ScrElemKind elem, size_t initial_cap) {
406
457
  ScrArr *a = malloc(sizeof(ScrArr));
407
458
  if (!a) scr_arr_oom();
@@ -455,7 +506,6 @@ void scr_arr_trace_v(void *a0, ScrTraceVisit visit, void *ctx) {
455
506
  static void scr_arr_gc_free(void *a0) {
456
507
  ScrArr *a = (ScrArr *)a0;
457
508
  free(a->data);
458
- free(a->present);
459
509
  free(a->sparse);
460
510
  for (size_t i = 0; i < a->prop_len; i++) free(a->props[i].key);
461
511
  free(a->props);
@@ -534,7 +584,6 @@ void scr_arr_release(ScrArr *a) {
534
584
  scr_arr_gc_free(a);
535
585
  } else {
536
586
  free(a->data);
537
- free(a->present);
538
587
  free(a->sparse);
539
588
  for (size_t i = 0; i < a->prop_len; i++) free(a->props[i].key);
540
589
  free(a->props);
@@ -649,6 +698,16 @@ void scr_arr_copy_range_ex(ScrArr *dst, size_t dst_start, const ScrArr *src,
649
698
  size_t src_start, size_t count, bool reverse,
650
699
  bool materialize_holes) {
651
700
  if (count == 0) return;
701
+ if (src != dst && src_start <= src->cap && count <= src->cap - src_start &&
702
+ dst_start <= dst->cap && count <= dst->cap - dst_start) {
703
+ size_t empty = 0;
704
+ while (empty < count && dst->present[dst_start + empty] == SCR_ARR_HOLE) empty++;
705
+ if (empty == count) {
706
+ scr_arr_copy_dense(dst, dst_start, src, src_start, count, reverse,
707
+ materialize_holes);
708
+ return;
709
+ }
710
+ }
652
711
  size_t end = src_start + count;
653
712
  size_t dense_start = src_start < src->cap ? src_start : src->cap;
654
713
  size_t dense_end = end < src->cap ? end : src->cap;
@@ -678,6 +737,76 @@ void scr_arr_copy_range_ex(ScrArr *dst, size_t dst_start, const ScrArr *src,
678
737
  }
679
738
  }
680
739
 
740
+ static size_t scr_arr_relative_index(double value, size_t length) {
741
+ double integer = isnan(value) ? 0 : trunc(value);
742
+ if (integer < 0) integer += (double)length;
743
+ return integer <= 0 ? 0 : integer >= (double)length ? length : (size_t)integer;
744
+ }
745
+
746
+ ScrArr *scr_arr_copy_within(ScrArr *a, double target, double start, double end) {
747
+ size_t to = scr_arr_relative_index(target, a->len);
748
+ size_t from = scr_arr_relative_index(start, a->len);
749
+ size_t last = scr_arr_relative_index(end, a->len);
750
+ size_t count = last > from ? last - from : 0;
751
+ if (count > a->len - to) count = a->len - to;
752
+ if (count == 0 || from == to) return scr_arr_retain(a);
753
+ if (!scr_elem_is_ref(a->elem) && from < a->cap && count <= a->cap - from &&
754
+ to < a->cap && count <= a->cap - to) {
755
+ scr_arr_move_dense(a, to, from, count);
756
+ return scr_arr_retain(a);
757
+ }
758
+ bool backwards = from < to && to - from < count;
759
+ for (size_t i = 0; i < count; i++) {
760
+ size_t offset = backwards ? count - i - 1 : i;
761
+ uint64_t slot = 0;
762
+ uint8_t state = scr_arr_state_at(a, from + offset, &slot);
763
+ if (state == SCR_ARR_HOLE) {
764
+ scr_arr_delete(a, (double)(to + offset));
765
+ } else {
766
+ if (state == SCR_ARR_VALUE) slot = scr_elem_retain_slot(a, slot);
767
+ /* Each replacement publishes its edge before releasing the previous
768
+ * owner; cycle collection can run between successive positions. */
769
+ scr_arr_replace_state_owned(a, to + offset, slot, state);
770
+ }
771
+ }
772
+ return scr_arr_retain(a);
773
+ }
774
+
775
+ static ScrArr *scr_arr_fill_slot(ScrArr *a, uint64_t slot, uint8_t state,
776
+ double start, double end) {
777
+ size_t from = scr_arr_relative_index(start, a->len);
778
+ size_t until = scr_arr_relative_index(end, a->len);
779
+ if (from >= until) return scr_arr_retain(a);
780
+ bool refs = scr_elem_is_ref(a->elem);
781
+ if (!refs && until <= SCR_ARR_DENSE_LIMIT) {
782
+ scr_arr_grow_dense(a, until);
783
+ for (size_t i = from; i < until; i++) a->data[i] = slot;
784
+ memset(a->present + from, state, until - from);
785
+ } else {
786
+ for (size_t i = from; i < until; i++) {
787
+ uint64_t value = refs && state == SCR_ARR_VALUE ? scr_elem_retain_slot(a, slot) : slot;
788
+ scr_arr_replace_state_owned(a, i, value, state);
789
+ }
790
+ }
791
+ return scr_arr_retain(a);
792
+ }
793
+
794
+ ScrArr *scr_arr_fill_f64(ScrArr *a, double value, double start, double end) {
795
+ return scr_arr_fill_slot(a, scr_slot_from_f64(value), SCR_ARR_VALUE, start, end);
796
+ }
797
+
798
+ ScrArr *scr_arr_fill_bool(ScrArr *a, bool value, double start, double end) {
799
+ return scr_arr_fill_slot(a, value ? 1 : 0, SCR_ARR_VALUE, start, end);
800
+ }
801
+
802
+ ScrArr *scr_arr_fill_ref(ScrArr *a, void *value, double start, double end) {
803
+ return scr_arr_fill_slot(a, scr_slot_from_ptr(value), SCR_ARR_VALUE, start, end);
804
+ }
805
+
806
+ ScrArr *scr_arr_fill_undefined(ScrArr *a, double start, double end) {
807
+ return scr_arr_fill_slot(a, 0, SCR_ARR_UNDEFINED, start, end);
808
+ }
809
+
681
810
  /* ── Math.max/min over one spread number[] ─────────────────────────────
682
811
  * The JS fold exactly (ECMA Math.max/min applied to the elements): any
683
812
  * NaN poisons the result, +0 beats -0 for max (the reverse for min), and
@@ -924,10 +1053,33 @@ double scr_arr_push_ref(ScrArr *a, void *v) {
924
1053
  return scr_arr_push_slot(a, scr_slot_from_ptr(v));
925
1054
  }
926
1055
 
1056
+ double scr_arr_push_many(ScrArr *a, size_t count, const uint64_t *slots) {
1057
+ if (count > SCR_ARR_MAX_LENGTH - a->len) scr_arr_oom();
1058
+ size_t from = a->len, next = from + count;
1059
+ if (next <= SCR_ARR_DENSE_LIMIT) {
1060
+ scr_arr_grow_dense(a, next);
1061
+ if (count) {
1062
+ memcpy(a->data + from, slots, count * sizeof(*slots));
1063
+ memset(a->present + from, SCR_ARR_VALUE, count);
1064
+ }
1065
+ } else {
1066
+ for (size_t i = 0; i < count; i++) scr_arr_store_owned(a, from + i, slots[i]);
1067
+ }
1068
+ a->len = next;
1069
+ return (double)next;
1070
+ }
1071
+
927
1072
  double scr_arr_push_spread(ScrArr *a, const ScrArr *src) {
928
1073
  size_t old_len = a->len;
929
1074
  size_t add = src->len;
930
1075
  if (add > SCR_ARR_MAX_LENGTH - old_len) scr_arr_oom();
1076
+ if (scr_arr_is_dense(a) && scr_arr_is_dense(src) &&
1077
+ old_len + add <= SCR_ARR_DENSE_LIMIT) {
1078
+ scr_arr_grow_dense(a, old_len + add);
1079
+ scr_arr_copy_dense(a, old_len, src, 0, add, false, true);
1080
+ a->len += add;
1081
+ return (double)a->len;
1082
+ }
931
1083
  if (src == a) {
932
1084
  ScrArrStorage old = scr_arr_take_storage(a);
933
1085
  a->len = 0;
@@ -962,6 +1114,13 @@ double scr_arr_concat_copy(ScrArr *a, const ScrArr *src) {
962
1114
  size_t old_len = a->len;
963
1115
  size_t add = src->len;
964
1116
  if (add > SCR_ARR_MAX_LENGTH - old_len) scr_arr_oom();
1117
+ if (scr_arr_is_dense(a) && scr_arr_is_dense(src) &&
1118
+ old_len + add <= SCR_ARR_DENSE_LIMIT) {
1119
+ scr_arr_grow_dense(a, old_len + add);
1120
+ scr_arr_copy_dense(a, old_len, src, 0, add, false, false);
1121
+ a->len += add;
1122
+ return (double)a->len;
1123
+ }
965
1124
  if (src == a) {
966
1125
  ScrArrStorage old = scr_arr_take_storage(a);
967
1126
  a->len = 0;
@@ -1003,6 +1162,14 @@ static double scr_arr_unshift_slot(ScrArr *a, uint64_t slot) {
1003
1162
  scr_arr_trap_oob((double)a->len, a->len);
1004
1163
  }
1005
1164
  size_t old_len = a->len;
1165
+ if (scr_arr_is_dense(a) && old_len < SCR_ARR_DENSE_LIMIT) {
1166
+ scr_arr_grow_dense(a, old_len + 1);
1167
+ scr_arr_move_dense(a, 1, 0, old_len);
1168
+ a->data[0] = slot;
1169
+ a->present[0] = SCR_ARR_VALUE;
1170
+ a->len++;
1171
+ return (double)a->len;
1172
+ }
1006
1173
  ScrArrStorage old = scr_arr_take_storage(a);
1007
1174
  a->len = 0;
1008
1175
  scr_arr_store_owned(a, 0, slot);
@@ -1030,11 +1197,46 @@ double scr_arr_unshift_ref(ScrArr *a, void *v) {
1030
1197
  return scr_arr_unshift_slot(a, scr_slot_from_ptr(v));
1031
1198
  }
1032
1199
 
1200
+ double scr_arr_unshift_many(ScrArr *a, size_t count, const uint64_t *slots) {
1201
+ size_t old_len = a->len;
1202
+ if (count == 0) return (double)old_len;
1203
+ if (count > SCR_ARR_MAX_LENGTH - old_len) scr_arr_oom();
1204
+ if (scr_arr_is_dense(a) && old_len + count <= SCR_ARR_DENSE_LIMIT) {
1205
+ scr_arr_grow_dense(a, old_len + count);
1206
+ scr_arr_move_dense(a, count, 0, old_len);
1207
+ memcpy(a->data, slots, count * sizeof(*slots));
1208
+ memset(a->present, SCR_ARR_VALUE, count);
1209
+ } else {
1210
+ ScrArrStorage old = scr_arr_take_storage(a);
1211
+ for (size_t i = 0; i < count; i++) scr_arr_store_owned(a, i, slots[i]);
1212
+ for (size_t i = 0; i < old.cap; i++) {
1213
+ if (old.present[i] != SCR_ARR_HOLE)
1214
+ scr_arr_store_state_owned(a, i + count, old.data[i], old.present[i]);
1215
+ }
1216
+ for (size_t i = 0; i < old.sparse_len; i++) {
1217
+ scr_arr_store_state_owned(a, old.sparse[i].index + count,
1218
+ old.sparse[i].slot, old.sparse[i].state);
1219
+ }
1220
+ scr_arr_free_storage(&old);
1221
+ }
1222
+ a->len = old_len + count;
1223
+ return (double)a->len;
1224
+ }
1225
+
1033
1226
  double scr_arr_unshift_spread(ScrArr *a, const ScrArr *src) {
1034
1227
  size_t old_len = a->len;
1035
1228
  size_t add = src->len;
1036
1229
  if (add == 0) return (double)old_len;
1037
1230
  if (add > SCR_ARR_MAX_LENGTH - old_len) scr_arr_oom();
1231
+ if (scr_arr_is_dense(a) && scr_arr_is_dense(src) &&
1232
+ old_len + add <= SCR_ARR_DENSE_LIMIT) {
1233
+ scr_arr_grow_dense(a, old_len + add);
1234
+ scr_arr_move_dense(a, add, 0, old_len);
1235
+ /* A self-spread reads the original values at their moved location. */
1236
+ scr_arr_copy_dense(a, 0, src, src == a ? add : 0, add, false, true);
1237
+ a->len += add;
1238
+ return (double)a->len;
1239
+ }
1038
1240
  ScrArrStorage old = scr_arr_take_storage(a);
1039
1241
  a->len = 0;
1040
1242
  for (size_t i = 0; i < add; i++) {
@@ -1064,6 +1266,19 @@ double scr_arr_unshift_spread(ScrArr *a, const ScrArr *src) {
1064
1266
 
1065
1267
  ScrArr *scr_arr_reverse(ScrArr *a) {
1066
1268
  size_t len = a->len;
1269
+ if (scr_arr_is_dense(a)) {
1270
+ for (size_t i = 0; i < len / 2; i++) {
1271
+ size_t j = len - i - 1;
1272
+ uint64_t slot;
1273
+ memcpy(&slot, a->data + i, sizeof slot);
1274
+ memcpy(a->data + i, a->data + j, sizeof slot);
1275
+ memcpy(a->data + j, &slot, sizeof slot);
1276
+ uint8_t state = a->present[i];
1277
+ a->present[i] = a->present[j];
1278
+ a->present[j] = state;
1279
+ }
1280
+ return scr_arr_retain(a);
1281
+ }
1067
1282
  ScrArrStorage old = scr_arr_take_storage(a);
1068
1283
  a->len = len;
1069
1284
  for (size_t i = 0; i < old.cap; i++) {
@@ -1113,6 +1328,14 @@ uint8_t scr_arr_shift_state(ScrArr *a, uint64_t *slot_out) {
1113
1328
  if (slot_out) *slot_out = 0;
1114
1329
  if (a->len == 0) return SCR_ARR_HOLE;
1115
1330
  size_t old_len = a->len;
1331
+ if (scr_arr_is_dense(a)) {
1332
+ uint8_t state = a->present[0];
1333
+ if (slot_out && state == SCR_ARR_VALUE) *slot_out = a->data[0];
1334
+ scr_arr_move_dense(a, 0, 1, old_len - 1);
1335
+ scr_arr_clear_dense(a, old_len - 1, 1);
1336
+ a->len--;
1337
+ return state;
1338
+ }
1116
1339
  ScrArrStorage old = scr_arr_take_storage(a);
1117
1340
  uint64_t s = 0;
1118
1341
  uint8_t state = scr_arr_state_at_storage(&old, 0, &s);
@@ -1169,6 +1392,16 @@ ScrArr *scr_arr_splice(ScrArr *a, double start, double deleteCount) {
1169
1392
  : scr_arr_new(a->elem, n ? n : 1);
1170
1393
  out->len = n;
1171
1394
  size_t old_len = a->len;
1395
+ if (scr_arr_is_dense(a)) {
1396
+ if (n) {
1397
+ memcpy(out->data, a->data + from, n * sizeof(*a->data));
1398
+ memcpy(out->present, a->present + from, n);
1399
+ }
1400
+ scr_arr_move_dense(a, from, from + n, old_len - from - n);
1401
+ scr_arr_clear_dense(a, old_len - n, n);
1402
+ a->len -= n;
1403
+ return out;
1404
+ }
1172
1405
  ScrArrStorage old = scr_arr_take_storage(a);
1173
1406
  a->len = 0;
1174
1407
  for (size_t i = 0; i < old.cap; i++) {
@@ -1215,6 +1448,30 @@ ScrArr *scr_arr_splice_insert(ScrArr *a, double start, double deleteCount,
1215
1448
  double d0 = isnan(deleteCount) ? 0 : trunc(deleteCount);
1216
1449
  size_t n = d0 <= 0 ? 0 : d0 >= avail ? (size_t)avail : (size_t)d0;
1217
1450
  if (items->len > SCR_ARR_MAX_LENGTH - (a->len - n)) scr_arr_oom();
1451
+ size_t add = items->len, next_len = a->len - n + add;
1452
+ if (scr_arr_is_dense(a) && scr_arr_is_dense(items) &&
1453
+ next_len <= SCR_ARR_DENSE_LIMIT) {
1454
+ /* Snapshot an aliased argument before changing the receiver. Ordinary
1455
+ * callers have already materialized variadic arguments, so this copy
1456
+ * is needed only by direct self-spread runtime callers. */
1457
+ ScrArr *snapshot = items == a ? scr_arr_slice(a, 0, INFINITY) : NULL;
1458
+ if (snapshot) items = snapshot;
1459
+ ScrArr *removed = a->elem == SCR_ELEM_REF
1460
+ ? scr_arr_new_ref(a->elem_retain, a->elem_release, a->elem_trace, n)
1461
+ : scr_arr_new(a->elem, n);
1462
+ if (n) {
1463
+ memcpy(removed->data, a->data + from, n * sizeof(*a->data));
1464
+ memcpy(removed->present, a->present + from, n);
1465
+ }
1466
+ removed->len = n;
1467
+ scr_arr_grow_dense(a, next_len);
1468
+ scr_arr_move_dense(a, from + add, from + n, a->len - from - n);
1469
+ scr_arr_copy_dense(a, from, items, 0, add, false, true);
1470
+ if (next_len < a->len) scr_arr_clear_dense(a, next_len, a->len - next_len);
1471
+ a->len = next_len;
1472
+ scr_arr_release(snapshot);
1473
+ return removed;
1474
+ }
1218
1475
  ScrArr *removed = scr_arr_splice(a, start, deleteCount);
1219
1476
  ScrArr *tail = scr_arr_splice(a, (double)from, INFINITY);
1220
1477
  scr_arr_push_spread(a, items);
@@ -1377,6 +1634,10 @@ ScrArr *scr_arr_slice(ScrArr *a, double start, double end) {
1377
1634
  ? scr_arr_new_ref(a->elem_retain, a->elem_release, a->elem_trace, n ? n : 1)
1378
1635
  : scr_arr_new(a->elem, n ? n : 1);
1379
1636
  out->len = n;
1637
+ if (to <= a->cap) {
1638
+ scr_arr_copy_dense(out, 0, a, from, n, false, false);
1639
+ return out;
1640
+ }
1380
1641
  for (size_t i = 0; i < a->cap && i < to; i++) {
1381
1642
  if (i < from || a->present[i] == SCR_ARR_HOLE) continue;
1382
1643
  uint8_t state = a->present[i];
@@ -14,20 +14,30 @@ test("fiber stacks commit on demand and preserve large frames across suspension"
14
14
  try {
15
15
  const bin = join(dir, "fiber-stacks");
16
16
  await execFileAsync("clang", [
17
- "-std=c11", "-O1", "-Wall", "-Wextra", "-Wno-deprecated-declarations",
17
+ "-std=c11",
18
+ "-O1",
19
+ "-Wall",
20
+ "-Wextra",
21
+ "-Wno-deprecated-declarations",
18
22
  "-pthread",
19
23
  ...(sanitize ? ["-fsanitize=address,undefined", "-DSCR_RC_AUDIT"] : []),
20
24
  ...(process.platform === "linux" ? ["-D_GNU_SOURCE"] : []),
21
25
  join(import.meta.dirname, "scr_async.test.c"),
22
- ...EXECUTABLE_RUNTIME_SOURCES
23
- .filter((name) => name !== "scr_async.c")
24
- .map((name) => join(import.meta.dirname, name)),
26
+ ...EXECUTABLE_RUNTIME_SOURCES.filter((name) => name !== "scr_async.c").map((name) =>
27
+ join(import.meta.dirname, name),
28
+ ),
25
29
  ...(process.platform === "linux" ? ["-lm"] : []),
26
- "-o", bin,
30
+ "-o",
31
+ bin,
27
32
  ]);
28
33
  const result = await execFileAsync(bin);
29
34
  expect(result.stdout).toBe("fiber stacks stay lazy and preserve large suspended frames\n");
30
- expect(result.stderr.replace(/^==\d+==WARNING: ASan doesn't fully support makecontext\/swapcontext.*\n/gm, "")).toBe("");
35
+ expect(
36
+ result.stderr.replace(
37
+ /^==\d+==WARNING: ASan doesn't fully support makecontext\/swapcontext.*\n/gm,
38
+ "",
39
+ ),
40
+ ).toBe("");
31
41
  } finally {
32
42
  await rm(dir, { recursive: true, force: true });
33
43
  }