@statewalker/webrun-msgpack 0.2.2 → 0.3.2
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/LICENSE +45 -0
- package/README.md +152 -33
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +540 -12
- package/dist/msgpack-core.d.ts +70 -0
- package/dist/msgpack-core.d.ts.map +1 -0
- package/dist/msgpack.d.ts +12 -4
- package/dist/msgpack.d.ts.map +1 -1
- package/dist/port-codec.d.ts.map +1 -1
- package/package.json +9 -8
- package/src/index.ts +8 -0
- package/src/msgpack-core.ts +617 -0
- package/src/msgpack.ts +18 -12
- package/src/port-codec.ts +1 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022-2026 statewalker
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---------------------------------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
This package contains a TypeScript port of msgpack.js (src/msgpack-core.ts), distributed under the
|
|
26
|
+
following license:
|
|
27
|
+
|
|
28
|
+
msgpack.js — https://github.com/ygoe/msgpack.js
|
|
29
|
+
|
|
30
|
+
Copyright © 2019, Yves Goergen, https://unclassified.software/source/msgpack-js
|
|
31
|
+
|
|
32
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
33
|
+
associated documentation files (the “Software”), to deal in the Software without restriction,
|
|
34
|
+
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
35
|
+
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
|
36
|
+
furnished to do so, subject to the following conditions:
|
|
37
|
+
|
|
38
|
+
The above copyright notice and this permission notice shall be included in all copies or
|
|
39
|
+
substantial portions of the Software.
|
|
40
|
+
|
|
41
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
|
42
|
+
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
43
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
44
|
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
45
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -3,12 +3,17 @@
|
|
|
3
3
|
MessagePack on the wire, in **two distinct shapes**:
|
|
4
4
|
|
|
5
5
|
- a **stream codec** — `encodeMsgpack` / `decodeMsgpack`, length-prefixed, for a transport with no
|
|
6
|
-
message boundaries (plus
|
|
6
|
+
message boundaries (plus specialisations for `Float32Array`);
|
|
7
7
|
- a **message codec** — `msgpackCodec`, a `PortCodec` for `@statewalker/webrun-rpc`'s
|
|
8
8
|
`multiplexPort`, with no length prefix, for a transport that already frames.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
Both sit on the package's own MessagePack implementation, `serialize` / `deserialize`, which is
|
|
11
|
+
exported too. It is a TypeScript port of Yves Goergen's
|
|
12
|
+
[msgpack.js](https://github.com/ygoe/msgpack.js) with a handful of fixes — see
|
|
13
|
+
[Provenance and credits](#provenance-and-credits). The package has no runtime dependencies.
|
|
14
|
+
|
|
15
|
+
The two codecs are not interchangeable, and reaching for the wrong one is easy. The table below is
|
|
16
|
+
the whole decision.
|
|
12
17
|
|
|
13
18
|
## Which codec
|
|
14
19
|
|
|
@@ -19,7 +24,7 @@ decision.
|
|
|
19
24
|
| Framing | **4-byte big-endian length prefix**, added by this package | **none** — the transport's own message boundaries are the framing |
|
|
20
25
|
| Use it when | the transport is a byte *stream*: a TCP-like socket, a `ReadableStream`, a file, anything where chunk boundaries are arbitrary | the transport preserves *message* boundaries: a WebSocket, an `RTCDataChannel`, a LiveKit data packet |
|
|
21
26
|
| Malformed input | a truncated trailing frame is never emitted; the consumer ends without yielding a partial value | dropped, never thrown — a bad frame from a peer cannot take the multiplexer down |
|
|
22
|
-
| Depends on |
|
|
27
|
+
| Depends on | nothing | **type-only** `@statewalker/webrun-rpc` |
|
|
23
28
|
|
|
24
29
|
Adding a length prefix on a transport that already frames is redundant framing; relying on message
|
|
25
30
|
boundaries where there are none is the truncation bug the stream codec exists to prevent. Pick by
|
|
@@ -31,7 +36,7 @@ Consumers that pipe values across transports (scanners writing chunks to a store
|
|
|
31
36
|
|
|
32
37
|
A raw MessagePack stream has no frame boundaries: a decoder can only succeed if the chunk boundaries happen to line up with the payload boundaries. Length-prefix framing fixes this — the decoder buffers incoming bytes and only yields when a complete `[length][payload]` pair is available. Partial trailing frames are NEVER emitted, so callers can detect truncation by comparing observed count to expected.
|
|
33
38
|
|
|
34
|
-
Previously the codec lived inside `@repo/streams` (private, unpublished). It's been extracted here so (a) consumers that only need framing don't pull in the broader `webrun-streams` surface, and (b)
|
|
39
|
+
Previously the codec lived inside `@repo/streams` (private, unpublished). It's been extracted here so (a) consumers that only need framing don't pull in the broader `webrun-streams` surface, and (b) MessagePack lives in exactly one place.
|
|
35
40
|
|
|
36
41
|
## Why the port codec exists
|
|
37
42
|
|
|
@@ -47,16 +52,17 @@ iframe. `msgpackCodec` is the byte-transport sibling: one envelope becomes one m
|
|
|
47
52
|
npm install @statewalker/webrun-msgpack
|
|
48
53
|
```
|
|
49
54
|
|
|
50
|
-
|
|
51
|
-
(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
No runtime dependencies **in the emitted bundle** — `dist/index.js` imports nothing — and no peer
|
|
56
|
+
dependencies. ESM only (`"type": "module"`). That is not the same as the install cost:
|
|
57
|
+
`@statewalker/webrun-rpc` is a declared `dependency`, so `npm install` also pulls it and,
|
|
58
|
+
transitively, `@statewalker/webrun-streams` into `node_modules` — even for a consumer who uses only
|
|
59
|
+
the stream codec or `serialize` / `deserialize`.
|
|
55
60
|
|
|
56
61
|
`@statewalker/webrun-rpc` is declared as a dependency but is **type-only**: `msgpackCodec` imports
|
|
57
62
|
the `PortCodec` interface from it and no runtime code, so nothing of `webrun-rpc` is in the built
|
|
58
|
-
bundle
|
|
59
|
-
|
|
63
|
+
bundle and `webrun-rpc` gains no msgpack dependency in either direction.
|
|
64
|
+
|
|
65
|
+
The runtime needs `TextDecoder`, which every current browser, Node, Deno and Bun provide.
|
|
60
66
|
|
|
61
67
|
## How to use
|
|
62
68
|
|
|
@@ -64,14 +70,36 @@ dependency in either direction.
|
|
|
64
70
|
|
|
65
71
|
| Export | Direction | Use case |
|
|
66
72
|
| --- | --- | --- |
|
|
67
|
-
| `encodeMsgpack<T>(src: AsyncIterable<T>)` | values →
|
|
68
|
-
| `decodeMsgpack<T>(src: AsyncIterable<Uint8Array>)` |
|
|
69
|
-
| `encodeFloat32Arrays(src: AsyncIterable<Float32Array>)` | arrays →
|
|
70
|
-
| `decodeFloat32Arrays(src: AsyncIterable<Uint8Array>)` |
|
|
73
|
+
| `encodeMsgpack<T>(src: Iterable<T> \| AsyncIterable<T>)` | values → frames | generic JSON-ish values |
|
|
74
|
+
| `decodeMsgpack<T>(src: Iterable<Uint8Array> \| AsyncIterable<Uint8Array>)` | frames → values | inverse of `encodeMsgpack` |
|
|
75
|
+
| `encodeFloat32Arrays(src: Iterable<Float32Array> \| AsyncIterable<Float32Array>)` | arrays → frames | float streaming, no per-element conversion |
|
|
76
|
+
| `decodeFloat32Arrays(src: Iterable<Uint8Array> \| AsyncIterable<Uint8Array>)` | frames → arrays | inverse of `encodeFloat32Arrays` |
|
|
71
77
|
| `msgpackCodec: PortCodec` | envelope ⇄ one framed message | `multiplexPort` over a byte transport |
|
|
78
|
+
| `serialize(value, options?)` | one value → one MessagePack document | the format itself, no framing |
|
|
79
|
+
| `deserialize(bytes, options?)` | one document → one value | inverse of `serialize` |
|
|
80
|
+
|
|
81
|
+
Types: `SerializeOptions`, `DeserializeOptions`, `MsgpackInput` (what `deserialize` accepts:
|
|
82
|
+
`Uint8Array`, `ArrayBuffer` or an array of byte values) and `MsgpackExtension` (an extension value
|
|
83
|
+
other than a timestamp: `{ type, data }`).
|
|
84
|
+
|
|
85
|
+
All four stream functions take synchronous iterables too — an array, a generator — so a fixed
|
|
86
|
+
list needs no async wrapper.
|
|
72
87
|
|
|
73
88
|
## Examples
|
|
74
89
|
|
|
90
|
+
### One value, no framing
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import { deserialize, serialize } from "@statewalker/webrun-msgpack";
|
|
94
|
+
|
|
95
|
+
const bytes = serialize({ id: 7, tags: ["a", "b"], at: new Date(0), raw: new Uint8Array([1, 2]) });
|
|
96
|
+
const value = deserialize(bytes); // same shape; `at` is a Date, `raw` a Uint8Array
|
|
97
|
+
|
|
98
|
+
// Several documents back to back:
|
|
99
|
+
const three = serialize([1, "two", { three: 3 }], { multiple: true });
|
|
100
|
+
deserialize(three, { multiple: true }); // [1, "two", { three: 3 }]
|
|
101
|
+
```
|
|
102
|
+
|
|
75
103
|
### Stream of values
|
|
76
104
|
|
|
77
105
|
```ts
|
|
@@ -115,8 +143,8 @@ for await (const arr of pipe) console.log(arr.length); // 4, 4
|
|
|
115
143
|
```ts
|
|
116
144
|
import { decodeMsgpack, encodeMsgpack } from "@statewalker/webrun-msgpack";
|
|
117
145
|
|
|
118
|
-
// Produce one frame, then split the bytes any way you like:
|
|
119
|
-
const bytes = [];
|
|
146
|
+
// Produce one frame (a plain array is a valid input), then split the bytes any way you like:
|
|
147
|
+
const bytes: Uint8Array[] = [];
|
|
120
148
|
for await (const f of encodeMsgpack([{ a: 1, b: "hi" }])) bytes.push(f);
|
|
121
149
|
// Hand the decoder arbitrarily small slices — it buffers until complete:
|
|
122
150
|
async function* byOne() {
|
|
@@ -258,17 +286,47 @@ wire. Whether the resulting `error` payload is msgpack-expressible therefore dep
|
|
|
258
286
|
code throws — a `cause` holding a `Map` or a class instance collapses to `{}`, and a circular
|
|
259
287
|
reference makes `serialize` throw.
|
|
260
288
|
|
|
261
|
-
##
|
|
289
|
+
## What `deserialize` refuses, and how
|
|
290
|
+
|
|
291
|
+
`deserialize` throws on input that is not MessagePack; it never logs. Specifically:
|
|
292
|
+
|
|
293
|
+
- **Truncated input** — any read that would run past the end — throws a `RangeError`
|
|
294
|
+
(`Insufficient data: …`). Every proper prefix of a valid encoding is refused this way, so a cut
|
|
295
|
+
integer can no longer come back as `NaN`, nor a cut `bin` as a shorter array.
|
|
296
|
+
- **The never-used type byte `0xc1`**, an empty input, a timestamp extension of an unknown size,
|
|
297
|
+
and a non-byte argument throw an `Error`.
|
|
298
|
+
- **Malformed UTF-8 inside a string is not an error**: each malformed sequence decodes to U+FFFD,
|
|
299
|
+
exactly as `TextDecoder` does, and the values after the string are read normally. Overlong
|
|
300
|
+
forms are malformed — `C0 AF` does not decode to `/`.
|
|
301
|
+
- **Bytes after the first document are ignored** unless `{ multiple: true }` asks for all of them.
|
|
302
|
+
|
|
303
|
+
`msgpackCodec` turns every one of these throws into a dropped message. (Before this package
|
|
304
|
+
carried its own implementation, `@ygoe/msgpack` printed the whole buffer with `console.debug` on
|
|
305
|
+
some truncated input before throwing. That is gone.)
|
|
262
306
|
|
|
263
|
-
|
|
264
|
-
with the whole offending buffer** before it throws. `msgpackCodec` catches the throw and drops the
|
|
265
|
-
frame, but it cannot suppress the log — the call is inside the library.
|
|
307
|
+
## The value model
|
|
266
308
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
309
|
+
What each JavaScript value becomes on the wire, and what comes back:
|
|
310
|
+
|
|
311
|
+
| Written | As | Read back as |
|
|
312
|
+
| --- | --- | --- |
|
|
313
|
+
| `null`, `undefined` | nil | `null` — but an object key whose value is `undefined` is **dropped** |
|
|
314
|
+
| `boolean` | bool | `boolean` |
|
|
315
|
+
| safe integer | the narrowest int / uint | `number`; `-0` is written as `0` and loses its sign |
|
|
316
|
+
| any other number (fraction, beyond ±2⁵³, `NaN`, `±Infinity`) | float 64 | `number` |
|
|
317
|
+
| `string` | str, UTF-8; a lone surrogate is written as U+FFFD, as `TextEncoder` does | `string` |
|
|
318
|
+
| `Uint8Array`, `Uint8ClampedArray` | bin | `Uint8Array` — a **view into the input**, not a copy |
|
|
319
|
+
| other typed arrays (`Float32Array`, `Int16Array`, …) | array of numbers | `number[]` |
|
|
320
|
+
| `Array` | array | `unknown[]` |
|
|
321
|
+
| `Date` | timestamp extension (type -1), 32/64/96-bit as the instant needs | `Date`, floored to the millisecond; an invalid `Date` throws |
|
|
322
|
+
| any other object | map of its **own** enumerable string keys | plain object; every key, `__proto__` included, is an own property |
|
|
323
|
+
| `bigint`, `function`, `symbol` | — throws, unless `invalidTypeReplacement` supplies a stand-in | |
|
|
324
|
+
|
|
325
|
+
Reading also accepts what other encoders write: float 32, int 64 / uint 64 (as the nearest
|
|
326
|
+
`number` — precision beyond 2⁵³ is lost), maps with non-string keys (the key is converted with
|
|
327
|
+
`String()`), and extension types other than timestamps, which come back as
|
|
328
|
+
`{ type, data }` with `type` as the unsigned byte (so type `-2` reads as `254`). A `Map` or `Set`
|
|
329
|
+
has no own enumerable keys and is written as an empty map.
|
|
272
330
|
|
|
273
331
|
## Internals
|
|
274
332
|
|
|
@@ -293,7 +351,7 @@ The decoder keeps a rolling `Uint8Array` buffer. Each incoming chunk is appended
|
|
|
293
351
|
1. If buffer is shorter than 4 bytes — wait for more.
|
|
294
352
|
2. Read the 32-bit BE length.
|
|
295
353
|
3. If buffer doesn't hold `4 + length` bytes — wait for more.
|
|
296
|
-
4.
|
|
354
|
+
4. Copy the payload out, `deserialize` it, yield.
|
|
297
355
|
5. Advance the buffer past this frame; repeat step 1.
|
|
298
356
|
|
|
299
357
|
Zero-length chunks are tolerated and simply no-op through the loop. Truncated trailing frames are silently dropped — the buffer retains them but the consuming `for await` ends without yielding a partial value.
|
|
@@ -317,9 +375,15 @@ a throwing `getPrototypeOf`. None is producible by a remote peer sending bytes
|
|
|
317
375
|
same-process JavaScript already holding the backing memory — so the guarantee is "cannot throw for
|
|
318
376
|
anything that arrives over a wire", not "cannot throw for any JavaScript value".
|
|
319
377
|
|
|
320
|
-
### Float32Array
|
|
378
|
+
### Float32Array: no per-element conversion
|
|
321
379
|
|
|
322
|
-
`encodeFloat32Arrays` constructs a `Uint8Array` view over the `Float32Array`'s underlying buffer and serialises it as a msgpack `bin` payload — no float-by-float conversion. `decodeFloat32Arrays` reinterprets the decoded `Uint8Array` as a `Float32Array
|
|
380
|
+
`encodeFloat32Arrays` constructs a `Uint8Array` view over the `Float32Array`'s underlying buffer and serialises it as a msgpack `bin` payload — no float-by-float conversion. `decodeFloat32Arrays` reinterprets the decoded `Uint8Array` as a `Float32Array`, copying it first when its `byteOffset` is not 4-byte aligned.
|
|
381
|
+
|
|
382
|
+
**In practice that copy always happens**, and the bytes are copied on the way out as well:
|
|
383
|
+
`serialize` copies the view into its output, and the frame is assembled by another copy. The
|
|
384
|
+
decoded `bin` is a view into the payload, starting just after its 2-, 3- or 5-byte header, and
|
|
385
|
+
none of those offsets is a multiple of 4. So "no per-element conversion" is the whole claim, not
|
|
386
|
+
"zero-copy".
|
|
323
387
|
|
|
324
388
|
### A trap when writing a transport pump
|
|
325
389
|
|
|
@@ -330,8 +394,8 @@ wire per message.
|
|
|
330
394
|
|
|
331
395
|
### Dependencies
|
|
332
396
|
|
|
333
|
-
- [`@ygoe/msgpack`](https://github.com/ygoe/msgpack.js) — single-file msgpack implementation (≈7 kB gzipped), no transitive deps.
|
|
334
397
|
- [`@statewalker/webrun-rpc`](../webrun-rpc) — **types only** (`PortCodec`, `PortEnvelope`); no runtime import is emitted.
|
|
398
|
+
- MessagePack itself is `src/msgpack-core.ts`, in this package — see below.
|
|
335
399
|
|
|
336
400
|
Dev: TypeScript, vitest, rolldown, rimraf (catalog versions from the monorepo root).
|
|
337
401
|
`@statewalker/webrun-streams` and `@statewalker/webrun-streams-conformance` are dev-only, for the
|
|
@@ -348,13 +412,68 @@ conformance run.
|
|
|
348
412
|
## Scripts
|
|
349
413
|
|
|
350
414
|
```sh
|
|
351
|
-
pnpm test # vitest run (
|
|
415
|
+
pnpm test # vitest run (406 tests / 7 files)
|
|
352
416
|
pnpm run build # rolldown + tsc --emitDeclarationOnly
|
|
353
417
|
pnpm lint # biome check src tests
|
|
354
418
|
pnpm typecheck # tsc --noEmit (src)
|
|
355
419
|
pnpm typecheck:tests # tsc -p tsconfig.tests.json — needs the sibling packages built
|
|
356
420
|
```
|
|
357
421
|
|
|
422
|
+
## Provenance and credits
|
|
423
|
+
|
|
424
|
+
`src/msgpack-core.ts` is a TypeScript port of **[msgpack.js](https://github.com/ygoe/msgpack.js)**
|
|
425
|
+
by **Yves Goergen**, © 2019, MIT license — the library this package depended on, as
|
|
426
|
+
[`@ygoe/msgpack`](https://www.npmjs.com/package/@ygoe/msgpack), until 0.3.0. Thank you.
|
|
427
|
+
|
|
428
|
+
It is ported from commit
|
|
429
|
+
[`05733cf`](https://github.com/ygoe/msgpack.js/tree/05733cfb43a2974cf669f0eb8693f43b548bdcd4)
|
|
430
|
+
(2024-04-16) on `master`, not from the npm release 1.0.3. `master` carries three fixes that 1.0.3
|
|
431
|
+
lacks, and they change what goes on the wire:
|
|
432
|
+
|
|
433
|
+
- [#34](https://github.com/ygoe/msgpack.js/pull/34): an integer beyond the safe range is written
|
|
434
|
+
as a float 64. 1.0.3 wrote `2 ** 100` as the maximal uint 64, which reads back as ~1.8e19.
|
|
435
|
+
- [#32](https://github.com/ygoe/msgpack.js/issues/32): a positive integer above uint 32 is written
|
|
436
|
+
with the uint 64 prefix `0xcf`, not int 64's `0xd3`.
|
|
437
|
+
- [#33](https://github.com/ygoe/msgpack.js/issues/33): a 16–255-byte `bin` gets the one-byte bin 8
|
|
438
|
+
header, not bin 16's two bytes.
|
|
439
|
+
|
|
440
|
+
The port keeps upstream's structure, comments and error messages. Before any change it was checked
|
|
441
|
+
against upstream `msgpack.js` itself: byte-identical output for 3,000 randomised values (226 MB
|
|
442
|
+
encoded), and the same value or the same error message for 20,000 random garbage inputs.
|
|
443
|
+
|
|
444
|
+
**Changes from upstream**, each marked `Modified from upstream` in the source and made where a
|
|
445
|
+
test adopted from another implementation failed:
|
|
446
|
+
|
|
447
|
+
1. **Truncated input throws a `RangeError`** instead of decoding to `NaN` or a short `bin`, and
|
|
448
|
+
nothing is logged — upstream called `console.debug` with the whole input.
|
|
449
|
+
2. **Timestamps are floored to the millisecond**, both ways. Upstream rounded
|
|
450
|
+
`…:07.999999999Z` up to the next second, read pre-1970 instants toward zero, and wrote
|
|
451
|
+
`new Date(-1002)` as second -1. An invalid `Date` throws instead of being written as second -1.
|
|
452
|
+
3. **Strings follow the WHATWG Encoding standard.** Decoding goes through `TextDecoder`: malformed
|
|
453
|
+
sequences, overlong forms included, become U+FFFD, where upstream decoded `C0 AF` to `/` and
|
|
454
|
+
threw on a sequence cut by the end of the string. Encoding writes a lone surrogate as U+FFFD,
|
|
455
|
+
where upstream threw on a high one and wrote a low one as invalid UTF-8.
|
|
456
|
+
4. **Object keys**: a `__proto__` map key is decoded as an own property — upstream's assignment
|
|
457
|
+
replaced the decoded object's prototype — and only own enumerable keys are written, where
|
|
458
|
+
upstream's `for…in` also wrote inherited ones.
|
|
459
|
+
5. TypeScript types, `unknown` in place of `any`, and the bounds `0xffffffffffffffff` /
|
|
460
|
+
`0x7fffffffffffffff` spelled `2 ** 64` / `2 ** 63` (the same doubles).
|
|
461
|
+
|
|
462
|
+
**Tests.** Besides this package's own, the suite runs:
|
|
463
|
+
|
|
464
|
+
- upstream's test page, ported to vitest — `tests/msgpack-core.upstream.test.ts`;
|
|
465
|
+
- [kawanet/msgpack-test-suite](https://github.com/kawanet/msgpack-test-suite) (MIT, © Yusuke
|
|
466
|
+
Kawasaki), vendored — `tests/msgpack-core.test-suite.test.ts`;
|
|
467
|
+
- cases adopted from [msgpack/msgpack-javascript](https://github.com/msgpack/msgpack-javascript)
|
|
468
|
+
(ISC, © The MessagePack Community) and [kriszyp/msgpackr](https://github.com/kriszyp/msgpackr)
|
|
469
|
+
(MIT, © Kris Zyp), with msgpackr's sample documents vendored —
|
|
470
|
+
`tests/msgpack-core.adopted.test.ts`.
|
|
471
|
+
|
|
472
|
+
Sources, commits and licenses of everything vendored are in
|
|
473
|
+
[`tests/fixtures/README.md`](./tests/fixtures/README.md). Outside the suite, the final
|
|
474
|
+
implementation was checked for interoperability with `@msgpack/msgpack` 3.1.3 and `msgpackr` 2.1.0:
|
|
475
|
+
2,000 random values encoded by each side decode identically on the other, in both directions.
|
|
476
|
+
|
|
358
477
|
## License
|
|
359
478
|
|
|
360
|
-
MIT © statewalker — see [LICENSE](
|
|
479
|
+
MIT © statewalker — see [LICENSE](./LICENSE), which also carries msgpack.js's MIT notice.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { decodeFloat32Arrays, decodeMsgpack, encodeFloat32Arrays, encodeMsgpack, } from "./msgpack.js";
|
|
2
|
+
export { type DeserializeOptions, deserialize, type MsgpackExtension, type MsgpackInput, type SerializeOptions, serialize, } from "./msgpack-core.js";
|
|
2
3
|
export { msgpackCodec } from "./port-codec.js";
|
|
3
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,kBAAkB,EACvB,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|