0.2.0 • Published 1 year ago
microrender-serialiser v0.2.0
MicroRender Serialiser
This is a serialiser designed MicroRender build to enable better serialisation of builtin and custom JS
objects than JSON.stringify() and JSON.parse(). One of the main focuses of the serialiser is code size,
so while other serialisers can serialise and deserialise a wider range of objects, this serialiser can do
it at a fraction of the code size.
Usage
Install from NPM:
npm install @microrender/serialiserESM import in javascript:
import { serialise, deserialise } from "microrender-serialiser"
serialise(object)
serialise(object, locals)
deserialise(string)
deserialise(string, locals)Examples
Plain objects
serialise({hello: "world"})<00 00 00 22 02 06 4f 62 6a 65 63 74 00 00 00 0b 03 00 68 65 6c 6c 6f 00 00 00 0b 03 00 77 6f 72 6c 64>Arrays and Maps
serialise([1, 2, 3, 4, 5])
serialise(new Map([["key", "value"], ["key2", "value2"]]))<00 00 00 51 01 05 41 72 72 61 79 00 00 00 0e 03 01 3f f0 00 00 00 00 00 00 00 00 00 0e 03 01 40 00 00 00 00 00 00 00 00 00 00 0e 03 01 40 08 00 00 00 00 00 00 00 00 00 0e 03 01 40 10 00 00 00 00 00 00 00 00 00 0e 03 01 40 14 00 00 00 00 00 00>
<00 00 00 49 01 03 4d 61 70 00 00 00 1f 01 05 41 72 72 61 79 00 00 00 09 03 00 6b 65 79 00 00 00 0b 03 00 76 61 6c 75 65 00 00 00 21 01 05 41 72 72 61 79 00 00 00 0a 03 00 6b 65 79 32 00 00 00 0c 03 00 76 61 6c 75 65 32>URL and Date objects
serialise(new URL("https://example.com/a/b/c"))
serialise(new Date(0))<00 00 00 28 00 03 55 52 4c 00 00 00 1f 03 00 68 74 74 70 73 3a 2f 2f 65 78 61 6d 70 6c 65 2e 63 6f 6d 2f 61 2f 62 2f 63>
<00 00 00 28 00 04 44 61 74 65 00 00 00 1e 03 00 31 39 37 30 2d 30 31 2d 30 31 54 30 30 3a 30 30 3a 30 30 2e 30 30 30 5a>About
The MicroRender serialiser uses a binary encoding format for efficiency. All numbers are stored big-endian (saves a few bytes of javascript)
- Each descriptor (an item including a description of type and length) is made up a number of components:
- Bytes 0-3: a Uint32 storing the length of the descriptor
- Byte 4: a Uint8 storing the method used to encode the descriptor:
0: ToJSON- A
toJSON()has been called on the object being serialised. - This is a composite descriptor containing a single child descriptor, a string.
- A
1: Iterable- The object being serialised was an iterable (has a
@@iterator()) method. - This is a composite descriptor containing each iterable entry as each child descriptor.
- Note that each item when iterating through JS
Mapis itself anArrayso it is stored as an iterable of iterables.
- The object being serialised was an iterable (has a
2: BasicObject- The object being serialised does not have an specific ways to serialise it, so its own enumerable string-keyed properties were stored.
- This is a composite descriptor containing each key and value as child descriptors (in key-value-key-value order)
- Note that objects that store data using symbols or private (
#) properties (eg. theRequestobject) cannot be serialised this way, and objects with mangled property names (added during minification) cannot be reliably serialised or deserialised this way either.
3: Primitive- The value being serialised was a primitive (
!(value instanceof Object).typeof valuemay beobjectifvalue === null) - This is a special primitive descriptor that behaves differently to the other descriptors, forming the 'leaves' of the descriptor tree.
- The value being serialised was a primitive (
- Bytes 5 onwards are dependent on the type of descriptor:
- Composite descriptors:
- Byte 5: a Uint8 storing the byte length of the object's constructor name
- Bytes 6-(6+value of byte 4): a UTF-8 encoded string storing the object's constructor's name
- Bytes (7+value of byte 4)-end: a series of child descriptors, stored end to end.
- Primitive descriptors
- Byte 5: a Uint8 storing the type of the descriptor, determining the encoding for the remainder of the entry:
0: string- The data is a UTF-8 encoded string.
1: number- The data is a Float64 number.
2: bigint- The data is a BigInt64 number.
3: boolean- The data is a Uint8 number, where 0 represents
falseand 1 representstrue.
- The data is a Uint8 number, where 0 represents
4: undefined- There is no data.
5: object (null)- There is no data.
- Because
typeof null === "object", this is stored asobjectinternally for consistency with the other primitive types.
- Byte 5: a Uint8 storing the type of the descriptor, determining the encoding for the remainder of the entry:
- Composite descriptors: