@calcit/procs 0.29.0-alpha.27 → 0.29.0-alpha.29

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.
@@ -37,6 +37,7 @@ export declare let newTag: (content: string) => CalcitTag;
37
37
  export declare let castTag: (x: CalcitValue) => CalcitTag;
38
38
  export declare var refsRegistry: Map<string, CalcitRef>;
39
39
  export declare let hashFunction: (x: CalcitValue) => Hash;
40
+ export declare let format_calcit_number: (x: number) => string;
40
41
  export declare let toString: (x: CalcitValue, escaped: boolean, disableJsDataWarning?: boolean) => string;
41
42
  export declare let to_js_data: (x: CalcitValue, options?: CalcitValue) => any;
42
43
  export declare let _$n_map_$o_get: (xs: CalcitValue, k: CalcitValue) => CalcitValue;
@@ -447,6 +447,38 @@ let hashCirru = (base, x) => {
447
447
  };
448
448
  // Dirty code to change ternary-tree behavior
449
449
  overwriteHashGenerator(hashFunction);
450
+ // Calcit number text, shared by `turn-string`, `str` and printing (see docs/data/number.md).
451
+ export let format_calcit_number = (x) => {
452
+ // Match native f64 Display, which expands finite exponents into decimal notation.
453
+ if (Object.is(x, -0)) {
454
+ return "-0";
455
+ }
456
+ if (x === Infinity) {
457
+ return "inf";
458
+ }
459
+ if (x === -Infinity) {
460
+ return "-inf";
461
+ }
462
+ const text = x.toString();
463
+ const exponentIndex = text.indexOf("e");
464
+ if (exponentIndex < 0) {
465
+ return text;
466
+ }
467
+ const mantissa = text.slice(0, exponentIndex);
468
+ const exponent = Number(text.slice(exponentIndex + 1));
469
+ const sign = mantissa.startsWith("-") ? "-" : "";
470
+ const unsigned = sign ? mantissa.slice(1) : mantissa;
471
+ const decimalPoint = unsigned.indexOf(".");
472
+ const decimalIndex = (decimalPoint < 0 ? unsigned.length : decimalPoint) + exponent;
473
+ const digits = unsigned.replace(".", "");
474
+ if (decimalIndex <= 0) {
475
+ return `${sign}0.${"0".repeat(-decimalIndex)}${digits}`;
476
+ }
477
+ if (decimalIndex >= digits.length) {
478
+ return `${sign}${digits}${"0".repeat(decimalIndex - digits.length)}`;
479
+ }
480
+ return `${sign}${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
481
+ };
450
482
  export let toString = (x, escaped, disableJsDataWarning = false) => {
451
483
  if (x === null) {
452
484
  return "nil";
@@ -468,7 +500,7 @@ export let toString = (x, escaped, disableJsDataWarning = false) => {
468
500
  }
469
501
  }
470
502
  if (typeof x === "number") {
471
- return x.toString();
503
+ return format_calcit_number(x);
472
504
  }
473
505
  if (typeof x === "boolean") {
474
506
  return x.toString();
@@ -398,7 +398,7 @@ export declare let macroexpand_all: () => void;
398
398
  export declare let _$n_get_calcit_running_mode: () => void;
399
399
  export declare let _$n_get_def_doc: () => void;
400
400
  export declare let _$n_get_def_schema: () => void;
401
- export declare let _$n_ffi_response_resolve: () => void;
402
- export declare let _$n_ffi_response_reject: () => void;
403
- export declare let _$n_ffi_task_cancel: () => void;
401
+ export declare let _$n_ffi_response_resolve: (..._args: CalcitValue[]) => never;
402
+ export declare let _$n_ffi_response_reject: (..._args: CalcitValue[]) => never;
403
+ export declare let _$n_ffi_task_cancel: (..._args: CalcitValue[]) => never;
404
404
  export declare let raise: () => void;
@@ -3,7 +3,7 @@ export const calcit_version = pkg.version;
3
3
  export const calcit_package_json = pkg;
4
4
  import { parse } from "@cirru/parser.ts";
5
5
  import { writeCirruCode } from "@cirru/writer.ts";
6
- import { CalcitSymbol, CalcitTag, CalcitRecur, castTag, newTag, refsRegistry, toString, getStringName, compareTagNames, _$n__$e_, hashFunction, } from "./calcit-data.mjs";
6
+ import { CalcitSymbol, CalcitTag, CalcitRecur, castTag, newTag, refsRegistry, toString, format_calcit_number, getStringName, compareTagNames, _$n__$e_, hashFunction, } from "./calcit-data.mjs";
7
7
  import { CalcitRef, atom } from "./js-ref.mjs";
8
8
  import { CalcitStructValue } from "./js-struct-value.mjs";
9
9
  import { CalcitImpl } from "./js-impl.mjs";
@@ -946,7 +946,9 @@ export let remove_watch = (a, k) => {
946
946
  }
947
947
  throw new Error(`remove-watch failed: listener with key \`${k.value}\` not found`);
948
948
  };
949
- const MAX_RANGE_LENGTH = 4294967295;
949
+ // Same eager range limit as native `MAX_RANGE_LEN` and WASM, 2^24 elements (#1852).
950
+ const MAX_RANGE_LENGTH = 2 ** 24;
951
+ const rangeTooLarge = () => new Error(`&list:range result is too large: more than ${MAX_RANGE_LENGTH} elements`);
950
952
  export let range = (n, m, step = 1) => {
951
953
  const base = m == null ? 0 : n;
952
954
  const bound = m == null ? n : m;
@@ -964,11 +966,13 @@ export let range = (n, m, step = 1) => {
964
966
  ? Math.ceil(Math.abs(base) / Math.abs(step) + Math.abs(bound) / Math.abs(step))
965
967
  : Math.ceil((bound - base) / step);
966
968
  if (!Number.isFinite(estimatedLength) || estimatedLength > MAX_RANGE_LENGTH) {
967
- throw new Error("&list:range result is too large");
969
+ throw rangeTooLarge();
968
970
  }
969
971
  const result = [];
970
972
  if (step > 0) {
971
973
  for (let value = base; value < bound;) {
974
+ if (result.length >= MAX_RANGE_LENGTH)
975
+ throw rangeTooLarge();
972
976
  result.push(value);
973
977
  const next = value + step;
974
978
  if (next === value) {
@@ -979,6 +983,8 @@ export let range = (n, m, step = 1) => {
979
983
  }
980
984
  else {
981
985
  for (let value = base; value > bound;) {
986
+ if (result.length >= MAX_RANGE_LENGTH)
987
+ throw rangeTooLarge();
982
988
  result.push(value);
983
989
  const next = value + step;
984
990
  if (next === value) {
@@ -1158,11 +1164,12 @@ export let _$n_list_$o_slice = (xs, from, to) => {
1158
1164
  if (to == null) {
1159
1165
  to = size;
1160
1166
  }
1161
- else if (to <= from) {
1162
- return new CalcitSliceList([]);
1167
+ // Bounds are integers with 0 <= from <= to <= size, as in native (docs/data/number.md).
1168
+ if (!Number.isInteger(from) || !Number.isInteger(to) || from < 0 || from > to || to > size) {
1169
+ throw new Error(`&list:slice expected integer bounds within 0..${size}, but received: ${from} ${to}`);
1163
1170
  }
1164
- else if (to > size) {
1165
- to = size;
1171
+ if (from === to) {
1172
+ return new CalcitSliceList([]);
1166
1173
  }
1167
1174
  return xs.slice(from, to);
1168
1175
  };
@@ -1360,13 +1367,19 @@ export let cos = (n) => {
1360
1367
  return Math.cos(n);
1361
1368
  };
1362
1369
  export let pow = (n, m) => {
1370
+ // IEEE 754 pow, which Math.pow breaks: pow(1, y) is 1 for any y, pow(-1, ±Infinity) is 1.
1371
+ if (n === 1 || (n === -1 && (m === Infinity || m === -Infinity))) {
1372
+ return 1;
1373
+ }
1363
1374
  return Math.pow(n, m);
1364
1375
  };
1365
1376
  export let ceil = (n) => {
1366
1377
  return Math.ceil(n);
1367
1378
  };
1368
1379
  export let round = (n) => {
1369
- return Math.round(n);
1380
+ // Ties round away from zero; `Math.round` alone rounds them toward +Infinity.
1381
+ // Negating keeps `-0` for inputs such as -0.4.
1382
+ return n < 0 ? -Math.round(-n) : Math.round(n);
1370
1383
  };
1371
1384
  export let _$n_number_$o_fract = (n) => {
1372
1385
  return n - Math.floor(n);
@@ -1519,6 +1532,10 @@ export let _$n_number_$o_format = (x, n) => {
1519
1532
  return x.toFixed(n);
1520
1533
  };
1521
1534
  export let _$n_number_$o_display_by = (x, n) => {
1535
+ // a non-negative safe integer, printed exactly (docs/data/number.md)
1536
+ if (typeof x !== "number" || !Number.isSafeInteger(x) || x < 0) {
1537
+ throw new Error(`&number:display-by expected a non-negative safe integer, but received: ${x}`);
1538
+ }
1522
1539
  switch (n) {
1523
1540
  case 2:
1524
1541
  return `0b${x.toString(2)}`;
@@ -1690,37 +1707,6 @@ export let quit_$x_ = (code) => {
1690
1707
  throw new Error(`quit!(${code})`);
1691
1708
  }
1692
1709
  };
1693
- let format_calcit_number = (x) => {
1694
- // Match native f64 Display, which expands finite exponents into decimal notation.
1695
- if (Object.is(x, -0)) {
1696
- return "-0";
1697
- }
1698
- if (x === Infinity) {
1699
- return "inf";
1700
- }
1701
- if (x === -Infinity) {
1702
- return "-inf";
1703
- }
1704
- const text = x.toString();
1705
- const exponentIndex = text.indexOf("e");
1706
- if (exponentIndex < 0) {
1707
- return text;
1708
- }
1709
- const mantissa = text.slice(0, exponentIndex);
1710
- const exponent = Number(text.slice(exponentIndex + 1));
1711
- const sign = mantissa.startsWith("-") ? "-" : "";
1712
- const unsigned = sign ? mantissa.slice(1) : mantissa;
1713
- const decimalPoint = unsigned.indexOf(".");
1714
- const decimalIndex = (decimalPoint < 0 ? unsigned.length : decimalPoint) + exponent;
1715
- const digits = unsigned.replace(".", "");
1716
- if (decimalIndex <= 0) {
1717
- return `${sign}0.${"0".repeat(-decimalIndex)}${digits}`;
1718
- }
1719
- if (decimalIndex >= digits.length) {
1720
- return `${sign}${digits}${"0".repeat(decimalIndex - digits.length)}`;
1721
- }
1722
- return `${sign}${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
1723
- };
1724
1710
  export let turn_string = (x) => {
1725
1711
  if (x === null) {
1726
1712
  return "";
@@ -2053,75 +2039,75 @@ const typed_edn_error = (path, message) => {
2053
2039
  const enum_prototype_name = (value) => {
2054
2040
  return value instanceof CalcitEnumDef ? value.name() : value.name.value;
2055
2041
  };
2056
- const decode_typed_edn_node = (graph, nodeId, input, path, depth) => {
2042
+ const decode_typed_edn_node = (graph, nodeId, input, path, depth, fail = typed_edn_error) => {
2057
2043
  if (depth > 1024)
2058
- typed_edn_error(path, "decode nesting exceeds 1024");
2044
+ fail(path, "decode nesting exceeds 1024");
2059
2045
  const node = graph.nodes[nodeId];
2060
2046
  if (node == null)
2061
- typed_edn_error(path, `invalid data shape node #${nodeId}`);
2047
+ fail(path, `invalid data shape node #${nodeId}`);
2062
2048
  switch (node.kind) {
2063
2049
  case "nil":
2064
2050
  if (input === null)
2065
2051
  return null;
2066
- return typed_edn_error(path, `expected Nil, got ${typed_edn_kind(input)}`);
2052
+ return fail(path, `expected nil, got ${typed_edn_kind(input)}`);
2067
2053
  case "unit":
2068
2054
  if (input === undefined)
2069
2055
  return input;
2070
- return typed_edn_error(path, `expected Unit, got ${typed_edn_kind(input)}`);
2056
+ return fail(path, `expected &unit, got ${typed_edn_kind(input)}`);
2071
2057
  case "bool":
2072
2058
  if (typeof input === "boolean")
2073
2059
  return input;
2074
- return typed_edn_error(path, `expected bool, got ${typed_edn_kind(input)}`);
2060
+ return fail(path, `expected bool, got ${typed_edn_kind(input)}`);
2075
2061
  case "number":
2076
2062
  if (typeof input === "number")
2077
2063
  return input;
2078
- return typed_edn_error(path, `expected number, got ${typed_edn_kind(input)}`);
2064
+ return fail(path, `expected number, got ${typed_edn_kind(input)}`);
2079
2065
  case "numeric":
2080
2066
  if (typeof input !== "number")
2081
- return typed_edn_error(path, `expected ${node.target}, got ${typed_edn_kind(input)}`);
2067
+ return fail(path, `expected ${node.target}, got ${typed_edn_kind(input)}`);
2082
2068
  if (_$n_number_$o_fits_$q_(input, newTag(node.target)))
2083
2069
  return input;
2084
- return typed_edn_error(path, `number ${input} does not fit ${node.target}`);
2070
+ return fail(path, `number ${input} does not fit ${node.target}`);
2085
2071
  case "string":
2086
2072
  if (typeof input === "string")
2087
2073
  return input;
2088
- return typed_edn_error(path, `expected string, got ${typed_edn_kind(input)}`);
2074
+ return fail(path, `expected string, got ${typed_edn_kind(input)}`);
2089
2075
  case "symbol":
2090
2076
  if (input instanceof CalcitSymbol)
2091
2077
  return input;
2092
- return typed_edn_error(path, `expected symbol, got ${typed_edn_kind(input)}`);
2078
+ return fail(path, `expected symbol, got ${typed_edn_kind(input)}`);
2093
2079
  case "tag":
2094
2080
  if (input instanceof CalcitTag)
2095
2081
  return input;
2096
- return typed_edn_error(path, `expected tag, got ${typed_edn_kind(input)}`);
2082
+ return fail(path, `expected tag, got ${typed_edn_kind(input)}`);
2097
2083
  case "buffer":
2098
2084
  if (input instanceof Uint8Array)
2099
2085
  return input;
2100
- return typed_edn_error(path, `expected buffer, got ${typed_edn_kind(input)}`);
2086
+ return fail(path, `expected buffer, got ${typed_edn_kind(input)}`);
2101
2087
  case "cirru-quote":
2102
2088
  if (input instanceof CalcitCirruQuote)
2103
2089
  return input;
2104
- return typed_edn_error(path, `expected cirru-quote, got ${typed_edn_kind(input)}`);
2090
+ return fail(path, `expected cirru-quote, got ${typed_edn_kind(input)}`);
2105
2091
  case "optional":
2106
- return input === null ? null : decode_typed_edn_node(graph, node.inner, input, path, depth + 1);
2092
+ return input === null ? null : decode_typed_edn_node(graph, node.inner, input, path, depth + 1, fail);
2107
2093
  case "list": {
2108
2094
  if (!(input instanceof CalcitList || input instanceof CalcitSliceList)) {
2109
- return typed_edn_error(path, `expected list, got ${typed_edn_kind(input)}`);
2095
+ return fail(path, `expected list, got ${typed_edn_kind(input)}`);
2110
2096
  }
2111
- const values = Array.from(input.items()).map((value, idx) => decode_typed_edn_node(graph, node.inner, value, `${path}[${idx}]`, depth + 1));
2097
+ const values = Array.from(input.items()).map((value, idx) => decode_typed_edn_node(graph, node.inner, value, `${path}[${idx}]`, depth + 1, fail));
2112
2098
  return new CalcitSliceList(values);
2113
2099
  }
2114
2100
  case "set": {
2115
2101
  if (!(input instanceof CalcitSet || input instanceof TypedEdnSetView)) {
2116
- return typed_edn_error(path, `expected set, got ${typed_edn_kind(input)}`);
2102
+ return fail(path, `expected set, got ${typed_edn_kind(input)}`);
2117
2103
  }
2118
2104
  const values = [];
2119
2105
  const inputValues = input instanceof TypedEdnSetView ? input.items : input.values();
2120
2106
  inputValues.forEach((value) => {
2121
2107
  const itemPath = `${path}.item`;
2122
- const decoded = decode_typed_edn_node(graph, node.inner, value, itemPath, depth + 1);
2108
+ const decoded = decode_typed_edn_node(graph, node.inner, value, itemPath, depth + 1, fail);
2123
2109
  if (values.some((existing) => _$n__$e_(existing, decoded))) {
2124
- typed_edn_error(itemPath, "duplicate decoded set value");
2110
+ fail(itemPath, "duplicate decoded set value");
2125
2111
  }
2126
2112
  values.push(decoded);
2127
2113
  });
@@ -2129,53 +2115,53 @@ const decode_typed_edn_node = (graph, nodeId, input, path, depth) => {
2129
2115
  }
2130
2116
  case "map": {
2131
2117
  if (!(input instanceof CalcitMap || input instanceof CalcitSliceMap)) {
2132
- return typed_edn_error(path, `expected map, got ${typed_edn_kind(input)}`);
2118
+ return fail(path, `expected map, got ${typed_edn_kind(input)}`);
2133
2119
  }
2134
2120
  const entries = [];
2135
2121
  input.pairs().forEach(([key, value]) => {
2136
2122
  const keyPath = `${path}.key`;
2137
- const decodedKey = decode_typed_edn_node(graph, node.key, key, keyPath, depth + 1);
2123
+ const decodedKey = decode_typed_edn_node(graph, node.key, key, keyPath, depth + 1, fail);
2138
2124
  for (let idx = 0; idx < entries.length; idx += 2) {
2139
2125
  if (_$n__$e_(entries[idx], decodedKey)) {
2140
- typed_edn_error(keyPath, "duplicate decoded map key");
2126
+ fail(keyPath, "duplicate decoded map key");
2141
2127
  }
2142
2128
  }
2143
- const decodedValue = decode_typed_edn_node(graph, node.value, value, `${path}.value`, depth + 1);
2129
+ const decodedValue = decode_typed_edn_node(graph, node.value, value, `${path}.value`, depth + 1, fail);
2144
2130
  entries.push(decodedKey, decodedValue);
2145
2131
  });
2146
2132
  return new CalcitSliceMap(entries);
2147
2133
  }
2148
2134
  case "ref":
2149
2135
  if (!(input instanceof CalcitRef))
2150
- return typed_edn_error(path, `expected atom, got ${typed_edn_kind(input)}`);
2151
- return atom(decode_typed_edn_node(graph, node.inner, input.value, `${path}.value`, depth + 1));
2136
+ return fail(path, `expected atom, got ${typed_edn_kind(input)}`);
2137
+ return atom(decode_typed_edn_node(graph, node.inner, input.value, `${path}.value`, depth + 1, fail));
2152
2138
  case "struct": {
2153
2139
  if (!(input instanceof CalcitStructValue)) {
2154
- return typed_edn_error(path, `expected struct :${node.nominal.name.value}, got ${typed_edn_kind(input)}`);
2140
+ return fail(path, `expected struct :${node.nominal.name.value}, got ${typed_edn_kind(input)}`);
2155
2141
  }
2156
2142
  if (input.name.value !== node.nominal.name.value) {
2157
- return typed_edn_error(path, `expected struct :${node.nominal.name.value}, got struct :${input.name.value}`);
2143
+ return fail(path, `expected struct :${node.nominal.name.value}, got struct :${input.name.value}`);
2158
2144
  }
2159
2145
  const expectedNames = node.fields.map(([name]) => name);
2160
2146
  const actualNames = input.fields.map((field) => field.value);
2161
2147
  const missing = expectedNames.filter((name) => !actualNames.includes(name)).sort();
2162
2148
  const unknown = actualNames.filter((name) => !expectedNames.includes(name)).sort();
2163
2149
  if (missing.length > 0 || unknown.length > 0 || expectedNames.length !== actualNames.length) {
2164
- return typed_edn_error(path, `struct :${node.nominal.name.value} fields mismatch; missing [${missing.join(", ")}], unknown [${unknown.join(", ")}]`);
2150
+ return fail(path, `struct :${node.nominal.name.value} fields mismatch; missing [${missing.join(", ")}], unknown [${unknown.join(", ")}]`);
2165
2151
  }
2166
2152
  const decodedFields = new Map();
2167
2153
  node.fields.forEach(([name, fieldNode]) => {
2168
2154
  const idx = actualNames.indexOf(name);
2169
- decodedFields.set(name, decode_typed_edn_node(graph, fieldNode, input.values[idx], `${path}.${name}`, depth + 1));
2155
+ decodedFields.set(name, decode_typed_edn_node(graph, fieldNode, input.values[idx], `${path}.${name}`, depth + 1, fail));
2170
2156
  });
2171
2157
  // Re-align by name so values produced by older runtimes or external data
2172
2158
  // still adopt the current nominal declaration's canonical field layout.
2173
2159
  if (decodedFields.size !== node.nominal.fields.length) {
2174
- return typed_edn_error(path, `struct :${node.nominal.name.value} decoder fields do not match its nominal declaration`);
2160
+ return fail(path, `struct :${node.nominal.name.value} decoder fields do not match its nominal declaration`);
2175
2161
  }
2176
2162
  const values = node.nominal.fields.map((field) => {
2177
2163
  if (!decodedFields.has(field.value)) {
2178
- return typed_edn_error(path, `struct :${node.nominal.name.value} is missing declared field :${field.value}`);
2164
+ return fail(path, `struct :${node.nominal.name.value} is missing declared field :${field.value}`);
2179
2165
  }
2180
2166
  return decodedFields.get(field.value);
2181
2167
  });
@@ -2183,28 +2169,28 @@ const decode_typed_edn_node = (graph, nodeId, input, path, depth) => {
2183
2169
  }
2184
2170
  case "enum": {
2185
2171
  if (!(input instanceof CalcitEnumValue) || input.enumPrototype == null) {
2186
- return typed_edn_error(path, `expected enum :${node.nominal.name()}, got ${typed_edn_kind(input)}`);
2172
+ return fail(path, `expected enum :${node.nominal.name()}, got ${typed_edn_kind(input)}`);
2187
2173
  }
2188
2174
  const actualEnumName = enum_prototype_name(input.enumPrototype);
2189
2175
  if (actualEnumName !== node.nominal.name()) {
2190
- return typed_edn_error(path, `expected enum :${node.nominal.name()}, got enum :${actualEnumName}`);
2176
+ return fail(path, `expected enum :${node.nominal.name()}, got enum :${actualEnumName}`);
2191
2177
  }
2192
2178
  if (!(input.tag instanceof CalcitTag)) {
2193
- return typed_edn_error(path, `enum :${node.nominal.name()} variant must be a tag`);
2179
+ return fail(path, `enum :${node.nominal.name()} variant must be a tag`);
2194
2180
  }
2195
2181
  const inputTag = input.tag;
2196
2182
  const variant = node.variants.find((candidate) => candidate.tag === inputTag.value);
2197
2183
  if (variant == null) {
2198
- return typed_edn_error(path, `enum :${node.nominal.name()} has no variant :${inputTag.value}`);
2184
+ return fail(path, `enum :${node.nominal.name()} has no variant :${inputTag.value}`);
2199
2185
  }
2200
2186
  if (variant.payload.length !== input.extra.length) {
2201
- return typed_edn_error(path, `enum :${node.nominal.name()} variant :${variant.tag} expects ${variant.payload.length} payload(s), got ${input.extra.length}`);
2187
+ return fail(path, `enum :${node.nominal.name()} variant :${variant.tag} expects ${variant.payload.length} payload(s), got ${input.extra.length}`);
2202
2188
  }
2203
- const values = variant.payload.map((payloadNode, idx) => decode_typed_edn_node(graph, payloadNode, input.extra[idx], `${path}.payload[${idx}]`, depth + 1));
2189
+ const values = variant.payload.map((payloadNode, idx) => decode_typed_edn_node(graph, payloadNode, input.extra[idx], `${path}.payload[${idx}]`, depth + 1, fail));
2204
2190
  return new CalcitEnumValue(newTag(variant.tag), values, node.nominal);
2205
2191
  }
2206
2192
  default:
2207
- return typed_edn_error(path, `invalid data shape node kind: ${node.kind}`);
2193
+ return fail(path, `invalid data shape node kind: ${node.kind}`);
2208
2194
  }
2209
2195
  };
2210
2196
  export let parse_cirru_edn_as = (code, graph) => {
@@ -2355,7 +2341,7 @@ const decode_runtime_map_node = (graph, nodeId, input, path, depth) => {
2355
2341
  return new CalcitEnumValue(newTag(variant.tag), values, node.nominal);
2356
2342
  }
2357
2343
  default:
2358
- return decode_typed_edn_node(graph, nodeId, input, path, depth);
2344
+ return decode_typed_edn_node(graph, nodeId, input, path, depth, map_decode_error);
2359
2345
  }
2360
2346
  };
2361
2347
  export let decode_map_as = (value, graph) => {
@@ -2980,23 +2966,30 @@ export let _$n_map_$o_diff_triple = (a, b) => {
2980
2966
  throw new Error("&map:diff-triple expected 2 maps");
2981
2967
  }
2982
2968
  };
2969
+ // Bitwise operands are integers within i32 (docs/data/number.md); JS would otherwise wrap or truncate them.
2970
+ let bit_operand = (name, x) => {
2971
+ if (typeof x !== "number" || !Number.isInteger(x) || x < -2147483648 || x > 2147483647) {
2972
+ throw new Error(`&math:${name} operand expected an integer within i32, but got: ${x}`);
2973
+ }
2974
+ return x;
2975
+ };
2983
2976
  export let bit_shr = (base, step) => {
2984
- return base >> step;
2977
+ return bit_operand("bit-shr", base) >> bit_operand("bit-shr", step);
2985
2978
  };
2986
2979
  export let bit_shl = (base, step) => {
2987
- return base << step;
2980
+ return bit_operand("bit-shl", base) << bit_operand("bit-shl", step);
2988
2981
  };
2989
2982
  export let bit_and = (a, b) => {
2990
- return a & b;
2983
+ return bit_operand("bit-and", a) & bit_operand("bit-and", b);
2991
2984
  };
2992
2985
  export let bit_or = (a, b) => {
2993
- return a | b;
2986
+ return bit_operand("bit-or", a) | bit_operand("bit-or", b);
2994
2987
  };
2995
2988
  export let bit_xor = (a, b) => {
2996
- return a ^ b;
2989
+ return bit_operand("bit-xor", a) ^ bit_operand("bit-xor", b);
2997
2990
  };
2998
2991
  export let bit_not = (a) => {
2999
- return ~a;
2992
+ return ~bit_operand("bit-not", a);
3000
2993
  };
3001
2994
  export let _$n_list_$o_to_set = (xs) => {
3002
2995
  var result = [];
@@ -3019,11 +3012,41 @@ export let _$n_list_$o_distinct = (xs) => {
3019
3012
  }
3020
3013
  return new CalcitSliceList(result);
3021
3014
  };
3015
+ // Longest padded string, the V8 string length limit, so every backend fails at the same size.
3016
+ const MAX_PADDED_LEN = 536870888;
3017
+ // Padding for `&str:pad-left` / `&str:pad-right`, measured in Unicode scalars like `&str:count`
3018
+ // (not UTF-16 units, so astral characters are never split). NaN and negative lengths pad nothing,
3019
+ // and so does an empty pattern.
3020
+ const strPadding = (procName, s, size, pattern) => {
3021
+ if (size > MAX_PADDED_LEN) {
3022
+ throw new Error(`${procName} expected a finite length up to ${MAX_PADDED_LEN}, but received: ${format_calcit_number(size)}`);
3023
+ }
3024
+ if (!(size > 0) || pattern === "")
3025
+ return "";
3026
+ let missing = Math.floor(size);
3027
+ for (const _scalar of s) {
3028
+ missing -= 1;
3029
+ if (missing <= 0)
3030
+ return "";
3031
+ }
3032
+ let patternCount = 0;
3033
+ for (const _scalar of pattern)
3034
+ patternCount += 1;
3035
+ let padding = pattern.repeat(Math.floor(missing / patternCount));
3036
+ let rest = missing % patternCount;
3037
+ for (const scalar of pattern) {
3038
+ if (rest <= 0)
3039
+ break;
3040
+ padding += scalar;
3041
+ rest -= 1;
3042
+ }
3043
+ return padding;
3044
+ };
3022
3045
  export let _$n_str_$o_pad_left = (s, size, pattern) => {
3023
- return s.padStart(size, pattern);
3046
+ return strPadding("&str:pad-left", s, size, pattern) + s;
3024
3047
  };
3025
3048
  export let _$n_str_$o_pad_right = (s, size, pattern) => {
3026
- return s.padEnd(size, pattern);
3049
+ return s + strPadding("&str:pad-right", s, size, pattern);
3027
3050
  };
3028
3051
  export let _$n_get_os = () => {
3029
3052
  return newTag("js-engine");
@@ -3079,8 +3102,12 @@ export let macroexpand_all = unavailableProc;
3079
3102
  export let _$n_get_calcit_running_mode = unavailableProc;
3080
3103
  export let _$n_get_def_doc = unavailableProc;
3081
3104
  export let _$n_get_def_schema = unavailableProc;
3082
- export let _$n_ffi_response_resolve = unavailableProc;
3083
- export let _$n_ffi_response_reject = unavailableProc;
3084
- export let _$n_ffi_task_cancel = unavailableProc;
3105
+ // A missing native lifecycle capability must not look like a successful Unit.
3106
+ const unavailableNativeFfi = (operation) => {
3107
+ throw new Error(`${operation}: native FFI capability is not available for calcit-js`);
3108
+ };
3109
+ export let _$n_ffi_response_resolve = (..._args) => unavailableNativeFfi("&ffi-response-resolve");
3110
+ export let _$n_ffi_response_reject = (..._args) => unavailableNativeFfi("&ffi-response-reject");
3111
+ export let _$n_ffi_task_cancel = (..._args) => unavailableNativeFfi("&ffi-task-cancel");
3085
3112
  // already handled in code emitter
3086
3113
  export let raise = unavailableProc;
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calcit/procs",
3
- "version": "0.29.0-alpha.27",
3
+ "version": "0.29.0-alpha.29",
4
4
  "main": "./lib/calcit.procs.mjs",
5
5
  "files": [
6
6
  "lib/",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calcit/procs",
3
- "version": "0.29.0-alpha.27",
3
+ "version": "0.29.0-alpha.29",
4
4
  "main": "./lib/calcit.procs.mjs",
5
5
  "files": [
6
6
  "lib/",