@scriptc/runtime 0.0.23 → 0.0.24

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.
package/src/scr_number.c CHANGED
@@ -24,6 +24,15 @@
24
24
  * unchanged. Provides d2d(), d2d_small_int(), decimalLength17(), div10(). */
25
25
  #include "../vendor/ryu/d2s.c"
26
26
 
27
+ /* ECMA ToUint32, shared by bitwise operators and split's limit: non-finite
28
+ * values become zero, finite values truncate toward zero and wrap mod 2^32. */
29
+ uint32_t scr_to_uint32(double d) {
30
+ if (!isfinite(d)) return 0;
31
+ double t = fmod(trunc(d), 4294967296.0);
32
+ if (t < 0) t += 4294967296.0;
33
+ return (uint32_t)t;
34
+ }
35
+
27
36
  /* The Ryū digit core, shared by the ECMA placement below and the Intl
28
37
  * en-US number formatter (scr_lib.c): the shortest round-tripping digit
29
38
  * string for a positive finite double — value = 0.digits × 10^n with no
package/src/scr_regex.c CHANGED
@@ -624,8 +624,10 @@ ScrStr *scr_regex_replace_all(ScrStr *s, ScrRegex *re, ScrStr *rep) {
624
624
 
625
625
  /* ── split ────────────────────────────────────────────────────────────── */
626
626
 
627
- ScrArr *scr_regex_split(ScrStr *s, ScrRegex *re) {
627
+ ScrArr *scr_regex_split_limit(ScrStr *s, ScrRegex *re, double limit_num) {
628
628
  uint8_t *bc = scr_regex_bc(re);
629
+ uint32_t limit = scr_to_uint32(limit_num);
630
+ if (limit == 0) return scr_arr_new(SCR_ELEM_STR, 0);
629
631
  if (lre_get_capture_count(bc) > 1) {
630
632
  /* JS splices every capture group's value into the result between the
631
633
  * pieces, changing the array's SHAPE per match — not modeled this
@@ -675,6 +677,11 @@ ScrArr *scr_regex_split(ScrStr *s, ScrRegex *re) {
675
677
  q = scr_advance(u, len, start, unicode);
676
678
  } else {
677
679
  scr_arr_push_ref(out, scr_str_from_utf16(u, p, start));
680
+ if (out->len == limit) {
681
+ free(capture);
682
+ free(u);
683
+ return out;
684
+ }
678
685
  p = end;
679
686
  q = p;
680
687
  }
@@ -685,6 +692,10 @@ ScrArr *scr_regex_split(ScrStr *s, ScrRegex *re) {
685
692
  return out;
686
693
  }
687
694
 
695
+ ScrArr *scr_regex_split(ScrStr *s, ScrRegex *re) {
696
+ return scr_regex_split_limit(s, re, 4294967295.0);
697
+ }
698
+
688
699
  /* ── String.prototype.toLowerCase / toUpperCase (the static path) ──────
689
700
  * ECMA-262 Default Case Conversion via the vendored libunicode's
690
701
  * lre_case_conv — the exact tables and algorithm the engine's own
package/src/scr_runtime.h CHANGED
@@ -612,12 +612,14 @@ ScrStr *scr_str_cp_at(ScrStr *s, double i);
612
612
  ScrStr *scr_str_trim_start(ScrStr *s);
613
613
  ScrStr *scr_str_trim_end(ScrStr *s);
614
614
 
615
- /* split(separator) with a STRING separator, no limit: empty separator
615
+ /* split(separator[, limit]) with a STRING separator: limit uses ToUint32;
616
+ * the no-limit wrapper supplies 2^32-1. Empty separator
616
617
  * splits into single UTF-16 code units (each half of an astral char is
617
618
  * U+FFFD — divergence, see above); otherwise splits on every occurrence,
618
619
  * empty pieces kept. Borrows both; returns a +1 string[] (SCR_ELEM_STR). */
619
620
  struct ScrArr;
620
621
  struct ScrArr *scr_str_split(ScrStr *s, ScrStr *sep);
622
+ struct ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit);
621
623
 
622
624
  /* padStart(maxLength, fill)/padEnd — ECMA StringPad, UTF-16 unit counts.
623
625
  * Target at or below the length (or empty fill) returns the receiver
@@ -720,6 +722,12 @@ void scr_qs_parse_into(ScrMap *out, const ScrStr *qs, const ScrStr *sep,
720
722
  const ScrStr *eq, double max_keys, uint32_t str_tag,
721
723
  uint32_t arr_tag);
722
724
 
725
+ /* node:util.parseArgs — the static checked-dynamic boundary. `config` is
726
+ * the documented JSON-safe configuration object; the returned dyn tree is
727
+ * a fresh ParsedResults object whose `values` child has null prototype.
728
+ * Borrows config; returns +1, or NULL with a Node-coded TypeError pending. */
729
+ struct ScrDyn *scr_util_parse_args(const struct ScrDyn *config);
730
+
723
731
  /* querystring.stringify — Node's stringify over a borrowed dyn value (the
724
732
  * frontend dynFroms the typed record; JS-world dyn values pass straight
725
733
  * through). Non-object dyn values answer "" like Node; object keys iterate in
@@ -880,6 +888,15 @@ double scr_arr_push_f64(ScrArr *a, double v);
880
888
  double scr_arr_push_bool(ScrArr *a, bool v);
881
889
  double scr_arr_push_ref(ScrArr *a, void *v);
882
890
 
891
+ /* unshift returns the new length and _ref takes ownership. The spread form
892
+ * borrows a same-element-kind source, retains copied refs, and snapshots
893
+ * self-spread. reverse mutates in place and returns the receiver at +1. */
894
+ double scr_arr_unshift_f64(ScrArr *a, double v);
895
+ double scr_arr_unshift_bool(ScrArr *a, bool v);
896
+ double scr_arr_unshift_ref(ScrArr *a, void *v);
897
+ double scr_arr_unshift_spread(ScrArr *a, const ScrArr *src);
898
+ ScrArr *scr_arr_reverse(ScrArr *a);
899
+
883
900
  /* pop traps on an empty array; _ref transfers ownership out (+1 to the
884
901
  * caller, no release). */
885
902
  double scr_arr_pop_f64(ScrArr *a);
@@ -983,8 +1000,10 @@ ScrStr *scr_regex_flags(ScrRegex *re); /* +1 */
983
1000
  ScrStr *scr_regex_replace(ScrStr *s, ScrRegex *re, ScrStr *rep);
984
1001
  /* replaceAll: throws Node's TypeError when /g is missing (may-throw). */
985
1002
  ScrStr *scr_regex_replace_all(ScrStr *s, ScrRegex *re, ScrStr *rep);
986
- /* split: capture-free patterns only — capture groups throw (may-throw). */
1003
+ /* split: capture-free patterns only — capture groups throw (may-throw).
1004
+ * limit uses ToUint32; the no-limit wrapper supplies 2^32-1. */
987
1005
  ScrArr *scr_regex_split(ScrStr *s, ScrRegex *re);
1006
+ ScrArr *scr_regex_split_limit(ScrStr *s, ScrRegex *re, double limit);
988
1007
  /* matchAll drained eagerly: +1 string[][] of honest match slices; throws
989
1008
  * Node's TypeError on a non-global regex (catchable). */
990
1009
  ScrArr *scr_regex_match_all(ScrStr *s, ScrRegex *re);
@@ -2047,6 +2066,11 @@ void scr_fs_chmod(ScrStr *path, double mode);
2047
2066
  void scr_fs_chown(ScrStr *path, double uid, double gid);
2048
2067
  void scr_fs_copyfile(ScrStr *src, ScrStr *dest);
2049
2068
  void scr_fs_rename(ScrStr *oldpath, ScrStr *newpath);
2069
+ /* The callback rename worker uses the non-throwing syscall seam off the
2070
+ * runtime thread, then materializes any Node-shaped Error back on the main
2071
+ * thread. raw returns 0 on success or a positive errno value on failure. */
2072
+ int scr_fs_rename_raw(const ScrStr *oldpath, const ScrStr *newpath);
2073
+ void scr_fs_rename_error(int error, const ScrStr *oldpath, const ScrStr *newpath);
2050
2074
  void scr_fs_write_file_mode(ScrStr *path, ScrStr *data, double mode);
2051
2075
  void scr_fs_mkdir_mode(ScrStr *path, double mode);
2052
2076
  void scr_fs_mkdir_recursive_mode(ScrStr *path, double mode);
@@ -2079,6 +2103,7 @@ double scr_process_columns(double fd);
2079
2103
  * stat(2) — follows symlinks, like Node's stat family. scr_fs_stat
2080
2104
  * THROWS like the other sync calls. */
2081
2105
  typedef struct ScrStats ScrStats;
2106
+ typedef struct ScrFileHandle ScrFileHandle;
2082
2107
  typedef struct ScrPromise ScrPromise; /* full section further down */
2083
2108
 
2084
2109
  ScrStats *scr_fs_stat(ScrStr *path); /* +1, or throws */
@@ -2091,6 +2116,9 @@ bool scr_stats_is_file(ScrStats *s);
2091
2116
  bool scr_stats_is_dir(ScrStats *s);
2092
2117
  bool scr_stats_is_symlink(ScrStats *s); /* lstat snapshots only */
2093
2118
  double scr_stats_size(ScrStats *s);
2119
+ double scr_stats_blocks(ScrStats *s); /* allocated size in 512-byte units */
2120
+ double scr_stats_nlink(ScrStats *s);
2121
+ double scr_stats_atime_ms(ScrStats *s); /* ms with the sub-second fraction */
2094
2122
  double scr_stats_mtime_ms(ScrStats *s); /* ms with the ns fraction */
2095
2123
 
2096
2124
  /* fs/promises: the SAME sync operations, minting an already-settled
@@ -2101,6 +2129,7 @@ double scr_stats_mtime_ms(ScrStats *s); /* ms with the ns fraction */
2101
2129
  * scr_lib.c without the fiber slice). */
2102
2130
  ScrPromise *scr_fsp_read_file(ScrStr *path);
2103
2131
  ScrPromise *scr_fsp_write_file(ScrStr *path, ScrStr *data);
2132
+ ScrPromise *scr_fsp_write_file_mode(ScrStr *path, ScrStr *data, double mode);
2104
2133
  ScrPromise *scr_fsp_mkdir(ScrStr *path);
2105
2134
  ScrPromise *scr_fsp_mkdir_mode(ScrStr *path, double mode);
2106
2135
  ScrPromise *scr_fsp_mkdir_recursive(ScrStr *path);
@@ -2110,6 +2139,24 @@ ScrPromise *scr_fsp_chmod(ScrStr *path, double mode);
2110
2139
  ScrPromise *scr_fsp_readdir(ScrStr *path);
2111
2140
  ScrPromise *scr_fsp_rm(ScrStr *path);
2112
2141
  ScrPromise *scr_fsp_stat(ScrStr *path);
2142
+ ScrPromise *scr_fsp_rename(ScrStr *oldpath, ScrStr *newpath);
2143
+ ScrPromise *scr_fsp_open(ScrStr *path, ScrStr *flags, double mode);
2144
+ ScrPromise *scr_file_handle_close_promise(ScrFileHandle *h);
2145
+ ScrPromise *scr_file_handle_read_file_promise(ScrFileHandle *h, ScrStr *encoding);
2146
+ ScrPromise *scr_file_handle_read_file_bytes_promise(ScrFileHandle *h, ScrStr *encoding);
2147
+ ScrPromise *scr_file_handle_write_file_promise(ScrFileHandle *h, ScrStr *data, ScrStr *encoding);
2148
+ ScrPromise *scr_file_handle_write_file_bytes_promise(ScrFileHandle *h, ScrBytes *data, ScrStr *encoding);
2149
+ ScrPromise *scr_file_handle_stat_promise(ScrFileHandle *h);
2150
+
2151
+ /* fs.rename: the syscall is submitted to a native worker immediately and
2152
+ * its error-first callback fires on a later event-loop turn through an
2153
+ * emitted, program-shaped adapter. Both paths and the callback are borrowed
2154
+ * at entry; the callback MOVES into the operation. err is borrowed and NULL
2155
+ * on success. */
2156
+ typedef void (*ScrFsRenameFn)(ScrClosure *cb, ScrError *err);
2157
+ void scr_fs_rename_async(ScrStr *oldpath, ScrStr *newpath,
2158
+ ScrClosure *cb /*moves*/, ScrFsRenameFn fn);
2159
+ void scr_fs_rename_thunk0(ScrClosure *cb, ScrError *err);
2113
2160
 
2114
2161
  /* ── node:timers/promises (scr_async.c) ──────────────────────────────
2115
2162
  * The promisified pair: a PENDING void promise a one-shot heap timer /
@@ -2459,10 +2506,36 @@ ScrStr *scr_path_win32_to_namespaced_path(ScrStr *path);
2459
2506
  * (failure throws the path-less "EBADF: bad file descriptor, close").
2460
2507
  * The pair behind spawn's fd-stdio form. */
2461
2508
  double scr_fs_open(ScrStr *path, ScrStr *flags);
2509
+ ScrFileHandle *scr_file_handle_open(ScrStr *path, ScrStr *flags, double mode);
2510
+ ScrFileHandle *scr_file_handle_retain(ScrFileHandle *h);
2511
+ void scr_file_handle_release(ScrFileHandle *h);
2512
+ void *scr_file_handle_retain_v(void *p);
2513
+ void scr_file_handle_release_v(void *p);
2514
+ double scr_file_handle_fd(ScrFileHandle *h);
2515
+ void scr_file_handle_close(ScrFileHandle *h);
2516
+ double scr_file_handle_read(ScrFileHandle *h, ScrBytes *buf, double offset,
2517
+ double length, double position, bool length_default);
2518
+ double scr_file_handle_write_bytes(ScrFileHandle *h, ScrBytes *buf,
2519
+ double offset, double length,
2520
+ double position, bool length_default);
2521
+ double scr_file_handle_write_str(ScrFileHandle *h, ScrStr *data,
2522
+ double position, ScrStr *encoding);
2523
+ ScrStr *scr_file_handle_read_file(ScrFileHandle *h);
2524
+ ScrBytes *scr_file_handle_read_file_bytes(ScrFileHandle *h);
2525
+ void scr_file_handle_write_file(ScrFileHandle *h, ScrStr *data);
2526
+ void scr_file_handle_write_file_bytes(ScrFileHandle *h, ScrBytes *data);
2527
+ ScrStats *scr_file_handle_stat(ScrFileHandle *h);
2462
2528
  /* position == -1 reads from and advances the descriptor's current offset;
2463
2529
  * nonnegative positions leave that offset unchanged (pread/ReadFile seam). */
2464
2530
  double scr_fs_read_sync(double fd, ScrBytes *buf, double offset, double length,
2465
2531
  double position);
2532
+ /* writeSync's classic Buffer window and utf8 string forms. position -1 (or
2533
+ * any other non-safe/nonnegative-integer value) writes at and advances the
2534
+ * current descriptor offset; safe nonnegative positions leave it unchanged. */
2535
+ double scr_fs_write_sync(double fd, ScrBytes *buf, double offset, double length,
2536
+ double position);
2537
+ double scr_fs_write_str_sync(double fd, ScrStr *data, double position,
2538
+ ScrStr *encoding);
2466
2539
  void scr_fs_close(double fd);
2467
2540
 
2468
2541
  /* ── WHATWG URL (scr_url.c) ──────────────────────────────────────────
@@ -3397,6 +3470,8 @@ typedef struct {
3397
3470
  } ScrJsonBuf;
3398
3471
 
3399
3472
  void scr_jb_init(ScrJsonBuf *b);
3473
+ /* Append one borrowed runtime string verbatim (no JSON quoting). */
3474
+ void scr_jb_put_str(ScrJsonBuf *b, const ScrStr *s);
3400
3475
  /* Push a container onto the circular-detection stack before serializing
3401
3476
  * its members. If `v` is already ON the stack, throws V8's exact
3402
3477
  * "Converting circular structure to JSON" TypeError (the --> starting at /
@@ -3712,6 +3787,10 @@ bool scr_immediate_has_ref(double handle);
3712
3787
  * teardown (they must never run yet must not leak). cb ownership moves
3713
3788
  * in. */
3714
3789
  void scr_next_tick(ScrClosure *cb);
3790
+ /* A successful process.stdout/stderr.write completion on that same queue.
3791
+ * The callback and its program-shaped Error | null adapter both MOVE into
3792
+ * the entry; the adapter is invoked with NULL (Node's success argument). */
3793
+ void scr_process_write_callback(ScrClosure *cb, ScrFsRenameFn fn);
3715
3794
  /* A raw C-hook entry on the SAME queue: the stream unit enqueues one
3716
3795
  * marker per deferred stream emission, so stream ticks and user
3717
3796
  * nextTicks run in true FIFO order (in Node they are the same queue).
@@ -4493,12 +4572,14 @@ double scr_date_get_minutes_utc(double ms);
4493
4572
  double scr_date_get_seconds_local(double ms);
4494
4573
  double scr_date_get_seconds_utc(double ms);
4495
4574
 
4496
- /* ── bitwise operators (scr_lib.c) ────────────────────────────────────
4575
+ /* ── numeric coercion + bitwise operators ─────────────────────────────
4497
4576
  * JS-exact ToInt32/ToUint32 semantics: NaN/±Infinity → 0, truncation
4498
4577
  * toward zero, modular wrap into 32 bits; the operation runs in 32-bit
4499
4578
  * space (shift counts mask to 5 bits, `>>` is an arithmetic shift spelled
4500
4579
  * portably — no C UB/implementation-defined shifts) and the result
4501
- * returns to f64: `>>>` as Uint32, everything else as Int32. */
4580
+ * returns to f64: `>>>` as Uint32, everything else as Int32.
4581
+ * scr_to_uint32 lives in scr_number.c; the bitwise operations in scr_lib.c. */
4582
+ uint32_t scr_to_uint32(double d);
4502
4583
  double scr_bit_and(double a, double b);
4503
4584
  double scr_bit_or(double a, double b);
4504
4585
  double scr_bit_xor(double a, double b);
@@ -4695,12 +4776,22 @@ void scr_bytes_set_from(ScrBytes *dst, const ScrBytes *src, double offset);
4695
4776
  * compiler fences other encodings). */
4696
4777
  ScrStr *scr_bytes_to_str(const ScrBytes *b, const ScrStr *enc);
4697
4778
  ScrStr *scr_bytes_to_str_range(const ScrBytes *b, const ScrStr *enc, double start, double end);
4779
+ /* Runtime-valued Buffer.toString encoding: aliases/case canonicalize;
4780
+ * unknown names throw ERR_UNKNOWN_ENCODING. +1, or NULL when throwing. */
4781
+ ScrStr *scr_bytes_to_str_checked(const ScrBytes *b, const ScrStr *enc);
4782
+ ScrStr *scr_bytes_to_str_checked_range(const ScrBytes *b, const ScrStr *enc, double start, double end);
4698
4783
 
4699
4784
  /* WHATWG TextDecoder.decode over u8 bytes (utf-8, default options): the
4700
4785
  * same replacement decode as toString("utf8") with the leading BOM
4701
4786
  * stripped. Borrows; +1; never throws. */
4702
4787
  ScrStr *scr_text_decode(const ScrBytes *b);
4703
4788
 
4789
+ /* TextDecoder with a compile-time WHATWG legacy-encoding id. The frontend
4790
+ * owns label canonicalization and emits only the ids understood by
4791
+ * scr_bytes.c; keeping this separate from scr_text_decode means default
4792
+ * UTF-8 users do not retain the legacy mapping tables. Borrows; +1. */
4793
+ ScrStr *scr_text_decode_legacy(const ScrBytes *b, double encoding);
4794
+
4704
4795
  /* Buffer.from(string, enc): "utf8" copies the bytes; "hex" parses pairs
4705
4796
  * and stops at the first invalid/odd tail (Node-lenient); "base64" and
4706
4797
  * "base64url" decode the standard AND url-safe alphabets, skipping
@@ -4895,10 +4986,12 @@ ScrPromise *scr_fsp_read_file_bytes(ScrStr *path); /* +1 */
4895
4986
  * RangeError catchably (same check as scr_crypto_random_string). */
4896
4987
  ScrBytes *scr_crypto_random_bytes(double n); /* +1 */
4897
4988
 
4898
- /* process.stdout/stderr.write(buf): the raw byte writes' Buffer overloads
4899
- * (same streams and buffering as the string forms). Constantly true. */
4900
- bool scr_process_stdout_write_bytes(const ScrBytes *b);
4901
- bool scr_process_stderr_write_bytes(const ScrBytes *b);
4989
+ /* process.stdout/stderr.write(buf[, encoding]): the raw byte writes' Buffer
4990
+ * overloads (same streams and buffering as the string forms). The encoding
4991
+ * is evaluated by the caller and ignored here, as Node does for bytes.
4992
+ * Constantly true. */
4993
+ bool scr_process_stdout_write_bytes(const ScrBytes *b, const ScrStr *encoding);
4994
+ bool scr_process_stderr_write_bytes(const ScrBytes *b, const ScrStr *encoding);
4902
4995
 
4903
4996
  /* The Node-shaped fs error thrower (scr_lib.c): formats "ENOENT: no such
4904
4997
  * file or directory, open 'x'" and throws it catchably. Shared with
package/src/scr_string.c CHANGED
@@ -678,7 +678,9 @@ ScrStr *scr_str_trim_end(ScrStr *s) {
678
678
  static const struct { size_t rc; size_t len; size_t cap; char data[4]; }
679
679
  scr_lit_fffd = {SIZE_MAX, 3, 3, "\xEF\xBF\xBD"};
680
680
 
681
- /* split(separator) with a STRING separator, no limit (ECMA-262 22.1.3.23):
681
+ /* split(separator, limit) with a STRING separator (ECMA-262 22.1.3.23):
682
+ * limit is ToUint32'd; zero returns [] and reaching the limit stops before
683
+ * any later separator probes. The no-limit wrapper supplies 2^32-1.
682
684
  * an empty separator splits into single UTF-16 code units ("".split("") is
683
685
  * [] — no probe matches nothing); a non-empty separator splits on every
684
686
  * byte-level occurrence (well-formed UTF-8 is self-synchronizing, so byte
@@ -688,8 +690,10 @@ static const struct { size_t rc; size_t len; size_t cap; char data[4]; }
688
690
  * yield the two lone surrogate halves, each half is U+FFFD here
689
691
  * (divergence 2 — the same substitution the island's boundary marshal
690
692
  * applied). Borrows both; returns a +1 string[]. */
691
- ScrArr *scr_str_split(ScrStr *s, ScrStr *sep) {
693
+ ScrArr *scr_str_split_limit(ScrStr *s, ScrStr *sep, double limit_num) {
692
694
  ScrArr *out = scr_arr_new(SCR_ELEM_STR, 0);
695
+ uint32_t limit = scr_to_uint32(limit_num);
696
+ if (limit == 0) return out;
693
697
  if (sep->len == 0) {
694
698
  size_t i = 0;
695
699
  while (i < s->len) {
@@ -697,10 +701,12 @@ ScrArr *scr_str_split(ScrStr *s, ScrStr *sep) {
697
701
  uint32_t cp = scr_utf8_decode(s->data + i, &adv);
698
702
  if (cp >= 0x10000) { /* two units in JS: both halves become U+FFFD */
699
703
  scr_arr_push_ref(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
704
+ if (out->len == limit) return out;
700
705
  scr_arr_push_ref(out, scr_str_retain((ScrStr *)&scr_lit_fffd));
701
706
  } else {
702
707
  scr_arr_push_ref(out, scr_str_from_span(s->data + i, adv));
703
708
  }
709
+ if (out->len == limit) return out;
704
710
  i += adv;
705
711
  }
706
712
  return out;
@@ -712,12 +718,17 @@ ScrArr *scr_str_split(ScrStr *s, ScrStr *sep) {
712
718
  if (!found) break;
713
719
  size_t at = (size_t)(found - s->data);
714
720
  scr_arr_push_ref(out, scr_str_from_span(s->data + start, at - start));
721
+ if (out->len == limit) return out;
715
722
  start = at + sep->len;
716
723
  }
717
724
  scr_arr_push_ref(out, scr_str_from_span(s->data + start, s->len - start));
718
725
  return out;
719
726
  }
720
727
 
728
+ ScrArr *scr_str_split(ScrStr *s, ScrStr *sep) {
729
+ return scr_str_split_limit(s, sep, 4294967295.0);
730
+ }
731
+
721
732
  /* StringPad (ECMA-262 22.1.3.16/17): target length in UTF-16 units, the
722
733
  * filler built from whole repetitions of `fill` plus a truncated prefix.
723
734
  * A target at or below the length (or an empty fill) returns the receiver