@webreflection/coincident
Version:
An Atomics based Proxy to simplify, and synchronize, Worker related tasks
121 lines (114 loc) • 3.39 kB
JavaScript
import { toSymbolValue } from '../utils/shared.js';
import createDecoder from '../utils/decoder.js';
import types from './types.js';
const { defineProperty } = Object;
const unflatten = arr => {
switch (arr[i++]) {
case types.array: {
const length = arr[i++];
const array = [];
arr[i - 2] = array;
for (let j = 0; j < length; j++)
array[j] = unflatten(arr);
return array;
}
case types.object: {
const length = arr[i++];
const object = {};
arr[i - 2] = object;
for (let j = 0; j < length; j++)
object[unflatten(arr)] = unflatten(arr);
return object;
}
case types.string: {
const string = arr[i++];
arr[i - 2] = string;
return string;
}
case types.ref: return arr[arr[i++]];
case types.number: return arr[i++];
case types.bigint: return BigInt(arr[i++]);
case types.true: return true;
case types.false: return false;
case types.null: return null;
case types.undefined: return void 0;
case types.buffer: {
const byteLength = arr[i++];
const maxByteLength = arr[i++];
const args = [byteLength];
if (maxByteLength) args.push({ maxByteLength });
const buffer = new ArrayBuffer(...args);
arr[i - 3] = buffer;
const ui8a = new Uint8Array(buffer, 0, byteLength);
for (let j = 0; j < byteLength; j++) ui8a[j] = arr[i++];
return buffer;
}
case types.view: {
const name = arr[i++];
const byteOffset = arr[i++];
const length = arr[i++];
const args = [unflatten(arr), byteOffset];
if (length) args.push(length);
const view = new globalThis[name](...args);
arr[i - 4] = view;
return view;
}
case types.symbol: {
return toSymbolValue(arr[i++]);
}
case types.date: {
const date = new Date(arr[i++]);
arr[i - 2] = date;
return date;
}
case types.map: {
const size = arr[i++];
const map = new Map;
arr[i - 2] = map;
for (let j = 0; j < size; j++) {
const key = unflatten(arr);
const value = unflatten(arr);
if (key !== void 0)
map.set(key, value);
}
return map;
}
case types.set: {
const size = arr[i++];
const set = new Set;
arr[i - 2] = set;
for (let j = 0; j < size; j++) {
const value = unflatten(arr);
if (value !== void 0)
set.add(value);
}
return set;
}
case types.regexp: {
const source = arr[i++];
const flags = arr[i++];
const regexp = new RegExp(source, flags);
arr[i - 3] = regexp;
return regexp;
}
case types.error: {
const Class = globalThis[arr[i++]] || Error;
const message = arr[i++];
const value = arr[i++];
const cause = arr[i++];
const error = new Class(message, { cause });
arr[i - 5] = defineProperty(error, 'stack', { value });
return error;
}
default:
throw new Error(`Unknown type: ${arr[i - 1]}`);
}
};
const { parse } = JSON;
let i = 0;
export const decode = json => {
i = 0;
const arr = parse(json);
return arr.length ? unflatten(arr) : void 0;
};
export const decoder = createDecoder(decode);