teptris 0.3.23 → 0.3.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/package.json +1 -1
- package/src/index.js +90 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "teptris",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.24",
|
|
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.js
CHANGED
|
@@ -3,6 +3,19 @@
|
|
|
3
3
|
|
|
4
4
|
const KIND_OFFSET = 4, KIND_LOCAL_DT = 5, KIND_DATE = 6, KIND_TIME = 7;
|
|
5
5
|
|
|
6
|
+
// Date instances are the JS ecosystem's datetime shape (smol-toml
|
|
7
|
+
// hands them back) - they re-enter as the engine's datetime op. The
|
|
8
|
+
// fields come straight off the Date (toISOString + the parse regex
|
|
9
|
+
// per value measured as the datetime-heavy hot cost); Date carries
|
|
10
|
+
// millisecond precision, so nanoseconds = ms * 1e6.
|
|
11
|
+
const dateToDt = (d) => ({
|
|
12
|
+
kind: KIND_OFFSET, /* toISOString always yields Z */
|
|
13
|
+
year: d.getUTCFullYear(), month: d.getUTCMonth() + 1,
|
|
14
|
+
day: d.getUTCDate(), hour: d.getUTCHours(),
|
|
15
|
+
minute: d.getUTCMinutes(), second: d.getUTCSeconds(),
|
|
16
|
+
nanosecond: d.getUTCMilliseconds() * 1e6, offset_seconds: 0,
|
|
17
|
+
});
|
|
18
|
+
|
|
6
19
|
function cstr(mod, s) {
|
|
7
20
|
const bytes = mod.lengthBytesUTF8(s) + 1;
|
|
8
21
|
const ptr = mod._teptris_wasm_alloc(bytes);
|
|
@@ -131,6 +144,15 @@ function buildValue(mod, b, key, v, errs) {
|
|
|
131
144
|
default:
|
|
132
145
|
break;
|
|
133
146
|
}
|
|
147
|
+
if (v instanceof Date) {
|
|
148
|
+
// the JS ecosystem's datetime shape re-enters as the engine's
|
|
149
|
+
// datetime op (same mapping as the RFC 3339 string form)
|
|
150
|
+
const dt = dateToDt(v);
|
|
151
|
+
mod._teptris_wasm_builder_put_datetime(
|
|
152
|
+
b, kp, dt.kind, dt.year, dt.month, dt.day, dt.hour,
|
|
153
|
+
dt.minute, dt.second, dt.nanosecond, dt.offset_seconds);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
134
156
|
if (Array.isArray(v)) {
|
|
135
157
|
mod._teptris_wasm_builder_open_array(b, kp);
|
|
136
158
|
for (const item of v) buildValue(mod, b, null, item, errs);
|
|
@@ -278,9 +300,73 @@ export function initApi(mod) {
|
|
|
278
300
|
n += 1 + written;
|
|
279
301
|
}
|
|
280
302
|
};
|
|
303
|
+
// the datetime record is value-only (the key op precedes it)
|
|
304
|
+
const writeDatetime = (k, dt) => {
|
|
305
|
+
if (k !== null) wkey(k);
|
|
306
|
+
ensure(27);
|
|
307
|
+
buf[n++] = 7;
|
|
308
|
+
buf[n++] = dt.kind;
|
|
309
|
+
i64(dt.year);
|
|
310
|
+
buf[n++] = dt.month; buf[n++] = dt.day; buf[n++] = dt.hour;
|
|
311
|
+
buf[n++] = dt.minute; buf[n++] = dt.second;
|
|
312
|
+
u32(dt.nanosecond);
|
|
313
|
+
i64(dt.offset_seconds);
|
|
314
|
+
};
|
|
281
315
|
const scalar = (k, v) => {
|
|
282
316
|
// array ELEMENTS carry no key op (writer grammar v0.3.11): the
|
|
283
317
|
// old klen-0 marker is now a genuine empty key
|
|
318
|
+
if (v instanceof Date) {
|
|
319
|
+
writeDatetime(k, dateToDt(v));
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
// HOT PATH: keyed int/bool scalars (the mega-flat shapes are
|
|
323
|
+
// exactly this) - ONE growth check for key + value together,
|
|
324
|
+
// wkey inlined, direct DataView writes. The profiled dump cost
|
|
325
|
+
// was 91% JS walk: per-byte closure calls dominated.
|
|
326
|
+
if (k !== null && typeof v === "number" && !Object.is(v, -0) &&
|
|
327
|
+
Number.isInteger(v) && v >= -I64_BOUND && v < I64_BOUND) {
|
|
328
|
+
ensure(4 + k.length * 3 + 8);
|
|
329
|
+
buf[n++] = 1; /* the KEY op */
|
|
330
|
+
let ascii = true;
|
|
331
|
+
for (let i = 0; i < k.length; i++) {
|
|
332
|
+
const c = k.charCodeAt(i);
|
|
333
|
+
if (c > 127) { ascii = false; break; }
|
|
334
|
+
buf[n + 1 + i] = c;
|
|
335
|
+
}
|
|
336
|
+
if (ascii) {
|
|
337
|
+
buf[n] = k.length; n += 1 + k.length;
|
|
338
|
+
} else {
|
|
339
|
+
const { written } = utf8enc.encodeInto(k, buf.subarray(n + 1));
|
|
340
|
+
buf[n] = written; n += 1 + written;
|
|
341
|
+
}
|
|
342
|
+
buf[n++] = 3;
|
|
343
|
+
if (v >= -2147483648 && v <= 2147483647) {
|
|
344
|
+
dv.setInt32(n, v, true);
|
|
345
|
+
dv.setInt32(n + 4, v < 0 ? -1 : 0, true);
|
|
346
|
+
} else {
|
|
347
|
+
dv.setBigInt64(n, BigInt(v), true);
|
|
348
|
+
}
|
|
349
|
+
n += 8;
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
if (k !== null && typeof v === "boolean") {
|
|
353
|
+
ensure(3 + k.length * 3 + 1);
|
|
354
|
+
buf[n++] = 1; /* the KEY op */
|
|
355
|
+
let ascii = true;
|
|
356
|
+
for (let i = 0; i < k.length; i++) {
|
|
357
|
+
const c = k.charCodeAt(i);
|
|
358
|
+
if (c > 127) { ascii = false; break; }
|
|
359
|
+
buf[n + 1 + i] = c;
|
|
360
|
+
}
|
|
361
|
+
if (ascii) {
|
|
362
|
+
buf[n] = k.length; n += 1 + k.length;
|
|
363
|
+
} else {
|
|
364
|
+
const { written } = utf8enc.encodeInto(k, buf.subarray(n + 1));
|
|
365
|
+
buf[n] = written; n += 1 + written;
|
|
366
|
+
}
|
|
367
|
+
buf[n++] = v ? 6 : 5;
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
284
370
|
if (k !== null) wkey(k);
|
|
285
371
|
if (typeof v === "boolean") { byte(v ? 6 : 5); return; }
|
|
286
372
|
if (typeof v === "number") {
|
|
@@ -304,18 +390,7 @@ export function initApi(mod) {
|
|
|
304
390
|
}
|
|
305
391
|
if (typeof v === "string") {
|
|
306
392
|
if (maybeRfc3339(v) && RFC3339.test(v)) {
|
|
307
|
-
|
|
308
|
-
// the key prefix is already written (top of scalar()); the
|
|
309
|
-
// datetime record is value-only - re-sending the key here
|
|
310
|
-
// crashed bare array elements (k === null)
|
|
311
|
-
ensure(27);
|
|
312
|
-
buf[n++] = 7;
|
|
313
|
-
buf[n++] = dt.kind;
|
|
314
|
-
i64(dt.year);
|
|
315
|
-
buf[n++] = dt.month; buf[n++] = dt.day; buf[n++] = dt.hour;
|
|
316
|
-
buf[n++] = dt.minute; buf[n++] = dt.second;
|
|
317
|
-
u32(dt.nanosecond);
|
|
318
|
-
i64(dt.offset_seconds);
|
|
393
|
+
writeDatetime(null, parseDateTime(v));
|
|
319
394
|
return;
|
|
320
395
|
}
|
|
321
396
|
ensure(5 + v.length * 3);
|
|
@@ -341,7 +416,8 @@ export function initApi(mod) {
|
|
|
341
416
|
const isScalar = (v) =>
|
|
342
417
|
v !== null && (typeof v !== "object" || Array.isArray(v) === false &&
|
|
343
418
|
(typeof v === "string" || typeof v === "number" ||
|
|
344
|
-
typeof v === "boolean" || typeof v === "bigint"))
|
|
419
|
+
typeof v === "boolean" || typeof v === "bigint")) ||
|
|
420
|
+
v instanceof Date;
|
|
345
421
|
let depth = 0;
|
|
346
422
|
const members = (o, inline) => {
|
|
347
423
|
// name the engine's 512 ceiling: without this the JS stack
|
|
@@ -365,7 +441,7 @@ export function initApi(mod) {
|
|
|
365
441
|
if (Array.isArray(v)) {
|
|
366
442
|
const aot = v.length > 0 && !inline && v.every(
|
|
367
443
|
(x) => x !== null && typeof x === "object" &&
|
|
368
|
-
!Array.isArray(x));
|
|
444
|
+
!Array.isArray(x) && !(x instanceof Date));
|
|
369
445
|
if (aot) {
|
|
370
446
|
// element bodies are EXPLICIT (the element opens with the
|
|
371
447
|
// section op): nested tables promote to [path.sub]
|