spexcode 0.6.8 → 0.7.0-next.0

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 (72) hide show
  1. package/node_modules/@spexcode/session-application/package.json +5 -5
  2. package/node_modules/@spexcode/session-events/package.json +2 -2
  3. package/node_modules/@spexcode/session-protocol/package.json +1 -1
  4. package/node_modules/@spexcode/session-runtime/package.json +2 -2
  5. package/node_modules/@spexcode/session-selflaunch/dist/locality.d.ts +12 -1
  6. package/node_modules/@spexcode/session-selflaunch/dist/locality.js +62 -10
  7. package/node_modules/@spexcode/session-selflaunch/package.json +3 -3
  8. package/node_modules/@spexcode/session-topology/package.json +2 -2
  9. package/node_modules/@spexcode/spec-cli/bin/spex.mjs +127 -10
  10. package/node_modules/@spexcode/spec-cli/dist/cli.js +19 -0
  11. package/node_modules/@spexcode/spec-cli/dist/file-write.js +14 -2
  12. package/node_modules/@spexcode/spec-cli/dist/guide.js +9 -11
  13. package/node_modules/@spexcode/spec-cli/dist/harness.d.ts +11 -5
  14. package/node_modules/@spexcode/spec-cli/dist/harness.js +185 -28
  15. package/node_modules/@spexcode/spec-cli/dist/host.js +5 -1
  16. package/node_modules/@spexcode/spec-cli/dist/index.js +21 -65
  17. package/node_modules/@spexcode/spec-cli/dist/machine-peer.d.ts +2 -1
  18. package/node_modules/@spexcode/spec-cli/dist/machine-peer.js +45 -14
  19. package/node_modules/@spexcode/spec-cli/dist/opencode.js +10 -2
  20. package/node_modules/@spexcode/spec-cli/dist/pi-harness.js +18 -5
  21. package/node_modules/@spexcode/spec-cli/dist/pi-headless.d.ts +2 -0
  22. package/node_modules/@spexcode/spec-cli/dist/pi-headless.js +27 -0
  23. package/node_modules/@spexcode/spec-cli/dist/session-transcript.d.ts +57 -0
  24. package/node_modules/@spexcode/spec-cli/dist/session-transcript.js +137 -0
  25. package/node_modules/@spexcode/spec-cli/dist/sessions.d.ts +4 -0
  26. package/node_modules/@spexcode/spec-cli/dist/sessions.js +103 -35
  27. package/node_modules/@spexcode/spec-cli/dist/shim-runtime.js +14 -0
  28. package/node_modules/@spexcode/spec-cli/dist/supervise.js +1 -1
  29. package/node_modules/@spexcode/spec-cli/package.json +8 -6
  30. package/node_modules/@spexcode/spec-core/dist/layout.d.ts +0 -1
  31. package/node_modules/@spexcode/spec-core/package.json +1 -1
  32. package/node_modules/@spexcode/spec-core/templates/spexcode.json +36 -13
  33. package/node_modules/@spexcode/spec-eval/package.json +2 -2
  34. package/node_modules/@spexcode/spec-forge/package.json +2 -2
  35. package/node_modules/@spexcode/transcript/dist/frames.d.ts +44 -0
  36. package/node_modules/@spexcode/transcript/dist/frames.js +85 -0
  37. package/node_modules/@spexcode/transcript/dist/index.d.ts +5 -0
  38. package/node_modules/@spexcode/transcript/dist/index.js +5 -0
  39. package/node_modules/@spexcode/transcript/dist/live.d.ts +16 -0
  40. package/node_modules/@spexcode/transcript/dist/live.js +65 -0
  41. package/node_modules/@spexcode/transcript/dist/parsers.d.ts +47 -0
  42. package/node_modules/@spexcode/transcript/dist/parsers.js +285 -0
  43. package/node_modules/@spexcode/transcript/dist/readers.d.ts +10 -0
  44. package/node_modules/@spexcode/transcript/dist/readers.js +296 -0
  45. package/node_modules/@spexcode/{spec-cli/dist/transcript-reader.d.ts → transcript/dist/turns.d.ts} +11 -5
  46. package/node_modules/@spexcode/transcript/dist/turns.js +11 -0
  47. package/node_modules/@spexcode/transcript/package.json +30 -0
  48. package/node_modules/smol-toml/LICENSE +24 -0
  49. package/node_modules/smol-toml/README.md +418 -0
  50. package/node_modules/smol-toml/dist/date.d.ts +41 -0
  51. package/node_modules/smol-toml/dist/date.js +127 -0
  52. package/node_modules/smol-toml/dist/error.d.ts +38 -0
  53. package/node_modules/smol-toml/dist/error.js +63 -0
  54. package/node_modules/smol-toml/dist/extract.js +69 -0
  55. package/node_modules/smol-toml/dist/index.cjs +734 -0
  56. package/node_modules/smol-toml/dist/index.d.ts +43 -0
  57. package/node_modules/smol-toml/dist/index.js +33 -0
  58. package/node_modules/smol-toml/dist/parse.d.ts +36 -0
  59. package/node_modules/smol-toml/dist/parse.js +149 -0
  60. package/node_modules/smol-toml/dist/primitive.js +238 -0
  61. package/node_modules/smol-toml/dist/stringify.d.ts +31 -0
  62. package/node_modules/smol-toml/dist/stringify.js +181 -0
  63. package/node_modules/smol-toml/dist/struct.js +179 -0
  64. package/node_modules/smol-toml/dist/util.d.ts +38 -0
  65. package/node_modules/smol-toml/dist/util.js +89 -0
  66. package/node_modules/smol-toml/package.json +68 -0
  67. package/package.json +3 -3
  68. package/node_modules/@spexcode/spec-cli/dist/execution-trace.d.ts +0 -27
  69. package/node_modules/@spexcode/spec-cli/dist/execution-trace.js +0 -475
  70. package/node_modules/@spexcode/spec-cli/dist/session-execution.d.ts +0 -10
  71. package/node_modules/@spexcode/spec-cli/dist/session-execution.js +0 -70
  72. package/node_modules/@spexcode/spec-cli/dist/transcript-reader.js +0 -251
@@ -0,0 +1,418 @@
1
+ # smol-toml
2
+ [![TOML 1.1.0](https://img.shields.io/badge/TOML-1.1.0-9c4221?style=flat-square)](https://toml.io/en/v1.1.0)
3
+ [![License](https://img.shields.io/github/license/squirrelchat/smol-toml.svg?style=flat-square)](https://github.com/squirrelchat/smol-toml/blob/mistress/LICENSE)
4
+ [![npm](https://img.shields.io/npm/v/smol-toml?style=flat-square)](https://npmx.dev/smol-toml)
5
+ [![Build](https://img.shields.io/github/actions/workflow/status/squirrelchat/smol-toml/build.yaml?style=flat-square&logo=github)](https://github.com/squirrelchat/smol-toml/actions/workflows/build.yaml)
6
+
7
+ [![GitHub Sponsors](https://img.shields.io/badge/GitHub%20Sponsors-support%20me-EA4AAA?style=flat-square)](https://github.com/sponsors/cyyynthia)
8
+ [![Weekly downloads](https://img.shields.io/npm/dw/smol-toml?style=flat-square)](https://npmx.dev/smol-toml)
9
+ [![Monthly downloads](https://img.shields.io/npm/dm/smol-toml?style=flat-square)](https://npmx.dev/smol-toml)
10
+
11
+ A small, fast, and correct TOML parser and serializer. smol-toml is fully(ish) spec-compliant with TOML v1.1.0.
12
+
13
+ Why yet another TOML parser? Well, the ecosystem of TOML parsers in JavaScript is quite underwhelming, most likely due
14
+ to a lack of interest. With most parsers being outdated, unmaintained, non-compliant, or a combination of these, a new
15
+ parser didn't feel too out of place.
16
+
17
+ *[insert xkcd 927]*
18
+
19
+ Nowadays, smol-toml is the most downloaded TOML parser on npm thanks to its quality. From frameworks to tooling, it
20
+ has been battle-tested and is actively used in production systems.
21
+
22
+ smol-toml passes most of the tests from the [`toml-test` suite](https://github.com/toml-lang/toml-test); use the
23
+ `run-toml-test.bash` script to run the tests. Due to the nature of JavaScript and the limits of the language,
24
+ it doesn't pass certain tests, namely:
25
+ - Invalid UTF-8 strings (and comments) are not rejected
26
+ - Certain invalid dates are not rejected
27
+ - For instance, `2023-02-30` would be accepted and parsed as `2023-03-02`. While additional checks could be performed
28
+ to reject these, they've not been added for performance reasons.
29
+
30
+ Please also note that by default, the behavior regarding integers doesn't preserve type information, nor does it allow
31
+ deserializing integers larger than 53 bits. See [Integers](#integers).
32
+
33
+ You can see a list of all tests smol-toml fails (and the reason why it fails these) in the list of skipped tests in
34
+ `run-toml-test.bash`. Note that some failures are *not* specification violations per-se. For instance, the TOML spec
35
+ does not require 64-bit integer range support or sub-millisecond time precision, but are included in the `toml-test`
36
+ suite. See https://github.com/toml-lang/toml-test/issues/154 and https://github.com/toml-lang/toml-test/issues/155
37
+
38
+ ## Installation
39
+ ```
40
+ [pnpm | yarn | npm] i smol-toml
41
+ ```
42
+
43
+ ## Usage
44
+ ```js
45
+ import { parse, stringify } from 'smol-toml'
46
+
47
+ const doc = '...'
48
+ const parsed = parse(doc)
49
+ console.log(parsed)
50
+
51
+ const toml = stringify(parsed)
52
+ console.log(toml)
53
+ ```
54
+
55
+ Alternatively, if you prefer something similar to the JSON global, you can import the library as follows
56
+ ```js
57
+ import * as TOML from 'smol-toml'
58
+
59
+ TOML.stringify({ ... })
60
+ ```
61
+
62
+ A few notes on the `stringify` function:
63
+ - `undefined` and `null` values on objects are ignored (does not produce a key/value).
64
+ - `undefined` and `null` values in arrays are **rejected**.
65
+ - Functions, classes and symbols are **rejected**.
66
+ - By default, floats will be serialized as integers if they don't have a decimal part. See [Integers](#integers)
67
+ - `stringify(parse('a = 1.0')) === 'a = 1'`
68
+ - JS `Date` will be serialized as Offset Date Time
69
+ - Use the [Temporal API] for representing other types (or alternatively the legacy [`TomlDate` object](#dates)).
70
+
71
+ ### Integers
72
+ When parsing, both integers and floats are read as plain JavaScript numbers, which essentially are floats. This means
73
+ loss of type information, and makes it impossible to safely represent integers beyond 53 bits.
74
+
75
+ When serializing, numbers without a decimal part are serialized as integers (except if they're outside of the safe
76
+ range; i.e. they cannot be represented as a signed 53-bit integer). This allows in most cases to preserve
77
+ whether a number is an integer or not, but fails to preserve type information for numbers like `1.0`.
78
+
79
+ #### Enabling BigInt support and type preservation
80
+ To parse integers beyond 53 bits, it's possible to tell the parser to return all integers as BigInt. This will
81
+ therefore preserve the type information at the cost of using a slightly more expensive container.
82
+
83
+ ```js
84
+ import { parse } from 'smol-toml'
85
+
86
+ const doc = '...'
87
+ const parsed = parse(doc, { integersAsBigInt: true })
88
+ ```
89
+
90
+ If you want to keep numbers for integers that can safely be represented as a JavaScript number, you can pass
91
+ `"asNeeded"` instead.
92
+
93
+ To get end-to-end type preservation, you can tell the serializer to always treat numbers as floating point numbers.
94
+ Then, only BigInts will be serialized as integers and numbers without a decimal part will still be serialized as float.
95
+
96
+ ```js
97
+ import { stringify } from 'smol-toml'
98
+
99
+ const obj = { ... }
100
+ const toml = stringify(obj, { numbersAsFloat: true })
101
+ ```
102
+
103
+ ### Dates
104
+ `smol-toml` uses an extended `Date` object to represent all types of TOML Dates. In the future, `smol-toml` will emit
105
+ objects from the Temporal API, but for now it only supports `Date` when parsing. When stringifying, `smol-toml` does
106
+ support objects from the [Temporal API] and will output the appropriate TOML type.
107
+
108
+ > [!IMPORTANT]
109
+ > If you create a `ZonedDateTime` with a timezone, it will be turned into an offset date-time; losing its precise timezone.
110
+ >
111
+ > For instance, if you create one with the timezone `Europe/Paris`, it'll be turned into an offset date-time `+02:00`
112
+ > or `+01:00`, depending on the offset observed at the instant referred to by the date-time.
113
+ >
114
+ > ```js
115
+ > Temporal.ZonedDateTime.from({ year: 2001, month: 9, day: 21, hour: 10, minute: 17, second: 0, timeZone: 'Europe/Paris' }).toString({ timeZoneName: 'never' })
116
+ > // 2001-09-21T10:17:00+02:00
117
+ > Temporal.ZonedDateTime.from({ year: 2012, month: 3, day: 19, hour: 8, minute: 0, second: 0, timeZone: 'Europe/Paris' }).toString({ timeZoneName: 'never' })
118
+ > // 2012-03-19T08:00:00+01:00
119
+ > ```
120
+
121
+ ```js
122
+ import { TomlDate } from 'smol-toml'
123
+
124
+ // Offset Date Time
125
+ const date = new TomlDate('1979-05-27T07:32:00.000-08:00')
126
+ console.log(date.isDateTime(), date.isDate(), date.isTime(), date.isLocal()) // ~> true, false, false, false
127
+ console.log(date.toISOString()) // ~> 1979-05-27T07:32:00.000-08:00
128
+
129
+ // Local Date Time
130
+ const date = new TomlDate('1979-05-27T07:32:00.000')
131
+ console.log(date.isDateTime(), date.isDate(), date.isTime(), date.isLocal()) // ~> true, false, false, true
132
+ console.log(date.toISOString()) // ~> 1979-05-27T07:32:00.000
133
+
134
+ // Local Date
135
+ const date = new TomlDate('1979-05-27')
136
+ console.log(date.isDateTime(), date.isDate(), date.isTime(), date.isLocal()) // ~> false, true, false, true
137
+ console.log(date.toISOString()) // ~> 1979-05-27
138
+
139
+ // Local Time
140
+ const date = new TomlDate('07:32:00')
141
+ console.log(date.isDateTime(), date.isDate(), date.isTime(), date.isLocal()) // ~> false, false, true, true
142
+ console.log(date.toISOString()) // ~> 07:32:00.000
143
+ ```
144
+
145
+ You can also wrap a native `Date` object and specify using different methods depending on the type of date you wish
146
+ to represent:
147
+
148
+ ```js
149
+ import { TomlDate } from 'smol-toml'
150
+
151
+ const jsDate = new Date()
152
+
153
+ const offsetDateTime = TomlDate.wrapAsOffsetDateTime(jsDate)
154
+ const localDateTime = TomlDate.wrapAsLocalDateTime(jsDate)
155
+ const localDate = TomlDate.wrapAsLocalDate(jsDate)
156
+ const localTime = TomlDate.wrapAsLocalTime(jsDate)
157
+ ```
158
+
159
+ ## Performance
160
+ The benchmark is ran using [mitata](https://github.com/evanwashere/mitata).
161
+
162
+ Parsers and serializers are tested in 2 scenarios: using the example from TOML's homepage and specification, and
163
+ using a ~5MB randomly generated[^generator] file.
164
+
165
+ [^generator]: The TOML generator used can be found [here](https://gist.github.com/cyyynthia/e77c744cb6494dabe37d0182506526b9)
166
+
167
+ While `fast-toml` is included as it's a challenging candidate, it takes a lot of shortcuts that makes it very fast,
168
+ but at the expense of correctness (it has significant defects and does not pass the TOML test suite). `smol-toml` is
169
+ almost as fast, without sacrificing correctness. 😎
170
+
171
+ | **Parse** | smol-toml@1.7.2 | @iarna/toml@3.0.0 | @ltd/j-toml@1.38.0 | fast-toml@0.5.4 | @std/toml@1.0.11 | toml@5.0.0 | js-toml@2.0.1 | @decimalturn/toml-patch@3.0.2 |
172
+ |----------------|--------------------|-------------------|--------------------|-------------------|------------------|----------------|----------------|-------------------------------|
173
+ | Spec example | **4.16 µs/iter** | 12.13 µs/iter | 30.44 µs/iter | 5.01 µs/iter | 22.34 µs/iter | 32.28 µs/iter | 24.71 µs/iter | 17.07 µs/iter |
174
+ | ~5MB test file | *113.76 ms/iter* | *DNF* | 189.89 ms/iter | **92.24 ms/iter** | 419.95 ms/iter | 549.86 ms/iter | 336.03 ms/iter | 186.32 ms/iter |
175
+
176
+ | **Stringify** | smol-toml@1.7.2 | @iarna/toml@3.0.0 | @ltd/j-toml@1.38.0 | fast-toml@0.5.4 | @std/toml@1.0.11 | toml@5.0.0 | js-toml@2.0.1 | @decimalturn/toml-patch@3.0.2 |
177
+ |----------------|--------------------|-------------------|--------------------|-----------------|------------------|----------------|----------------|-------------------------------|
178
+ | Spec example | **2.29 µs/iter** | 8.58 µs/iter | 89.59 µs/iter | N/A | 3.96 µs/iter | N/A | 3.69 µs/iter | N/A[^toml-patch-note] |
179
+ | ~5MB test file | **45.33 ms/iter** | 130.01 ms/iter | 928.19 ms/iter | N/A | 68.58 ms/iter | N/A | 110.26 ms/iter | N/A[^toml-patch-note] |
180
+
181
+ [^toml-patch-note]: Stringify performance is not included here, as the library is not meant to be fast, but rather
182
+ capable of doing precise non-destructive edits that preserve the entire document's shape and format. Putting it here
183
+ wouldn't be fair.
184
+
185
+ <details>
186
+ <summary>Detailed benchmark data</summary>
187
+
188
+ ```
189
+ node --expose-gc bench/parse.bench.ts
190
+ clk: ~5.52 GHz
191
+ cpu: AMD Ryzen 9 9950X3D 16-Core Processor
192
+ runtime: node 26.5.0 (x64-linux)
193
+
194
+ benchmark avg (min … max) p75 / p99 (min … top 1%)
195
+ ------------------------------------------- -------------------------------
196
+ • spec document
197
+ ------------------------------------------- -------------------------------
198
+ smol-toml 4.16 µs/iter 4.14 µs █
199
+ (3.99 µs … 91.94 µs) 4.95 µs ▂█▃
200
+ ( 1.41 kb … 417.70 kb) 9.63 kb ▁███▅▃▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁
201
+ 4.01 ipc ( 99.54% cache) 19.70 branch misses
202
+ 23.81k cycles 95.44k instructions 3.05k c-refs 14.12 c-misses
203
+
204
+ @iarna/toml 12.13 µs/iter 12.04 µs █
205
+ (11.59 µs … 133.43 µs) 15.94 µs █▄
206
+ ( 0.00 b … 677.01 kb) 24.08 kb ▃██▄▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
207
+ 3.97 ipc ( 99.63% cache) 75.32 branch misses
208
+ 68.16k cycles 270.90k instructions 10.39k c-refs 38.82 c-misses
209
+
210
+ @ltd/j-toml 30.44 µs/iter 29.57 µs █
211
+ (28.19 µs … 1.18 ms) 44.30 µs █▅
212
+ (432.00 b … 692.05 kb) 27.57 kb ▂██▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
213
+ 3.42 ipc ( 99.37% cache) 284.51 branch misses
214
+ 169.50k cycles 579.61k instructions 25.59k c-refs 162.02 c-misses
215
+
216
+ fast-toml 5.01 µs/iter 4.98 µs ▄█
217
+ (4.75 µs … 90.47 µs) 5.84 µs ██▃
218
+ (336.00 b … 302.06 kb) 12.56 kb ▁▅███▆▅▃▂▂▁▁▁▁▁▁▁▁▁▁▁
219
+ 4.40 ipc ( 99.53% cache) 25.73 branch misses
220
+ 28.21k cycles 124.23k instructions 3.76k c-refs 17.82 c-misses
221
+
222
+ deno's @std/toml 22.34 µs/iter 22.15 µs █▅
223
+ (20.78 µs … 155.43 µs) 36.68 µs ██
224
+ ( 1.52 kb … 547.05 kb) 64.73 kb ▂██▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
225
+ 3.80 ipc ( 99.53% cache) 111.24 branch misses
226
+ 124.05k cycles 471.06k instructions 21.13k c-refs 100.20 c-misses
227
+
228
+ node-toml 32.28 µs/iter 31.78 µs █
229
+ (30.33 µs … 221.49 µs) 53.65 µs █
230
+ ( 2.00 kb … 968.27 kb) 109.52 kb ▆█▄▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
231
+ 3.89 ipc ( 99.18% cache) 193.02 branch misses
232
+ 178.72k cycles 695.61k instructions 29.40k c-refs 240.75 c-misses
233
+
234
+ js-toml 24.71 µs/iter 23.17 µs ▅█
235
+ (21.20 µs … 731.20 µs) 39.47 µs ██
236
+ (744.00 b … 861.36 kb) 92.95 kb ▂██▅▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁
237
+ 3.79 ipc ( 98.12% cache) 205.75 branch misses
238
+ 134.81k cycles 510.43k instructions 19.00k c-refs 357.65 c-misses
239
+
240
+ @decimalturn/toml-patch 17.07 µs/iter 16.85 µs █▆
241
+ (15.93 µs … 224.97 µs) 23.30 µs ██
242
+ (632.00 b … 635.14 kb) 55.51 kb ▂██▇▃▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁
243
+ 3.56 ipc ( 99.37% cache) 73.96 branch misses
244
+ 95.58k cycles 339.88k instructions 18.52k c-refs 116.43 c-misses
245
+
246
+ summary
247
+ smol-toml
248
+ 1.2x faster than fast-toml
249
+ 2.92x faster than @iarna/toml
250
+ 4.1x faster than @decimalturn/toml-patch
251
+ 5.37x faster than deno's @std/toml
252
+ 5.94x faster than js-toml
253
+ 7.31x faster than @ltd/j-toml
254
+ 7.76x faster than node-toml
255
+
256
+ • 5MB document
257
+ ------------------------------------------- -------------------------------
258
+ smol-toml 113.76 ms/iter 115.67 ms █ █ █
259
+ (106.25 ms … 121.53 ms) 118.63 ms ▅ █ ▅ █ ▅ █ ▅ ▅
260
+ ( 37.31 mb … 49.50 mb) 43.97 mb █▁▁▁▁█▁▁▁█▁█▁█▁█▁█▁▁█
261
+ 2.47 ipc ( 98.58% cache) 3.12M branch misses
262
+ 606.38M cycles 1.50G instructions 78.32M c-refs 1.11M c-misses
263
+
264
+ @iarna/toml error: Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z at row 5, col 45, pos 569:
265
+ 4: NfF6LuAerfn5mDPI7Cp 2qsrB4vGmJTyb5jNubOIBYYWrWlAsrw PX93S57gjb5GEhR8qOU5blDQmwfVJTA YvmJ9cE3cUZU NAJQgAbIdpZLhc4lOs4ZhMEWehhZqXCsVD1YP1vN2GEoM2WX''', 1986-05-27T18:36:13Z, -5460, "2ZAV3fYlb23hf7r7QoftVlicWE2iuwp", 4790.2253 ]
266
+ 5> SzeC4Me8T = [ 5928.9340, 1991-04-28 19:24:24, 7807, -782.4516, 0b1000011111, "YvXRZKBGle9d51sqE90t8hP" ]
267
+ ^
268
+ 6: SLMvBirT.pmpX1D.9PivpfFBo = 2010-09-29
269
+
270
+
271
+
272
+ @ltd/j-toml 189.89 ms/iter 197.10 ms ██ █
273
+ (172.17 ms … 237.08 ms) 210.60 ms ▅ ▅██ ▅ ▅ █ ▅
274
+ ( 19.71 mb … 56.03 mb) 36.30 mb █▁███▁█▁▁█▁▁▁█▁▁▁▁▁▁█
275
+ 2.41 ipc ( 97.92% cache) 3.88M branch misses
276
+ 1.03G cycles 2.49G instructions 143.96M c-refs 3.00M c-misses
277
+
278
+ fast-toml 92.24 ms/iter 95.41 ms █ █
279
+ (88.83 ms … 96.21 ms) 96.00 ms █ ▅ ▅▅█▅ ▅▅▅
280
+ ( 13.32 mb … 34.90 mb) 24.06 mb █▁█▁▁████▁▁▁▁▁▁▁▁▁███
281
+ 2.90 ipc ( 98.44% cache) 2.44M branch misses
282
+ 495.57M cycles 1.44G instructions 56.61M c-refs 881.60k c-misses
283
+
284
+ deno's @std/toml 419.95 ms/iter 428.09 ms █
285
+ (408.44 ms … 434.51 ms) 431.58 ms █ █
286
+ (182.20 mb … 203.81 mb) 188.26 mb ██▁▁▁█▁█▁▁▁▁▁▁█▁▁██▁█
287
+ 3.28 ipc ( 97.22% cache) 6.72M branch misses
288
+ 2.27G cycles 7.46G instructions 215.21M c-refs 5.98M c-misses
289
+
290
+ node-toml 549.86 ms/iter 559.64 ms █ █
291
+ (527.73 ms … 574.83 ms) 571.47 ms ▅▅ █ ▅ ▅ █ ▅ ▅▅
292
+ ( 21.62 mb … 74.99 mb) 46.84 mb ██▁█▁█▁▁▁█▁▁▁█▁█▁▁▁██
293
+ 4.24 ipc ( 96.62% cache) 6.29M branch misses
294
+ 2.95G cycles 12.49G instructions 236.46M c-refs 7.99M c-misses
295
+
296
+ js-toml 336.03 ms/iter 328.58 ms █
297
+ (310.28 ms … 431.93 ms) 379.93 ms ▅█ ▅
298
+ (267.75 mb … 279.44 mb) 273.42 mb ██▁▁▇█▁▁▁▁▁▁▁▁▁▇▁▁▁▁▇
299
+ 2.02 ipc ( 94.74% cache) 5.08M branch misses
300
+ 1.65G cycles 3.33G instructions 113.18M c-refs 5.95M c-misses
301
+
302
+ @decimalturn/toml-patch 186.32 ms/iter 185.91 ms █ █
303
+ (178.55 ms … 209.69 ms) 190.20 ms ▅ ▅▅ █ ▅█▅ ▅ ▅
304
+ ( 22.18 mb … 62.13 mb) 26.09 mb █▁▁██▁▁▁▁█▁███▁█▁▁▁▁█
305
+ 2.90 ipc ( 97.50% cache) 3.72M branch misses
306
+ 999.99M cycles 2.90G instructions 120.73M c-refs 3.01M c-misses
307
+
308
+ summary
309
+ fast-toml
310
+ 1.23x faster than smol-toml
311
+ 2.02x faster than @decimalturn/toml-patch
312
+ 2.06x faster than @ltd/j-toml
313
+ 3.64x faster than js-toml
314
+ 4.55x faster than deno's @std/toml
315
+ 5.96x faster than node-toml
316
+ node --expose-gc bench/stringify.bench.ts
317
+ clk: ~5.52 GHz
318
+ cpu: AMD Ryzen 9 9950X3D 16-Core Processor
319
+ runtime: node 26.5.0 (x64-linux)
320
+
321
+ benchmark avg (min … max) p75 / p99 (min … top 1%)
322
+ ------------------------------------------- -------------------------------
323
+ • spec document
324
+ ------------------------------------------- -------------------------------
325
+ smol-toml 2.29 µs/iter 2.30 µs ▅ █
326
+ (2.26 µs … 2.33 µs) 2.33 µs ▆▆ ▃▆█ ██▃ ▃
327
+ ( 4.28 kb … 4.65 kb) 4.54 kb █████████████▄▆▄▄▁▄▆▄
328
+ 4.45 ipc ( 99.40% cache) 5.23 branch misses
329
+ 12.67k cycles 56.39k instructions 909.08 c-refs 5.43 c-misses
330
+
331
+ @iarna/toml 8.58 µs/iter 8.57 µs █
332
+ (8.54 µs … 8.79 µs) 8.63 µs ████ █
333
+ (509.76 b … 1.39 kb) 574.04 b █████▁██▁▁▁▁▁▁▁█▁▁▁▁█
334
+ 3.99 ipc ( 99.30% cache) 24.95 branch misses
335
+ 48.05k cycles 191.70k instructions 6.20k c-refs 43.23 c-misses
336
+
337
+ @ltd/j-toml 89.59 µs/iter 89.41 µs █
338
+ (70.85 µs … 242.29 µs) 127.85 µs █
339
+ ( 4.02 kb … 375.16 kb) 37.41 kb ▁▁▂▂▁▁█▇▃▁▁▁▁▁▁▁▁▁▁▁▁
340
+ 4.16 ipc ( 99.69% cache) 721.33 branch misses
341
+ 495.22k cycles 2.06M instructions 28.23k c-refs 88.81 c-misses
342
+
343
+ deno's @std/toml 3.96 µs/iter 3.96 µs █ ▄ ▄
344
+ (3.91 µs … 4.43 µs) 4.01 µs ▅██ █▅█ █
345
+ (803.91 b … 3.95 kb) 965.01 b ▅███▅███▅█▅▅▅▅▁▁▁▁▅▁▅
346
+ 3.85 ipc ( 99.45% cache) 11.59 branch misses
347
+ 22.20k cycles 85.43k instructions 3.02k c-refs 16.58 c-misses
348
+
349
+ js-toml 3.69 µs/iter 3.71 µs █ ▄
350
+ (3.65 µs … 3.82 µs) 3.77 µs ▅█▅██ █▅█
351
+ ( 6.46 kb … 7.23 kb) 7.10 kb ██████▅████▅▁█▁▁▁▅▁▁▅
352
+ 4.14 ipc ( 98.79% cache) 11.99 branch misses
353
+ 20.62k cycles 85.48k instructions 1.97k c-refs 23.80 c-misses
354
+
355
+ @decimalturn/toml-patch 48.60 µs/iter 48.28 µs █
356
+ (45.59 µs … 296.88 µs) 81.95 µs █
357
+ (128.00 b … 703.46 kb) 93.31 kb ▆█▇▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
358
+ 4.05 ipc ( 99.26% cache) 533.40 branch misses
359
+ 270.34k cycles 1.09M instructions 37.72k c-refs 278.17 c-misses
360
+
361
+ summary
362
+ smol-toml
363
+ 1.61x faster than js-toml
364
+ 1.73x faster than deno's @std/toml
365
+ 3.75x faster than @iarna/toml
366
+ 21.25x faster than @decimalturn/toml-patch
367
+ 39.18x faster than @ltd/j-toml
368
+
369
+ • 5MB document
370
+ ------------------------------------------- -------------------------------
371
+ smol-toml 45.33 ms/iter 46.14 ms █ █
372
+ (42.89 ms … 48.08 ms) 47.97 ms ▅▅ ▅ ▅ █▅ █ ▅ ▅
373
+ ( 9.41 mb … 35.68 mb) 12.98 mb ██▁█▁█▁▁██▁▁▁█▁█▁▁▁▁█
374
+ 1.98 ipc ( 94.06% cache) 1.62M branch misses
375
+ 234.88M cycles 464.38M instructions 12.57M c-refs 746.25k c-misses
376
+
377
+ @iarna/toml 130.01 ms/iter 130.79 ms █ █
378
+ (127.84 ms … 135.01 ms) 132.06 ms █ ▅█ ▅▅ ▅▅ ▅ ▅
379
+ ( 23.69 mb … 51.95 mb) 41.55 mb █▁▁██▁██▁▁▁▁▁██▁▁▁█▁█
380
+ 2.54 ipc ( 96.96% cache) 4.31M branch misses
381
+ 707.33M cycles 1.80G instructions 73.12M c-refs 2.22M c-misses
382
+
383
+ @ltd/j-toml 928.19 ms/iter 933.90 ms █
384
+ (903.30 ms … 940.61 ms) 934.55 ms █ █
385
+ ( 1.89 mb … 32.62 mb) 12.57 mb █▁▁▁▁▁▁▁▁▁▁█▁▁██▁████
386
+ 4.02 ipc ( 99.15% cache) 7.29M branch misses
387
+ 5.09G cycles 20.45G instructions 194.29M c-refs 1.66M c-misses
388
+
389
+ deno's @std/toml 68.58 ms/iter 70.20 ms █
390
+ (63.51 ms … 78.12 ms) 75.83 ms ▅ █
391
+ ( 29.19 mb … 62.19 mb) 33.69 mb █▁▁▇▁█▇▁▁▁▁▇▁▁▇▁▁▁▁▁▇
392
+ 2.14 ipc ( 94.82% cache) 1.78M branch misses
393
+ 341.59M cycles 731.18M instructions 26.60M c-refs 1.38M c-misses
394
+
395
+ js-toml 110.26 ms/iter 111.58 ms █
396
+ (106.23 ms … 118.30 ms) 116.43 ms █
397
+ ( 31.58 mb … 62.06 mb) 43.79 mb ▇▁▇█▇▇▁▁▁▁▇▁▁▁▁▁▁▇▁▁▇
398
+ 2.29 ipc ( 96.17% cache) 3.09M branch misses
399
+ 596.81M cycles 1.36G instructions 41.90M c-refs 1.60M c-misses
400
+
401
+ @decimalturn/toml-patch 933.72 ms/iter 950.61 ms █ █ █
402
+ (898.60 ms … 969.27 ms) 955.92 ms █ ▅ ▅▅ ▅ █ ▅ █
403
+ (119.41 mb … 147.95 mb) 122.51 mb █▁▁▁▁█▁██▁▁█▁▁▁▁█▁█▁█
404
+ 3.20 ipc ( 93.32% cache) 12.50M branch misses
405
+ 5.05G cycles 16.18G instructions 694.63M c-refs 46.41M c-misses
406
+
407
+ summary
408
+ smol-toml
409
+ 1.51x faster than deno's @std/toml
410
+ 2.43x faster than js-toml
411
+ 2.87x faster than @iarna/toml
412
+ 20.48x faster than @ltd/j-toml
413
+ 20.6x faster than @decimalturn/toml-patch
414
+ ```
415
+
416
+ </details>
417
+
418
+ [Temporal API]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Temporal
@@ -0,0 +1,41 @@
1
+ /*!
2
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ * this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * 3. Neither the name of the copyright holder nor the names of its contributors
14
+ * may be used to endorse or promote products derived from this software without
15
+ * specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+ export declare class TomlDate extends Date {
29
+ #private;
30
+ constructor(date: string | Date);
31
+ isDateTime(): boolean;
32
+ isLocal(): boolean;
33
+ isDate(): boolean;
34
+ isTime(): boolean;
35
+ isValid(): boolean;
36
+ toISOString(): string;
37
+ static wrapAsOffsetDateTime(jsDate: Date, offset?: string): TomlDate;
38
+ static wrapAsLocalDateTime(jsDate: Date): TomlDate;
39
+ static wrapAsLocalDate(jsDate: Date): TomlDate;
40
+ static wrapAsLocalTime(jsDate: Date): TomlDate;
41
+ }
@@ -0,0 +1,127 @@
1
+ /*!
2
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ * this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * 3. Neither the name of the copyright holder nor the names of its contributors
14
+ * may be used to endorse or promote products derived from this software without
15
+ * specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+ let DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
29
+ export class TomlDate extends Date {
30
+ #hasDate = false;
31
+ #hasTime = false;
32
+ #offset = null;
33
+ constructor(date) {
34
+ let hasDate = true;
35
+ let hasTime = true;
36
+ let offset = 'Z';
37
+ if (typeof date === 'string') {
38
+ let match = date.match(DATE_TIME_RE);
39
+ if (match) {
40
+ if (!match[1]) {
41
+ hasDate = false;
42
+ date = `0000-01-01T${date}`;
43
+ }
44
+ hasTime = !!match[2];
45
+ // Make sure to use T instead of a space. Breaks in case of extreme values otherwise.
46
+ hasTime && date[10] === ' ' && (date = date.replace(' ', 'T'));
47
+ // Do not allow rollover hours.
48
+ if (match[2] && +match[2] > 23) {
49
+ date = '';
50
+ }
51
+ else {
52
+ offset = match[3] || null;
53
+ date = date.toUpperCase();
54
+ if (!offset && hasTime)
55
+ date += 'Z';
56
+ }
57
+ }
58
+ else {
59
+ date = '';
60
+ }
61
+ }
62
+ super(date);
63
+ if (!isNaN(this.getTime())) {
64
+ this.#hasDate = hasDate;
65
+ this.#hasTime = hasTime;
66
+ this.#offset = offset;
67
+ }
68
+ }
69
+ isDateTime() {
70
+ return this.#hasDate && this.#hasTime;
71
+ }
72
+ isLocal() {
73
+ return !this.#hasDate || !this.#hasTime || !this.#offset;
74
+ }
75
+ isDate() {
76
+ return this.#hasDate && !this.#hasTime;
77
+ }
78
+ isTime() {
79
+ return this.#hasTime && !this.#hasDate;
80
+ }
81
+ isValid() {
82
+ return this.#hasDate || this.#hasTime;
83
+ }
84
+ toISOString() {
85
+ let iso = super.toISOString();
86
+ // Local Date
87
+ if (this.isDate())
88
+ return iso.slice(0, 10);
89
+ // Local Time
90
+ if (this.isTime())
91
+ return iso.slice(11, 23);
92
+ // Local DateTime
93
+ if (this.#offset === null)
94
+ return iso.slice(0, -1);
95
+ // Offset DateTime
96
+ if (this.#offset === 'Z')
97
+ return iso;
98
+ // This part is quite annoying: JS strips the original timezone from the ISO string representation
99
+ // Instead of using a "modified" date and "Z", we restore the representation "as authored"
100
+ let offset = (+(this.#offset.slice(1, 3)) * 60) + +(this.#offset.slice(4, 6));
101
+ offset = this.#offset[0] === '-' ? offset : -offset;
102
+ let offsetDate = new Date(this.getTime() - (offset * 60e3));
103
+ return offsetDate.toISOString().slice(0, -1) + this.#offset;
104
+ }
105
+ static wrapAsOffsetDateTime(jsDate, offset = 'Z') {
106
+ let date = new TomlDate(jsDate);
107
+ date.#offset = offset;
108
+ return date;
109
+ }
110
+ static wrapAsLocalDateTime(jsDate) {
111
+ let date = new TomlDate(jsDate);
112
+ date.#offset = null;
113
+ return date;
114
+ }
115
+ static wrapAsLocalDate(jsDate) {
116
+ let date = new TomlDate(jsDate);
117
+ date.#hasTime = false;
118
+ date.#offset = null;
119
+ return date;
120
+ }
121
+ static wrapAsLocalTime(jsDate) {
122
+ let date = new TomlDate(jsDate);
123
+ date.#hasDate = false;
124
+ date.#offset = null;
125
+ return date;
126
+ }
127
+ }
@@ -0,0 +1,38 @@
1
+ /*!
2
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
3
+ * SPDX-License-Identifier: BSD-3-Clause
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ * this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * 3. Neither the name of the copyright holder nor the names of its contributors
14
+ * may be used to endorse or promote products derived from this software without
15
+ * specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+ type TomlErrorOptions = ErrorOptions & {
29
+ toml: string;
30
+ ptr: number;
31
+ };
32
+ export declare class TomlError extends Error {
33
+ line: number;
34
+ column: number;
35
+ codeblock: string;
36
+ constructor(message: string, options: TomlErrorOptions);
37
+ }
38
+ export {};