teptris 0.3.13 → 0.3.15
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/dist/teptris.wasm +0 -0
- package/package.json +1 -1
- package/src/index.d.ts +7 -1
- package/src/index.js +40 -10
package/dist/teptris.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "teptris",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.15",
|
|
4
4
|
"description": "TOML for JavaScript/TypeScript at libteptris speed (WebAssembly, no fallback) - version tracks the engine ({engine}.{iteration}; npm semver is 3-part)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
package/src/index.d.ts
CHANGED
|
@@ -32,7 +32,13 @@ export interface TeptrisError extends Error {
|
|
|
32
32
|
export interface TeptrisApi {
|
|
33
33
|
/** Parse TOML into a JS object (natural-JSON view: real numbers,
|
|
34
34
|
* booleans, RFC 3339 datetime strings, non-finite floats as
|
|
35
|
-
* null). Throws TeptrisError on invalid input.
|
|
35
|
+
* null). Throws TeptrisError on invalid input.
|
|
36
|
+
*
|
|
37
|
+
* Precision floor: JS numbers lose precision past 2^53, so
|
|
38
|
+
* integer literals beyond that round (9223372036854775807 reads
|
|
39
|
+
* back as 9223372036854776000). dump() never wraps: values past
|
|
40
|
+
* the int64 bounds emit as floats, and bigints outside int64
|
|
41
|
+
* throw. */
|
|
36
42
|
loads(toml: string): TomlTable;
|
|
37
43
|
|
|
38
44
|
/** Serialize a table to canonical TOML via the engine builder.
|
package/src/index.js
CHANGED
|
@@ -53,6 +53,16 @@ function parseDateTime(str) {
|
|
|
53
53
|
const RFC3339 =
|
|
54
54
|
/^\d{4}-\d{2}-\d{2}([T ]\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?)?$|^\d{2}:\d{2}:\d{2}(\.\d+)?$/;
|
|
55
55
|
|
|
56
|
+
// int64 bounds for the dump integer path: Number.isInteger is true for
|
|
57
|
+
// values like 1e21, and the op-stream's int64 encode wraps silently
|
|
58
|
+
// past these bounds. The bound is 2^63 EXCLUSIVE (exactly representable
|
|
59
|
+
// as a number; 2^63-1 is not - its literal rounds up to 2^63).
|
|
60
|
+
// BigInt(number) of an integral in-range f64 is exact, so anything
|
|
61
|
+
// between 2^53 and 2^63 is still lossless.
|
|
62
|
+
const I64_BOUND = 9223372036854775808; /* 2 ** 63 */
|
|
63
|
+
const I64_MIN_BIG = -9223372036854775808n;
|
|
64
|
+
const I64_MAX_BIG = 9223372036854775807n;
|
|
65
|
+
|
|
56
66
|
// cheap charset pre-check before the RFC 3339 regex: datetimes start
|
|
57
67
|
// with a digit and only ever contain digits, date/time punctuation
|
|
58
68
|
// and TZ marks - rejects nearly all plain strings without the regex.
|
|
@@ -70,11 +80,17 @@ function buildValue(mod, b, key, v, errs) {
|
|
|
70
80
|
const kp = key == null ? 0 : cstr(mod, key);
|
|
71
81
|
try {
|
|
72
82
|
if (v === null || v === undefined) {
|
|
73
|
-
throw new Error("null/undefined cannot round-trip through TOML");
|
|
83
|
+
throw new Error("null/undefined cannot round-trip through TOML (nan/inf parse to null in loads() and cannot re-enter)");
|
|
74
84
|
}
|
|
75
85
|
switch (typeof v) {
|
|
76
86
|
case "number":
|
|
77
|
-
|
|
87
|
+
// same int64-exactness guard as the op-stream path: put_integer
|
|
88
|
+
// truncates BigInts past the int64 bounds, and -0.0 keeps its
|
|
89
|
+
// sign only as a float
|
|
90
|
+
if (Object.is(v, -0)) {
|
|
91
|
+
mod._teptris_wasm_builder_put_float(b, kp, v);
|
|
92
|
+
} else if (Number.isInteger(v) &&
|
|
93
|
+
v >= -I64_BOUND && v < I64_BOUND) {
|
|
78
94
|
mod._teptris_wasm_builder_put_integer(b, kp, BigInt(v));
|
|
79
95
|
} else {
|
|
80
96
|
mod._teptris_wasm_builder_put_float(b, kp, v);
|
|
@@ -248,15 +264,29 @@ export function initApi(mod) {
|
|
|
248
264
|
}
|
|
249
265
|
};
|
|
250
266
|
const scalar = (k, v) => {
|
|
251
|
-
|
|
252
|
-
|
|
267
|
+
// array ELEMENTS carry no key op (writer grammar v0.3.11): the
|
|
268
|
+
// old klen-0 marker is now a genuine empty key
|
|
269
|
+
if (k !== null) wkey(k);
|
|
253
270
|
if (typeof v === "boolean") { byte(v ? 6 : 5); return; }
|
|
254
271
|
if (typeof v === "number") {
|
|
255
|
-
|
|
256
|
-
|
|
272
|
+
// the integer path only for numbers the int64 op can carry
|
|
273
|
+
// EXACTLY: Number.isInteger alone is true for 1e21 and for
|
|
274
|
+
// loads-rounded values past i64max, and setBigInt64 silently
|
|
275
|
+
// WRAPS out-of-range values (9223372036854775807 dumped as
|
|
276
|
+
// INT64_MIN); -0.0 must keep its sign, so it goes to the
|
|
277
|
+
// float path too
|
|
278
|
+
if (Object.is(v, -0)) { byte(4); f64(v); return; }
|
|
279
|
+
if (Number.isInteger(v) &&
|
|
280
|
+
v >= -I64_BOUND && v < I64_BOUND) { byte(3); i64(v); return; }
|
|
281
|
+
byte(4); f64(v);
|
|
257
282
|
return;
|
|
258
283
|
}
|
|
259
|
-
if (typeof v === "bigint") {
|
|
284
|
+
if (typeof v === "bigint") {
|
|
285
|
+
if (v < I64_MIN_BIG || v > I64_MAX_BIG) {
|
|
286
|
+
throw new Error(`bigint out of int64 range: ${v}`);
|
|
287
|
+
}
|
|
288
|
+
byte(3); i64(v); return;
|
|
289
|
+
}
|
|
260
290
|
if (typeof v === "string") {
|
|
261
291
|
if (maybeRfc3339(v) && RFC3339.test(v)) {
|
|
262
292
|
const dt = parseDateTime(v);
|
|
@@ -291,7 +321,7 @@ export function initApi(mod) {
|
|
|
291
321
|
}
|
|
292
322
|
return;
|
|
293
323
|
}
|
|
294
|
-
throw new Error("null/undefined cannot round-trip through TOML");
|
|
324
|
+
throw new Error("null/undefined cannot round-trip through TOML (nan/inf parse to null in loads() and cannot re-enter)");
|
|
295
325
|
};
|
|
296
326
|
const isScalar = (v) =>
|
|
297
327
|
v !== null && (typeof v !== "object" || Array.isArray(v) === false &&
|
|
@@ -307,7 +337,7 @@ export function initApi(mod) {
|
|
|
307
337
|
const k = keys[i], v = o[k];
|
|
308
338
|
if (isScalar(v)) continue;
|
|
309
339
|
if (v === null || v === undefined) {
|
|
310
|
-
throw new Error("null/undefined cannot round-trip through TOML");
|
|
340
|
+
throw new Error("null/undefined cannot round-trip through TOML (nan/inf parse to null in loads() and cannot re-enter)");
|
|
311
341
|
}
|
|
312
342
|
wkey(k);
|
|
313
343
|
if (Array.isArray(v)) {
|
|
@@ -339,7 +369,7 @@ export function initApi(mod) {
|
|
|
339
369
|
return;
|
|
340
370
|
}
|
|
341
371
|
if (el === null || el === undefined) {
|
|
342
|
-
throw new Error("null/undefined cannot round-trip through TOML");
|
|
372
|
+
throw new Error("null/undefined cannot round-trip through TOML (nan/inf parse to null in loads() and cannot re-enter)");
|
|
343
373
|
}
|
|
344
374
|
byte(0x0B);
|
|
345
375
|
members(el, true);
|