yabson.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. /* global TextEncoder, TextDecoder */
  2. const DEFAULT_CHUNK_SIZE = 8 * 1024 * 1024;
  3. const TYPE_REFERENCE = 0;
  4. const SPECIAL_TYPES = [TYPE_REFERENCE];
  5. const EMPTY_SLOT_VALUE = Symbol();
  6. const textEncoder = new TextEncoder();
  7. const textDecoder = new TextDecoder();
  8. const types = new Array(256);
  9. let typeIndex = 0;
  10. registerType(serializeCircularReference, parseCircularReference, testCircularReference, TYPE_REFERENCE);
  11. registerType(null, parseObject, testObject);
  12. registerType(serializeArray, parseArray, testArray);
  13. registerType(serializeString, parseString, testString);
  14. registerType(serializeTypedArray, parseFloat64Array, testFloat64Array);
  15. registerType(serializeTypedArray, parseFloat32Array, testFloat32Array);
  16. registerType(serializeTypedArray, parseUint32Array, testUint32Array);
  17. registerType(serializeTypedArray, parseInt32Array, testInt32Array);
  18. registerType(serializeTypedArray, parseUint16Array, testUint16Array);
  19. registerType(serializeTypedArray, parseInt16Array, testInt16Array);
  20. registerType(serializeTypedArray, parseUint8ClampedArray, testUint8ClampedArray);
  21. registerType(serializeTypedArray, parseUint8Array, testUint8Array);
  22. registerType(serializeTypedArray, parseInt8Array, testInt8Array);
  23. registerType(serializeArrayBuffer, parseArrayBuffer, testArrayBuffer);
  24. registerType(serializeNumber, parseNumber, testNumber);
  25. registerType(serializeUint32, parseUint32, testUint32);
  26. registerType(serializeInt32, parseInt32, testInt32);
  27. registerType(serializeUint16, parseUint16, testUint16);
  28. registerType(serializeInt16, parseInt16, testInt16);
  29. registerType(serializeUint8, parseUint8, testUint8);
  30. registerType(serializeInt8, parseInt8, testInt8);
  31. registerType(null, parseUndefined, testUndefined);
  32. registerType(null, parseNull, testNull);
  33. registerType(null, parseNaN, testNaN);
  34. registerType(serializeBoolean, parseBoolean, testBoolean);
  35. registerType(serializeSymbol, parseSymbol, testSymbol);
  36. registerType(null, parseEmptySlot, testEmptySlot);
  37. registerType(serializeMap, parseMap, testMap);
  38. registerType(serializeSet, parseSet, testSet);
  39. registerType(serializeDate, parseDate, testDate);
  40. registerType(serializeError, parseError, testError);
  41. registerType(serializeRegExp, parseRegExp, testRegExp);
  42. registerType(serializeStringObject, parseStringObject, testStringObject);
  43. registerType(serializeNumberObject, parseNumberObject, testNumberObject);
  44. registerType(serializeBooleanObject, parseBooleanObject, testBooleanObject);
  45. export {
  46. getSerializer,
  47. getParser,
  48. registerType,
  49. clone,
  50. serialize,
  51. parse,
  52. serializeValue,
  53. serializeArray,
  54. serializeString,
  55. serializeTypedArray,
  56. serializeArrayBuffer,
  57. serializeNumber,
  58. serializeUint32,
  59. serializeInt32,
  60. serializeUint16,
  61. serializeInt16,
  62. serializeUint8,
  63. serializeInt8,
  64. serializeBoolean,
  65. serializeMap,
  66. serializeSet,
  67. serializeDate,
  68. serializeError,
  69. serializeRegExp,
  70. serializeStringObject,
  71. serializeNumberObject,
  72. serializeBooleanObject,
  73. serializeSymbol,
  74. parseValue,
  75. parseObject,
  76. parseArray,
  77. parseString,
  78. parseFloat64Array,
  79. parseFloat32Array,
  80. parseUint32Array,
  81. parseInt32Array,
  82. parseUint16Array,
  83. parseInt16Array,
  84. parseUint8ClampedArray,
  85. parseUint8Array,
  86. parseInt8Array,
  87. parseArrayBuffer,
  88. parseNumber,
  89. parseUint32,
  90. parseInt32,
  91. parseUint16,
  92. parseInt16,
  93. parseUint8,
  94. parseInt8,
  95. parseUndefined,
  96. parseNull,
  97. parseNaN,
  98. parseBoolean,
  99. parseMap,
  100. parseSet,
  101. parseDate,
  102. parseError,
  103. parseRegExp,
  104. parseStringObject,
  105. parseNumberObject,
  106. parseBooleanObject,
  107. parseSymbol,
  108. testObject,
  109. testArray,
  110. testString,
  111. testFloat64Array,
  112. testFloat32Array,
  113. testUint32Array,
  114. testInt32Array,
  115. testUint16Array,
  116. testInt16Array,
  117. testUint8ClampedArray,
  118. testUint8Array,
  119. testInt8Array,
  120. testArrayBuffer,
  121. testNumber,
  122. testBigInt,
  123. testUint32,
  124. testInt32,
  125. testUint16,
  126. testInt16,
  127. testUint8,
  128. testInt8,
  129. testInteger,
  130. testUndefined,
  131. testNull,
  132. testNaN,
  133. testBoolean,
  134. testMap,
  135. testSet,
  136. testDate,
  137. testError,
  138. testRegExp,
  139. testStringObject,
  140. testNumberObject,
  141. testBooleanObject,
  142. testSymbol
  143. };
  144. function registerType(serialize, parse, test, type) {
  145. if (type === undefined) {
  146. typeIndex++;
  147. if (types.length - typeIndex >= SPECIAL_TYPES.length) {
  148. types[types.length - typeIndex] = { serialize, parse, test };
  149. } else {
  150. throw new Error("Reached maximum number of custom types");
  151. }
  152. } else {
  153. types[type] = { serialize, parse, test };
  154. }
  155. }
  156. async function clone(object, options) {
  157. const serializer = getSerializer(object, options);
  158. const parser = getParser();
  159. let result;
  160. for await (const chunk of serializer) {
  161. result = await parser.next(chunk);
  162. }
  163. result = await parser.next();
  164. return result.value;
  165. }
  166. async function serialize(object, options) {
  167. const serializer = getSerializer(object, options);
  168. let result = new Uint8Array([]);
  169. for await (const chunk of serializer) {
  170. const previousResult = result;
  171. result = new Uint8Array(previousResult.length + chunk.length);
  172. result.set(previousResult, 0);
  173. result.set(chunk, previousResult.length);
  174. }
  175. return result;
  176. }
  177. async function parse(array) {
  178. const parser = getParser();
  179. await parser.next(array);
  180. const result = await parser.next();
  181. return result.value;
  182. }
  183. class SerializerData {
  184. constructor(appendData, chunkSize) {
  185. this.stream = new WriteStream(appendData, chunkSize);
  186. this.objects = [];
  187. }
  188. append(array) {
  189. return this.stream.append(array);
  190. }
  191. flush() {
  192. return this.stream.flush();
  193. }
  194. addObject(value) {
  195. this.objects.push(testReferenceable(value) && !testCircularReference(value, this) ? value : undefined);
  196. }
  197. }
  198. class WriteStream {
  199. constructor(appendData, chunkSize) {
  200. this.offset = 0;
  201. this.appendData = appendData;
  202. this.value = new Uint8Array(chunkSize);
  203. }
  204. async append(array) {
  205. if (this.offset + array.length > this.value.length) {
  206. const offset = this.value.length - this.offset;
  207. await this.append(array.subarray(0, offset));
  208. await this.appendData({ value: this.value });
  209. this.offset = 0;
  210. await this.append(array.subarray(offset));
  211. } else {
  212. this.value.set(array, this.offset);
  213. this.offset += array.length;
  214. }
  215. }
  216. async flush() {
  217. if (this.offset) {
  218. await this.appendData({ value: this.value.subarray(0, this.offset), done: true });
  219. }
  220. }
  221. }
  222. function getSerializer(value, { chunkSize = DEFAULT_CHUNK_SIZE } = {}) {
  223. let serializerData, result, setResult, iterationDone, previousResult, resolvePreviousResult;
  224. return {
  225. [Symbol.asyncIterator]() {
  226. return {
  227. next() {
  228. return iterationDone ? { done: iterationDone } : getResult();
  229. },
  230. return() {
  231. return { done: true };
  232. }
  233. };
  234. }
  235. };
  236. async function getResult() {
  237. if (resolvePreviousResult) {
  238. resolvePreviousResult();
  239. } else {
  240. initSerializerData().catch(() => { /* ignored */ });
  241. }
  242. initPreviousData();
  243. const value = await getValue();
  244. return { value };
  245. }
  246. async function initSerializerData() {
  247. initResult();
  248. serializerData = new SerializerData(appendData, chunkSize);
  249. await serializeValue(serializerData, value);
  250. await serializerData.flush();
  251. }
  252. function initResult() {
  253. result = new Promise(resolve => setResult = resolve);
  254. }
  255. function initPreviousData() {
  256. previousResult = new Promise(resolve => resolvePreviousResult = resolve);
  257. }
  258. async function appendData(result) {
  259. setResult(result);
  260. await previousResult;
  261. }
  262. async function getValue() {
  263. const { value, done } = await result;
  264. iterationDone = done;
  265. if (!done) {
  266. initResult();
  267. }
  268. return value;
  269. }
  270. }
  271. async function serializeValue(data, value) {
  272. const type = types.findIndex(({ test } = {}) => test && test(value, data));
  273. data.addObject(value);
  274. await data.append(new Uint8Array([type]));
  275. const serialize = types[type].serialize;
  276. if (serialize) {
  277. await serialize(data, value);
  278. }
  279. if (type != TYPE_REFERENCE && testObject(value)) {
  280. await serializeSymbols(data, value);
  281. await serializeOwnProperties(data, value);
  282. }
  283. }
  284. async function serializeSymbols(data, value) {
  285. const ownPropertySymbols = Object.getOwnPropertySymbols(value);
  286. const symbols = ownPropertySymbols.map(propertySymbol => [propertySymbol, value[propertySymbol]]);
  287. await serializeArray(data, symbols);
  288. }
  289. async function serializeOwnProperties(data, value) {
  290. if (!ArrayBuffer.isView(value)) {
  291. let entries = Object.entries(value);
  292. if (testArray(value)) {
  293. entries = entries.filter(([key]) => !testInteger(Number(key)));
  294. }
  295. await serializeValue(data, entries.length);
  296. for (const [key, value] of entries) {
  297. await serializeString(data, key);
  298. await serializeValue(data, value);
  299. }
  300. } else {
  301. await serializeValue(data, 0);
  302. }
  303. }
  304. async function serializeCircularReference(data, value) {
  305. const index = data.objects.indexOf(value);
  306. await serializeValue(data, index);
  307. }
  308. async function serializeArray(data, array) {
  309. await serializeValue(data, array.length);
  310. const notEmptyIndexes = Object.keys(array).filter(key => testInteger(Number(key))).map(key => Number(key));
  311. let indexNotEmptyIndexes = 0, currentNotEmptyIndex = notEmptyIndexes[indexNotEmptyIndexes];
  312. for (const [indexArray, value] of array.entries()) {
  313. if (currentNotEmptyIndex == indexArray) {
  314. currentNotEmptyIndex = notEmptyIndexes[++indexNotEmptyIndexes];
  315. await serializeValue(data, value);
  316. } else {
  317. await serializeValue(data, EMPTY_SLOT_VALUE);
  318. }
  319. }
  320. }
  321. async function serializeString(data, string) {
  322. const encodedString = textEncoder.encode(string);
  323. await serializeValue(data, encodedString.length);
  324. await data.append(encodedString);
  325. }
  326. async function serializeTypedArray(data, array) {
  327. await serializeValue(data, array.length);
  328. await data.append(array.constructor.name == "Uint8Array" ? array : new Uint8Array(array.buffer));
  329. }
  330. async function serializeArrayBuffer(data, arrayBuffer) {
  331. await serializeValue(data, arrayBuffer.byteLength);
  332. await data.append(new Uint8Array(arrayBuffer));
  333. }
  334. async function serializeNumber(data, number) {
  335. const serializedNumber = new Uint8Array(new Float64Array([number]).buffer);
  336. await data.append(serializedNumber);
  337. }
  338. async function serializeUint32(data, number) {
  339. const serializedNumber = new Uint8Array(new Uint32Array([number]).buffer);
  340. await data.append(serializedNumber);
  341. }
  342. async function serializeInt32(data, number) {
  343. const serializedNumber = new Uint8Array(new Int32Array([number]).buffer);
  344. await data.append(serializedNumber);
  345. }
  346. async function serializeUint16(data, number) {
  347. const serializedNumber = new Uint8Array(new Uint16Array([number]).buffer);
  348. await data.append(serializedNumber);
  349. }
  350. async function serializeInt16(data, number) {
  351. const serializedNumber = new Uint8Array(new Int16Array([number]).buffer);
  352. await data.append(serializedNumber);
  353. }
  354. async function serializeUint8(data, number) {
  355. const serializedNumber = new Uint8Array([number]);
  356. await data.append(serializedNumber);
  357. }
  358. async function serializeInt8(data, number) {
  359. const serializedNumber = new Uint8Array(new Int8Array([number]).buffer);
  360. await data.append(serializedNumber);
  361. }
  362. async function serializeBoolean(data, boolean) {
  363. const serializedBoolean = new Uint8Array([Number(boolean)]);
  364. await data.append(serializedBoolean);
  365. }
  366. async function serializeMap(data, map) {
  367. const entries = map.entries();
  368. await serializeValue(data, map.size);
  369. for (const [key, value] of entries) {
  370. await serializeValue(data, key);
  371. await serializeValue(data, value);
  372. }
  373. }
  374. async function serializeSet(data, set) {
  375. await serializeValue(data, set.size);
  376. for (const value of set) {
  377. await serializeValue(data, value);
  378. }
  379. }
  380. async function serializeDate(data, date) {
  381. await serializeNumber(data, date.getTime());
  382. }
  383. async function serializeError(data, error) {
  384. await serializeString(data, error.message);
  385. await serializeString(data, error.stack);
  386. }
  387. async function serializeRegExp(data, regExp) {
  388. await serializeString(data, regExp.source);
  389. await serializeString(data, regExp.flags);
  390. }
  391. async function serializeStringObject(data, string) {
  392. await serializeString(data, string.valueOf());
  393. }
  394. async function serializeNumberObject(data, number) {
  395. await serializeNumber(data, number.valueOf());
  396. }
  397. async function serializeBooleanObject(data, boolean) {
  398. await serializeBoolean(data, boolean.valueOf());
  399. }
  400. async function serializeSymbol(data, symbol) {
  401. await serializeString(data, symbol.description);
  402. }
  403. class Reference {
  404. constructor(index, data) {
  405. this.index = index;
  406. this.data = data;
  407. }
  408. getObject() {
  409. return this.data.objects[this.index];
  410. }
  411. }
  412. class ParserData {
  413. constructor(consumeData) {
  414. this.stream = new ReadStream(consumeData);
  415. this.objects = [];
  416. this.setters = [];
  417. }
  418. consume(size) {
  419. return this.stream.consume(size);
  420. }
  421. getObjectId() {
  422. const objectIndex = this.objects.length;
  423. this.objects.push(undefined);
  424. return objectIndex;
  425. }
  426. resolveObject(objectId, value) {
  427. if (testReferenceable(value) && !testReference(value)) {
  428. this.objects[objectId] = value;
  429. }
  430. }
  431. setObject(functionArguments, setterFunction) {
  432. this.setters.push({ functionArguments, setterFunction });
  433. }
  434. executeSetters() {
  435. this.setters.forEach(({ functionArguments, setterFunction }) => {
  436. const resolvedArguments = functionArguments.map(argument => testReference(argument) ? argument.getObject() : argument);
  437. setterFunction(...resolvedArguments);
  438. });
  439. }
  440. }
  441. class ReadStream {
  442. constructor(consumeData) {
  443. this.offset = 0;
  444. this.value = new Uint8Array(0);
  445. this.consumeData = consumeData;
  446. }
  447. async consume(size) {
  448. if (this.offset + size > this.value.length) {
  449. const pending = this.value.subarray(this.offset, this.value.length);
  450. const value = await this.consumeData();
  451. if (pending.length + value.length != this.value.length) {
  452. this.value = new Uint8Array(pending.length + value.length);
  453. }
  454. this.value.set(pending);
  455. this.value.set(value, pending.length);
  456. this.offset = 0;
  457. return this.consume(size);
  458. } else {
  459. const result = this.value.slice(this.offset, this.offset + size);
  460. this.offset += result.length;
  461. return result;
  462. }
  463. }
  464. }
  465. function getParser() {
  466. let parserData, input, setInput, value, previousData, resolvePreviousData;
  467. return {
  468. async next(input) {
  469. return input ? getResult(input) : { value: await value, done: true };
  470. },
  471. return() {
  472. return { done: true };
  473. }
  474. };
  475. async function getResult(input) {
  476. if (previousData) {
  477. await previousData;
  478. } else {
  479. initParserData().catch(() => { /* ignored */ });
  480. }
  481. initPreviousData();
  482. setInput(input);
  483. return { done: false };
  484. }
  485. async function initParserData() {
  486. let setValue;
  487. value = new Promise(resolve => setValue = resolve);
  488. parserData = new ParserData(consumeData);
  489. initChunk();
  490. const data = await parseValue(parserData);
  491. parserData.executeSetters();
  492. setValue(data);
  493. }
  494. function initChunk() {
  495. input = new Promise(resolve => setInput = resolve);
  496. }
  497. function initPreviousData() {
  498. previousData = new Promise(resolve => resolvePreviousData = resolve);
  499. }
  500. async function consumeData() {
  501. const data = await input;
  502. initChunk();
  503. if (resolvePreviousData) {
  504. resolvePreviousData();
  505. }
  506. return data;
  507. }
  508. }
  509. async function parseValue(data) {
  510. const array = await data.consume(1);
  511. const parserType = array[0];
  512. const parse = types[parserType].parse;
  513. const valueId = data.getObjectId();
  514. const result = await parse(data);
  515. if (parserType != TYPE_REFERENCE && testObject(result)) {
  516. await parseSymbols(data, result);
  517. await parseOwnProperties(data, result);
  518. }
  519. data.resolveObject(valueId, result);
  520. return result;
  521. }
  522. async function parseSymbols(data, value) {
  523. const symbols = await parseArray(data);
  524. data.setObject([symbols], symbols => symbols.forEach(([symbol, propertyValue]) => value[symbol] = propertyValue));
  525. }
  526. async function parseOwnProperties(data, object) {
  527. const size = await parseValue(data);
  528. if (size) {
  529. await parseNextProperty();
  530. }
  531. async function parseNextProperty(indexKey = 0) {
  532. const key = await parseString(data);
  533. const value = await parseValue(data);
  534. data.setObject([value], value => object[key] = value);
  535. if (indexKey < size - 1) {
  536. await parseNextProperty(indexKey + 1);
  537. }
  538. }
  539. }
  540. async function parseCircularReference(data) {
  541. const index = await parseValue(data);
  542. const result = new Reference(index, data);
  543. return result;
  544. }
  545. function parseObject() {
  546. return {};
  547. }
  548. async function parseArray(data) {
  549. const length = await parseValue(data);
  550. const array = new Array(length);
  551. if (length) {
  552. await parseNextSlot();
  553. }
  554. return array;
  555. async function parseNextSlot(indexArray = 0) {
  556. const value = await parseValue(data);
  557. if (!testEmptySlot(value)) {
  558. data.setObject([value], value => array[indexArray] = value);
  559. }
  560. if (indexArray < length - 1) {
  561. await parseNextSlot(indexArray + 1);
  562. }
  563. }
  564. }
  565. function parseEmptySlot() {
  566. return EMPTY_SLOT_VALUE;
  567. }
  568. async function parseString(data) {
  569. const size = await parseValue(data);
  570. const array = await data.consume(size);
  571. return textDecoder.decode(array);
  572. }
  573. async function parseFloat64Array(data) {
  574. const length = await parseValue(data);
  575. const array = await data.consume(length * 8);
  576. return new Float64Array(array.buffer);
  577. }
  578. async function parseFloat32Array(data) {
  579. const length = await parseValue(data);
  580. const array = await data.consume(length * 4);
  581. return new Float32Array(array.buffer);
  582. }
  583. async function parseUint32Array(data) {
  584. const length = await parseValue(data);
  585. const array = await data.consume(length * 4);
  586. return new Uint32Array(array.buffer);
  587. }
  588. async function parseInt32Array(data) {
  589. const length = await parseValue(data);
  590. const array = await data.consume(length * 4);
  591. return new Int32Array(array.buffer);
  592. }
  593. async function parseUint16Array(data) {
  594. const length = await parseValue(data);
  595. const array = await data.consume(length * 2);
  596. return new Uint16Array(array.buffer);
  597. }
  598. async function parseInt16Array(data) {
  599. const length = await parseValue(data);
  600. const array = await data.consume(length * 2);
  601. return new Int16Array(array.buffer);
  602. }
  603. async function parseUint8ClampedArray(data) {
  604. const length = await parseValue(data);
  605. const array = await data.consume(length);
  606. return new Uint8ClampedArray(array.buffer);
  607. }
  608. async function parseUint8Array(data) {
  609. const length = await parseValue(data);
  610. const array = await data.consume(length);
  611. return array;
  612. }
  613. async function parseInt8Array(data) {
  614. const length = await parseValue(data);
  615. const array = await data.consume(length);
  616. return new Int8Array(array.buffer);
  617. }
  618. async function parseArrayBuffer(data) {
  619. const length = await parseValue(data);
  620. const array = await data.consume(length);
  621. return array.buffer;
  622. }
  623. async function parseNumber(data) {
  624. const array = await data.consume(8);
  625. return new Float64Array(array.buffer)[0];
  626. }
  627. async function parseUint32(data) {
  628. const array = await data.consume(4);
  629. return new Uint32Array(array.buffer)[0];
  630. }
  631. async function parseInt32(data) {
  632. const array = await data.consume(4);
  633. return new Int32Array(array.buffer)[0];
  634. }
  635. async function parseUint16(data) {
  636. const array = await data.consume(2);
  637. return new Uint16Array(array.buffer)[0];
  638. }
  639. async function parseInt16(data) {
  640. const array = await data.consume(2);
  641. return new Int16Array(array.buffer)[0];
  642. }
  643. async function parseUint8(data) {
  644. const array = await data.consume(1);
  645. return new Uint8Array(array.buffer)[0];
  646. }
  647. async function parseInt8(data) {
  648. const array = await data.consume(1);
  649. return new Int8Array(array.buffer)[0];
  650. }
  651. function parseUndefined() {
  652. return undefined;
  653. }
  654. function parseNull() {
  655. return null;
  656. }
  657. function parseNaN() {
  658. return NaN;
  659. }
  660. async function parseBoolean(data) {
  661. const array = await data.consume(1);
  662. return Boolean(array[0]);
  663. }
  664. async function parseMap(data) {
  665. const size = await parseValue(data);
  666. const map = new Map();
  667. if (size) {
  668. await parseNextEntry();
  669. }
  670. return map;
  671. async function parseNextEntry(indexKey = 0) {
  672. const key = await parseValue(data);
  673. const value = await parseValue(data);
  674. data.setObject([key, value], (key, value) => map.set(key, value));
  675. if (indexKey < size - 1) {
  676. await parseNextEntry(indexKey + 1);
  677. }
  678. }
  679. }
  680. async function parseSet(data) {
  681. const size = await parseValue(data);
  682. const set = new Set();
  683. if (size) {
  684. await parseNextEntry();
  685. }
  686. return set;
  687. async function parseNextEntry(indexKey = 0) {
  688. const value = await parseValue(data);
  689. data.setObject([value], value => set.add(value));
  690. if (indexKey < size - 1) {
  691. await parseNextEntry(indexKey + 1);
  692. }
  693. }
  694. }
  695. async function parseDate(data) {
  696. const milliseconds = await parseNumber(data);
  697. return new Date(milliseconds);
  698. }
  699. async function parseError(data) {
  700. const message = await parseString(data);
  701. const stack = await parseString(data);
  702. const error = new Error(message);
  703. error.stack = stack;
  704. return error;
  705. }
  706. async function parseRegExp(data) {
  707. const source = await parseString(data);
  708. const flags = await parseString(data);
  709. return new RegExp(source, flags);
  710. }
  711. async function parseStringObject(data) {
  712. return new String(await parseString(data));
  713. }
  714. async function parseNumberObject(data) {
  715. return new Number(await parseNumber(data));
  716. }
  717. async function parseBooleanObject(data) {
  718. return new Boolean(await parseBoolean(data));
  719. }
  720. async function parseSymbol(data) {
  721. const description = await parseString(data);
  722. return Symbol(description);
  723. }
  724. function testCircularReference(value, data) {
  725. return testObject(value) && data.objects.includes(value);
  726. }
  727. function testReference(value) {
  728. return value instanceof Reference;
  729. }
  730. function testObject(value) {
  731. return value === Object(value);
  732. }
  733. function testArray(value) {
  734. return typeof value.length == "number";
  735. }
  736. function testEmptySlot(value) {
  737. return value === EMPTY_SLOT_VALUE;
  738. }
  739. function testString(value) {
  740. return typeof value == "string";
  741. }
  742. function testFloat64Array(value) {
  743. return value.constructor.name == "Float64Array";
  744. }
  745. function testUint32Array(value) {
  746. return value.constructor.name == "Uint32Array";
  747. }
  748. function testInt32Array(value) {
  749. return value.constructor.name == "Int32Array";
  750. }
  751. function testUint16Array(value) {
  752. return value.constructor.name == "Uint16Array";
  753. }
  754. function testFloat32Array(value) {
  755. return value.constructor.name == "Float32Array";
  756. }
  757. function testInt16Array(value) {
  758. return value.constructor.name == "Int16Array";
  759. }
  760. function testUint8ClampedArray(value) {
  761. return value.constructor.name == "Uint8ClampedArray";
  762. }
  763. function testUint8Array(value) {
  764. return value.constructor.name == "Uint8Array";
  765. }
  766. function testInt8Array(value) {
  767. return value.constructor.name == "Int8Array";
  768. }
  769. function testArrayBuffer(value) {
  770. return value.constructor.name == "ArrayBuffer";
  771. }
  772. function testNumber(value) {
  773. return typeof value == "number";
  774. }
  775. function testBigInt(value) {
  776. return typeof value == "bigint";
  777. }
  778. function testUint32(value) {
  779. return testInteger(value) && value >= 0 && value <= 4294967295;
  780. }
  781. function testInt32(value) {
  782. return testInteger(value) && value >= -2147483648 && value <= 2147483647;
  783. }
  784. function testUint16(value) {
  785. return testInteger(value) && value >= 0 && value <= 65535;
  786. }
  787. function testInt16(value) {
  788. return testInteger(value) && value >= -32768 && value <= 32767;
  789. }
  790. function testUint8(value) {
  791. return testInteger(value) && value >= 0 && value <= 255;
  792. }
  793. function testInt8(value) {
  794. return testInteger(value) && value >= -128 && value <= 127;
  795. }
  796. function testInteger(value) {
  797. return testNumber(value) && Number.isInteger(value);
  798. }
  799. function testUndefined(value) {
  800. return value === undefined;
  801. }
  802. function testNull(value) {
  803. return value === null;
  804. }
  805. function testNaN(value) {
  806. return Number.isNaN(value);
  807. }
  808. function testBoolean(value) {
  809. return typeof value == "boolean";
  810. }
  811. function testMap(value) {
  812. return value instanceof Map;
  813. }
  814. function testSet(value) {
  815. return value instanceof Set;
  816. }
  817. function testDate(value) {
  818. return value instanceof Date;
  819. }
  820. function testError(value) {
  821. return value instanceof Error;
  822. }
  823. function testRegExp(value) {
  824. return value instanceof RegExp;
  825. }
  826. function testStringObject(value) {
  827. return value instanceof String;
  828. }
  829. function testNumberObject(value) {
  830. return value instanceof Number;
  831. }
  832. function testBooleanObject(value) {
  833. return value instanceof Boolean;
  834. }
  835. function testSymbol(value) {
  836. return typeof value == "symbol";
  837. }
  838. function testReferenceable(value) {
  839. return testObject(value) || testSymbol(value);
  840. }