| [9af201e] | 1 | import {
|
|---|
| 2 | VOID, PRIMITIVE,
|
|---|
| 3 | ARRAY, OBJECT,
|
|---|
| 4 | DATE, REGEXP, MAP, SET,
|
|---|
| 5 | ERROR, BIGINT
|
|---|
| 6 | } from './types.js';
|
|---|
| 7 |
|
|---|
| 8 | const env = typeof self === 'object' ? self : globalThis;
|
|---|
| 9 |
|
|---|
| 10 | const guard = (name, init) => {
|
|---|
| 11 | switch (name) {
|
|---|
| 12 | case 'Function':
|
|---|
| 13 | case 'SharedWorker':
|
|---|
| 14 | case 'Worker':
|
|---|
| 15 | case 'eval':
|
|---|
| 16 | case 'setInterval':
|
|---|
| 17 | case 'setTimeout':
|
|---|
| 18 | throw new TypeError('unable to deserialize ' + name);
|
|---|
| 19 | }
|
|---|
| 20 | return new env[name](init);
|
|---|
| 21 | };
|
|---|
| 22 |
|
|---|
| 23 | const deserializer = ($, _) => {
|
|---|
| 24 | const as = (out, index) => {
|
|---|
| 25 | $.set(index, out);
|
|---|
| 26 | return out;
|
|---|
| 27 | };
|
|---|
| 28 |
|
|---|
| 29 | const unpair = index => {
|
|---|
| 30 | if ($.has(index))
|
|---|
| 31 | return $.get(index);
|
|---|
| 32 |
|
|---|
| 33 | const [type, value] = _[index];
|
|---|
| 34 | switch (type) {
|
|---|
| 35 | case PRIMITIVE:
|
|---|
| 36 | case VOID:
|
|---|
| 37 | return as(value, index);
|
|---|
| 38 | case ARRAY: {
|
|---|
| 39 | const arr = as([], index);
|
|---|
| 40 | for (const index of value)
|
|---|
| 41 | arr.push(unpair(index));
|
|---|
| 42 | return arr;
|
|---|
| 43 | }
|
|---|
| 44 | case OBJECT: {
|
|---|
| 45 | const object = as({}, index);
|
|---|
| 46 | for (const [key, index] of value)
|
|---|
| 47 | object[unpair(key)] = unpair(index);
|
|---|
| 48 | return object;
|
|---|
| 49 | }
|
|---|
| 50 | case DATE:
|
|---|
| 51 | return as(new Date(value), index);
|
|---|
| 52 | case REGEXP: {
|
|---|
| 53 | const {source, flags} = value;
|
|---|
| 54 | return as(new RegExp(source, flags), index);
|
|---|
| 55 | }
|
|---|
| 56 | case MAP: {
|
|---|
| 57 | const map = as(new Map, index);
|
|---|
| 58 | for (const [key, index] of value)
|
|---|
| 59 | map.set(unpair(key), unpair(index));
|
|---|
| 60 | return map;
|
|---|
| 61 | }
|
|---|
| 62 | case SET: {
|
|---|
| 63 | const set = as(new Set, index);
|
|---|
| 64 | for (const index of value)
|
|---|
| 65 | set.add(unpair(index));
|
|---|
| 66 | return set;
|
|---|
| 67 | }
|
|---|
| 68 | case ERROR: {
|
|---|
| 69 | const {name, message} = value;
|
|---|
| 70 | return as(guard(name, message), index);
|
|---|
| 71 | }
|
|---|
| 72 | case BIGINT:
|
|---|
| 73 | return as(BigInt(value), index);
|
|---|
| 74 | case 'BigInt':
|
|---|
| 75 | return as(Object(BigInt(value)), index);
|
|---|
| 76 | case 'ArrayBuffer':
|
|---|
| 77 | return as(new Uint8Array(value).buffer, value);
|
|---|
| 78 | case 'DataView': {
|
|---|
| 79 | const { buffer } = new Uint8Array(value);
|
|---|
| 80 | return as(new DataView(buffer), value);
|
|---|
| 81 | }
|
|---|
| 82 | }
|
|---|
| 83 | return as(guard(type, value), index);
|
|---|
| 84 | };
|
|---|
| 85 |
|
|---|
| 86 | return unpair;
|
|---|
| 87 | };
|
|---|
| 88 |
|
|---|
| 89 | /**
|
|---|
| 90 | * @typedef {Array<string,any>} Record a type representation
|
|---|
| 91 | */
|
|---|
| 92 |
|
|---|
| 93 | /**
|
|---|
| 94 | * Returns a deserialized value from a serialized array of Records.
|
|---|
| 95 | * @param {Record[]} serialized a previously serialized value.
|
|---|
| 96 | * @returns {any}
|
|---|
| 97 | */
|
|---|
| 98 | export const deserialize = serialized => deserializer(new Map, serialized)(0);
|
|---|