Website Structure

This commit is contained in:
supalerk-ar66 2026-01-13 10:46:40 +07:00
parent 62812f2090
commit 71f0676a62
22365 changed files with 4265753 additions and 791 deletions

7
Frontend-Learner/node_modules/seroval/LICENSE generated vendored Normal file
View file

@ -0,0 +1,7 @@
MIT License Copyright (c) 2025 Alexis Munsayac <alexis.munsayac@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

110
Frontend-Learner/node_modules/seroval/README.md generated vendored Normal file
View file

@ -0,0 +1,110 @@
# seroval
> Stringify JS values
[![NPM](https://img.shields.io/npm/v/seroval.svg)](https://www.npmjs.com/package/seroval) [![JavaScript Style Guide](https://badgen.net/badge/code%20style/airbnb/ff5a5f?icon=airbnb)](https://github.com/airbnb/javascript)
## Install
```bash
npm install --save seroval
```
```bash
yarn add seroval
```
```bash
pnpm add seroval
```
## Usage
```js
import { serialize } from 'seroval';
const object = {
number: [Math.random(), -0, NaN, Infinity, -Infinity],
string: ['hello world', '<script>Hello World</script>'],
boolean: [true, false],
null: null,
undefined: undefined,
bigint: 9007199254740991n,
array: [,,,], // holes
regexp: /[a-z0-9]+/i,
date: new Date(),
map: new Map([['hello', 'world']]),
set: new Set(['hello', 'world']),
};
// self cyclic references
// recursive objects
object.self = object;
// recursive arrays
object.array.push(object.array);
// recursive maps
object.map.set('self', object.map);
// recursive sets
object.set.add(object.set);
// mutual cyclic references
object.array.push(object.map);
object.map.set('mutual', object.set);
object.set.add(object.array);
const result = serialize(object);
console.log(result);
```
Output (as a string):
```js
((h,j,k,m,o)=>(o={number:[0.5337763749243287,-0,0/0,1/0,-1/0],string:["hello world","\x3Cscript>Hello World\x3C/script>"],boolean:[!0,!1],null:null,undefined:void 0,bigint:9007199254740991n,array:h=[,,,,k=(j=[],new Map([["hello","world"],["mutual",m=new Set(["hello","world"])]]))],regexp:/[a-z0-9]+/i,date:new Date("2023-12-07T17:28:57.909Z"),map:k,set:m},h[3]=h,k.set("self",k),m.add(m).add(h),o.self=o,o))()
// Formatted for readability
((h, j, k, m, o) => (
(o = {
number: [0.5337763749243287, -0, 0 / 0, 1 / 0, -1 / 0],
string: ["hello world", "\x3Cscript>Hello World\x3C/script>"],
boolean: [!0, !1],
null: null,
undefined: void 0,
bigint: 9007199254740991n,
array: (h = [
,
,
,
,
(k =
((j = []),
new Map([
["hello", "world"],
["mutual", (m = new Set(["hello", "world"]))],
]))),
]),
regexp: /[a-z0-9]+/i,
date: new Date("2023-12-07T17:28:57.909Z"),
map: k,
set: m,
}),
(h[3] = h),
k.set("self", k),
m.add(m).add(h),
(o.self = o),
o
))();
```
## Docs
- [Serialization](https://github.com/lxsmnsyc/seroval/blob/main/docs/serialization.md)
- [Compatibility](https://github.com/lxsmnsyc/seroval/blob/main/docs/compatibility.md)
- [Isomorphic References](https://github.com/lxsmnsyc/seroval/blob/main/docs/isomorphic-refs.md)
## Sponsors
![Sponsors](https://github.com/lxsmnsyc/sponsors/blob/main/sponsors.svg?raw=true)
## License
MIT © [lxsmnsyc](https://github.com/lxsmnsyc)

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,28 @@
import { type PluginAccessOptions } from './plugin';
export interface SerializerOptions extends PluginAccessOptions {
globalIdentifier: string;
scopeId?: string;
disabledFeatures?: number;
onData: (result: string) => void;
onError: (error: unknown) => void;
onDone?: () => void;
}
export default class Serializer {
private options;
private alive;
private flushed;
private done;
private pending;
private cleanups;
private refs;
private plugins?;
constructor(options: SerializerOptions);
keys: Set<string>;
write(key: string, value: unknown): void;
ids: number;
private getNextID;
push(value: unknown): string;
flush(): void;
close(): void;
}
//# sourceMappingURL=Serializer.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"Serializer.d.ts","sourceRoot":"","sources":["../../../src/core/Serializer.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,UAAU,CAAC;AAGlB,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,OAAO,UAAU;IAejB,OAAO,CAAC,OAAO;IAd3B,OAAO,CAAC,KAAK,CAAQ;IAErB,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,IAAI,CAAS;IAErB,OAAO,CAAC,OAAO,CAAK;IAEpB,OAAO,CAAC,QAAQ,CAAsB;IAEtC,OAAO,CAAC,IAAI,CAA8B;IAE1C,OAAO,CAAC,OAAO,CAAC,CAAqB;gBAEjB,OAAO,EAAE,iBAAiB;IAI9C,IAAI,cAAqB;IAEzB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IA2CxC,GAAG,SAAK;IAER,OAAO,CAAC,SAAS;IAOjB,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAM5B,KAAK,IAAI,IAAI;IAUb,KAAK,IAAI,IAAI;CAYd"}

View file

@ -0,0 +1,27 @@
import type { WellKnownSymbols } from './constants';
import type { SerovalAggregateErrorNode, SerovalArrayNode, SerovalAsyncIteratorFactoryInstanceNode, SerovalBigIntNode, SerovalBigIntTypedArrayNode, SerovalBoxedNode, SerovalConstantNode, SerovalDataViewNode, SerovalDateNode, SerovalErrorNode, SerovalIndexedValueNode, SerovalIteratorFactoryInstanceNode, SerovalNode, SerovalNodeWithID, SerovalNumberNode, SerovalObjectRecordNode, SerovalPluginNode, SerovalReferenceNode, SerovalRegExpNode, SerovalSetNode, SerovalStreamConstructorNode, SerovalStreamNextNode, SerovalStreamReturnNode, SerovalStreamThrowNode, SerovalStringNode, SerovalTypedArrayNode, SerovalWKSymbolNode } from './types';
import type { BigIntTypedArrayValue, TypedArrayValue } from './utils/typed-array';
export declare function createNumberNode(value: number): SerovalConstantNode | SerovalNumberNode;
export declare function createStringNode(value: string): SerovalStringNode;
export declare function createBigIntNode(current: bigint): SerovalBigIntNode;
export declare function createIndexedValueNode(id: number): SerovalIndexedValueNode;
export declare function createDateNode(id: number, current: Date): SerovalDateNode;
export declare function createRegExpNode(id: number, current: RegExp): SerovalRegExpNode;
export declare function createWKSymbolNode(id: number, current: WellKnownSymbols): SerovalWKSymbolNode;
export declare function createReferenceNode<T>(id: number, ref: T): SerovalReferenceNode;
export declare function createPluginNode(id: number, tag: string, value: unknown): SerovalPluginNode;
export declare function createArrayNode(id: number, current: unknown[], parsedItems: SerovalArrayNode['a']): SerovalArrayNode;
export declare function createBoxedNode(id: number, boxed: SerovalNode): SerovalBoxedNode;
export declare function createTypedArrayNode(id: number, current: TypedArrayValue, buffer: SerovalNode): SerovalTypedArrayNode;
export declare function createBigIntTypedArrayNode(id: number, current: BigIntTypedArrayValue, buffer: SerovalNode): SerovalBigIntTypedArrayNode;
export declare function createDataViewNode(id: number, current: DataView, buffer: SerovalNode): SerovalDataViewNode;
export declare function createErrorNode(id: number, current: Error, options: SerovalObjectRecordNode | undefined): SerovalErrorNode;
export declare function createAggregateErrorNode(id: number, current: AggregateError, options: SerovalObjectRecordNode | undefined): SerovalAggregateErrorNode;
export declare function createSetNode(id: number, items: SerovalNode[]): SerovalSetNode;
export declare function createIteratorFactoryInstanceNode(factory: SerovalNodeWithID, items: SerovalNode): SerovalIteratorFactoryInstanceNode;
export declare function createAsyncIteratorFactoryInstanceNode(factory: SerovalNodeWithID, items: SerovalNode): SerovalAsyncIteratorFactoryInstanceNode;
export declare function createStreamConstructorNode(id: number, factory: SerovalNodeWithID, sequence: SerovalNode[]): SerovalStreamConstructorNode;
export declare function createStreamNextNode(id: number, parsed: SerovalNode): SerovalStreamNextNode;
export declare function createStreamThrowNode(id: number, parsed: SerovalNode): SerovalStreamThrowNode;
export declare function createStreamReturnNode(id: number, parsed: SerovalNode): SerovalStreamReturnNode;
//# sourceMappingURL=base-primitives.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"base-primitives.d.ts","sourceRoot":"","sources":["../../../src/core/base-primitives.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAWpD,OAAO,KAAK,EACV,yBAAyB,EACzB,gBAAgB,EAChB,uCAAuC,EACvC,iBAAiB,EACjB,2BAA2B,EAC3B,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,kCAAkC,EAClC,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,4BAA4B,EAC5B,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAGjB,OAAO,KAAK,EACV,qBAAqB,EACrB,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAE7B,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,GACZ,mBAAmB,GAAG,iBAAiB,CA2BzC;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAejE;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAenE;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,CAe1E;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,eAAe,CAgBzE;AAED,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACd,iBAAiB,CAenB;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,gBAAgB,GACxB,mBAAmB,CAerB;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,CAAC,GACL,oBAAoB,CAetB;AAED,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,GACb,iBAAiB,CAenB;AAED,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,EAAE,EAClB,WAAW,EAAE,gBAAgB,CAAC,GAAG,CAAC,GACjC,gBAAgB,CAelB;AAED,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,WAAW,GACjB,gBAAgB,CAelB;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,WAAW,GAClB,qBAAqB,CAevB;AAED,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,WAAW,GAClB,2BAA2B,CAe7B;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,QAAQ,EACjB,MAAM,EAAE,WAAW,GAClB,mBAAmB,CAerB;AAED,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,KAAK,EACd,OAAO,EAAE,uBAAuB,GAAG,SAAS,GAC3C,gBAAgB,CAelB;AAED,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,uBAAuB,GAAG,SAAS,GAC3C,yBAAyB,CAe3B;AAED,wBAAgB,aAAa,CAC3B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,WAAW,EAAE,GACnB,cAAc,CAehB;AAED,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,WAAW,GACjB,kCAAkC,CAepC;AAED,wBAAgB,sCAAsC,CACpD,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,WAAW,GACjB,uCAAuC,CAezC;AAED,wBAAgB,2BAA2B,CACzC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,WAAW,EAAE,GACtB,4BAA4B,CAe9B;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,WAAW,GAClB,qBAAqB,CAevB;AAED,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,WAAW,GAClB,sBAAsB,CAexB;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,WAAW,GAClB,uBAAuB,CAezB"}

View file

@ -0,0 +1,15 @@
/**
* References
* - https://compat-table.github.io/compat-table/es6/
* - MDN
*/
export declare enum Feature {
AggregateError = 1,
ArrowFunction = 2,
ErrorPrototypeStack = 4,
ObjectAssign = 8,
BigIntTypedArray = 16,
RegExp = 32
}
export declare const ALL_ENABLED: number;
//# sourceMappingURL=compat.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../../../src/core/compat.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,oBAAY,OAAO;IACjB,cAAc,IAAO;IAErB,aAAa,IAAO;IACpB,mBAAmB,IAAO;IAC1B,YAAY,IAAO;IACnB,gBAAgB,KAAO;IACvB,MAAM,KAAO;CACd;AAED,eAAO,MAAM,WAAW,QAMR,CAAC"}

View file

@ -0,0 +1,104 @@
import { SYM_ASYNC_ITERATOR, SYM_HAS_INSTANCE, SYM_IS_CONCAT_SPREADABLE, SYM_ITERATOR, SYM_MATCH, SYM_MATCH_ALL, SYM_REPLACE, SYM_SEARCH, SYM_SPECIES, SYM_SPLIT, SYM_TO_PRIMITIVE, SYM_TO_STRING_TAG, SYM_UNSCOPABLES } from './symbols';
export declare const enum SerovalConstant {
Null = 0,
Undefined = 1,
True = 2,
False = 3,
NegZero = 4,
Inf = 5,
NegInf = 6,
Nan = 7
}
export declare const enum SerovalNodeType {
Number = 0,
String = 1,
Constant = 2,
BigInt = 3,
IndexedValue = 4,
Date = 5,
RegExp = 6,
Set = 7,
Map = 8,
Array = 9,
Object = 10,
NullConstructor = 11,
Promise = 12,
Error = 13,
AggregateError = 14,
TypedArray = 15,
BigIntTypedArray = 16,
WKSymbol = 17,
Reference = 18,
ArrayBuffer = 19,
DataView = 20,
Boxed = 21,
PromiseConstructor = 22,
PromiseSuccess = 23,
PromiseFailure = 24,
Plugin = 25,
SpecialReference = 26,
IteratorFactory = 27,
IteratorFactoryInstance = 28,
AsyncIteratorFactory = 29,
AsyncIteratorFactoryInstance = 30,
StreamConstructor = 31,
StreamNext = 32,
StreamThrow = 33,
StreamReturn = 34
}
export declare const enum SerovalObjectFlags {
None = 0,
NonExtensible = 1,
Sealed = 2,
Frozen = 3
}
export declare const enum Symbols {
AsyncIterator = 0,
HasInstance = 1,
IsConcatSpreadable = 2,
Iterator = 3,
Match = 4,
MatchAll = 5,
Replace = 6,
Search = 7,
Species = 8,
Split = 9,
ToPrimitive = 10,
ToStringTag = 11,
Unscopables = 12
}
export declare const SYMBOL_STRING: Record<Symbols, string>;
export declare const INV_SYMBOL_REF: {
[Symbol.asyncIterator]: Symbols;
[Symbol.hasInstance]: Symbols;
[Symbol.isConcatSpreadable]: Symbols;
[Symbol.iterator]: Symbols;
[Symbol.match]: Symbols;
[Symbol.matchAll]: Symbols;
[Symbol.replace]: Symbols;
[Symbol.search]: Symbols;
[Symbol.species]: Symbols;
[Symbol.split]: Symbols;
[Symbol.toPrimitive]: Symbols;
[Symbol.toStringTag]: Symbols;
[Symbol.unscopables]: Symbols;
};
export type WellKnownSymbols = keyof typeof INV_SYMBOL_REF;
export declare const SYMBOL_REF: Record<Symbols, WellKnownSymbols>;
export declare const CONSTANT_STRING: Record<SerovalConstant, string>;
export declare const NIL: undefined;
export declare const CONSTANT_VAL: Record<SerovalConstant, unknown>;
export declare const enum ErrorConstructorTag {
Error = 0,
EvalError = 1,
RangeError = 2,
ReferenceError = 3,
SyntaxError = 4,
TypeError = 5,
URIError = 6
}
export declare const ERROR_CONSTRUCTOR_STRING: Record<ErrorConstructorTag, string>;
type ErrorConstructors = ErrorConstructor | EvalErrorConstructor | RangeErrorConstructor | ReferenceErrorConstructor | SyntaxErrorConstructor | TypeErrorConstructor | URIErrorConstructor;
export declare const ERROR_CONSTRUCTOR: Record<ErrorConstructorTag, ErrorConstructors>;
export {};
//# sourceMappingURL=constants.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/core/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EACxB,YAAY,EACZ,SAAS,EACT,aAAa,EACb,WAAW,EACX,UAAU,EACV,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EAChB,MAAM,WAAW,CAAC;AAEnB,0BAAkB,eAAe;IAC/B,IAAI,IAAI;IACR,SAAS,IAAI;IACb,IAAI,IAAI;IACR,KAAK,IAAI;IACT,OAAO,IAAI;IACX,GAAG,IAAI;IACP,MAAM,IAAI;IACV,GAAG,IAAI;CACR;AAED,0BAAkB,eAAe;IAC/B,MAAM,IAAI;IACV,MAAM,IAAI;IACV,QAAQ,IAAI;IACZ,MAAM,IAAI;IACV,YAAY,IAAI;IAChB,IAAI,IAAI;IACR,MAAM,IAAI;IACV,GAAG,IAAI;IACP,GAAG,IAAI;IACP,KAAK,IAAI;IACT,MAAM,KAAK;IACX,eAAe,KAAK;IACpB,OAAO,KAAK;IACZ,KAAK,KAAK;IACV,cAAc,KAAK;IACnB,UAAU,KAAK;IACf,gBAAgB,KAAK;IACrB,QAAQ,KAAK;IACb,SAAS,KAAK;IACd,WAAW,KAAK;IAChB,QAAQ,KAAK;IACb,KAAK,KAAK;IACV,kBAAkB,KAAK;IACvB,cAAc,KAAK;IACnB,cAAc,KAAK;IACnB,MAAM,KAAK;IACX,gBAAgB,KAAK;IACrB,eAAe,KAAK;IACpB,uBAAuB,KAAK;IAC5B,oBAAoB,KAAK;IACzB,4BAA4B,KAAK;IACjC,iBAAiB,KAAK;IACtB,UAAU,KAAK;IACf,WAAW,KAAK;IAChB,YAAY,KAAK;CAClB;AAED,0BAAkB,kBAAkB;IAClC,IAAI,IAAI;IACR,aAAa,IAAI;IACjB,MAAM,IAAI;IACV,MAAM,IAAI;CACX;AAED,0BAAkB,OAAO;IACvB,aAAa,IAAI;IACjB,WAAW,IAAI;IACf,kBAAkB,IAAI;IACtB,QAAQ,IAAI;IACZ,KAAK,IAAI;IACT,QAAQ,IAAI;IACZ,OAAO,IAAI;IACX,MAAM,IAAI;IACV,OAAO,IAAI;IACX,KAAK,IAAI;IACT,WAAW,KAAK;IAChB,WAAW,KAAK;IAChB,WAAW,KAAK;CACjB;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAcjD,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;CAc1B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,cAAc,CAAC;AAE3D,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE,gBAAgB,CAcxD,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAS3D,CAAC;AAEF,eAAO,MAAM,GAAG,WAAS,CAAC;AAE1B,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,eAAe,EAAE,OAAO,CASzD,CAAC;AAEF,0BAAkB,mBAAmB;IACnC,KAAK,IAAI;IACT,SAAS,IAAI;IACb,UAAU,IAAI;IACd,cAAc,IAAI;IAClB,WAAW,IAAI;IACf,SAAS,IAAI;IACb,QAAQ,IAAI;CACb;AAED,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAQxE,CAAC;AAEF,KAAK,iBAAiB,GAClB,gBAAgB,GAChB,oBAAoB,GACpB,qBAAqB,GACrB,yBAAyB,GACzB,sBAAsB,GACtB,oBAAoB,GACpB,mBAAmB,CAAC;AAExB,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,mBAAmB,EAAE,iBAAiB,CAS1E,CAAC"}

View file

@ -0,0 +1,54 @@
import type { Stream } from './stream';
type SpecialPromise = Promise<unknown> & {
s?: 1 | 2;
v?: unknown;
};
export interface PromiseConstructorResolver {
p: SpecialPromise;
s: (value: unknown) => void;
f: (value: unknown) => void;
}
export declare const PROMISE_CONSTRUCTOR: () => PromiseConstructorResolver;
export declare const PROMISE_SUCCESS: (resolver: PromiseConstructorResolver, data: unknown) => void;
export declare const PROMISE_FAILURE: (resolver: PromiseConstructorResolver, data: unknown) => void;
export declare const SERIALIZED_PROMISE_CONSTRUCTOR: string;
export declare const SERIALIZED_PROMISE_SUCCESS: string;
export declare const SERIALIZED_PROMISE_FAILURE: string;
interface StreamListener<T> {
next(value: T): void;
throw(value: unknown): void;
return(value: T): void;
}
export declare const STREAM_CONSTRUCTOR: () => {
__SEROVAL_STREAM__: boolean;
on: (listener: StreamListener<unknown>) => () => void;
next: (value: unknown) => void;
throw: (value: unknown) => void;
return: (value: unknown) => void;
};
export declare const SERIALIZED_STREAM_CONSTRUCTOR: string;
export interface Sequence {
v: unknown[];
t: number;
d: number;
}
export declare const ITERATOR_CONSTRUCTOR: (symbol: symbol) => (sequence: Sequence) => () => {
[x: symbol]: () => /*elided*/ any;
next: () => {
done: boolean;
value: unknown;
};
};
export declare const SERIALIZED_ITERATOR_CONSTRUCTOR: string;
export declare const ASYNC_ITERATOR_CONSTRUCTOR: (symbol: symbol, createPromise: typeof PROMISE_CONSTRUCTOR) => (stream: Stream<unknown>) => () => {
[x: symbol]: () => /*elided*/ any;
next: () => SpecialPromise | {
done: boolean;
value: unknown;
};
};
export declare const SERIALIZED_ASYNC_ITERATOR_CONSTRUCTOR: string;
export declare const ARRAY_BUFFER_CONSTRUCTOR: (b64: string) => ArrayBuffer;
export declare const SERIALIZED_ARRAY_BUFFER_CONSTRUCTOR: string;
export {};
//# sourceMappingURL=constructors.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"constructors.d.ts","sourceRoot":"","sources":["../../../src/core/constructors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,KAAK,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG;IAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEpE,MAAM,WAAW,0BAA0B;IACzC,CAAC,EAAE,cAAc,CAAC;IAClB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5B,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7B;AAED,eAAO,MAAM,mBAAmB,QAAO,0BAWtC,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,UAAU,0BAA0B,EACpC,MAAM,OAAO,KACZ,IAIF,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,UAAU,0BAA0B,EACpC,MAAM,OAAO,KACZ,IAIF,CAAC;AAEF,eAAO,MAAM,8BAA8B,QACK,CAAC;AACjD,eAAO,MAAM,0BAA0B,QACK,CAAC;AAC7C,eAAO,MAAM,0BAA0B,QACK,CAAC;AAE7C,UAAU,cAAc,CAAC,CAAC;IACxB,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACrB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,kBAAkB;;mBA+CZ,cAAc,CAAC,OAAO,CAAC;kBACxB,OAAO;mBAMN,OAAO;oBASN,OAAO;CAU1B,CAAC;AAEF,eAAO,MAAM,6BAA6B,QACK,CAAC;AAEhD,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,OAAO,EAAE,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,eAAO,MAAM,oBAAoB,GAC9B,QAAQ,MAAM,MAAM,UAAU,QAAQ;;;;;;CAuBtC,CAAC;AAEJ,eAAO,MAAM,+BAA+B,QACK,CAAC;AAElD,eAAO,MAAM,0BAA0B,GACpC,QAAQ,MAAM,EAAE,eAAe,OAAO,mBAAmB,MACzD,QAAQ,MAAM,CAAC,OAAO,CAAC;;;;;;CAoFvB,CAAC;AAEJ,eAAO,MAAM,qCAAqC,QACK,CAAC;AAExD,eAAO,MAAM,wBAAwB,GAAI,KAAK,MAAM,gBAQnD,CAAC;AAEF,eAAO,MAAM,mCAAmC,QACK,CAAC"}

View file

@ -0,0 +1,20 @@
import type { SerovalMode } from '../plugin';
import type { SerovalNode } from '../types';
import type { BaseParserContext, BaseParserContextOptions } from './parser';
export type AsyncParserContextOptions = BaseParserContextOptions;
export interface AsyncParserContext {
base: BaseParserContext;
child: AsyncParsePluginContext | undefined;
}
export declare function createAsyncParserContext(mode: SerovalMode, options: AsyncParserContextOptions): AsyncParserContext;
export declare class AsyncParsePluginContext {
private _p;
private depth;
constructor(_p: AsyncParserContext, depth: number);
parse<T>(current: T): Promise<SerovalNode>;
}
export declare function parseObjectAsync(ctx: AsyncParserContext, depth: number, id: number, current: object): Promise<SerovalNode>;
export declare function parseFunctionAsync(ctx: AsyncParserContext, depth: number, current: unknown): Promise<SerovalNode>;
export declare function parseAsync<T>(ctx: AsyncParserContext, depth: number, current: T): Promise<SerovalNode>;
export declare function parseTopAsync<T>(ctx: AsyncParserContext, current: T): Promise<SerovalNode>;
//# sourceMappingURL=async-parser.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"async-parser.d.ts","sourceRoot":"","sources":["../../../../src/core/context/async-parser.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAW7C,OAAO,KAAK,EAQV,WAAW,EAUZ,MAAM,UAAU,CAAC;AAQlB,OAAO,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAoB5E,MAAM,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAEjE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE,uBAAuB,GAAG,SAAS,CAAC;CAC5C;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,yBAAyB,GACjC,kBAAkB,CAKpB;AAED,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,KAAK;gBADL,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,MAAM;IAGvB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;CAG3C;AAsUD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,kBAAkB,EACvB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CAoItB;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,kBAAkB,EACvB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,WAAW,CAAC,CAUtB;AAED,wBAAsB,UAAU,CAAC,CAAC,EAChC,GAAG,EAAE,kBAAkB,EACvB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,GACT,OAAO,CAAC,WAAW,CAAC,CA4BtB;AAED,wBAAsB,aAAa,CAAC,CAAC,EACnC,GAAG,EAAE,kBAAkB,EACvB,OAAO,EAAE,CAAC,GACT,OAAO,CAAC,WAAW,CAAC,CAQtB"}

View file

@ -0,0 +1,49 @@
import type { PluginAccessOptions } from '../plugin';
import { SerovalMode } from '../plugin';
import type { SerovalNode } from '../types';
export interface BaseDeserializerContextOptions extends PluginAccessOptions {
refs?: Map<number, unknown>;
features?: number;
disabledFeatures?: number;
depthLimit?: number;
}
export interface BaseDeserializerContext extends PluginAccessOptions {
readonly mode: SerovalMode;
/**
* Mapping ids to values
*/
refs: Map<number, unknown>;
features: number;
depthLimit: number;
}
export declare function createBaseDeserializerContext(mode: SerovalMode, options: BaseDeserializerContextOptions): BaseDeserializerContext;
export interface VanillaDeserializerContextOptions extends Omit<BaseDeserializerContextOptions, 'refs'> {
markedRefs: number[] | Set<number>;
}
export interface VanillaDeserializerState {
marked: Set<number>;
}
export interface VanillaDeserializerContext {
mode: SerovalMode.Vanilla;
base: BaseDeserializerContext;
child: DeserializePluginContext | undefined;
state: VanillaDeserializerState;
}
export declare function createVanillaDeserializerContext(options: VanillaDeserializerContextOptions): VanillaDeserializerContext;
export interface CrossDeserializerContext {
mode: SerovalMode.Cross;
base: BaseDeserializerContext;
child: DeserializePluginContext | undefined;
}
export type CrossDeserializerContextOptions = BaseDeserializerContextOptions;
export declare function createCrossDeserializerContext(options: CrossDeserializerContextOptions): CrossDeserializerContext;
type DeserializerContext = VanillaDeserializerContext | CrossDeserializerContext;
export declare class DeserializePluginContext {
private _p;
private depth;
constructor(_p: DeserializerContext, depth: number);
deserialize<T>(node: SerovalNode): T;
}
export declare function deserializeTop(ctx: DeserializerContext, node: SerovalNode): unknown;
export {};
//# sourceMappingURL=deserializer.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"deserializer.d.ts","sourceRoot":"","sources":["../../../../src/core/context/deserializer.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAWxC,OAAO,KAAK,EAcV,WAAW,EAiBZ,MAAM,UAAU,CAAC;AA6BlB,MAAM,WAAW,8BAA+B,SAAQ,mBAAmB;IACzE,IAAI,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAwB,SAAQ,mBAAmB;IAClE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B;;OAEG;IACH,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,8BAA8B,GACtC,uBAAuB,CAQzB;AAED,MAAM,WAAW,iCACf,SAAQ,IAAI,CAAC,8BAA8B,EAAE,MAAM,CAAC;IACpD,UAAU,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC;IAC1B,IAAI,EAAE,uBAAuB,CAAC;IAC9B,KAAK,EAAE,wBAAwB,GAAG,SAAS,CAAC;IAC5C,KAAK,EAAE,wBAAwB,CAAC;CACjC;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,iCAAiC,GACzC,0BAA0B,CAS5B;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC;IACxB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,KAAK,EAAE,wBAAwB,GAAG,SAAS,CAAC;CAC7C;AAED,MAAM,MAAM,+BAA+B,GAAG,8BAA8B,CAAC;AAE7E,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,+BAA+B,GACvC,wBAAwB,CAM1B;AAED,KAAK,mBAAmB,GACpB,0BAA0B,GAC1B,wBAAwB,CAAC;AAE7B,qBAAa,wBAAwB;IAEjC,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,KAAK;gBADL,EAAE,EAAE,mBAAmB,EACvB,KAAK,EAAE,MAAM;IAGvB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,GAAG,CAAC;CAGrC;AAsmBD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,mBAAmB,EACxB,IAAI,EAAE,WAAW,GAChB,OAAO,CAMT"}

View file

@ -0,0 +1,62 @@
import type { PluginAccessOptions, SerovalMode } from '../plugin';
import { SpecialReference } from '../special-reference';
import type { SerovalArrayBufferNode, SerovalAsyncIteratorFactoryNode, SerovalIndexedValueNode, SerovalIteratorFactoryNode, SerovalMapNode, SerovalNode, SerovalNullConstructorNode, SerovalObjectNode, SerovalObjectRecordNode, SerovalPromiseConstructorNode, SerovalReferenceNode, SerovalSpecialReferenceNode, SerovalWKSymbolNode } from '../types';
export interface BaseParserContextOptions extends PluginAccessOptions {
disabledFeatures?: number;
refs?: Map<unknown, number>;
depthLimit?: number;
}
export declare const enum ParserNodeType {
Fresh = 0,
Indexed = 1,
Referenced = 2
}
export interface FreshNode {
type: ParserNodeType.Fresh;
value: number;
}
export interface IndexedNode {
type: ParserNodeType.Indexed;
value: SerovalIndexedValueNode;
}
export interface ReferencedNode {
type: ParserNodeType.Referenced;
value: SerovalReferenceNode;
}
type ObjectNode = FreshNode | IndexedNode | ReferencedNode;
export interface BaseParserContext extends PluginAccessOptions {
readonly mode: SerovalMode;
marked: Set<number>;
refs: Map<unknown, number>;
features: number;
depthLimit: number;
}
export declare function createBaseParserContext(mode: SerovalMode, options: BaseParserContextOptions): BaseParserContext;
/**
* Ensures that the value (based on an identifier) has been visited by the parser.
* @param ctx
* @param id
*/
export declare function markParserRef(ctx: BaseParserContext, id: number): void;
export declare function isParserRefMarked(ctx: BaseParserContext, id: number): boolean;
/**
* Creates an identifier for a value
* @param ctx
* @param current
*/
export declare function createIndexForValue<T>(ctx: BaseParserContext, current: T): number;
export declare function getNodeForIndexedValue<T>(ctx: BaseParserContext, current: T): FreshNode | IndexedNode;
export declare function getReferenceNode<T>(ctx: BaseParserContext, current: T): ObjectNode;
/**
* Parsing methods
*/
export declare function parseWellKnownSymbol(ctx: BaseParserContext, current: symbol): SerovalIndexedValueNode | SerovalWKSymbolNode | SerovalReferenceNode;
export declare function parseSpecialReference(ctx: BaseParserContext, ref: SpecialReference): SerovalIndexedValueNode | SerovalSpecialReferenceNode;
export declare function parseIteratorFactory(ctx: BaseParserContext): SerovalIndexedValueNode | SerovalIteratorFactoryNode;
export declare function parseAsyncIteratorFactory(ctx: BaseParserContext): SerovalIndexedValueNode | SerovalAsyncIteratorFactoryNode;
export declare function createObjectNode(id: number, current: Record<string, unknown>, empty: boolean, record: SerovalObjectRecordNode): SerovalObjectNode | SerovalNullConstructorNode;
export declare function createMapNode(ctx: BaseParserContext, id: number, k: SerovalNode[], v: SerovalNode[]): SerovalMapNode;
export declare function createPromiseConstructorNode(ctx: BaseParserContext, id: number, resolver: number): SerovalPromiseConstructorNode;
export declare function createArrayBufferNode(ctx: BaseParserContext, id: number, current: ArrayBuffer): SerovalArrayBufferNode;
export {};
//# sourceMappingURL=parser.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../../src/core/context/parser.ts"],"names":[],"mappings":"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"}

View file

@ -0,0 +1,96 @@
import { SerovalObjectFlags } from '../constants';
import type { PluginAccessOptions } from '../plugin';
import { SerovalMode } from '../plugin';
import type { SerovalNode } from '../types';
declare const enum AssignmentType {
Index = 0,
Add = 1,
Set = 2,
Delete = 3
}
interface IndexAssignment {
t: AssignmentType.Index;
s: string;
k: undefined;
v: string;
}
interface SetAssignment {
t: AssignmentType.Set;
s: string;
k: string;
v: string;
}
interface AddAssignment {
t: AssignmentType.Add;
s: string;
k: undefined;
v: string;
}
interface DeleteAssignment {
t: AssignmentType.Delete;
s: string;
k: string;
v: undefined;
}
type Assignment = IndexAssignment | AddAssignment | SetAssignment | DeleteAssignment;
export interface FlaggedObject {
type: SerovalObjectFlags;
value: string;
}
export interface BaseSerializerContextOptions extends PluginAccessOptions {
features: number;
markedRefs: number[] | Set<number>;
}
export interface BaseSerializerContext extends PluginAccessOptions {
readonly mode: SerovalMode;
features: number;
stack: number[];
/**
* Array of object mutations
*/
flags: FlaggedObject[];
/**
* Array of assignments to be done (used for recursion)
*/
assignments: Assignment[];
/**
* Refs that are...referenced
*/
marked: Set<number>;
}
export interface CrossContextOptions {
scopeId?: string;
}
export declare function createBaseSerializerContext(mode: SerovalMode, options: BaseSerializerContextOptions): BaseSerializerContext;
export interface VanillaSerializerState {
valid: Map<number, number>;
vars: string[];
}
export interface VanillaSerializerContext {
mode: SerovalMode.Vanilla;
base: BaseSerializerContext;
state: VanillaSerializerState;
child: SerializePluginContext | undefined;
}
export type VanillaSerializerContextOptions = BaseSerializerContextOptions;
export declare function createVanillaSerializerContext(options: VanillaSerializerContextOptions): VanillaSerializerContext;
export interface CrossSerializerContext {
mode: SerovalMode.Cross;
base: BaseSerializerContext;
state: CrossContextOptions;
child: SerializePluginContext | undefined;
}
export interface CrossSerializerContextOptions extends BaseSerializerContextOptions, CrossContextOptions {
}
export declare function createCrossSerializerContext(options: CrossSerializerContextOptions): CrossSerializerContext;
type SerializerContext = VanillaSerializerContext | CrossSerializerContext;
export declare class SerializePluginContext {
private _p;
constructor(_p: SerializerContext);
serialize(node: SerovalNode): string;
}
export declare function serializeRoot(ctx: SerializerContext, node: SerovalNode): string;
export declare function serializeTopVanilla(ctx: VanillaSerializerContext, tree: SerovalNode): string;
export declare function serializeTopCross(ctx: CrossSerializerContext, tree: SerovalNode): string;
export {};
//# sourceMappingURL=serializer.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../../../../src/core/context/serializer.ts"],"names":[],"mappings":"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"}

View file

@ -0,0 +1,59 @@
import { SerovalMode } from '../plugin';
import type { SerovalNode } from '../types';
import type { BaseParserContext, BaseParserContextOptions } from './parser';
export type SyncParserContextOptions = BaseParserContextOptions;
declare const enum ParserMode {
Sync = 1,
Stream = 2
}
export interface SyncParserContext {
type: ParserMode.Sync;
base: BaseParserContext;
child: SyncParsePluginContext | undefined;
}
export declare function createSyncParserContext(mode: SerovalMode, options: SyncParserContextOptions): SyncParserContext;
export declare class SyncParsePluginContext {
private _p;
private depth;
constructor(_p: SyncParserContext, depth: number);
parse<T>(current: T): SerovalNode;
}
export interface StreamParserContextOptions extends SyncParserContextOptions {
onParse: (node: SerovalNode, initial: boolean) => void;
onError?: (error: unknown) => void;
onDone?: () => void;
}
export interface StreamParserContext {
type: ParserMode.Stream;
base: BaseParserContext;
state: StreamParserState;
}
export declare class StreamParsePluginContext {
private _p;
private depth;
constructor(_p: StreamParserContext, depth: number);
parse<T>(current: T): SerovalNode;
parseWithError<T>(current: T): SerovalNode | undefined;
isAlive(): boolean;
pushPendingState(): void;
popPendingState(): void;
onParse(node: SerovalNode): void;
onError(error: unknown): void;
}
interface StreamParserState {
alive: boolean;
pending: number;
initial: boolean;
buffer: SerovalNode[];
onParse: (node: SerovalNode, initial: boolean) => void;
onError?: (error: unknown) => void;
onDone?: () => void;
}
export declare function createStreamParserContext(options: StreamParserContextOptions): StreamParserContext;
type SOSParserContext = SyncParserContext | StreamParserContext;
export declare function parseSOS<T>(ctx: SOSParserContext, depth: number, current: T): SerovalNode;
export declare function parseTop<T>(ctx: SyncParserContext, current: T): SerovalNode;
export declare function startStreamParse<T>(ctx: StreamParserContext, current: T): void;
export declare function destroyStreamParse(ctx: StreamParserContext): void;
export {};
//# sourceMappingURL=sync-parser.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"sync-parser.d.ts","sourceRoot":"","sources":["../../../../src/core/context/sync-parser.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAe,WAAW,EAAE,MAAM,WAAW,CAAC;AAerD,OAAO,KAAK,EAQV,WAAW,EASZ,MAAM,UAAU,CAAC;AAOlB,OAAO,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAkB5E,MAAM,MAAM,wBAAwB,GAAG,wBAAwB,CAAC;AAEhE,mBAAW,UAAU;IACnB,IAAI,IAAI;IACR,MAAM,IAAI;CACX;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE,sBAAsB,GAAG,SAAS,CAAC;CAC3C;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CAMnB;AAED,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,KAAK;gBADL,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,MAAM;IAGvB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,WAAW;CAGlC;AAED,MAAM,WAAW,0BAA2B,SAAQ,wBAAwB;IAC1E,OAAO,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACvD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AACD,qBAAa,wBAAwB;IAEjC,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,KAAK;gBADL,EAAE,EAAE,mBAAmB,EACvB,KAAK,EAAE,MAAM;IAGvB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,WAAW;IAIjC,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,WAAW,GAAG,SAAS;IAItD,OAAO,IAAI,OAAO;IAIlB,gBAAgB,IAAI,IAAI;IAIxB,eAAe,IAAI,IAAI;IAIvB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAIhC,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;CAG9B;AAED,UAAU,iBAAiB;IAEzB,KAAK,EAAE,OAAO,CAAC;IAEf,OAAO,EAAE,MAAM,CAAC;IAEhB,OAAO,EAAE,OAAO,CAAC;IAEjB,MAAM,EAAE,WAAW,EAAE,CAAC;IAEtB,OAAO,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACvD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAgBD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CAMrB;AAED,KAAK,gBAAgB,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;AA6iBhE,wBAAgB,QAAQ,CAAC,CAAC,EACxB,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,GACT,WAAW,CAgCb;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,GAAG,WAAW,CAQ3E;AA+DD,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,GAAG,EAAE,mBAAmB,EACxB,OAAO,EAAE,CAAC,GACT,IAAI,CAYN;AAWD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,CAKjE"}

View file

@ -0,0 +1,24 @@
import type { AsyncParserContextOptions } from '../context/async-parser';
import type { CrossDeserializerContextOptions } from '../context/deserializer';
import type { CrossContextOptions } from '../context/serializer';
import type { StreamParserContextOptions, SyncParserContextOptions } from '../context/sync-parser';
import type { SerovalNode } from '../types';
export interface CrossSerializeOptions extends SyncParserContextOptions, CrossContextOptions {
}
export declare function crossSerialize<T>(source: T, options?: CrossSerializeOptions): string;
export interface CrossSerializeAsyncOptions extends AsyncParserContextOptions, CrossContextOptions {
}
export declare function crossSerializeAsync<T>(source: T, options?: CrossSerializeAsyncOptions): Promise<string>;
export type ToCrossJSONOptions = SyncParserContextOptions;
export declare function toCrossJSON<T>(source: T, options?: ToCrossJSONOptions): SerovalNode;
export type ToCrossJSONAsyncOptions = AsyncParserContextOptions;
export declare function toCrossJSONAsync<T>(source: T, options?: ToCrossJSONAsyncOptions): Promise<SerovalNode>;
export interface CrossSerializeStreamOptions extends Omit<StreamParserContextOptions, 'onParse'>, CrossContextOptions {
onSerialize: (data: string, initial: boolean) => void;
}
export declare function crossSerializeStream<T>(source: T, options: CrossSerializeStreamOptions): () => void;
export type ToCrossJSONStreamOptions = StreamParserContextOptions;
export declare function toCrossJSONStream<T>(source: T, options: ToCrossJSONStreamOptions): () => void;
export type FromCrossJSONOptions = CrossDeserializerContextOptions;
export declare function fromCrossJSON<T>(source: SerovalNode, options: FromCrossJSONOptions): T;
//# sourceMappingURL=index.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/cross/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAKzE,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,yBAAyB,CAAC;AAK/E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAKjE,OAAO,KAAK,EACV,0BAA0B,EAC1B,wBAAwB,EACzB,MAAM,wBAAwB,CAAC;AAShC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,WAAW,qBACf,SAAQ,wBAAwB,EAC9B,mBAAmB;CAAG;AAE1B,wBAAgB,cAAc,CAAC,CAAC,EAC9B,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,qBAA0B,GAClC,MAAM,CAeR;AAED,MAAM,WAAW,0BACf,SAAQ,yBAAyB,EAC/B,mBAAmB;CAAG;AAE1B,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,MAAM,MAAM,kBAAkB,GAAG,wBAAwB,CAAC;AAE1D,wBAAgB,WAAW,CAAC,CAAC,EAC3B,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,kBAAuB,GAC/B,WAAW,CAQb;AAED,MAAM,MAAM,uBAAuB,GAAG,yBAAyB,CAAC;AAEhE,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,WAAW,CAAC,CAQtB;AAED,MAAM,WAAW,2BACf,SAAQ,IAAI,CAAC,0BAA0B,EAAE,SAAS,CAAC,EACjD,mBAAmB;IACrB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACvD;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,2BAA2B,GACnC,MAAM,IAAI,CAkCZ;AAED,MAAM,MAAM,wBAAwB,GAAG,0BAA0B,CAAC;AAElE,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,wBAAwB,GAChC,MAAM,IAAI,CAcZ;AAED,MAAM,MAAM,oBAAoB,GAAG,+BAA+B,CAAC;AAEnE,wBAAgB,aAAa,CAAC,CAAC,EAC7B,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,oBAAoB,GAC5B,CAAC,CASH"}

View file

@ -0,0 +1,47 @@
import type { SerovalNode } from './types';
export declare class SerovalError extends Error {
cause: any;
constructor(type: string, cause: any);
}
export declare class SerovalParserError extends SerovalError {
constructor(cause: any);
}
export declare class SerovalSerializationError extends SerovalError {
constructor(cause: any);
}
export declare class SerovalDeserializationError extends SerovalError {
constructor(cause: any);
}
export declare class SerovalUnsupportedTypeError extends Error {
value: unknown;
constructor(value: unknown);
}
export declare class SerovalUnsupportedNodeError extends Error {
constructor(node: SerovalNode);
}
export declare class SerovalMissingPluginError extends Error {
constructor(tag: string);
}
export declare class SerovalMissingInstanceError extends Error {
constructor(tag: string);
}
export declare class SerovalMissingReferenceError extends Error {
value: unknown;
constructor(value: unknown);
}
export declare class SerovalMissingReferenceForIdError extends Error {
constructor(id: string);
}
export declare class SerovalUnknownTypedArrayError extends Error {
constructor(name: string);
}
export declare class SerovalMalformedNodeError extends Error {
constructor(node: SerovalNode);
}
export declare class SerovalConflictedNodeIdError extends Error {
constructor(node: SerovalNode);
}
export declare class SerovalDepthLimitError extends Error {
constructor(limit: number);
}
//# sourceMappingURL=errors.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/core/errors.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AA0C3C,qBAAa,YAAa,SAAQ,KAAK;IAG5B,KAAK,EAAE,GAAG;gBADjB,IAAI,EAAE,MAAM,EACL,KAAK,EAAE,GAAG;CAIpB;AAED,qBAAa,kBAAmB,SAAQ,YAAY;gBACtC,KAAK,EAAE,GAAG;CAGvB;AAED,qBAAa,yBAA0B,SAAQ,YAAY;gBAC7C,KAAK,EAAE,GAAG;CAGvB;AAED,qBAAa,2BAA4B,SAAQ,YAAY;gBAC/C,KAAK,EAAE,GAAG;CAGvB;AAmBD,qBAAa,2BAA4B,SAAQ,KAAK;IACjC,KAAK,EAAE,OAAO;gBAAd,KAAK,EAAE,OAAO;CAWlC;AAED,qBAAa,2BAA4B,SAAQ,KAAK;gBACxC,IAAI,EAAE,WAAW;CAO9B;AAED,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,GAAG,EAAE,MAAM;CAOxB;AAED,qBAAa,2BAA4B,SAAQ,KAAK;gBACxC,GAAG,EAAE,MAAM;CAOxB;AAED,qBAAa,4BAA6B,SAAQ,KAAK;IAClC,KAAK,EAAE,OAAO;gBAAd,KAAK,EAAE,OAAO;CAWlC;AAED,qBAAa,iCAAkC,SAAQ,KAAK;gBAC9C,EAAE,EAAE,MAAM;CAOvB;AAED,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,IAAI,EAAE,MAAM;CAOzB;AAED,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,IAAI,EAAE,WAAW;CAO9B;AAED,qBAAa,4BAA6B,SAAQ,KAAK;gBACzC,IAAI,EAAE,WAAW;CAO9B;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,KAAK,EAAE,MAAM;CAO1B"}

View file

@ -0,0 +1,3 @@
export declare function createFunction(parameters: string[], body: string): string;
export declare function createEffectfulFunction(parameters: string[], body: string): string;
//# sourceMappingURL=function-string.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"function-string.d.ts","sourceRoot":"","sources":["../../../src/core/function-string.ts"],"names":[],"mappings":"AAQA,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CASzE;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAAE,EACpB,IAAI,EAAE,MAAM,GACX,MAAM,CASR"}

View file

@ -0,0 +1,4 @@
export declare const REFERENCES_KEY = "__SEROVAL_REFS__";
export declare const GLOBAL_CONTEXT_REFERENCES = "$R";
export declare function getCrossReferenceHeader(id?: string): string;
//# sourceMappingURL=keys.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/core/keys.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,qBAAqB,CAAC;AAEjD,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAI9C,wBAAgB,uBAAuB,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAO3D"}

View file

@ -0,0 +1,10 @@
import type { SerovalConstantNode } from './types';
export declare const TRUE_NODE: SerovalConstantNode;
export declare const FALSE_NODE: SerovalConstantNode;
export declare const UNDEFINED_NODE: SerovalConstantNode;
export declare const NULL_NODE: SerovalConstantNode;
export declare const NEG_ZERO_NODE: SerovalConstantNode;
export declare const INFINITY_NODE: SerovalConstantNode;
export declare const NEG_INFINITY_NODE: SerovalConstantNode;
export declare const NAN_NODE: SerovalConstantNode;
//# sourceMappingURL=literals.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"literals.d.ts","sourceRoot":"","sources":["../../../src/core/literals.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAmBnD,eAAO,MAAM,SAAS,qBAErB,CAAC;AACF,eAAO,MAAM,UAAU,qBAEtB,CAAC;AACF,eAAO,MAAM,cAAc,qBAE1B,CAAC;AACF,eAAO,MAAM,SAAS,qBAErB,CAAC;AACF,eAAO,MAAM,aAAa,qBAEzB,CAAC;AACF,eAAO,MAAM,aAAa,qBAEzB,CAAC;AACF,eAAO,MAAM,iBAAiB,qBAE7B,CAAC;AACF,eAAO,MAAM,QAAQ,qBAA0D,CAAC"}

View file

@ -0,0 +1,8 @@
import type { SerovalNodeType } from './constants';
import type { SerovalNode } from './types';
type ExtractedNodeType<T extends SerovalNodeType> = Extract<SerovalNode, {
t: T;
}>;
export declare function createSerovalNode<T extends SerovalNodeType, N extends ExtractedNodeType<T>>(t: T, i: N['i'], s: N['s'], c: N['c'], m: N['m'], p: N['p'], e: N['e'], a: N['a'], f: N['f'], b: N['b'], o: N['o'], l: N['l']): N;
export {};
//# sourceMappingURL=node.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/core/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,KAAK,iBAAiB,CAAC,CAAC,SAAS,eAAe,IAAI,OAAO,CACzD,WAAW,EACX;IAAE,CAAC,EAAE,CAAC,CAAA;CAAE,CACT,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,CAAC,SAAS,eAAe,EACzB,CAAC,SAAS,iBAAiB,CAAC,CAAC,CAAC,EAE9B,CAAC,EAAE,CAAC,EACJ,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EACT,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EACT,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EACT,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EACT,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EACT,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EACT,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EACT,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EACT,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EACT,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EACT,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GACR,CAAC,CAeH"}

View file

@ -0,0 +1,9 @@
/**
* An opaque reference allows hiding values from the serializer.
*/
export declare class OpaqueReference<V, R = undefined> {
readonly value: V;
readonly replacement?: R | undefined;
constructor(value: V, replacement?: R | undefined);
}
//# sourceMappingURL=opaque-reference.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"opaque-reference.d.ts","sourceRoot":"","sources":["../../../src/core/opaque-reference.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,eAAe,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS;aAEzB,KAAK,EAAE,CAAC;aACR,WAAW,CAAC,EAAE,CAAC;gBADf,KAAK,EAAE,CAAC,EACR,WAAW,CAAC,EAAE,CAAC,YAAA;CAElC"}

View file

@ -0,0 +1,48 @@
import type { AsyncParsePluginContext } from './context/async-parser';
import type { DeserializePluginContext } from './context/deserializer';
import type { SerializePluginContext } from './context/serializer';
import type { StreamParsePluginContext, SyncParsePluginContext } from './context/sync-parser';
export declare const enum SerovalMode {
Vanilla = 1,
Cross = 2
}
export interface PluginData {
id: number;
}
export interface Plugin<Value, Node> {
/**
* A unique string that helps idenfity the plugin
*/
tag: string;
/**
* List of dependency plugins
*/
extends?: Plugin<any, any>[];
/**
* Method to test if a value is an expected value of the plugin
* @param value
*/
test(value: unknown): boolean;
/**
* Parsing modes
*/
parse: {
sync?: (value: Value, ctx: SyncParsePluginContext, data: PluginData) => Node;
async?: (value: Value, ctx: AsyncParsePluginContext, data: PluginData) => Promise<Node>;
stream?: (value: Value, ctx: StreamParsePluginContext, data: PluginData) => Node;
};
/**
* Convert the parsed node into a JS string
*/
serialize(node: Node, ctx: SerializePluginContext, data: PluginData): string;
/**
* Convert the parsed node into its runtime equivalent.
*/
deserialize(node: Node, ctx: DeserializePluginContext, data: PluginData): Value;
}
export declare function createPlugin<Value, Node>(plugin: Plugin<Value, Node>): Plugin<Value, Node>;
export interface PluginAccessOptions {
plugins?: Plugin<any, any>[];
}
export declare function resolvePlugins(plugins?: Plugin<any, any>[]): Plugin<any, any>[] | undefined;
//# sourceMappingURL=plugin.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/core/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EACV,wBAAwB,EACxB,sBAAsB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,0BAAkB,WAAW;IAC3B,OAAO,IAAI;IACX,KAAK,IAAI;CACV;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,MAAM,CAAC,KAAK,EAAE,IAAI;IACjC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;IAC7B;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAC9B;;OAEG;IACH,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,CACL,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,sBAAsB,EAC3B,IAAI,EAAE,UAAU,KACb,IAAI,CAAC;QACV,KAAK,CAAC,EAAE,CACN,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,uBAAuB,EAC5B,IAAI,EAAE,UAAU,KACb,OAAO,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM,CAAC,EAAE,CACP,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,UAAU,KACb,IAAI,CAAC;KACX,CAAC;IACF;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,sBAAsB,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;IAC7E;;OAEG;IACH,WAAW,CACT,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,UAAU,GACf,KAAK,CAAC;CACV;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,IAAI,EACtC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAC1B,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAErB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;CAC9B;AAiBD,wBAAgB,cAAc,CAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAC3B,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,SAAS,CAOhC"}

View file

@ -0,0 +1,6 @@
export declare function createReference<T>(id: string, value: T): T;
export declare function hasReferenceID<T>(value: T): boolean;
export declare function hasReference(id: string): boolean;
export declare function getReferenceID<T>(value: T): string;
export declare function getReference<T>(id: string): T;
//# sourceMappingURL=reference.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../../src/core/reference.ts"],"names":[],"mappings":"AASA,wBAAgB,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAI1D;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAEnD;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAKlD;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,CAK7C"}

View file

@ -0,0 +1,16 @@
export declare const ITERATOR: {};
export declare const ASYNC_ITERATOR: {};
export declare const enum SpecialReference {
MapSentinel = 0,
PromiseConstructor = 1,
PromiseSuccess = 2,
PromiseFailure = 3,
StreamConstructor = 4,
ArrayBufferConstructor = 5
}
/**
* Placeholder references
*/
export declare const SPECIAL_REFS: Record<SpecialReference, unknown>;
export declare const SPECIAL_REF_STRING: Record<SpecialReference, string>;
//# sourceMappingURL=special-reference.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"special-reference.d.ts","sourceRoot":"","sources":["../../../src/core/special-reference.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,QAAQ,IAAK,CAAC;AAE3B,eAAO,MAAM,cAAc,IAAK,CAAC;AAEjC,0BAAkB,gBAAgB;IAChC,WAAW,IAAI;IACf,kBAAkB,IAAI;IACtB,cAAc,IAAI;IAClB,cAAc,IAAI;IAClB,iBAAiB,IAAI;IACrB,sBAAsB,IAAI;CAC3B;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,gBAAgB,EAAE,OAAO,CAO1D,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAQ/D,CAAC"}

View file

@ -0,0 +1,17 @@
export interface StreamListener<T> {
next(value: T): void;
throw(value: unknown): void;
return(value: T): void;
}
export interface Stream<T> {
__SEROVAL_STREAM__: true;
on(listener: StreamListener<T>): () => void;
next(value: T): void;
throw(value: unknown): void;
return(value: T): void;
}
export declare function isStream<T>(value: object): value is Stream<T>;
export declare function createStream<T>(): Stream<T>;
export declare function createStreamFromAsyncIterable<T>(iterable: AsyncIterable<T>): Stream<T>;
export declare function streamToAsyncIterable<T>(stream: Stream<T>): () => AsyncIterableIterator<T>;
//# sourceMappingURL=stream.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../src/core/stream.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACrB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,MAAM,CAAC,CAAC;IACvB,kBAAkB,EAAE,IAAI,CAAC;IAEzB,EAAE,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IAE5C,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACrB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;CACxB;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,CAE7D;AAED,wBAAgB,YAAY,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAE3C;AAED,wBAAgB,6BAA6B,CAAC,CAAC,EAC7C,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GACzB,MAAM,CAAC,CAAC,CAAC,CAwBX;AAOD,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAChB,MAAM,qBAAqB,CAAC,CAAC,CAAC,CAIhC"}

View file

@ -0,0 +1,4 @@
export declare function serializeChar(str: string): string | undefined;
export declare function serializeString(str: string): string;
export declare function deserializeString(str: string): string;
//# sourceMappingURL=string.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../../../src/core/string.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAyB7D;AAOD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiBnD;AA6BD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKrD"}

View file

@ -0,0 +1,14 @@
export declare const SYM_ASYNC_ITERATOR: typeof Symbol.asyncIterator;
export declare const SYM_HAS_INSTANCE: typeof Symbol.hasInstance;
export declare const SYM_IS_CONCAT_SPREADABLE: typeof Symbol.isConcatSpreadable;
export declare const SYM_ITERATOR: typeof Symbol.iterator;
export declare const SYM_MATCH: typeof Symbol.match;
export declare const SYM_MATCH_ALL: typeof Symbol.matchAll;
export declare const SYM_REPLACE: typeof Symbol.replace;
export declare const SYM_SEARCH: typeof Symbol.search;
export declare const SYM_SPECIES: typeof Symbol.species;
export declare const SYM_SPLIT: typeof Symbol.split;
export declare const SYM_TO_PRIMITIVE: typeof Symbol.toPrimitive;
export declare const SYM_TO_STRING_TAG: typeof Symbol.toStringTag;
export declare const SYM_UNSCOPABLES: typeof Symbol.unscopables;
//# sourceMappingURL=symbols.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"symbols.d.ts","sourceRoot":"","sources":["../../../src/core/symbols.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,EAAE,OAAO,MAAM,CAAC,aAAoC,CAAC;AACpF,eAAO,MAAM,gBAAgB,EAAE,OAAO,MAAM,CAAC,WAAgC,CAAC;AAC9E,eAAO,MAAM,wBAAwB,EAAE,OAAO,MAAM,CAAC,kBAA8C,CAAC;AACpG,eAAO,MAAM,YAAY,EAAE,OAAO,MAAM,CAAC,QAA0B,CAAC;AACpE,eAAO,MAAM,SAAS,EAAE,OAAO,MAAM,CAAC,KAAoB,CAAC;AAC3D,eAAO,MAAM,aAAa,EAAE,OAAO,MAAM,CAAC,QAA0B,CAAC;AACrE,eAAO,MAAM,WAAW,EAAE,OAAO,MAAM,CAAC,OAAwB,CAAC;AACjE,eAAO,MAAM,UAAU,EAAE,OAAO,MAAM,CAAC,MAAsB,CAAC;AAC9D,eAAO,MAAM,WAAW,EAAE,OAAO,MAAM,CAAC,OAAwB,CAAC;AACjE,eAAO,MAAM,SAAS,EAAE,OAAO,MAAM,CAAC,KAAoB,CAAC;AAC3D,eAAO,MAAM,gBAAgB,EAAE,OAAO,MAAM,CAAC,WAAgC,CAAC;AAC9E,eAAO,MAAM,iBAAiB,EAAE,OAAO,MAAM,CAAC,WAAgC,CAAC;AAC/E,eAAO,MAAM,eAAe,EAAE,OAAO,MAAM,CAAC,WAAgC,CAAC"}

View file

@ -0,0 +1,21 @@
import type { BaseParserContextOptions } from '../context/parser';
import { type PluginAccessOptions } from '../plugin';
import type { SerovalNode } from '../types';
export type SyncParserContextOptions = Omit<BaseParserContextOptions, 'refs'>;
export type AsyncParserContextOptions = Omit<BaseParserContextOptions, 'refs'>;
export declare function serialize<T>(source: T, options?: SyncParserContextOptions): string;
export declare function serializeAsync<T>(source: T, options?: AsyncParserContextOptions): Promise<string>;
export declare function deserialize<T>(source: string): T;
export interface SerovalJSON {
t: SerovalNode;
f: number;
m: number[];
}
export interface FromJSONOptions extends PluginAccessOptions {
disabledFeatures?: number;
}
export declare function toJSON<T>(source: T, options?: SyncParserContextOptions): SerovalJSON;
export declare function toJSONAsync<T>(source: T, options?: AsyncParserContextOptions): Promise<SerovalJSON>;
export declare function compileJSON(source: SerovalJSON, options?: PluginAccessOptions): string;
export declare function fromJSON<T>(source: SerovalJSON, options?: FromJSONOptions): T;
//# sourceMappingURL=index.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/tree/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAMlE,OAAO,EACL,KAAK,mBAAmB,EAGzB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,MAAM,wBAAwB,GAAG,IAAI,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAAC;AAC9E,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAAC;AAE/E,wBAAgB,SAAS,CAAC,CAAC,EACzB,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,wBAA6B,GACrC,MAAM,CAaR;AAED,wBAAsB,cAAc,CAAC,CAAC,EACpC,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,MAAM,CAAC,CAajB;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,CAEhD;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,WAAW,CAAC;IACf,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,EAAE,CAAC;CACb;AAED,MAAM,WAAW,eAAgB,SAAQ,mBAAmB;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,MAAM,CAAC,CAAC,EACtB,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,wBAA6B,GACrC,WAAW,CAWb;AAED,wBAAsB,WAAW,CAAC,CAAC,EACjC,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,WAAW,CAAC,CAWtB;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,mBAAwB,GAChC,MAAM,CAQR;AAED,wBAAgB,QAAQ,CAAC,CAAC,EACxB,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,eAAoB,GAC5B,CAAC,CAWH"}

View file

@ -0,0 +1,226 @@
import type { ErrorConstructorTag, SerovalConstant, SerovalNodeType, SerovalObjectFlags, Symbols } from './constants';
import type { SpecialReference } from './special-reference';
export interface SerovalBaseNode {
t: SerovalNodeType;
i: number | undefined;
s: unknown;
c: string | undefined;
m: string | undefined;
p: SerovalObjectRecordNode | undefined;
e: SerovalMapRecordNode | undefined;
a: (SerovalNode | 0)[] | undefined;
f: SerovalNode | undefined;
b: number | undefined;
o: SerovalObjectFlags | undefined;
l: number | undefined;
}
export type SerovalObjectRecordKey = string | SerovalNode;
export interface SerovalObjectRecordNode {
k: SerovalObjectRecordKey[];
v: SerovalNode[];
}
export interface SerovalMapRecordNode {
k: SerovalNode[];
v: SerovalNode[];
}
export interface SerovalNumberNode extends SerovalBaseNode {
t: SerovalNodeType.Number;
s: number;
}
export interface SerovalStringNode extends SerovalBaseNode {
t: SerovalNodeType.String;
s: string;
}
export interface SerovalConstantNode extends SerovalBaseNode {
t: SerovalNodeType.Constant;
s: SerovalConstant;
}
export type SerovalPrimitiveNode = SerovalNumberNode | SerovalStringNode | SerovalConstantNode;
export interface SerovalIndexedValueNode extends SerovalBaseNode {
t: SerovalNodeType.IndexedValue;
i: number;
}
export interface SerovalBigIntNode extends SerovalBaseNode {
t: SerovalNodeType.BigInt;
s: string;
}
export interface SerovalDateNode extends SerovalBaseNode {
t: SerovalNodeType.Date;
i: number;
s: string;
}
export interface SerovalRegExpNode extends SerovalBaseNode {
t: SerovalNodeType.RegExp;
i: number;
c: string;
m: string;
}
export interface SerovalArrayBufferNode extends SerovalBaseNode {
t: SerovalNodeType.ArrayBuffer;
i: number;
s: string;
f: SerovalNodeWithID;
}
export interface SerovalTypedArrayNode extends SerovalBaseNode {
t: SerovalNodeType.TypedArray;
i: number;
c: string;
f: SerovalNode;
b: number;
l: number;
}
export interface SerovalBigIntTypedArrayNode extends SerovalBaseNode {
t: SerovalNodeType.BigIntTypedArray;
i: number;
c: string;
f: SerovalNode;
b: number;
l: number;
}
export type SerovalSemiPrimitiveNode = SerovalBigIntNode | SerovalDateNode | SerovalRegExpNode | SerovalTypedArrayNode | SerovalBigIntTypedArrayNode;
export interface SerovalSetNode extends SerovalBaseNode {
t: SerovalNodeType.Set;
i: number;
a: SerovalNode[];
}
export interface SerovalMapNode extends SerovalBaseNode {
t: SerovalNodeType.Map;
i: number;
e: SerovalMapRecordNode;
f: SerovalNodeWithID;
}
export interface SerovalArrayNode extends SerovalBaseNode {
t: SerovalNodeType.Array;
a: (SerovalNode | 0)[];
i: number;
o: SerovalObjectFlags;
}
export interface SerovalObjectNode extends SerovalBaseNode {
t: SerovalNodeType.Object;
p: SerovalObjectRecordNode;
i: number;
o: SerovalObjectFlags;
}
export interface SerovalNullConstructorNode extends SerovalBaseNode {
t: SerovalNodeType.NullConstructor;
p: SerovalObjectRecordNode;
i: number;
o: SerovalObjectFlags;
}
export interface SerovalPromiseNode extends SerovalBaseNode {
t: SerovalNodeType.Promise;
s: 0 | 1;
f: SerovalNode;
i: number;
}
export interface SerovalErrorNode extends SerovalBaseNode {
t: SerovalNodeType.Error;
s: ErrorConstructorTag;
m: string;
p: SerovalObjectRecordNode | undefined;
i: number;
}
export interface SerovalAggregateErrorNode extends SerovalBaseNode {
t: SerovalNodeType.AggregateError;
i: number;
m: string;
p: SerovalObjectRecordNode | undefined;
}
export interface SerovalWKSymbolNode extends SerovalBaseNode {
t: SerovalNodeType.WKSymbol;
i: number;
s: Symbols;
}
export interface SerovalReferenceNode extends SerovalBaseNode {
t: SerovalNodeType.Reference;
i: number;
s: string;
}
export interface SerovalDataViewNode extends SerovalBaseNode {
t: SerovalNodeType.DataView;
i: number;
f: SerovalNode;
b: number;
l: number;
}
export interface SerovalBoxedNode extends SerovalBaseNode {
t: SerovalNodeType.Boxed;
i: number;
f: SerovalNode;
}
export interface SerovalPromiseConstructorNode extends SerovalBaseNode {
t: SerovalNodeType.PromiseConstructor;
i: number;
s: number;
f: SerovalNodeWithID;
}
export interface SerovalPromiseResolveNode extends SerovalBaseNode {
t: SerovalNodeType.PromiseSuccess;
i: number;
a: [resolver: SerovalNodeWithID, resolved: SerovalNode];
}
export interface SerovalPromiseRejectNode extends SerovalBaseNode {
t: SerovalNodeType.PromiseFailure;
i: number;
a: [resolver: SerovalNodeWithID, resolved: SerovalNode];
}
export interface SerovalPluginNode extends SerovalBaseNode {
t: SerovalNodeType.Plugin;
i: number;
s: unknown;
c: string;
}
/**
* Represents special values as placeholders
*/
export interface SerovalSpecialReferenceNode extends SerovalBaseNode {
t: SerovalNodeType.SpecialReference;
i: number;
s: SpecialReference;
}
export interface SerovalIteratorFactoryNode extends SerovalBaseNode {
t: SerovalNodeType.IteratorFactory;
i: number;
f: SerovalNodeWithID;
}
export interface SerovalIteratorFactoryInstanceNode extends SerovalBaseNode {
t: SerovalNodeType.IteratorFactoryInstance;
a: [instance: SerovalNodeWithID, sequence: SerovalNode];
}
export interface SerovalAsyncIteratorFactoryNode extends SerovalBaseNode {
t: SerovalNodeType.AsyncIteratorFactory;
i: number;
a: [promise: SerovalNodeWithID, symbol: SerovalNodeWithID];
}
export interface SerovalAsyncIteratorFactoryInstanceNode extends SerovalBaseNode {
t: SerovalNodeType.AsyncIteratorFactoryInstance;
a: [instance: SerovalNodeWithID, sequence: SerovalNode];
}
export interface SerovalStreamConstructorNode extends SerovalBaseNode {
t: SerovalNodeType.StreamConstructor;
i: number;
a: SerovalNode[];
f: SerovalNodeWithID;
}
export interface SerovalStreamNextNode extends SerovalBaseNode {
t: SerovalNodeType.StreamNext;
i: number;
f: SerovalNode;
}
export interface SerovalStreamThrowNode extends SerovalBaseNode {
t: SerovalNodeType.StreamThrow;
i: number;
f: SerovalNode;
}
export interface SerovalStreamReturnNode extends SerovalBaseNode {
t: SerovalNodeType.StreamReturn;
i: number;
f: SerovalNode;
}
export type SerovalSyncNode = SerovalPrimitiveNode | SerovalIndexedValueNode | SerovalSemiPrimitiveNode | SerovalSetNode | SerovalMapNode | SerovalArrayNode | SerovalObjectNode | SerovalNullConstructorNode | SerovalPromiseNode | SerovalErrorNode | SerovalAggregateErrorNode | SerovalWKSymbolNode | SerovalReferenceNode | SerovalArrayBufferNode | SerovalDataViewNode | SerovalBoxedNode | SerovalPluginNode | SerovalSpecialReferenceNode | SerovalIteratorFactoryNode | SerovalIteratorFactoryInstanceNode | SerovalAsyncIteratorFactoryNode | SerovalAsyncIteratorFactoryInstanceNode;
export type SerovalAsyncNode = SerovalPromiseNode | SerovalPromiseConstructorNode | SerovalPromiseResolveNode | SerovalPromiseRejectNode | SerovalStreamConstructorNode | SerovalStreamNextNode | SerovalStreamThrowNode | SerovalStreamReturnNode;
export type SerovalNode = SerovalSyncNode | SerovalAsyncNode;
export type SerovalNodeWithID = Extract<SerovalNode, {
i: number;
}>;
//# sourceMappingURL=types.d.ts.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,6 @@
import { ErrorConstructorTag } from '../constants';
type ErrorValue = Error | AggregateError | EvalError | RangeError | ReferenceError | TypeError | SyntaxError | URIError;
export declare function getErrorConstructor(error: ErrorValue): ErrorConstructorTag;
export declare function getErrorOptions(error: Error, features: number): Record<string, unknown> | undefined;
export {};
//# sourceMappingURL=error.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/error.ts"],"names":[],"mappings":"AACA,OAAO,EAA4B,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE7E,KAAK,UAAU,GACX,KAAK,GACL,cAAc,GACd,SAAS,GACT,UAAU,GACV,cAAc,GACd,SAAS,GACT,WAAW,GACX,QAAQ,CAAC;AAEb,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,mBAAmB,CAoB1E;AAkBD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAkBrC"}

View file

@ -0,0 +1,2 @@
export default function getIdentifier(index: number): string;
//# sourceMappingURL=get-identifier.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"get-identifier.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/get-identifier.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAU3D"}

View file

@ -0,0 +1,3 @@
import { SerovalObjectFlags } from '../constants';
export declare function getObjectFlag(obj: unknown): SerovalObjectFlags;
//# sourceMappingURL=get-object-flag.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"get-object-flag.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/get-object-flag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAW9D"}

View file

@ -0,0 +1,2 @@
export declare function isValidIdentifier(name: string): boolean;
//# sourceMappingURL=is-valid-identifier.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"is-valid-identifier.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/is-valid-identifier.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASvD"}

View file

@ -0,0 +1,8 @@
export interface Sequence {
v: unknown[];
t: number;
d: number;
}
export declare function iteratorToSequence<T>(source: Iterable<T>): Sequence;
export declare function sequenceToIterator<T>(sequence: Sequence): () => IterableIterator<T>;
//# sourceMappingURL=iterator-to-sequence.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"iterator-to-sequence.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/iterator-to-sequence.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,OAAO,EAAE,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CA0BnE;AAID,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,QAAQ,EAAE,QAAQ,GACjB,MAAM,gBAAgB,CAAC,CAAC,CAAC,CAE3B"}

View file

@ -0,0 +1,2 @@
export default function promiseToResult(current: Promise<unknown>): Promise<[0 | 1, unknown]>;
//# sourceMappingURL=promise-to-result.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"promise-to-result.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/promise-to-result.ts"],"names":[],"mappings":"AAAA,wBAA8B,eAAe,CAC3C,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GACxB,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,CAM3B"}

View file

@ -0,0 +1,6 @@
type TypedArrayConstructor = Int8ArrayConstructor | Int16ArrayConstructor | Int32ArrayConstructor | Uint8ArrayConstructor | Uint16ArrayConstructor | Uint32ArrayConstructor | Uint8ClampedArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor | BigInt64ArrayConstructor | BigUint64ArrayConstructor;
export type TypedArrayValue = Int8Array | Int16Array | Int32Array | Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array;
export type BigIntTypedArrayValue = BigInt64Array | BigUint64Array;
export declare function getTypedArrayConstructor(name: string): TypedArrayConstructor;
export {};
//# sourceMappingURL=typed-array.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"typed-array.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/typed-array.ts"],"names":[],"mappings":"AAEA,KAAK,qBAAqB,GACtB,oBAAoB,GACpB,qBAAqB,GACrB,qBAAqB,GACrB,qBAAqB,GACrB,sBAAsB,GACtB,sBAAsB,GACtB,4BAA4B,GAC5B,uBAAuB,GACvB,uBAAuB,GACvB,wBAAwB,GACxB,yBAAyB,CAAC;AAE9B,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,UAAU,GACV,UAAU,GACV,UAAU,GACV,WAAW,GACX,WAAW,GACX,iBAAiB,GACjB,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG,cAAc,CAAC;AAEnE,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,CA2B5E"}

View file

@ -0,0 +1,18 @@
export { Feature } from './core/compat';
export type { AsyncParsePluginContext, AsyncParserContextOptions, } from './core/context/async-parser';
export type { BaseDeserializerContextOptions, CrossDeserializerContextOptions, DeserializePluginContext, VanillaDeserializerContextOptions, } from './core/context/deserializer';
export type { BaseParserContextOptions } from './core/context/parser';
export type { BaseSerializerContextOptions, CrossContextOptions, CrossSerializerContextOptions, SerializePluginContext, VanillaSerializerContextOptions, } from './core/context/serializer';
export type { StreamParsePluginContext, StreamParserContextOptions, SyncParsePluginContext, SyncParserContextOptions, } from './core/context/sync-parser';
export * from './core/cross';
export * from './core/errors';
export { getCrossReferenceHeader } from './core/keys';
export { OpaqueReference } from './core/opaque-reference';
export * from './core/plugin';
export { createReference } from './core/reference';
export { default as Serializer } from './core/Serializer';
export { createStream } from './core/stream';
export type { Stream, StreamListener } from './core/stream';
export * from './core/tree';
export type { SerovalNode } from './core/types';
//# sourceMappingURL=index.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,YAAY,EACV,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,8BAA8B,EAC9B,+BAA+B,EAC/B,wBAAwB,EACxB,iCAAiC,GAClC,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,YAAY,EACV,4BAA4B,EAC5B,mBAAmB,EACnB,6BAA6B,EAC7B,sBAAsB,EACtB,+BAA+B,GAChC,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC5D,cAAc,aAAa,CAAC;AAC5B,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}

67
Frontend-Learner/node_modules/seroval/package.json generated vendored Normal file
View file

@ -0,0 +1,67 @@
{
"name": "seroval",
"type": "module",
"version": "1.4.2",
"files": [
"dist",
"src"
],
"engines": {
"node": ">=10"
},
"license": "MIT",
"keywords": [
"pridepack"
],
"devDependencies": {
"@types/node": "^24.10.0",
"@vitest/ui": "^4.0.6",
"pridepack": "2.6.4",
"ts-prune": "^0.10.3",
"tslib": "^2.8.1",
"typescript": "^5.9.3",
"vitest": "^4.0.6"
},
"private": false,
"description": "Stringify JS values",
"repository": {
"url": "https://github.com/lxsmnsyc/seroval.git",
"type": "git"
},
"homepage": "https://github.com/lxsmnsyc/seroval/tree/main/packages/seroval",
"bugs": {
"url": "https://github.com/lxsmnsyc/seroval/issues"
},
"publishConfig": {
"access": "public"
},
"author": "Alexis Munsayac",
"types": "./dist/types/index.d.ts",
"main": "./dist/cjs/production/index.cjs",
"module": "./dist/esm/production/index.mjs",
"exports": {
".": {
"types": "./dist/types/index.d.ts",
"development": {
"require": "./dist/cjs/development/index.cjs",
"import": "./dist/esm/development/index.mjs"
},
"require": "./dist/cjs/production/index.cjs",
"import": "./dist/esm/production/index.mjs"
}
},
"typesVersions": {
"*": {}
},
"scripts": {
"build": "pridepack build",
"type-check": "pridepack check",
"clean": "pridepack clean",
"watch": "pridepack watch",
"start": "pridepack start",
"dev": "pridepack dev",
"test": "vitest",
"test:ui": "vitest --ui",
"prune": "ts-prune"
}
}

View file

@ -0,0 +1,119 @@
import { crossSerializeStream } from './cross';
import {
resolvePlugins,
type Plugin,
type PluginAccessOptions,
} from './plugin';
import { serializeString } from './string';
export interface SerializerOptions extends PluginAccessOptions {
globalIdentifier: string;
scopeId?: string;
disabledFeatures?: number;
onData: (result: string) => void;
onError: (error: unknown) => void;
onDone?: () => void;
}
export default class Serializer {
private alive = true;
private flushed = false;
private done = false;
private pending = 0;
private cleanups: (() => void)[] = [];
private refs = new Map<unknown, number>();
private plugins?: Plugin<any, any>[];
constructor(private options: SerializerOptions) {
this.plugins = resolvePlugins(options.plugins);
}
keys = new Set<string>();
write(key: string, value: unknown): void {
if (this.alive && !this.flushed) {
this.pending++;
this.keys.add(key);
this.cleanups.push(
crossSerializeStream(value, {
plugins: this.plugins,
scopeId: this.options.scopeId,
refs: this.refs,
disabledFeatures: this.options.disabledFeatures,
onError: this.options.onError,
onSerialize: (data, initial) => {
if (this.alive) {
this.options.onData(
initial
? this.options.globalIdentifier +
'["' +
serializeString(key) +
'"]=' +
data
: data,
);
}
},
onDone: () => {
if (this.alive) {
this.pending--;
if (
this.pending <= 0 &&
this.flushed &&
!this.done &&
this.options.onDone
) {
this.options.onDone();
this.done = true;
}
}
},
}),
);
}
}
ids = 0;
private getNextID(): string {
while (this.keys.has('' + this.ids)) {
this.ids++;
}
return '' + this.ids;
}
push(value: unknown): string {
const newID = this.getNextID();
this.write(newID, value);
return newID;
}
flush(): void {
if (this.alive) {
this.flushed = true;
if (this.pending <= 0 && !this.done && this.options.onDone) {
this.options.onDone();
this.done = true;
}
}
}
close(): void {
if (this.alive) {
for (let i = 0, len = this.cleanups.length; i < len; i++) {
this.cleanups[i]();
}
if (!this.done && this.options.onDone) {
this.options.onDone();
this.done = true;
}
this.alive = false;
}
}
}

View file

@ -0,0 +1,514 @@
import type { WellKnownSymbols } from './constants';
import { INV_SYMBOL_REF, NIL, SerovalNodeType } from './constants';
import {
INFINITY_NODE,
NAN_NODE,
NEG_INFINITY_NODE,
NEG_ZERO_NODE,
} from './literals';
import { createSerovalNode } from './node';
import { getReferenceID } from './reference';
import { serializeString } from './string';
import type {
SerovalAggregateErrorNode,
SerovalArrayNode,
SerovalAsyncIteratorFactoryInstanceNode,
SerovalBigIntNode,
SerovalBigIntTypedArrayNode,
SerovalBoxedNode,
SerovalConstantNode,
SerovalDataViewNode,
SerovalDateNode,
SerovalErrorNode,
SerovalIndexedValueNode,
SerovalIteratorFactoryInstanceNode,
SerovalNode,
SerovalNodeWithID,
SerovalNumberNode,
SerovalObjectRecordNode,
SerovalPluginNode,
SerovalReferenceNode,
SerovalRegExpNode,
SerovalSetNode,
SerovalStreamConstructorNode,
SerovalStreamNextNode,
SerovalStreamReturnNode,
SerovalStreamThrowNode,
SerovalStringNode,
SerovalTypedArrayNode,
SerovalWKSymbolNode,
} from './types';
import { getErrorConstructor } from './utils/error';
import { getObjectFlag } from './utils/get-object-flag';
import type {
BigIntTypedArrayValue,
TypedArrayValue,
} from './utils/typed-array';
export function createNumberNode(
value: number,
): SerovalConstantNode | SerovalNumberNode {
switch (value) {
case Number.POSITIVE_INFINITY:
return INFINITY_NODE;
case Number.NEGATIVE_INFINITY:
return NEG_INFINITY_NODE;
}
if (value !== value) {
return NAN_NODE;
}
if (Object.is(value, -0)) {
return NEG_ZERO_NODE;
}
return createSerovalNode(
SerovalNodeType.Number,
NIL,
value,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function createStringNode(value: string): SerovalStringNode {
return createSerovalNode(
SerovalNodeType.String,
NIL,
serializeString(value),
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function createBigIntNode(current: bigint): SerovalBigIntNode {
return createSerovalNode(
SerovalNodeType.BigInt,
NIL,
'' + current,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function createIndexedValueNode(id: number): SerovalIndexedValueNode {
return createSerovalNode(
SerovalNodeType.IndexedValue,
id,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function createDateNode(id: number, current: Date): SerovalDateNode {
const timestamp = current.valueOf();
return createSerovalNode(
SerovalNodeType.Date,
id,
timestamp !== timestamp ? '' : current.toISOString(),
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function createRegExpNode(
id: number,
current: RegExp,
): SerovalRegExpNode {
return createSerovalNode(
SerovalNodeType.RegExp,
id,
NIL,
serializeString(current.source),
current.flags,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function createWKSymbolNode(
id: number,
current: WellKnownSymbols,
): SerovalWKSymbolNode {
return createSerovalNode(
SerovalNodeType.WKSymbol,
id,
INV_SYMBOL_REF[current],
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function createReferenceNode<T>(
id: number,
ref: T,
): SerovalReferenceNode {
return createSerovalNode(
SerovalNodeType.Reference,
id,
serializeString(getReferenceID(ref)),
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function createPluginNode(
id: number,
tag: string,
value: unknown,
): SerovalPluginNode {
return createSerovalNode(
SerovalNodeType.Plugin,
id,
value,
serializeString(tag),
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function createArrayNode(
id: number,
current: unknown[],
parsedItems: SerovalArrayNode['a'],
): SerovalArrayNode {
return createSerovalNode(
SerovalNodeType.Array,
id,
NIL,
NIL,
NIL,
NIL,
NIL,
parsedItems,
NIL,
NIL,
getObjectFlag(current),
NIL,
);
}
export function createBoxedNode(
id: number,
boxed: SerovalNode,
): SerovalBoxedNode {
return createSerovalNode(
SerovalNodeType.Boxed,
id,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
boxed,
NIL,
NIL,
NIL,
);
}
export function createTypedArrayNode(
id: number,
current: TypedArrayValue,
buffer: SerovalNode,
): SerovalTypedArrayNode {
return createSerovalNode(
SerovalNodeType.TypedArray,
id,
NIL,
current.constructor.name,
NIL,
NIL,
NIL,
NIL,
buffer,
current.byteOffset,
NIL,
current.length,
);
}
export function createBigIntTypedArrayNode(
id: number,
current: BigIntTypedArrayValue,
buffer: SerovalNode,
): SerovalBigIntTypedArrayNode {
return createSerovalNode(
SerovalNodeType.BigIntTypedArray,
id,
NIL,
current.constructor.name,
NIL,
NIL,
NIL,
NIL,
buffer,
current.byteOffset,
NIL,
current.byteLength,
);
}
export function createDataViewNode(
id: number,
current: DataView,
buffer: SerovalNode,
): SerovalDataViewNode {
return createSerovalNode(
SerovalNodeType.DataView,
id,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
buffer,
current.byteOffset,
NIL,
current.byteLength,
);
}
export function createErrorNode(
id: number,
current: Error,
options: SerovalObjectRecordNode | undefined,
): SerovalErrorNode {
return createSerovalNode(
SerovalNodeType.Error,
id,
getErrorConstructor(current),
NIL,
serializeString(current.message),
options,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function createAggregateErrorNode(
id: number,
current: AggregateError,
options: SerovalObjectRecordNode | undefined,
): SerovalAggregateErrorNode {
return createSerovalNode(
SerovalNodeType.AggregateError,
id,
getErrorConstructor(current),
NIL,
serializeString(current.message),
options,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function createSetNode(
id: number,
items: SerovalNode[],
): SerovalSetNode {
return createSerovalNode(
SerovalNodeType.Set,
id,
NIL,
NIL,
NIL,
NIL,
NIL,
items,
NIL,
NIL,
NIL,
NIL,
);
}
export function createIteratorFactoryInstanceNode(
factory: SerovalNodeWithID,
items: SerovalNode,
): SerovalIteratorFactoryInstanceNode {
return createSerovalNode(
SerovalNodeType.IteratorFactoryInstance,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
[factory, items],
NIL,
NIL,
NIL,
NIL,
);
}
export function createAsyncIteratorFactoryInstanceNode(
factory: SerovalNodeWithID,
items: SerovalNode,
): SerovalAsyncIteratorFactoryInstanceNode {
return createSerovalNode(
SerovalNodeType.AsyncIteratorFactoryInstance,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
[factory, items],
NIL,
NIL,
NIL,
NIL,
);
}
export function createStreamConstructorNode(
id: number,
factory: SerovalNodeWithID,
sequence: SerovalNode[],
): SerovalStreamConstructorNode {
return createSerovalNode(
SerovalNodeType.StreamConstructor,
id,
NIL,
NIL,
NIL,
NIL,
NIL,
sequence,
factory,
NIL,
NIL,
NIL,
);
}
export function createStreamNextNode(
id: number,
parsed: SerovalNode,
): SerovalStreamNextNode {
return createSerovalNode(
SerovalNodeType.StreamNext,
id,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
parsed,
NIL,
NIL,
NIL,
);
}
export function createStreamThrowNode(
id: number,
parsed: SerovalNode,
): SerovalStreamThrowNode {
return createSerovalNode(
SerovalNodeType.StreamThrow,
id,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
parsed,
NIL,
NIL,
NIL,
);
}
export function createStreamReturnNode(
id: number,
parsed: SerovalNode,
): SerovalStreamReturnNode {
return createSerovalNode(
SerovalNodeType.StreamReturn,
id,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
parsed,
NIL,
NIL,
NIL,
);
}

View file

@ -0,0 +1,23 @@
/**
* References
* - https://compat-table.github.io/compat-table/es6/
* - MDN
*/
export enum Feature {
AggregateError = 0x01,
// @deprecated
ArrowFunction = 0x02,
ErrorPrototypeStack = 0x04,
ObjectAssign = 0x08,
BigIntTypedArray = 0x10,
RegExp = 0x20,
}
export const ALL_ENABLED =
Feature.AggregateError |
Feature.ArrowFunction |
Feature.ErrorPrototypeStack |
Feature.ObjectAssign |
Feature.BigIntTypedArray |
Feature.RegExp;

View file

@ -0,0 +1,201 @@
import {
SYM_ASYNC_ITERATOR,
SYM_HAS_INSTANCE,
SYM_IS_CONCAT_SPREADABLE,
SYM_ITERATOR,
SYM_MATCH,
SYM_MATCH_ALL,
SYM_REPLACE,
SYM_SEARCH,
SYM_SPECIES,
SYM_SPLIT,
SYM_TO_PRIMITIVE,
SYM_TO_STRING_TAG,
SYM_UNSCOPABLES,
} from './symbols';
export const enum SerovalConstant {
Null = 0,
Undefined = 1,
True = 2,
False = 3,
NegZero = 4,
Inf = 5,
NegInf = 6,
Nan = 7,
}
export const enum SerovalNodeType {
Number = 0,
String = 1,
Constant = 2,
BigInt = 3,
IndexedValue = 4,
Date = 5,
RegExp = 6,
Set = 7,
Map = 8,
Array = 9,
Object = 10,
NullConstructor = 11,
Promise = 12,
Error = 13,
AggregateError = 14,
TypedArray = 15,
BigIntTypedArray = 16,
WKSymbol = 17,
Reference = 18,
ArrayBuffer = 19,
DataView = 20,
Boxed = 21,
PromiseConstructor = 22,
PromiseSuccess = 23,
PromiseFailure = 24,
Plugin = 25,
SpecialReference = 26,
IteratorFactory = 27,
IteratorFactoryInstance = 28,
AsyncIteratorFactory = 29,
AsyncIteratorFactoryInstance = 30,
StreamConstructor = 31,
StreamNext = 32,
StreamThrow = 33,
StreamReturn = 34,
}
export const enum SerovalObjectFlags {
None = 0,
NonExtensible = 1,
Sealed = 2,
Frozen = 3,
}
export const enum Symbols {
AsyncIterator = 0,
HasInstance = 1,
IsConcatSpreadable = 2,
Iterator = 3,
Match = 4,
MatchAll = 5,
Replace = 6,
Search = 7,
Species = 8,
Split = 9,
ToPrimitive = 10,
ToStringTag = 11,
Unscopables = 12,
}
export const SYMBOL_STRING: Record<Symbols, string> = {
[Symbols.AsyncIterator]: 'Symbol.asyncIterator',
[Symbols.HasInstance]: 'Symbol.hasInstance',
[Symbols.IsConcatSpreadable]: 'Symbol.isConcatSpreadable',
[Symbols.Iterator]: 'Symbol.iterator',
[Symbols.Match]: 'Symbol.match',
[Symbols.MatchAll]: 'Symbol.matchAll',
[Symbols.Replace]: 'Symbol.replace',
[Symbols.Search]: 'Symbol.search',
[Symbols.Species]: 'Symbol.species',
[Symbols.Split]: 'Symbol.split',
[Symbols.ToPrimitive]: 'Symbol.toPrimitive',
[Symbols.ToStringTag]: 'Symbol.toStringTag',
[Symbols.Unscopables]: 'Symbol.unscopables',
};
export const INV_SYMBOL_REF = /* @__PURE__ */ {
[SYM_ASYNC_ITERATOR]: Symbols.AsyncIterator,
[SYM_HAS_INSTANCE]: Symbols.HasInstance,
[SYM_IS_CONCAT_SPREADABLE]: Symbols.IsConcatSpreadable,
[SYM_ITERATOR]: Symbols.Iterator,
[SYM_MATCH]: Symbols.Match,
[SYM_MATCH_ALL]: Symbols.MatchAll,
[SYM_REPLACE]: Symbols.Replace,
[SYM_SEARCH]: Symbols.Search,
[SYM_SPECIES]: Symbols.Species,
[SYM_SPLIT]: Symbols.Split,
[SYM_TO_PRIMITIVE]: Symbols.ToPrimitive,
[SYM_TO_STRING_TAG]: Symbols.ToStringTag,
[SYM_UNSCOPABLES]: Symbols.Unscopables,
};
export type WellKnownSymbols = keyof typeof INV_SYMBOL_REF;
export const SYMBOL_REF: Record<Symbols, WellKnownSymbols> = {
[Symbols.AsyncIterator]: SYM_ASYNC_ITERATOR,
[Symbols.HasInstance]: SYM_HAS_INSTANCE,
[Symbols.IsConcatSpreadable]: SYM_IS_CONCAT_SPREADABLE,
[Symbols.Iterator]: SYM_ITERATOR,
[Symbols.Match]: SYM_MATCH,
[Symbols.MatchAll]: SYM_MATCH_ALL,
[Symbols.Replace]: SYM_REPLACE,
[Symbols.Search]: SYM_SEARCH,
[Symbols.Species]: SYM_SPECIES,
[Symbols.Split]: SYM_SPLIT,
[Symbols.ToPrimitive]: SYM_TO_PRIMITIVE,
[Symbols.ToStringTag]: SYM_TO_STRING_TAG,
[Symbols.Unscopables]: SYM_UNSCOPABLES,
};
export const CONSTANT_STRING: Record<SerovalConstant, string> = {
[SerovalConstant.True]: '!0',
[SerovalConstant.False]: '!1',
[SerovalConstant.Undefined]: 'void 0',
[SerovalConstant.Null]: 'null',
[SerovalConstant.NegZero]: '-0',
[SerovalConstant.Inf]: '1/0',
[SerovalConstant.NegInf]: '-1/0',
[SerovalConstant.Nan]: '0/0',
};
export const NIL = void 0;
export const CONSTANT_VAL: Record<SerovalConstant, unknown> = {
[SerovalConstant.True]: true,
[SerovalConstant.False]: false,
[SerovalConstant.Undefined]: NIL,
[SerovalConstant.Null]: null,
[SerovalConstant.NegZero]: -0,
[SerovalConstant.Inf]: Number.POSITIVE_INFINITY,
[SerovalConstant.NegInf]: Number.NEGATIVE_INFINITY,
[SerovalConstant.Nan]: Number.NaN,
};
export const enum ErrorConstructorTag {
Error = 0,
EvalError = 1,
RangeError = 2,
ReferenceError = 3,
SyntaxError = 4,
TypeError = 5,
URIError = 6,
}
export const ERROR_CONSTRUCTOR_STRING: Record<ErrorConstructorTag, string> = {
[ErrorConstructorTag.Error]: 'Error',
[ErrorConstructorTag.EvalError]: 'EvalError',
[ErrorConstructorTag.RangeError]: 'RangeError',
[ErrorConstructorTag.ReferenceError]: 'ReferenceError',
[ErrorConstructorTag.SyntaxError]: 'SyntaxError',
[ErrorConstructorTag.TypeError]: 'TypeError',
[ErrorConstructorTag.URIError]: 'URIError',
};
type ErrorConstructors =
| ErrorConstructor
| EvalErrorConstructor
| RangeErrorConstructor
| ReferenceErrorConstructor
| SyntaxErrorConstructor
| TypeErrorConstructor
| URIErrorConstructor;
export const ERROR_CONSTRUCTOR: Record<ErrorConstructorTag, ErrorConstructors> =
{
[ErrorConstructorTag.Error]: Error,
[ErrorConstructorTag.EvalError]: EvalError,
[ErrorConstructorTag.RangeError]: RangeError,
[ErrorConstructorTag.ReferenceError]: ReferenceError,
[ErrorConstructorTag.SyntaxError]: SyntaxError,
[ErrorConstructorTag.TypeError]: TypeError,
[ErrorConstructorTag.URIError]: URIError,
};

View file

@ -0,0 +1,270 @@
import type { Stream } from './stream';
type SpecialPromise = Promise<unknown> & { s?: 1 | 2; v?: unknown };
export interface PromiseConstructorResolver {
p: SpecialPromise;
s: (value: unknown) => void;
f: (value: unknown) => void;
}
export const PROMISE_CONSTRUCTOR = (): PromiseConstructorResolver => {
const resolver = {
p: 0,
s: 0,
f: 0,
} as unknown as PromiseConstructorResolver;
resolver.p = new Promise((resolve, reject) => {
resolver.s = resolve;
resolver.f = reject;
});
return resolver;
};
export const PROMISE_SUCCESS = (
resolver: PromiseConstructorResolver,
data: unknown,
): void => {
resolver.s(data);
resolver.p.s = 1;
resolver.p.v = data;
};
export const PROMISE_FAILURE = (
resolver: PromiseConstructorResolver,
data: unknown,
): void => {
resolver.f(data);
resolver.p.s = 2;
resolver.p.v = data;
};
export const SERIALIZED_PROMISE_CONSTRUCTOR =
/* @__PURE__ */ PROMISE_CONSTRUCTOR.toString();
export const SERIALIZED_PROMISE_SUCCESS =
/* @__PURE__ */ PROMISE_SUCCESS.toString();
export const SERIALIZED_PROMISE_FAILURE =
/* @__PURE__ */ PROMISE_FAILURE.toString();
interface StreamListener<T> {
next(value: T): void;
throw(value: unknown): void;
return(value: T): void;
}
export const STREAM_CONSTRUCTOR = () => {
const buffer: unknown[] = [];
const listeners: StreamListener<unknown>[] = [];
let alive = true;
let success = false;
let count = 0;
const flush = (
value: unknown,
mode: keyof StreamListener<unknown>,
x?: number,
) => {
for (x = 0; x < count; x++) {
if (listeners[x]) {
listeners[x][mode](value);
}
}
};
const up = (
listener: StreamListener<unknown>,
x?: number,
z?: number,
current?: unknown,
) => {
for (x = 0, z = buffer.length; x < z; x++) {
current = buffer[x];
if (!alive && x === z - 1) {
listener[success ? 'return' : 'throw'](current);
} else {
listener.next(current);
}
}
};
const on = (listener: StreamListener<unknown>, temp?: number) => {
if (alive) {
temp = count++;
listeners[temp] = listener;
}
up(listener);
return () => {
if (alive) {
listeners[temp!] = listeners[count];
listeners[count--] = undefined as any;
}
};
};
return {
__SEROVAL_STREAM__: true,
on: (listener: StreamListener<unknown>) => on(listener),
next: (value: unknown) => {
if (alive) {
buffer.push(value);
flush(value, 'next');
}
},
throw: (value: unknown) => {
if (alive) {
buffer.push(value);
flush(value, 'throw');
alive = false;
success = false;
listeners.length = 0;
}
},
return: (value: unknown) => {
if (alive) {
buffer.push(value);
flush(value, 'return');
alive = false;
success = true;
listeners.length = 0;
}
},
};
};
export const SERIALIZED_STREAM_CONSTRUCTOR =
/* @__PURE__ */ STREAM_CONSTRUCTOR.toString();
export interface Sequence {
v: unknown[];
t: number;
d: number;
}
export const ITERATOR_CONSTRUCTOR =
(symbol: symbol) => (sequence: Sequence) => () => {
let index = 0;
const instance = {
[symbol]: () => instance,
next: () => {
if (index > sequence.d) {
return {
done: true,
value: undefined,
};
}
const currentIndex = index++;
const data = sequence.v[currentIndex];
if (currentIndex === sequence.t) {
throw data;
}
return {
done: currentIndex === sequence.d,
value: data,
};
},
};
return instance;
};
export const SERIALIZED_ITERATOR_CONSTRUCTOR =
/* @__PURE__ */ ITERATOR_CONSTRUCTOR.toString();
export const ASYNC_ITERATOR_CONSTRUCTOR =
(symbol: symbol, createPromise: typeof PROMISE_CONSTRUCTOR) =>
(stream: Stream<unknown>) =>
() => {
let count = 0;
let doneAt = -1;
let isThrow = false;
const buffer: unknown[] = [];
const pending: PromiseConstructorResolver[] = [];
const finalize = (i = 0, len = pending.length) => {
for (; i < len; i++) {
pending[i].s({
done: true,
value: undefined,
});
}
};
stream.on({
next: value => {
const temp = pending.shift();
if (temp) {
temp.s({ done: false, value });
}
buffer.push(value);
},
throw: value => {
const temp = pending.shift();
if (temp) {
temp.f(value);
}
finalize();
doneAt = buffer.length;
isThrow = true;
buffer.push(value);
},
return: value => {
const temp = pending.shift();
if (temp) {
temp.s({ done: true, value });
}
finalize();
doneAt = buffer.length;
buffer.push(value);
},
});
const instance = {
[symbol]: () => instance,
next: () => {
if (doneAt === -1) {
const index = count++;
if (index >= buffer.length) {
const temp = createPromise();
pending.push(temp);
return temp.p;
}
return {
done: false,
value: buffer[index],
};
}
if (count > doneAt) {
return {
done: true,
value: undefined,
};
}
const index = count++;
const value = buffer[index];
if (index !== doneAt) {
return {
done: false,
value,
};
}
if (isThrow) {
throw value;
}
return {
done: true,
value,
};
},
};
return instance;
};
export const SERIALIZED_ASYNC_ITERATOR_CONSTRUCTOR =
/* @__PURE__ */ ASYNC_ITERATOR_CONSTRUCTOR.toString();
export const ARRAY_BUFFER_CONSTRUCTOR = (b64: string) => {
const decoded = atob(b64);
const length = decoded.length;
const arr = new Uint8Array(length);
for (let i = 0; i < length; i++) {
arr[i] = decoded.charCodeAt(i);
}
return arr.buffer;
};
export const SERIALIZED_ARRAY_BUFFER_CONSTRUCTOR =
/* @__PURE__ */ ARRAY_BUFFER_CONSTRUCTOR.toString();

View file

@ -0,0 +1,638 @@
import {
createAggregateErrorNode,
createArrayNode,
createAsyncIteratorFactoryInstanceNode,
createBigIntNode,
createBigIntTypedArrayNode,
createBoxedNode,
createDataViewNode,
createDateNode,
createErrorNode,
createIteratorFactoryInstanceNode,
createNumberNode,
createPluginNode,
createRegExpNode,
createSetNode,
createStreamConstructorNode,
createStreamNextNode,
createStreamReturnNode,
createStreamThrowNode,
createStringNode,
createTypedArrayNode,
} from '../base-primitives';
import { Feature } from '../compat';
import { NIL, SerovalNodeType } from '../constants';
import { SerovalParserError, SerovalUnsupportedTypeError } from '../errors';
import { FALSE_NODE, NULL_NODE, TRUE_NODE, UNDEFINED_NODE } from '../literals';
import { createSerovalNode } from '../node';
import { OpaqueReference } from '../opaque-reference';
import type { SerovalMode } from '../plugin';
import { SpecialReference } from '../special-reference';
import type { Stream } from '../stream';
import { createStreamFromAsyncIterable, isStream } from '../stream';
import { serializeString } from '../string';
import {
SYM_ASYNC_ITERATOR,
SYM_IS_CONCAT_SPREADABLE,
SYM_ITERATOR,
SYM_TO_STRING_TAG,
} from '../symbols';
import type {
SerovalAggregateErrorNode,
SerovalArrayNode,
SerovalBigIntTypedArrayNode,
SerovalBoxedNode,
SerovalDataViewNode,
SerovalErrorNode,
SerovalMapNode,
SerovalNode,
SerovalNullConstructorNode,
SerovalObjectNode,
SerovalObjectRecordKey,
SerovalObjectRecordNode,
SerovalPluginNode,
SerovalPromiseNode,
SerovalSetNode,
SerovalStreamConstructorNode,
SerovalTypedArrayNode,
} from '../types';
import { getErrorOptions } from '../utils/error';
import { iteratorToSequence } from '../utils/iterator-to-sequence';
import promiseToResult from '../utils/promise-to-result';
import type {
BigIntTypedArrayValue,
TypedArrayValue,
} from '../utils/typed-array';
import type { BaseParserContext, BaseParserContextOptions } from './parser';
import {
createArrayBufferNode,
createBaseParserContext,
createMapNode,
createObjectNode,
getReferenceNode,
markParserRef,
parseAsyncIteratorFactory,
parseIteratorFactory,
ParserNodeType,
parseSpecialReference,
parseWellKnownSymbol,
} from './parser';
type ObjectLikeNode =
| SerovalObjectNode
| SerovalNullConstructorNode
| SerovalPromiseNode;
export type AsyncParserContextOptions = BaseParserContextOptions;
export interface AsyncParserContext {
base: BaseParserContext;
child: AsyncParsePluginContext | undefined;
}
export function createAsyncParserContext(
mode: SerovalMode,
options: AsyncParserContextOptions,
): AsyncParserContext {
return {
base: createBaseParserContext(mode, options),
child: undefined,
};
}
export class AsyncParsePluginContext {
constructor(
private _p: AsyncParserContext,
private depth: number,
) {}
parse<T>(current: T): Promise<SerovalNode> {
return parseAsync(this._p, this.depth, current);
}
}
async function parseItems(
ctx: AsyncParserContext,
depth: number,
current: unknown[],
): Promise<(SerovalNode | 0)[]> {
const nodes: (SerovalNode | 0)[] = [];
for (let i = 0, len = current.length; i < len; i++) {
// For consistency in holes
if (i in current) {
nodes[i] = await parseAsync(ctx, depth, current[i]);
} else {
nodes[i] = 0;
}
}
return nodes;
}
async function parseArray(
ctx: AsyncParserContext,
depth: number,
id: number,
current: unknown[],
): Promise<SerovalArrayNode> {
return createArrayNode(id, current, await parseItems(ctx, depth, current));
}
async function parseProperties(
ctx: AsyncParserContext,
depth: number,
properties: Record<string | symbol, unknown>,
): Promise<SerovalObjectRecordNode> {
const entries = Object.entries(properties);
const keyNodes: SerovalObjectRecordKey[] = [];
const valueNodes: SerovalNode[] = [];
for (let i = 0, len = entries.length; i < len; i++) {
keyNodes.push(serializeString(entries[i][0]));
valueNodes.push(await parseAsync(ctx, depth, entries[i][1]));
}
// Check special properties
if (SYM_ITERATOR in properties) {
keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ITERATOR));
valueNodes.push(
createIteratorFactoryInstanceNode(
parseIteratorFactory(ctx.base),
await parseAsync(
ctx,
depth,
iteratorToSequence(properties as unknown as Iterable<unknown>),
),
),
);
}
if (SYM_ASYNC_ITERATOR in properties) {
keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ASYNC_ITERATOR));
valueNodes.push(
createAsyncIteratorFactoryInstanceNode(
parseAsyncIteratorFactory(ctx.base),
await parseAsync(
ctx,
depth,
createStreamFromAsyncIterable(
properties as unknown as AsyncIterable<unknown>,
),
),
),
);
}
if (SYM_TO_STRING_TAG in properties) {
keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_TO_STRING_TAG));
valueNodes.push(createStringNode(properties[SYM_TO_STRING_TAG] as string));
}
if (SYM_IS_CONCAT_SPREADABLE in properties) {
keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_IS_CONCAT_SPREADABLE));
valueNodes.push(
properties[SYM_IS_CONCAT_SPREADABLE] ? TRUE_NODE : FALSE_NODE,
);
}
return {
k: keyNodes,
v: valueNodes,
};
}
async function parsePlainObject(
ctx: AsyncParserContext,
depth: number,
id: number,
current: Record<string, unknown>,
empty: boolean,
): Promise<ObjectLikeNode> {
return createObjectNode(
id,
current,
empty,
await parseProperties(ctx, depth, current),
);
}
// TODO: check if parseBoxedSync can be used
async function parseBoxed(
ctx: AsyncParserContext,
depth: number,
id: number,
current: object,
): Promise<SerovalBoxedNode> {
return createBoxedNode(id, await parseAsync(ctx, depth, current.valueOf()));
}
async function parseTypedArray(
ctx: AsyncParserContext,
depth: number,
id: number,
current: TypedArrayValue,
): Promise<SerovalTypedArrayNode> {
return createTypedArrayNode(
id,
current,
await parseAsync(ctx, depth, current.buffer),
);
}
async function parseBigIntTypedArray(
ctx: AsyncParserContext,
depth: number,
id: number,
current: BigIntTypedArrayValue,
): Promise<SerovalBigIntTypedArrayNode> {
return createBigIntTypedArrayNode(
id,
current,
await parseAsync(ctx, depth, current.buffer),
);
}
async function parseDataView(
ctx: AsyncParserContext,
depth: number,
id: number,
current: DataView,
): Promise<SerovalDataViewNode> {
return createDataViewNode(
id,
current,
await parseAsync(ctx, depth, current.buffer),
);
}
async function parseError(
ctx: AsyncParserContext,
depth: number,
id: number,
current: Error,
): Promise<SerovalErrorNode> {
const options = getErrorOptions(current, ctx.base.features);
return createErrorNode(
id,
current,
options ? await parseProperties(ctx, depth, options) : NIL,
);
}
async function parseAggregateError(
ctx: AsyncParserContext,
depth: number,
id: number,
current: AggregateError,
): Promise<SerovalAggregateErrorNode> {
const options = getErrorOptions(current, ctx.base.features);
return createAggregateErrorNode(
id,
current,
options ? await parseProperties(ctx, depth, options) : NIL,
);
}
async function parseMap(
ctx: AsyncParserContext,
depth: number,
id: number,
current: Map<unknown, unknown>,
): Promise<SerovalMapNode> {
const keyNodes: SerovalNode[] = [];
const valueNodes: SerovalNode[] = [];
for (const [key, value] of current.entries()) {
keyNodes.push(await parseAsync(ctx, depth, key));
valueNodes.push(await parseAsync(ctx, depth, value));
}
return createMapNode(ctx.base, id, keyNodes, valueNodes);
}
async function parseSet(
ctx: AsyncParserContext,
depth: number,
id: number,
current: Set<unknown>,
): Promise<SerovalSetNode> {
const items: SerovalNode[] = [];
for (const item of current.keys()) {
items.push(await parseAsync(ctx, depth, item));
}
return createSetNode(id, items);
}
async function parsePlugin(
ctx: AsyncParserContext,
depth: number,
id: number,
current: unknown,
): Promise<SerovalPluginNode | undefined> {
const currentPlugins = ctx.base.plugins;
if (currentPlugins) {
for (let i = 0, len = currentPlugins.length; i < len; i++) {
const plugin = currentPlugins[i];
if (plugin.parse.async && plugin.test(current)) {
return createPluginNode(
id,
plugin.tag,
await plugin.parse.async(
current,
new AsyncParsePluginContext(ctx, depth),
{
id,
},
),
);
}
}
}
return NIL;
}
async function parsePromise(
ctx: AsyncParserContext,
depth: number,
id: number,
current: Promise<unknown>,
): Promise<SerovalPromiseNode> {
const [status, result] = await promiseToResult(current);
return createSerovalNode(
SerovalNodeType.Promise,
id,
status,
NIL,
NIL,
NIL,
NIL,
NIL,
await parseAsync(ctx, depth, result),
NIL,
NIL,
NIL,
);
}
function parseStreamHandle<T>(
this: AsyncParserContext,
depth: number,
id: number,
current: Stream<T>,
resolve: (value: SerovalNode[] | PromiseLike<SerovalNode[]>) => void,
reject: (reason?: any) => void,
): void {
const sequence: SerovalNode[] = [];
// TODO Optimizable
const cleanup = current.on({
next: value => {
markParserRef(this.base, id);
parseAsync(this, depth, value).then(
data => {
sequence.push(createStreamNextNode(id, data));
},
data => {
reject(data);
cleanup();
},
);
},
throw: value => {
markParserRef(this.base, id);
parseAsync(this, depth, value).then(
data => {
sequence.push(createStreamThrowNode(id, data));
resolve(sequence);
cleanup();
},
data => {
reject(data);
cleanup();
},
);
},
return: value => {
markParserRef(this.base, id);
parseAsync(this, depth, value).then(
data => {
sequence.push(createStreamReturnNode(id, data));
resolve(sequence);
cleanup();
},
data => {
reject(data);
cleanup();
},
);
},
});
}
async function parseStream(
ctx: AsyncParserContext,
depth: number,
id: number,
current: Stream<unknown>,
): Promise<SerovalStreamConstructorNode> {
return createStreamConstructorNode(
id,
parseSpecialReference(ctx.base, SpecialReference.StreamConstructor),
await new Promise<SerovalNode[]>(
parseStreamHandle.bind(ctx, depth, id, current),
),
);
}
export async function parseObjectAsync(
ctx: AsyncParserContext,
depth: number,
id: number,
current: object,
): Promise<SerovalNode> {
if (Array.isArray(current)) {
return parseArray(ctx, depth, id, current);
}
if (isStream(current)) {
return parseStream(ctx, depth, id, current);
}
const currentClass = current.constructor;
if (currentClass === OpaqueReference) {
return parseAsync(
ctx,
depth,
(current as OpaqueReference<unknown, unknown>).replacement,
);
}
const parsed = await parsePlugin(ctx, depth, id, current);
if (parsed) {
return parsed;
}
switch (currentClass) {
case Object:
return parsePlainObject(
ctx,
depth,
id,
current as Record<string, unknown>,
false,
);
case NIL:
return parsePlainObject(
ctx,
depth,
id,
current as Record<string, unknown>,
true,
);
case Date:
return createDateNode(id, current as unknown as Date);
case Error:
case EvalError:
case RangeError:
case ReferenceError:
case SyntaxError:
case TypeError:
case URIError:
return parseError(ctx, depth, id, current as unknown as Error);
case Number:
case Boolean:
case String:
case BigInt:
return parseBoxed(ctx, depth, id, current);
case ArrayBuffer:
return createArrayBufferNode(
ctx.base,
id,
current as unknown as ArrayBuffer,
);
case Int8Array:
case Int16Array:
case Int32Array:
case Uint8Array:
case Uint16Array:
case Uint32Array:
case Uint8ClampedArray:
case Float32Array:
case Float64Array:
return parseTypedArray(
ctx,
depth,
id,
current as unknown as TypedArrayValue,
);
case DataView:
return parseDataView(ctx, depth, id, current as unknown as DataView);
case Map:
return parseMap(
ctx,
depth,
id,
current as unknown as Map<unknown, unknown>,
);
case Set:
return parseSet(ctx, depth, id, current as unknown as Set<unknown>);
default:
break;
}
// Promises
if (currentClass === Promise || current instanceof Promise) {
return parsePromise(ctx, depth, id, current as unknown as Promise<unknown>);
}
const currentFeatures = ctx.base.features;
if (currentFeatures & Feature.RegExp && currentClass === RegExp) {
return createRegExpNode(id, current as unknown as RegExp);
}
// BigInt Typed Arrays
if (currentFeatures & Feature.BigIntTypedArray) {
switch (currentClass) {
case BigInt64Array:
case BigUint64Array:
return parseBigIntTypedArray(
ctx,
depth,
id,
current as unknown as BigIntTypedArrayValue,
);
default:
break;
}
}
if (
currentFeatures & Feature.AggregateError &&
typeof AggregateError !== 'undefined' &&
(currentClass === AggregateError || current instanceof AggregateError)
) {
return parseAggregateError(
ctx,
depth,
id,
current as unknown as AggregateError,
);
}
// Slow path. We only need to handle Errors and Iterators
// since they have very broad implementations.
if (current instanceof Error) {
return parseError(ctx, depth, id, current);
}
// Generator functions don't have a global constructor
// despite existing
if (SYM_ITERATOR in current || SYM_ASYNC_ITERATOR in current) {
return parsePlainObject(ctx, depth, id, current, !!currentClass);
}
throw new SerovalUnsupportedTypeError(current);
}
export async function parseFunctionAsync(
ctx: AsyncParserContext,
depth: number,
current: unknown,
): Promise<SerovalNode> {
const ref = getReferenceNode(ctx.base, current);
if (ref.type !== ParserNodeType.Fresh) {
return ref.value;
}
const plugin = await parsePlugin(ctx, depth, ref.value, current);
if (plugin) {
return plugin;
}
throw new SerovalUnsupportedTypeError(current);
}
export async function parseAsync<T>(
ctx: AsyncParserContext,
depth: number,
current: T,
): Promise<SerovalNode> {
switch (typeof current) {
case 'boolean':
return current ? TRUE_NODE : FALSE_NODE;
case 'undefined':
return UNDEFINED_NODE;
case 'string':
return createStringNode(current as string);
case 'number':
return createNumberNode(current as number);
case 'bigint':
return createBigIntNode(current as bigint);
case 'object': {
if (current) {
const ref = getReferenceNode(ctx.base, current);
return ref.type === 0
? await parseObjectAsync(ctx, depth + 1, ref.value, current as object)
: ref.value;
}
return NULL_NODE;
}
case 'symbol':
return parseWellKnownSymbol(ctx.base, current);
case 'function':
return parseFunctionAsync(ctx, depth, current);
default:
throw new SerovalUnsupportedTypeError(current);
}
}
export async function parseTopAsync<T>(
ctx: AsyncParserContext,
current: T,
): Promise<SerovalNode> {
try {
return await parseAsync(ctx, 0, current);
} catch (error) {
throw error instanceof SerovalParserError
? error
: new SerovalParserError(error);
}
}

View file

@ -0,0 +1,810 @@
import { ALL_ENABLED, Feature } from '../compat';
import {
CONSTANT_VAL,
ERROR_CONSTRUCTOR,
NIL,
SerovalNodeType,
SerovalObjectFlags,
SYMBOL_REF,
} from '../constants';
import {
ARRAY_BUFFER_CONSTRUCTOR,
PROMISE_CONSTRUCTOR,
type PromiseConstructorResolver,
} from '../constructors';
import {
SerovalDepthLimitError,
SerovalDeserializationError,
SerovalMalformedNodeError,
SerovalMissingInstanceError,
SerovalMissingPluginError,
SerovalUnsupportedNodeError,
} from '../errors';
import type { PluginAccessOptions } from '../plugin';
import { SerovalMode } from '../plugin';
import { getReference } from '../reference';
import type { Stream } from '../stream';
import { createStream, isStream, streamToAsyncIterable } from '../stream';
import { deserializeString } from '../string';
import {
SYM_ASYNC_ITERATOR,
SYM_IS_CONCAT_SPREADABLE,
SYM_ITERATOR,
SYM_TO_STRING_TAG,
} from '../symbols';
import type {
SerovalAggregateErrorNode,
SerovalArrayBufferNode,
SerovalArrayNode,
SerovalAsyncIteratorFactoryInstanceNode,
SerovalAsyncIteratorFactoryNode,
SerovalBigIntTypedArrayNode,
SerovalBoxedNode,
SerovalDataViewNode,
SerovalDateNode,
SerovalErrorNode,
SerovalIteratorFactoryInstanceNode,
SerovalIteratorFactoryNode,
SerovalMapNode,
SerovalNode,
SerovalNullConstructorNode,
SerovalObjectNode,
SerovalObjectRecordNode,
SerovalPluginNode,
SerovalPromiseConstructorNode,
SerovalPromiseNode,
SerovalPromiseRejectNode,
SerovalPromiseResolveNode,
SerovalReferenceNode,
SerovalRegExpNode,
SerovalSetNode,
SerovalStreamConstructorNode,
SerovalStreamNextNode,
SerovalStreamReturnNode,
SerovalStreamThrowNode,
SerovalTypedArrayNode,
} from '../types';
import type { Sequence } from '../utils/iterator-to-sequence';
import { sequenceToIterator } from '../utils/iterator-to-sequence';
import type {
BigIntTypedArrayValue,
TypedArrayValue,
} from '../utils/typed-array';
import { getTypedArrayConstructor } from '../utils/typed-array';
const MAX_BASE64_LENGTH = 1_000_000; // ~0.75MB decoded
const MAX_BIGINT_LENGTH = 10_000;
const MAX_REGEXP_SOURCE_LENGTH = 20_000;
function applyObjectFlag(obj: unknown, flag: SerovalObjectFlags): unknown {
switch (flag) {
case SerovalObjectFlags.Frozen:
return Object.freeze(obj);
case SerovalObjectFlags.NonExtensible:
return Object.preventExtensions(obj);
case SerovalObjectFlags.Sealed:
return Object.seal(obj);
default:
return obj;
}
}
type AssignableValue = AggregateError | Error | Iterable<unknown>;
type AssignableNode = SerovalAggregateErrorNode | SerovalErrorNode;
export interface BaseDeserializerContextOptions extends PluginAccessOptions {
refs?: Map<number, unknown>;
features?: number;
disabledFeatures?: number;
depthLimit?: number;
}
export interface BaseDeserializerContext extends PluginAccessOptions {
readonly mode: SerovalMode;
/**
* Mapping ids to values
*/
refs: Map<number, unknown>;
features: number;
depthLimit: number;
}
const DEFAULT_DEPTH_LIMIT = 1000;
export function createBaseDeserializerContext(
mode: SerovalMode,
options: BaseDeserializerContextOptions,
): BaseDeserializerContext {
return {
mode,
plugins: options.plugins,
refs: options.refs || new Map(),
features: options.features ?? ALL_ENABLED ^ (options.disabledFeatures || 0),
depthLimit: options.depthLimit || DEFAULT_DEPTH_LIMIT,
};
}
export interface VanillaDeserializerContextOptions
extends Omit<BaseDeserializerContextOptions, 'refs'> {
markedRefs: number[] | Set<number>;
}
export interface VanillaDeserializerState {
marked: Set<number>;
}
export interface VanillaDeserializerContext {
mode: SerovalMode.Vanilla;
base: BaseDeserializerContext;
child: DeserializePluginContext | undefined;
state: VanillaDeserializerState;
}
export function createVanillaDeserializerContext(
options: VanillaDeserializerContextOptions,
): VanillaDeserializerContext {
return {
mode: SerovalMode.Vanilla,
base: createBaseDeserializerContext(SerovalMode.Vanilla, options),
child: NIL,
state: {
marked: new Set(options.markedRefs),
},
};
}
export interface CrossDeserializerContext {
mode: SerovalMode.Cross;
base: BaseDeserializerContext;
child: DeserializePluginContext | undefined;
}
export type CrossDeserializerContextOptions = BaseDeserializerContextOptions;
export function createCrossDeserializerContext(
options: CrossDeserializerContextOptions,
): CrossDeserializerContext {
return {
mode: SerovalMode.Cross,
base: createBaseDeserializerContext(SerovalMode.Cross, options),
child: NIL,
};
}
type DeserializerContext =
| VanillaDeserializerContext
| CrossDeserializerContext;
export class DeserializePluginContext {
constructor(
private _p: DeserializerContext,
private depth: number,
) {}
deserialize<T>(node: SerovalNode): T {
return deserialize(this._p, this.depth, node) as T;
}
}
function guardIndexedValue(ctx: BaseDeserializerContext, id: number): void {
if (id < 0 || !Number.isFinite(id) || !Number.isInteger(id)) {
throw new SerovalMalformedNodeError({
t: SerovalNodeType.IndexedValue,
i: id,
} as SerovalNode);
}
if (ctx.refs.has(id)) {
throw new Error('Conflicted ref id: ' + id);
}
}
function assignIndexedValueVanilla<T>(
ctx: VanillaDeserializerContext,
id: number,
value: T,
): T {
guardIndexedValue(ctx.base, id);
if (ctx.state.marked.has(id)) {
ctx.base.refs.set(id, value);
}
return value;
}
function assignIndexedValueCross<T>(
ctx: CrossDeserializerContext,
id: number,
value: T,
): T {
guardIndexedValue(ctx.base, id);
ctx.base.refs.set(id, value);
return value;
}
function assignIndexedValue<T>(
ctx: DeserializerContext,
id: number,
value: T,
): T {
return ctx.mode === SerovalMode.Vanilla
? assignIndexedValueVanilla(ctx, id, value)
: assignIndexedValueCross(ctx, id, value);
}
function deserializeKnownValue<
T extends Record<string, unknown>,
K extends keyof T,
>(node: SerovalNode, record: T, key: K): T[K] {
if (Object.hasOwn(record, key)) {
return record[key];
}
throw new SerovalMalformedNodeError(node);
}
function deserializeReference(
ctx: DeserializerContext,
node: SerovalReferenceNode,
): unknown {
return assignIndexedValue(
ctx,
node.i,
getReference(deserializeString(node.s)),
);
}
function deserializeArray(
ctx: DeserializerContext,
depth: number,
node: SerovalArrayNode,
): unknown[] {
const items = node.a;
const len = items.length;
const result: unknown[] = assignIndexedValue(
ctx,
node.i,
new Array<unknown>(len),
);
for (let i = 0, item: SerovalNode | 0; i < len; i++) {
item = items[i];
if (item) {
result[i] = deserialize(ctx, depth, item);
}
}
applyObjectFlag(result, node.o);
return result;
}
function isValidKey(key: string): boolean {
switch (key) {
case 'constructor':
case '__proto__':
case 'prototype':
case '__defineGetter__':
case '__defineSetter__':
case '__lookupGetter__':
case '__lookupSetter__':
// case 'then':
return false;
default:
return true;
}
}
function isValidSymbol(symbol: symbol): boolean {
switch (symbol) {
case SYM_ASYNC_ITERATOR:
case SYM_IS_CONCAT_SPREADABLE:
case SYM_TO_STRING_TAG:
case SYM_ITERATOR:
return true;
default:
return false;
}
}
function assignStringProperty(
object: Record<string | symbol, unknown>,
key: string,
value: unknown,
): void {
if (isValidKey(key)) {
object[key] = value;
} else {
Object.defineProperty(object, key, {
value,
configurable: true,
enumerable: true,
writable: true,
});
}
}
function assignProperty(
ctx: DeserializerContext,
depth: number,
object: Record<string | symbol, unknown>,
key: string | SerovalNode,
value: SerovalNode,
): void {
if (typeof key === 'string') {
assignStringProperty(object, key, deserialize(ctx, depth, value));
} else {
const actual = deserialize(ctx, depth, key);
switch (typeof actual) {
case 'string':
assignStringProperty(object, actual, deserialize(ctx, depth, value));
break;
case 'symbol':
if (isValidSymbol(actual)) {
object[actual] = deserialize(ctx, depth, value);
}
break;
default:
throw new SerovalMalformedNodeError(key);
}
}
}
function deserializeProperties(
ctx: DeserializerContext,
depth: number,
node: SerovalObjectRecordNode,
result: Record<string | symbol, unknown>,
): Record<string | symbol, unknown> {
const keys = node.k;
const len = keys.length;
if (len > 0) {
for (let i = 0, vals = node.v, len = keys.length; i < len; i++) {
assignProperty(ctx, depth, result, keys[i], vals[i]);
}
}
return result;
}
function deserializeObject(
ctx: DeserializerContext,
depth: number,
node: SerovalObjectNode | SerovalNullConstructorNode,
): Record<string, unknown> {
const result = assignIndexedValue(
ctx,
node.i,
(node.t === SerovalNodeType.Object ? {} : Object.create(null)) as Record<
string,
unknown
>,
);
deserializeProperties(ctx, depth, node.p, result);
applyObjectFlag(result, node.o);
return result;
}
function deserializeDate(
ctx: DeserializerContext,
node: SerovalDateNode,
): Date {
return assignIndexedValue(ctx, node.i, new Date(node.s));
}
function deserializeRegExp(
ctx: DeserializerContext,
node: SerovalRegExpNode,
): RegExp {
if (ctx.base.features & Feature.RegExp) {
const source = deserializeString(node.c);
if (source.length > MAX_REGEXP_SOURCE_LENGTH) {
throw new SerovalMalformedNodeError(node);
}
return assignIndexedValue(ctx, node.i, new RegExp(source, node.m));
}
throw new SerovalUnsupportedNodeError(node);
}
function deserializeSet(
ctx: DeserializerContext,
depth: number,
node: SerovalSetNode,
): Set<unknown> {
const result = assignIndexedValue(ctx, node.i, new Set<unknown>());
for (let i = 0, items = node.a, len = items.length; i < len; i++) {
result.add(deserialize(ctx, depth, items[i]));
}
return result;
}
function deserializeMap(
ctx: DeserializerContext,
depth: number,
node: SerovalMapNode,
): Map<unknown, unknown> {
const result = assignIndexedValue(ctx, node.i, new Map<unknown, unknown>());
for (
let i = 0, keys = node.e.k, vals = node.e.v, len = keys.length;
i < len;
i++
) {
result.set(
deserialize(ctx, depth, keys[i]),
deserialize(ctx, depth, vals[i]),
);
}
return result;
}
function deserializeArrayBuffer(
ctx: DeserializerContext,
node: SerovalArrayBufferNode,
): ArrayBuffer {
if (node.s.length > MAX_BASE64_LENGTH) {
throw new SerovalMalformedNodeError(node);
}
const result = assignIndexedValue(
ctx,
node.i,
ARRAY_BUFFER_CONSTRUCTOR(deserializeString(node.s)),
);
return result;
}
function deserializeTypedArray(
ctx: DeserializerContext,
depth: number,
node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
): TypedArrayValue | BigIntTypedArrayValue {
const construct = getTypedArrayConstructor(node.c) as Int8ArrayConstructor;
const source = deserialize(ctx, depth, node.f) as ArrayBuffer;
const offset = node.b ?? 0;
if (offset < 0 || offset > source.byteLength) {
throw new SerovalMalformedNodeError(node);
}
const result = assignIndexedValue(
ctx,
node.i,
new construct(source, offset, node.l),
);
return result;
}
function deserializeDataView(
ctx: DeserializerContext,
depth: number,
node: SerovalDataViewNode,
): DataView {
const source = deserialize(ctx, depth, node.f) as ArrayBuffer;
const offset = node.b ?? 0;
if (offset < 0 || offset > source.byteLength) {
throw new SerovalMalformedNodeError(node);
}
const result = assignIndexedValue(
ctx,
node.i,
new DataView(source, offset, node.l),
);
return result;
}
function deserializeDictionary<T extends AssignableValue>(
ctx: DeserializerContext,
depth: number,
node: AssignableNode,
result: T,
): T {
if (node.p) {
const fields = deserializeProperties(ctx, depth, node.p, {});
Object.defineProperties(result, Object.getOwnPropertyDescriptors(fields));
}
return result;
}
function deserializeAggregateError(
ctx: DeserializerContext,
depth: number,
node: SerovalAggregateErrorNode,
): AggregateError {
// Serialize the required arguments
const result = assignIndexedValue(
ctx,
node.i,
new AggregateError([], deserializeString(node.m)),
);
// `AggregateError` might've been extended
// either through class or custom properties
// Make sure to assign extra properties
return deserializeDictionary(ctx, depth, node, result);
}
function deserializeError(
ctx: DeserializerContext,
depth: number,
node: SerovalErrorNode,
): Error {
const construct = deserializeKnownValue(node, ERROR_CONSTRUCTOR, node.s);
const result = assignIndexedValue(
ctx,
node.i,
new construct(deserializeString(node.m)),
);
return deserializeDictionary(ctx, depth, node, result);
}
function deserializePromise(
ctx: DeserializerContext,
depth: number,
node: SerovalPromiseNode,
): Promise<unknown> {
const deferred = PROMISE_CONSTRUCTOR();
const result = assignIndexedValue(ctx, node.i, deferred.p);
const deserialized = deserialize(ctx, depth, node.f);
if (node.s) {
deferred.s(deserialized);
} else {
deferred.f(deserialized);
}
return result;
}
function deserializeBoxed(
ctx: DeserializerContext,
depth: number,
node: SerovalBoxedNode,
): unknown {
return assignIndexedValue(
ctx,
node.i,
// biome-ignore lint/style/useConsistentBuiltinInstantiation: intended
Object(deserialize(ctx, depth, node.f)),
);
}
function deserializePlugin(
ctx: DeserializerContext,
depth: number,
node: SerovalPluginNode,
): unknown {
const currentPlugins = ctx.base.plugins;
if (currentPlugins) {
const tag = deserializeString(node.c);
for (let i = 0, len = currentPlugins.length; i < len; i++) {
const plugin = currentPlugins[i];
if (plugin.tag === tag) {
return assignIndexedValue(
ctx,
node.i,
plugin.deserialize(node.s, new DeserializePluginContext(ctx, depth), {
id: node.i,
}),
);
}
}
}
throw new SerovalMissingPluginError(node.c);
}
function deserializePromiseConstructor(
ctx: DeserializerContext,
node: SerovalPromiseConstructorNode,
): unknown {
return assignIndexedValue(
ctx,
node.i,
assignIndexedValue(ctx, node.s, PROMISE_CONSTRUCTOR()).p,
);
}
function deserializePromiseResolve(
ctx: DeserializerContext,
depth: number,
node: SerovalPromiseResolveNode,
): unknown {
const deferred = ctx.base.refs.get(node.i) as
| PromiseConstructorResolver
| undefined;
if (deferred) {
deferred.s(deserialize(ctx, depth, node.a[1]));
return NIL;
}
throw new SerovalMissingInstanceError('Promise');
}
function deserializePromiseReject(
ctx: DeserializerContext,
depth: number,
node: SerovalPromiseRejectNode,
): unknown {
const deferred = ctx.base.refs.get(node.i) as
| PromiseConstructorResolver
| undefined;
if (deferred) {
deferred.f(deserialize(ctx, depth, node.a[1]));
return NIL;
}
throw new SerovalMissingInstanceError('Promise');
}
function deserializeIteratorFactoryInstance(
ctx: DeserializerContext,
depth: number,
node: SerovalIteratorFactoryInstanceNode,
): unknown {
deserialize(ctx, depth, node.a[0]);
const source = deserialize(ctx, depth, node.a[1]);
return sequenceToIterator(source as Sequence);
}
function deserializeAsyncIteratorFactoryInstance(
ctx: DeserializerContext,
depth: number,
node: SerovalAsyncIteratorFactoryInstanceNode,
): unknown {
deserialize(ctx, depth, node.a[0]);
const source = deserialize(ctx, depth, node.a[1]);
return streamToAsyncIterable(source as Stream<any>);
}
function deserializeStreamConstructor(
ctx: DeserializerContext,
depth: number,
node: SerovalStreamConstructorNode,
): unknown {
const result = assignIndexedValue(ctx, node.i, createStream());
const items = node.a;
const len = items.length;
if (len) {
for (let i = 0; i < len; i++) {
deserialize(ctx, depth, items[i]);
}
}
return result;
}
function deserializeStreamNext(
ctx: DeserializerContext,
depth: number,
node: SerovalStreamNextNode,
): unknown {
const deferred = ctx.base.refs.get(node.i) as Stream<unknown> | undefined;
if (deferred && isStream(deferred)) {
deferred.next(deserialize(ctx, depth, node.f));
return NIL;
}
throw new SerovalMissingInstanceError('Stream');
}
function deserializeStreamThrow(
ctx: DeserializerContext,
depth: number,
node: SerovalStreamThrowNode,
): unknown {
const deferred = ctx.base.refs.get(node.i) as Stream<unknown> | undefined;
if (deferred && isStream(deferred)) {
deferred.throw(deserialize(ctx, depth, node.f));
return NIL;
}
throw new SerovalMissingInstanceError('Stream');
}
function deserializeStreamReturn(
ctx: DeserializerContext,
depth: number,
node: SerovalStreamReturnNode,
): unknown {
const deferred = ctx.base.refs.get(node.i) as Stream<unknown> | undefined;
if (deferred && isStream(deferred)) {
deferred.return(deserialize(ctx, depth, node.f));
return NIL;
}
throw new SerovalMissingInstanceError('Stream');
}
function deserializeIteratorFactory(
ctx: DeserializerContext,
depth: number,
node: SerovalIteratorFactoryNode,
): unknown {
deserialize(ctx, depth, node.f);
return NIL;
}
function deserializeAsyncIteratorFactory(
ctx: DeserializerContext,
depth: number,
node: SerovalAsyncIteratorFactoryNode,
): unknown {
deserialize(ctx, depth, node.a[1]);
return NIL;
}
function deserialize(
ctx: DeserializerContext,
depth: number,
node: SerovalNode,
): unknown {
if (depth > ctx.base.depthLimit) {
throw new SerovalDepthLimitError(ctx.base.depthLimit);
}
depth += 1;
switch (node.t) {
case SerovalNodeType.Constant:
return deserializeKnownValue(node, CONSTANT_VAL, node.s);
case SerovalNodeType.Number:
return Number(node.s);
case SerovalNodeType.String:
return deserializeString(String(node.s));
case SerovalNodeType.BigInt:
if (String(node.s).length > MAX_BIGINT_LENGTH) {
throw new SerovalMalformedNodeError(node);
}
return BigInt(node.s);
case SerovalNodeType.IndexedValue:
return ctx.base.refs.get(node.i);
case SerovalNodeType.Reference:
return deserializeReference(ctx, node);
case SerovalNodeType.Array:
return deserializeArray(ctx, depth, node);
case SerovalNodeType.Object:
case SerovalNodeType.NullConstructor:
return deserializeObject(ctx, depth, node);
case SerovalNodeType.Date:
return deserializeDate(ctx, node);
case SerovalNodeType.RegExp:
return deserializeRegExp(ctx, node);
case SerovalNodeType.Set:
return deserializeSet(ctx, depth, node);
case SerovalNodeType.Map:
return deserializeMap(ctx, depth, node);
case SerovalNodeType.ArrayBuffer:
return deserializeArrayBuffer(ctx, node);
case SerovalNodeType.BigIntTypedArray:
case SerovalNodeType.TypedArray:
return deserializeTypedArray(ctx, depth, node);
case SerovalNodeType.DataView:
return deserializeDataView(ctx, depth, node);
case SerovalNodeType.AggregateError:
return deserializeAggregateError(ctx, depth, node);
case SerovalNodeType.Error:
return deserializeError(ctx, depth, node);
case SerovalNodeType.Promise:
return deserializePromise(ctx, depth, node);
case SerovalNodeType.WKSymbol:
return deserializeKnownValue(node, SYMBOL_REF, node.s);
case SerovalNodeType.Boxed:
return deserializeBoxed(ctx, depth, node);
case SerovalNodeType.Plugin:
return deserializePlugin(ctx, depth, node);
case SerovalNodeType.PromiseConstructor:
return deserializePromiseConstructor(ctx, node);
case SerovalNodeType.PromiseSuccess:
return deserializePromiseResolve(ctx, depth, node);
case SerovalNodeType.PromiseFailure:
return deserializePromiseReject(ctx, depth, node);
case SerovalNodeType.IteratorFactoryInstance:
return deserializeIteratorFactoryInstance(ctx, depth, node);
case SerovalNodeType.AsyncIteratorFactoryInstance:
return deserializeAsyncIteratorFactoryInstance(ctx, depth, node);
case SerovalNodeType.StreamConstructor:
return deserializeStreamConstructor(ctx, depth, node);
case SerovalNodeType.StreamNext:
return deserializeStreamNext(ctx, depth, node);
case SerovalNodeType.StreamThrow:
return deserializeStreamThrow(ctx, depth, node);
case SerovalNodeType.StreamReturn:
return deserializeStreamReturn(ctx, depth, node);
case SerovalNodeType.IteratorFactory:
return deserializeIteratorFactory(ctx, depth, node);
case SerovalNodeType.AsyncIteratorFactory:
return deserializeAsyncIteratorFactory(ctx, depth, node);
// case SerovalNodeType.SpecialReference:
default:
throw new SerovalUnsupportedNodeError(node);
}
}
export function deserializeTop(
ctx: DeserializerContext,
node: SerovalNode,
): unknown {
try {
return deserialize(ctx, 0, node);
} catch (error) {
throw new SerovalDeserializationError(error);
}
}

View file

@ -0,0 +1,335 @@
import {
createIndexedValueNode,
createReferenceNode,
createWKSymbolNode,
} from '../base-primitives';
import { ALL_ENABLED } from '../compat';
import type { WellKnownSymbols } from '../constants';
import { INV_SYMBOL_REF, NIL, SerovalNodeType } from '../constants';
import { SerovalUnsupportedTypeError } from '../errors';
import { createSerovalNode } from '../node';
import type { PluginAccessOptions, SerovalMode } from '../plugin';
import { hasReferenceID } from '../reference';
import {
ASYNC_ITERATOR,
ITERATOR,
SPECIAL_REFS,
SpecialReference,
} from '../special-reference';
import { serializeString } from '../string';
import { SYM_ASYNC_ITERATOR, SYM_ITERATOR } from '../symbols';
import type {
SerovalArrayBufferNode,
SerovalAsyncIteratorFactoryNode,
SerovalIndexedValueNode,
SerovalIteratorFactoryNode,
SerovalMapNode,
SerovalNode,
SerovalNullConstructorNode,
SerovalObjectNode,
SerovalObjectRecordNode,
SerovalPromiseConstructorNode,
SerovalReferenceNode,
SerovalSpecialReferenceNode,
SerovalWKSymbolNode,
} from '../types';
import { getObjectFlag } from '../utils/get-object-flag';
export interface BaseParserContextOptions extends PluginAccessOptions {
disabledFeatures?: number;
refs?: Map<unknown, number>;
depthLimit?: number;
}
export const enum ParserNodeType {
Fresh = 0,
Indexed = 1,
Referenced = 2,
}
export interface FreshNode {
type: ParserNodeType.Fresh;
value: number;
}
export interface IndexedNode {
type: ParserNodeType.Indexed;
value: SerovalIndexedValueNode;
}
export interface ReferencedNode {
type: ParserNodeType.Referenced;
value: SerovalReferenceNode;
}
type ObjectNode = FreshNode | IndexedNode | ReferencedNode;
export interface BaseParserContext extends PluginAccessOptions {
readonly mode: SerovalMode;
marked: Set<number>;
refs: Map<unknown, number>;
features: number;
depthLimit: number;
}
export function createBaseParserContext(
mode: SerovalMode,
options: BaseParserContextOptions,
): BaseParserContext {
return {
plugins: options.plugins,
mode,
marked: new Set(),
features: ALL_ENABLED ^ (options.disabledFeatures || 0),
refs: options.refs || new Map(),
depthLimit: options.depthLimit || 1000,
};
}
/**
* Ensures that the value (based on an identifier) has been visited by the parser.
* @param ctx
* @param id
*/
export function markParserRef(ctx: BaseParserContext, id: number): void {
ctx.marked.add(id);
}
export function isParserRefMarked(ctx: BaseParserContext, id: number): boolean {
return ctx.marked.has(id);
}
/**
* Creates an identifier for a value
* @param ctx
* @param current
*/
export function createIndexForValue<T>(
ctx: BaseParserContext,
current: T,
): number {
const id = ctx.refs.size;
ctx.refs.set(current, id);
return id;
}
export function getNodeForIndexedValue<T>(
ctx: BaseParserContext,
current: T,
): FreshNode | IndexedNode {
const registeredId = ctx.refs.get(current);
if (registeredId != null) {
markParserRef(ctx, registeredId);
return {
type: ParserNodeType.Indexed,
value: createIndexedValueNode(registeredId),
};
}
return {
type: ParserNodeType.Fresh,
value: createIndexForValue(ctx, current),
};
}
export function getReferenceNode<T>(
ctx: BaseParserContext,
current: T,
): ObjectNode {
const indexed = getNodeForIndexedValue(ctx, current);
if (indexed.type === ParserNodeType.Indexed) {
return indexed;
}
// Special references are special ;)
if (hasReferenceID(current)) {
return {
type: ParserNodeType.Referenced,
value: createReferenceNode(indexed.value, current),
};
}
return indexed;
}
/**
* Parsing methods
*/
export function parseWellKnownSymbol(
ctx: BaseParserContext,
current: symbol,
): SerovalIndexedValueNode | SerovalWKSymbolNode | SerovalReferenceNode {
const ref = getReferenceNode(ctx, current);
if (ref.type !== ParserNodeType.Fresh) {
return ref.value;
}
if (current in INV_SYMBOL_REF) {
return createWKSymbolNode(ref.value, current as WellKnownSymbols);
}
throw new SerovalUnsupportedTypeError(current);
}
export function parseSpecialReference(
ctx: BaseParserContext,
ref: SpecialReference,
): SerovalIndexedValueNode | SerovalSpecialReferenceNode {
const result = getNodeForIndexedValue(ctx, SPECIAL_REFS[ref]);
if (result.type === ParserNodeType.Indexed) {
return result.value;
}
return createSerovalNode(
SerovalNodeType.SpecialReference,
result.value,
ref,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export function parseIteratorFactory(
ctx: BaseParserContext,
): SerovalIndexedValueNode | SerovalIteratorFactoryNode {
const result = getNodeForIndexedValue(ctx, ITERATOR);
if (result.type === ParserNodeType.Indexed) {
return result.value;
}
return createSerovalNode(
SerovalNodeType.IteratorFactory,
result.value,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
parseWellKnownSymbol(ctx, SYM_ITERATOR),
NIL,
NIL,
NIL,
);
}
export function parseAsyncIteratorFactory(
ctx: BaseParserContext,
): SerovalIndexedValueNode | SerovalAsyncIteratorFactoryNode {
const result = getNodeForIndexedValue(ctx, ASYNC_ITERATOR);
if (result.type === ParserNodeType.Indexed) {
return result.value;
}
return createSerovalNode(
SerovalNodeType.AsyncIteratorFactory,
result.value,
NIL,
NIL,
NIL,
NIL,
NIL,
[
parseSpecialReference(ctx, SpecialReference.PromiseConstructor),
parseWellKnownSymbol(ctx, SYM_ASYNC_ITERATOR),
],
NIL,
NIL,
NIL,
NIL,
);
}
export function createObjectNode(
id: number,
current: Record<string, unknown>,
empty: boolean,
record: SerovalObjectRecordNode,
): SerovalObjectNode | SerovalNullConstructorNode {
return createSerovalNode(
empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
id,
NIL,
NIL,
NIL,
record,
NIL,
NIL,
NIL,
NIL,
getObjectFlag(current),
NIL,
);
}
export function createMapNode(
ctx: BaseParserContext,
id: number,
k: SerovalNode[],
v: SerovalNode[],
): SerovalMapNode {
return createSerovalNode(
SerovalNodeType.Map,
id,
NIL,
NIL,
NIL,
NIL,
{ k, v },
NIL,
parseSpecialReference(ctx, SpecialReference.MapSentinel),
NIL,
NIL,
NIL,
);
}
export function createPromiseConstructorNode(
ctx: BaseParserContext,
id: number,
resolver: number,
): SerovalPromiseConstructorNode {
return createSerovalNode(
SerovalNodeType.PromiseConstructor,
id,
resolver,
NIL,
NIL,
NIL,
NIL,
NIL,
parseSpecialReference(ctx, SpecialReference.PromiseConstructor),
NIL,
NIL,
NIL,
);
}
export function createArrayBufferNode(
ctx: BaseParserContext,
id: number,
current: ArrayBuffer,
): SerovalArrayBufferNode {
const bytes = new Uint8Array(current);
let result = '';
for (let i = 0, len = bytes.length; i < len; i++) {
result += String.fromCharCode(bytes[i]);
}
return createSerovalNode(
SerovalNodeType.ArrayBuffer,
id,
serializeString(btoa(result)),
NIL,
NIL,
NIL,
NIL,
NIL,
parseSpecialReference(ctx, SpecialReference.ArrayBufferConstructor),
NIL,
NIL,
NIL,
);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,907 @@
import {
createAggregateErrorNode,
createArrayNode,
createAsyncIteratorFactoryInstanceNode,
createBigIntNode,
createBigIntTypedArrayNode,
createBoxedNode,
createDataViewNode,
createDateNode,
createErrorNode,
createIteratorFactoryInstanceNode,
createNumberNode,
createPluginNode,
createRegExpNode,
createSetNode,
createStreamConstructorNode,
createStreamNextNode,
createStreamReturnNode,
createStreamThrowNode,
createStringNode,
createTypedArrayNode,
} from '../base-primitives';
import { Feature } from '../compat';
import { NIL, SerovalNodeType } from '../constants';
import {
SerovalDepthLimitError,
SerovalParserError,
SerovalUnsupportedTypeError,
} from '../errors';
import { FALSE_NODE, NULL_NODE, TRUE_NODE, UNDEFINED_NODE } from '../literals';
import { createSerovalNode } from '../node';
import { OpaqueReference } from '../opaque-reference';
import { type Plugin, SerovalMode } from '../plugin';
import { SpecialReference } from '../special-reference';
import type { Stream } from '../stream';
import {
createStream,
createStreamFromAsyncIterable,
isStream,
} from '../stream';
import { serializeString } from '../string';
import {
SYM_ASYNC_ITERATOR,
SYM_IS_CONCAT_SPREADABLE,
SYM_ITERATOR,
SYM_TO_STRING_TAG,
} from '../symbols';
import type {
SerovalAggregateErrorNode,
SerovalArrayNode,
SerovalBigIntTypedArrayNode,
SerovalBoxedNode,
SerovalDataViewNode,
SerovalErrorNode,
SerovalMapNode,
SerovalNode,
SerovalNullConstructorNode,
SerovalObjectNode,
SerovalObjectRecordKey,
SerovalObjectRecordNode,
SerovalPluginNode,
SerovalPromiseConstructorNode,
SerovalSetNode,
SerovalTypedArrayNode,
} from '../types';
import { getErrorOptions } from '../utils/error';
import { iteratorToSequence } from '../utils/iterator-to-sequence';
import type {
BigIntTypedArrayValue,
TypedArrayValue,
} from '../utils/typed-array';
import type { BaseParserContext, BaseParserContextOptions } from './parser';
import {
createArrayBufferNode,
createBaseParserContext,
createIndexForValue,
createMapNode,
createObjectNode,
createPromiseConstructorNode,
getReferenceNode,
parseAsyncIteratorFactory,
parseIteratorFactory,
ParserNodeType,
parseSpecialReference,
parseWellKnownSymbol,
} from './parser';
type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode;
export type SyncParserContextOptions = BaseParserContextOptions;
const enum ParserMode {
Sync = 1,
Stream = 2,
}
export interface SyncParserContext {
type: ParserMode.Sync;
base: BaseParserContext;
child: SyncParsePluginContext | undefined;
}
export function createSyncParserContext(
mode: SerovalMode,
options: SyncParserContextOptions,
): SyncParserContext {
return {
type: ParserMode.Sync,
base: createBaseParserContext(mode, options),
child: NIL,
};
}
export class SyncParsePluginContext {
constructor(
private _p: SyncParserContext,
private depth: number,
) {}
parse<T>(current: T): SerovalNode {
return parseSOS(this._p, this.depth, current);
}
}
export interface StreamParserContextOptions extends SyncParserContextOptions {
onParse: (node: SerovalNode, initial: boolean) => void;
onError?: (error: unknown) => void;
onDone?: () => void;
}
export interface StreamParserContext {
type: ParserMode.Stream;
base: BaseParserContext;
state: StreamParserState;
}
export class StreamParsePluginContext {
constructor(
private _p: StreamParserContext,
private depth: number,
) {}
parse<T>(current: T): SerovalNode {
return parseSOS(this._p, this.depth, current);
}
parseWithError<T>(current: T): SerovalNode | undefined {
return parseWithError(this._p, this.depth, current);
}
isAlive(): boolean {
return this._p.state.alive;
}
pushPendingState(): void {
pushPendingState(this._p);
}
popPendingState(): void {
popPendingState(this._p);
}
onParse(node: SerovalNode): void {
onParse(this._p, node);
}
onError(error: unknown): void {
onError(this._p, error);
}
}
interface StreamParserState {
// Life cycle
alive: boolean;
// Number of pending things
pending: number;
//
initial: boolean;
//
buffer: SerovalNode[];
// Callbacks
onParse: (node: SerovalNode, initial: boolean) => void;
onError?: (error: unknown) => void;
onDone?: () => void;
}
function createStreamParserState(
options: StreamParserContextOptions,
): StreamParserState {
return {
alive: true,
pending: 0,
initial: true,
buffer: [],
onParse: options.onParse,
onError: options.onError,
onDone: options.onDone,
};
}
export function createStreamParserContext(
options: StreamParserContextOptions,
): StreamParserContext {
return {
type: ParserMode.Stream,
base: createBaseParserContext(SerovalMode.Cross, options),
state: createStreamParserState(options),
};
}
type SOSParserContext = SyncParserContext | StreamParserContext;
function parseItems(
ctx: SOSParserContext,
depth: number,
current: unknown[],
): (SerovalNode | 0)[] {
const nodes: (SerovalNode | 0)[] = [];
for (let i = 0, len = current.length; i < len; i++) {
if (i in current) {
nodes[i] = parseSOS(ctx, depth, current[i]);
} else {
nodes[i] = 0;
}
}
return nodes;
}
function parseArray(
ctx: SOSParserContext,
depth: number,
id: number,
current: unknown[],
): SerovalArrayNode {
return createArrayNode(id, current, parseItems(ctx, depth, current));
}
function parseProperties(
ctx: SOSParserContext,
depth: number,
properties: Record<string | symbol, unknown>,
): SerovalObjectRecordNode {
const entries = Object.entries(properties);
const keyNodes: SerovalObjectRecordKey[] = [];
const valueNodes: SerovalNode[] = [];
for (let i = 0, len = entries.length; i < len; i++) {
keyNodes.push(serializeString(entries[i][0]));
valueNodes.push(parseSOS(ctx, depth, entries[i][1]));
}
// Check special properties, symbols in this case
if (SYM_ITERATOR in properties) {
keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ITERATOR));
valueNodes.push(
createIteratorFactoryInstanceNode(
parseIteratorFactory(ctx.base),
parseSOS(
ctx,
depth,
iteratorToSequence(properties as unknown as Iterable<unknown>),
),
),
);
}
if (SYM_ASYNC_ITERATOR in properties) {
keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ASYNC_ITERATOR));
valueNodes.push(
createAsyncIteratorFactoryInstanceNode(
parseAsyncIteratorFactory(ctx.base),
parseSOS(
ctx,
depth,
ctx.type === ParserMode.Sync
? createStream()
: createStreamFromAsyncIterable(
properties as unknown as AsyncIterable<unknown>,
),
),
),
);
}
if (SYM_TO_STRING_TAG in properties) {
keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_TO_STRING_TAG));
valueNodes.push(createStringNode(properties[SYM_TO_STRING_TAG] as string));
}
if (SYM_IS_CONCAT_SPREADABLE in properties) {
keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_IS_CONCAT_SPREADABLE));
valueNodes.push(
properties[SYM_IS_CONCAT_SPREADABLE] ? TRUE_NODE : FALSE_NODE,
);
}
return {
k: keyNodes,
v: valueNodes,
};
}
function parsePlainObject(
ctx: SOSParserContext,
depth: number,
id: number,
current: Record<string, unknown>,
empty: boolean,
): ObjectLikeNode {
return createObjectNode(
id,
current,
empty,
parseProperties(ctx, depth, current),
);
}
function parseBoxed(
ctx: SOSParserContext,
depth: number,
id: number,
current: object,
): SerovalBoxedNode {
return createBoxedNode(id, parseSOS(ctx, depth, current.valueOf()));
}
function parseTypedArray(
ctx: SOSParserContext,
depth: number,
id: number,
current: TypedArrayValue,
): SerovalTypedArrayNode {
return createTypedArrayNode(
id,
current,
parseSOS(ctx, depth, current.buffer),
);
}
function parseBigIntTypedArray(
ctx: SOSParserContext,
depth: number,
id: number,
current: BigIntTypedArrayValue,
): SerovalBigIntTypedArrayNode {
return createBigIntTypedArrayNode(
id,
current,
parseSOS(ctx, depth, current.buffer),
);
}
function parseDataView(
ctx: SOSParserContext,
depth: number,
id: number,
current: DataView,
): SerovalDataViewNode {
return createDataViewNode(id, current, parseSOS(ctx, depth, current.buffer));
}
function parseError(
ctx: SOSParserContext,
depth: number,
id: number,
current: Error,
): SerovalErrorNode {
const options = getErrorOptions(current, ctx.base.features);
return createErrorNode(
id,
current,
options ? parseProperties(ctx, depth, options) : NIL,
);
}
function parseAggregateError(
ctx: SOSParserContext,
depth: number,
id: number,
current: AggregateError,
): SerovalAggregateErrorNode {
const options = getErrorOptions(current, ctx.base.features);
return createAggregateErrorNode(
id,
current,
options ? parseProperties(ctx, depth, options) : NIL,
);
}
function parseMap(
ctx: SOSParserContext,
depth: number,
id: number,
current: Map<unknown, unknown>,
): SerovalMapNode {
const keyNodes: SerovalNode[] = [];
const valueNodes: SerovalNode[] = [];
for (const [key, value] of current.entries()) {
keyNodes.push(parseSOS(ctx, depth, key));
valueNodes.push(parseSOS(ctx, depth, value));
}
return createMapNode(ctx.base, id, keyNodes, valueNodes);
}
function parseSet(
ctx: SOSParserContext,
depth: number,
id: number,
current: Set<unknown>,
): SerovalSetNode {
const items: SerovalNode[] = [];
for (const item of current.keys()) {
items.push(parseSOS(ctx, depth, item));
}
return createSetNode(id, items);
}
function parseStream(
ctx: SOSParserContext,
depth: number,
id: number,
current: Stream<unknown>,
): SerovalNode {
const result = createStreamConstructorNode(
id,
parseSpecialReference(ctx.base, SpecialReference.StreamConstructor),
[],
);
if (ctx.type === ParserMode.Sync) {
return result;
}
pushPendingState(ctx);
current.on({
next: value => {
if (ctx.state.alive) {
const parsed = parseWithError(ctx, depth, value);
if (parsed) {
onParse(ctx, createStreamNextNode(id, parsed));
}
}
},
throw: value => {
if (ctx.state.alive) {
const parsed = parseWithError(ctx, depth, value);
if (parsed) {
onParse(ctx, createStreamThrowNode(id, parsed));
}
}
popPendingState(ctx);
},
return: value => {
if (ctx.state.alive) {
const parsed = parseWithError(ctx, depth, value);
if (parsed) {
onParse(ctx, createStreamReturnNode(id, parsed));
}
}
popPendingState(ctx);
},
});
return result;
}
function handlePromiseSuccess(
this: StreamParserContext,
id: number,
depth: number,
data: unknown,
): void {
if (this.state.alive) {
const parsed = parseWithError(this, depth, data);
if (parsed) {
onParse(
this,
createSerovalNode(
SerovalNodeType.PromiseSuccess,
id,
NIL,
NIL,
NIL,
NIL,
NIL,
[
parseSpecialReference(this.base, SpecialReference.PromiseSuccess),
parsed,
],
NIL,
NIL,
NIL,
NIL,
),
);
}
popPendingState(this);
}
}
function handlePromiseFailure(
this: StreamParserContext,
id: number,
depth: number,
data: unknown,
): void {
if (this.state.alive) {
const parsed = parseWithError(this, depth, data);
if (parsed) {
onParse(
this,
createSerovalNode(
SerovalNodeType.PromiseFailure,
id,
NIL,
NIL,
NIL,
NIL,
NIL,
[
parseSpecialReference(this.base, SpecialReference.PromiseFailure),
parsed,
],
NIL,
NIL,
NIL,
NIL,
),
);
}
}
popPendingState(this);
}
function parsePromise(
ctx: SOSParserContext,
depth: number,
id: number,
current: Promise<unknown>,
): SerovalPromiseConstructorNode {
// Creates a unique reference for the promise resolver
const resolver = createIndexForValue(ctx.base, {});
if (ctx.type === ParserMode.Stream) {
pushPendingState(ctx);
current.then(
handlePromiseSuccess.bind(ctx, resolver, depth),
handlePromiseFailure.bind(ctx, resolver, depth),
);
}
return createPromiseConstructorNode(ctx.base, id, resolver);
}
function parsePluginSync(
ctx: SyncParserContext,
depth: number,
id: number,
current: unknown,
currentPlugins: Plugin<any, any>[],
): SerovalPluginNode | undefined {
for (let i = 0, len = currentPlugins.length; i < len; i++) {
const plugin = currentPlugins[i];
if (plugin.parse.sync && plugin.test(current)) {
return createPluginNode(
id,
plugin.tag,
plugin.parse.sync(current, new SyncParsePluginContext(ctx, depth), {
id,
}),
);
}
}
return NIL;
}
function parsePluginStream(
ctx: StreamParserContext,
depth: number,
id: number,
current: unknown,
currentPlugins: Plugin<any, any>[],
): SerovalPluginNode | undefined {
for (let i = 0, len = currentPlugins.length; i < len; i++) {
const plugin = currentPlugins[i];
if (plugin.parse.stream && plugin.test(current)) {
return createPluginNode(
id,
plugin.tag,
plugin.parse.stream(current, new StreamParsePluginContext(ctx, depth), {
id,
}),
);
}
}
return NIL;
}
function parsePlugin(
ctx: SOSParserContext,
depth: number,
id: number,
current: unknown,
): SerovalPluginNode | undefined {
const currentPlugins = ctx.base.plugins;
if (currentPlugins) {
return ctx.type === ParserMode.Sync
? parsePluginSync(ctx, depth, id, current, currentPlugins)
: parsePluginStream(ctx, depth, id, current, currentPlugins);
}
return NIL;
}
function parseObjectPhase2(
ctx: SOSParserContext,
depth: number,
id: number,
current: object,
currentClass: unknown,
): SerovalNode {
switch (currentClass) {
case Object:
return parsePlainObject(
ctx,
depth,
id,
current as Record<string, unknown>,
false,
);
case NIL:
return parsePlainObject(
ctx,
depth,
id,
current as Record<string, unknown>,
true,
);
case Date:
return createDateNode(id, current as unknown as Date);
case Error:
case EvalError:
case RangeError:
case ReferenceError:
case SyntaxError:
case TypeError:
case URIError:
return parseError(ctx, depth, id, current as unknown as Error);
case Number:
case Boolean:
case String:
case BigInt:
return parseBoxed(ctx, depth, id, current);
case ArrayBuffer:
return createArrayBufferNode(
ctx.base,
id,
current as unknown as ArrayBuffer,
);
case Int8Array:
case Int16Array:
case Int32Array:
case Uint8Array:
case Uint16Array:
case Uint32Array:
case Uint8ClampedArray:
case Float32Array:
case Float64Array:
return parseTypedArray(
ctx,
depth,
id,
current as unknown as TypedArrayValue,
);
case DataView:
return parseDataView(ctx, depth, id, current as unknown as DataView);
case Map:
return parseMap(
ctx,
depth,
id,
current as unknown as Map<unknown, unknown>,
);
case Set:
return parseSet(ctx, depth, id, current as unknown as Set<unknown>);
default:
break;
}
// Promises
if (currentClass === Promise || current instanceof Promise) {
return parsePromise(ctx, depth, id, current as unknown as Promise<unknown>);
}
const currentFeatures = ctx.base.features;
if (currentFeatures & Feature.RegExp && currentClass === RegExp) {
return createRegExpNode(id, current as unknown as RegExp);
}
// BigInt Typed Arrays
if (currentFeatures & Feature.BigIntTypedArray) {
switch (currentClass) {
case BigInt64Array:
case BigUint64Array:
return parseBigIntTypedArray(
ctx,
depth,
id,
current as unknown as BigIntTypedArrayValue,
);
default:
break;
}
}
if (
currentFeatures & Feature.AggregateError &&
typeof AggregateError !== 'undefined' &&
(currentClass === AggregateError || current instanceof AggregateError)
) {
return parseAggregateError(
ctx,
depth,
id,
current as unknown as AggregateError,
);
}
// Slow path. We only need to handle Errors and Iterators
// since they have very broad implementations.
if (current instanceof Error) {
return parseError(ctx, depth, id, current);
}
// Generator functions don't have a global constructor
// despite existing
if (SYM_ITERATOR in current || SYM_ASYNC_ITERATOR in current) {
return parsePlainObject(ctx, depth, id, current, !!currentClass);
}
throw new SerovalUnsupportedTypeError(current);
}
function parseObject(
ctx: SOSParserContext,
depth: number,
id: number,
current: object,
): SerovalNode {
if (Array.isArray(current)) {
return parseArray(ctx, depth, id, current);
}
if (isStream(current)) {
return parseStream(ctx, depth, id, current);
}
const currentClass = current.constructor;
if (currentClass === OpaqueReference) {
return parseSOS(
ctx,
depth,
(current as OpaqueReference<unknown, unknown>).replacement,
);
}
const parsed = parsePlugin(ctx, depth, id, current);
if (parsed) {
return parsed;
}
return parseObjectPhase2(ctx, depth, id, current, currentClass);
}
function parseFunction(
ctx: SOSParserContext,
depth: number,
current: unknown,
): SerovalNode {
const ref = getReferenceNode(ctx.base, current);
if (ref.type !== ParserNodeType.Fresh) {
return ref.value;
}
const plugin = parsePlugin(ctx, depth, ref.value, current);
if (plugin) {
return plugin;
}
throw new SerovalUnsupportedTypeError(current);
}
export function parseSOS<T>(
ctx: SOSParserContext,
depth: number,
current: T,
): SerovalNode {
if (depth >= ctx.base.depthLimit) {
throw new SerovalDepthLimitError(ctx.base.depthLimit);
}
switch (typeof current) {
case 'boolean':
return current ? TRUE_NODE : FALSE_NODE;
case 'undefined':
return UNDEFINED_NODE;
case 'string':
return createStringNode(current as string);
case 'number':
return createNumberNode(current as number);
case 'bigint':
return createBigIntNode(current as bigint);
case 'object': {
if (current) {
const ref = getReferenceNode(ctx.base, current);
return ref.type === ParserNodeType.Fresh
? parseObject(ctx, depth + 1, ref.value, current as object)
: ref.value;
}
return NULL_NODE;
}
case 'symbol':
return parseWellKnownSymbol(ctx.base, current);
case 'function': {
return parseFunction(ctx, depth, current);
}
default:
throw new SerovalUnsupportedTypeError(current);
}
}
export function parseTop<T>(ctx: SyncParserContext, current: T): SerovalNode {
try {
return parseSOS(ctx, 0, current);
} catch (error) {
throw error instanceof SerovalParserError
? error
: new SerovalParserError(error);
}
}
function onParse(ctx: StreamParserContext, node: SerovalNode): void {
// If the value emitted happens to be during parsing, we push to the
// buffer and emit after the initial parsing is done.
if (ctx.state.initial) {
ctx.state.buffer.push(node);
} else {
onParseInternal(ctx, node, false);
}
}
function onError(ctx: StreamParserContext, error: unknown): void {
if (ctx.state.onError) {
ctx.state.onError(error);
} else {
throw error instanceof SerovalParserError
? error
: new SerovalParserError(error);
}
}
function onDone(ctx: StreamParserContext): void {
if (ctx.state.onDone) {
ctx.state.onDone();
}
}
function onParseInternal(
ctx: StreamParserContext,
node: SerovalNode,
initial: boolean,
): void {
try {
ctx.state.onParse(node, initial);
} catch (error) {
onError(ctx, error);
}
}
function pushPendingState(ctx: StreamParserContext): void {
ctx.state.pending++;
}
function popPendingState(ctx: StreamParserContext): void {
if (--ctx.state.pending <= 0) {
onDone(ctx);
}
}
function parseWithError<T>(
ctx: StreamParserContext,
depth: number,
current: T,
): SerovalNode | undefined {
try {
return parseSOS(ctx, depth, current);
} catch (err) {
onError(ctx, err);
return NIL;
}
}
export function startStreamParse<T>(
ctx: StreamParserContext,
current: T,
): void {
const parsed = parseWithError(ctx, 0, current);
if (parsed) {
onParseInternal(ctx, parsed, true);
ctx.state.initial = false;
flushStreamParse(ctx, ctx.state);
// Check if there's any pending pushes
if (ctx.state.pending <= 0) {
destroyStreamParse(ctx);
}
}
}
function flushStreamParse(
ctx: StreamParserContext,
state: StreamParserState,
): void {
for (let i = 0, len = state.buffer.length; i < len; i++) {
onParseInternal(ctx, state.buffer[i], false);
}
}
export function destroyStreamParse(ctx: StreamParserContext): void {
if (ctx.state.alive) {
onDone(ctx);
ctx.state.alive = false;
}
}

View file

@ -0,0 +1,188 @@
import type { AsyncParserContextOptions } from '../context/async-parser';
import {
createAsyncParserContext,
parseTopAsync,
} from '../context/async-parser';
import type { CrossDeserializerContextOptions } from '../context/deserializer';
import {
createCrossDeserializerContext,
deserializeTop,
} from '../context/deserializer';
import type { CrossContextOptions } from '../context/serializer';
import {
createCrossSerializerContext,
serializeTopCross,
} from '../context/serializer';
import type {
StreamParserContextOptions,
SyncParserContextOptions,
} from '../context/sync-parser';
import {
createStreamParserContext,
createSyncParserContext,
destroyStreamParse,
parseTop,
startStreamParse,
} from '../context/sync-parser';
import { resolvePlugins, SerovalMode } from '../plugin';
import type { SerovalNode } from '../types';
export interface CrossSerializeOptions
extends SyncParserContextOptions,
CrossContextOptions {}
export function crossSerialize<T>(
source: T,
options: CrossSerializeOptions = {},
): string {
const plugins = resolvePlugins(options.plugins);
const ctx = createSyncParserContext(SerovalMode.Cross, {
plugins,
disabledFeatures: options.disabledFeatures,
refs: options.refs,
});
const tree = parseTop(ctx, source);
const serial = createCrossSerializerContext({
plugins,
features: ctx.base.features,
scopeId: options.scopeId,
markedRefs: ctx.base.marked,
});
return serializeTopCross(serial, tree);
}
export interface CrossSerializeAsyncOptions
extends AsyncParserContextOptions,
CrossContextOptions {}
export async function crossSerializeAsync<T>(
source: T,
options: CrossSerializeAsyncOptions = {},
): Promise<string> {
const plugins = resolvePlugins(options.plugins);
const ctx = createAsyncParserContext(SerovalMode.Cross, {
plugins,
disabledFeatures: options.disabledFeatures,
refs: options.refs,
});
const tree = await parseTopAsync(ctx, source);
const serial = createCrossSerializerContext({
plugins,
features: ctx.base.features,
scopeId: options.scopeId,
markedRefs: ctx.base.marked,
});
return serializeTopCross(serial, tree);
}
export type ToCrossJSONOptions = SyncParserContextOptions;
export function toCrossJSON<T>(
source: T,
options: ToCrossJSONOptions = {},
): SerovalNode {
const plugins = resolvePlugins(options.plugins);
const ctx = createSyncParserContext(SerovalMode.Cross, {
plugins,
disabledFeatures: options.disabledFeatures,
refs: options.refs,
});
return parseTop(ctx, source);
}
export type ToCrossJSONAsyncOptions = AsyncParserContextOptions;
export async function toCrossJSONAsync<T>(
source: T,
options: ToCrossJSONAsyncOptions = {},
): Promise<SerovalNode> {
const plugins = resolvePlugins(options.plugins);
const ctx = createAsyncParserContext(SerovalMode.Cross, {
plugins,
disabledFeatures: options.disabledFeatures,
refs: options.refs,
});
return await parseTopAsync(ctx, source);
}
export interface CrossSerializeStreamOptions
extends Omit<StreamParserContextOptions, 'onParse'>,
CrossContextOptions {
onSerialize: (data: string, initial: boolean) => void;
}
export function crossSerializeStream<T>(
source: T,
options: CrossSerializeStreamOptions,
): () => void {
const plugins = resolvePlugins(options.plugins);
const ctx = createStreamParserContext({
plugins,
refs: options.refs,
disabledFeatures: options.disabledFeatures,
onParse(node, initial): void {
const serial = createCrossSerializerContext({
plugins,
features: ctx.base.features,
scopeId: options.scopeId,
markedRefs: ctx.base.marked,
});
let serialized: string;
try {
serialized = serializeTopCross(serial, node);
} catch (err) {
if (options.onError) {
options.onError(err);
}
return;
}
options.onSerialize(serialized, initial);
},
onError: options.onError,
onDone: options.onDone,
});
startStreamParse(ctx, source);
return destroyStreamParse.bind(null, ctx);
}
export type ToCrossJSONStreamOptions = StreamParserContextOptions;
export function toCrossJSONStream<T>(
source: T,
options: ToCrossJSONStreamOptions,
): () => void {
const plugins = resolvePlugins(options.plugins);
const ctx = createStreamParserContext({
plugins,
refs: options.refs,
disabledFeatures: options.disabledFeatures,
onParse: options.onParse,
onError: options.onError,
onDone: options.onDone,
});
startStreamParse(ctx, source);
return destroyStreamParse.bind(null, ctx);
}
export type FromCrossJSONOptions = CrossDeserializerContextOptions;
export function fromCrossJSON<T>(
source: SerovalNode,
options: FromCrossJSONOptions,
): T {
const plugins = resolvePlugins(options.plugins);
const ctx = createCrossDeserializerContext({
plugins,
refs: options.refs,
features: options.features,
disabledFeatures: options.disabledFeatures,
});
return deserializeTop(ctx, source) as T;
}

View file

@ -0,0 +1,196 @@
/// <reference types="pridepack/env" />
import { serializeString } from './string';
import type { SerovalNode } from './types';
const { toString: objectToString } = /* @__PURE__ */ Object.prototype;
const enum StepErrorCodes {
Parse = 1,
Serialize = 2,
Deserialize = 3,
}
function getErrorMessageDev(type: string, cause: any): string {
if (cause instanceof Error) {
return `Seroval caught an error during the ${type} process.
${cause.name}
${cause.message}
- For more information, please check the "cause" property of this error.
- If you believe this is an error in Seroval, please submit an issue at https://github.com/lxsmnsyc/seroval/issues/new`;
}
return `Seroval caught an error during the ${type} process.
"${objectToString.call(cause)}"
For more information, please check the "cause" property of this error.`;
}
const STEP_ERROR_CODES: Record<string, StepErrorCodes> = {
parsing: StepErrorCodes.Parse,
serialization: StepErrorCodes.Serialize,
deserialization: StepErrorCodes.Deserialize,
};
function getErrorMessageProd(type: string): string {
return `Seroval Error (step: ${STEP_ERROR_CODES[type]})`;
}
const getErrorMessage = (type: string, cause: any) =>
import.meta.env.PROD
? getErrorMessageProd(type)
: getErrorMessageDev(type, cause);
export class SerovalError extends Error {
constructor(
type: string,
public cause: any,
) {
super(getErrorMessage(type, cause));
}
}
export class SerovalParserError extends SerovalError {
constructor(cause: any) {
super('parsing', cause);
}
}
export class SerovalSerializationError extends SerovalError {
constructor(cause: any) {
super('serialization', cause);
}
}
export class SerovalDeserializationError extends SerovalError {
constructor(cause: any) {
super('deserialization', cause);
}
}
const enum SpecificErrorCodes {
UnsupportedType = 1,
UnsupportedNode = 2,
MissingPlugin = 3,
MissingInstance = 4,
MissingReference = 5,
MissingReferenceForId = 6,
UnknownTypedArray = 7,
MalformedNode = 8,
ConflictedNodeId = 9,
DepthLimit = 10,
}
function getSpecificErrorMessage(code: SpecificErrorCodes): string {
return `Seroval Error (specific: ${code})`;
}
export class SerovalUnsupportedTypeError extends Error {
constructor(public value: unknown) {
super(
import.meta.env.PROD
? getSpecificErrorMessage(SpecificErrorCodes.UnsupportedType)
: `The value ${objectToString.call(value)} of type "${typeof value}" cannot be parsed/serialized.
There are few workarounds for this problem:
- Transform the value in a way that it can be serialized.
- If the reference is present on multiple runtimes (isomorphic), you can use the Reference API to map the references.`,
);
}
}
export class SerovalUnsupportedNodeError extends Error {
constructor(node: SerovalNode) {
super(
import.meta.env.PROD
? getSpecificErrorMessage(SpecificErrorCodes.UnsupportedNode)
: 'Unsupported node type "' + node.t + '".',
);
}
}
export class SerovalMissingPluginError extends Error {
constructor(tag: string) {
super(
import.meta.env.PROD
? getSpecificErrorMessage(SpecificErrorCodes.MissingPlugin)
: 'Missing plugin for tag "' + tag + '".',
);
}
}
export class SerovalMissingInstanceError extends Error {
constructor(tag: string) {
super(
import.meta.env.PROD
? getSpecificErrorMessage(SpecificErrorCodes.MissingInstance)
: 'Missing "' + tag + '" instance.',
);
}
}
export class SerovalMissingReferenceError extends Error {
constructor(public value: unknown) {
super(
import.meta.env.PROD
? getSpecificErrorMessage(SpecificErrorCodes.MissingReference)
: 'Missing reference for the value "' +
objectToString.call(value) +
'" of type "' +
typeof value +
'"',
);
}
}
export class SerovalMissingReferenceForIdError extends Error {
constructor(id: string) {
super(
import.meta.env.PROD
? getSpecificErrorMessage(SpecificErrorCodes.MissingReferenceForId)
: 'Missing reference for id "' + serializeString(id) + '"',
);
}
}
export class SerovalUnknownTypedArrayError extends Error {
constructor(name: string) {
super(
import.meta.env.PROD
? getSpecificErrorMessage(SpecificErrorCodes.UnknownTypedArray)
: 'Unknown TypedArray "' + name + '"',
);
}
}
export class SerovalMalformedNodeError extends Error {
constructor(node: SerovalNode) {
super(
import.meta.env.PROD
? getSpecificErrorMessage(SpecificErrorCodes.MalformedNode)
: 'Malformed node type "' + node.t + '".',
);
}
}
export class SerovalConflictedNodeIdError extends Error {
constructor(node: SerovalNode) {
super(
import.meta.env.PROD
? getSpecificErrorMessage(SpecificErrorCodes.ConflictedNodeId)
: 'Conflicted node id "' + node.i + '".',
);
}
}
export class SerovalDepthLimitError extends Error {
constructor(limit: number) {
super(
import.meta.env.PROD
? getSpecificErrorMessage(SpecificErrorCodes.ConflictedNodeId)
: 'Depth limit of ' + limit + ' reached',
);
}
}

View file

@ -0,0 +1,32 @@
declare const T: unknown;
const RETURN = () => T;
const SERIALIZED_RETURN = /* @__PURE__ */ RETURN.toString();
const IS_MODERN = /* @__PURE__ */ /=>/.test(SERIALIZED_RETURN);
export function createFunction(parameters: string[], body: string): string {
if (IS_MODERN) {
const joined =
parameters.length === 1
? parameters[0]
: '(' + parameters.join(',') + ')';
return joined + '=>' + (body.startsWith('{') ? '(' + body + ')' : body);
}
return 'function(' + parameters.join(',') + '){return ' + body + '}';
}
export function createEffectfulFunction(
parameters: string[],
body: string,
): string {
if (IS_MODERN) {
const joined =
parameters.length === 1
? parameters[0]
: '(' + parameters.join(',') + ')';
return joined + '=>{' + body + '}';
}
return 'function(' + parameters.join(',') + '){' + body + '}';
}

17
Frontend-Learner/node_modules/seroval/src/core/keys.ts generated vendored Normal file
View file

@ -0,0 +1,17 @@
import { serializeString } from './string';
// Used for mapping isomorphic references
export const REFERENCES_KEY = '__SEROVAL_REFS__';
export const GLOBAL_CONTEXT_REFERENCES = '$R';
const GLOBAL_CONTEXT_R = `self.${GLOBAL_CONTEXT_REFERENCES}`;
export function getCrossReferenceHeader(id?: string): string {
if (id == null) {
return `${GLOBAL_CONTEXT_R}=${GLOBAL_CONTEXT_R}||[]`;
}
return `(${GLOBAL_CONTEXT_R}=${GLOBAL_CONTEXT_R}||{})["${serializeString(
id,
)}"]=[]`;
}

View file

@ -0,0 +1,43 @@
import { NIL, SerovalConstant, SerovalNodeType } from './constants';
import { createSerovalNode } from './node';
import type { SerovalConstantNode } from './types';
function createConstantNode(value: SerovalConstant): SerovalConstantNode {
return createSerovalNode(
SerovalNodeType.Constant,
NIL,
value,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
NIL,
);
}
export const TRUE_NODE = /* @__PURE__ */ createConstantNode(
SerovalConstant.True,
);
export const FALSE_NODE = /* @__PURE__ */ createConstantNode(
SerovalConstant.False,
);
export const UNDEFINED_NODE = /* @__PURE__ */ createConstantNode(
SerovalConstant.Undefined,
);
export const NULL_NODE = /* @__PURE__ */ createConstantNode(
SerovalConstant.Null,
);
export const NEG_ZERO_NODE = /* @__PURE__ */ createConstantNode(
SerovalConstant.NegZero,
);
export const INFINITY_NODE = /* @__PURE__ */ createConstantNode(
SerovalConstant.Inf,
);
export const NEG_INFINITY_NODE = /* @__PURE__ */ createConstantNode(
SerovalConstant.NegInf,
);
export const NAN_NODE = /* @__PURE__ */ createConstantNode(SerovalConstant.Nan);

40
Frontend-Learner/node_modules/seroval/src/core/node.ts generated vendored Normal file
View file

@ -0,0 +1,40 @@
import type { SerovalNodeType } from './constants';
import type { SerovalNode } from './types';
type ExtractedNodeType<T extends SerovalNodeType> = Extract<
SerovalNode,
{ t: T }
>;
export function createSerovalNode<
T extends SerovalNodeType,
N extends ExtractedNodeType<T>,
>(
t: T,
i: N['i'],
s: N['s'],
c: N['c'],
m: N['m'],
p: N['p'],
e: N['e'],
a: N['a'],
f: N['f'],
b: N['b'],
o: N['o'],
l: N['l'],
): N {
return {
t,
i,
s,
c,
m,
p,
e,
a,
f,
b,
o,
l,
} as N;
}

View file

@ -0,0 +1,9 @@
/**
* An opaque reference allows hiding values from the serializer.
*/
export class OpaqueReference<V, R = undefined> {
constructor(
public readonly value: V,
public readonly replacement?: R,
) {}
}

View file

@ -0,0 +1,100 @@
import type { AsyncParsePluginContext } from './context/async-parser';
import type { DeserializePluginContext } from './context/deserializer';
import type { SerializePluginContext } from './context/serializer';
import type {
StreamParsePluginContext,
SyncParsePluginContext,
} from './context/sync-parser';
export const enum SerovalMode {
Vanilla = 1,
Cross = 2,
}
export interface PluginData {
id: number;
}
export interface Plugin<Value, Node> {
/**
* A unique string that helps idenfity the plugin
*/
tag: string;
/**
* List of dependency plugins
*/
extends?: Plugin<any, any>[];
/**
* Method to test if a value is an expected value of the plugin
* @param value
*/
test(value: unknown): boolean;
/**
* Parsing modes
*/
parse: {
sync?: (
value: Value,
ctx: SyncParsePluginContext,
data: PluginData,
) => Node;
async?: (
value: Value,
ctx: AsyncParsePluginContext,
data: PluginData,
) => Promise<Node>;
stream?: (
value: Value,
ctx: StreamParsePluginContext,
data: PluginData,
) => Node;
};
/**
* Convert the parsed node into a JS string
*/
serialize(node: Node, ctx: SerializePluginContext, data: PluginData): string;
/**
* Convert the parsed node into its runtime equivalent.
*/
deserialize(
node: Node,
ctx: DeserializePluginContext,
data: PluginData,
): Value;
}
export function createPlugin<Value, Node>(
plugin: Plugin<Value, Node>,
): Plugin<Value, Node> {
return plugin;
}
export interface PluginAccessOptions {
plugins?: Plugin<any, any>[];
}
function dedupePlugins(
deduped: Set<Plugin<any, any>>,
plugins: Plugin<any, any>[],
): void {
for (let i = 0, len = plugins.length; i < len; i++) {
const current = plugins[i];
if (!deduped.has(current)) {
deduped.add(current);
if (current.extends) {
dedupePlugins(deduped, current.extends);
}
}
}
}
export function resolvePlugins(
plugins?: Plugin<any, any>[],
): Plugin<any, any>[] | undefined {
if (plugins) {
const deduped = new Set<Plugin<any, any>>();
dedupePlugins(deduped, plugins);
return [...deduped];
}
return undefined;
}

View file

@ -0,0 +1,66 @@
import {
SerovalMissingReferenceError,
SerovalMissingReferenceForIdError,
} from '..';
import { REFERENCES_KEY } from './keys';
const REFERENCE = new Map<unknown, string>();
const INV_REFERENCE = new Map<string, unknown>();
export function createReference<T>(id: string, value: T): T {
REFERENCE.set(value, id);
INV_REFERENCE.set(id, value);
return value;
}
export function hasReferenceID<T>(value: T): boolean {
return REFERENCE.has(value);
}
export function hasReference(id: string): boolean {
return INV_REFERENCE.has(id);
}
export function getReferenceID<T>(value: T): string {
if (hasReferenceID(value)) {
return REFERENCE.get(value)!;
}
throw new SerovalMissingReferenceError(value);
}
export function getReference<T>(id: string): T {
if (hasReference(id)) {
return INV_REFERENCE.get(id) as T;
}
throw new SerovalMissingReferenceForIdError(id);
}
if (typeof globalThis !== 'undefined') {
Object.defineProperty(globalThis, REFERENCES_KEY, {
value: INV_REFERENCE,
configurable: true,
writable: false,
enumerable: false,
});
} else if (typeof window !== 'undefined') {
Object.defineProperty(window, REFERENCES_KEY, {
value: INV_REFERENCE,
configurable: true,
writable: false,
enumerable: false,
});
} else if (typeof self !== 'undefined') {
Object.defineProperty(self, REFERENCES_KEY, {
value: INV_REFERENCE,
configurable: true,
writable: false,
enumerable: false,
});
} else if (typeof global !== 'undefined') {
Object.defineProperty(global, REFERENCES_KEY, {
value: INV_REFERENCE,
configurable: true,
writable: false,
enumerable: false,
});
}

View file

@ -0,0 +1,42 @@
import {
SERIALIZED_ARRAY_BUFFER_CONSTRUCTOR,
SERIALIZED_PROMISE_CONSTRUCTOR,
SERIALIZED_PROMISE_FAILURE,
SERIALIZED_PROMISE_SUCCESS,
SERIALIZED_STREAM_CONSTRUCTOR,
} from './constructors';
export const ITERATOR = {};
export const ASYNC_ITERATOR = {};
export const enum SpecialReference {
MapSentinel = 0,
PromiseConstructor = 1,
PromiseSuccess = 2,
PromiseFailure = 3,
StreamConstructor = 4,
ArrayBufferConstructor = 5,
}
/**
* Placeholder references
*/
export const SPECIAL_REFS: Record<SpecialReference, unknown> = {
[SpecialReference.MapSentinel]: {},
[SpecialReference.PromiseConstructor]: {},
[SpecialReference.PromiseSuccess]: {},
[SpecialReference.PromiseFailure]: {},
[SpecialReference.StreamConstructor]: {},
[SpecialReference.ArrayBufferConstructor]: {},
};
export const SPECIAL_REF_STRING: Record<SpecialReference, string> = {
[SpecialReference.MapSentinel]: '[]',
[SpecialReference.PromiseConstructor]: SERIALIZED_PROMISE_CONSTRUCTOR,
[SpecialReference.PromiseSuccess]: SERIALIZED_PROMISE_SUCCESS,
[SpecialReference.PromiseFailure]: SERIALIZED_PROMISE_FAILURE,
[SpecialReference.StreamConstructor]: SERIALIZED_STREAM_CONSTRUCTOR,
[SpecialReference.ArrayBufferConstructor]:
SERIALIZED_ARRAY_BUFFER_CONSTRUCTOR,
};

View file

@ -0,0 +1,71 @@
import {
ASYNC_ITERATOR_CONSTRUCTOR,
PROMISE_CONSTRUCTOR,
STREAM_CONSTRUCTOR,
} from './constructors';
import { SYM_ASYNC_ITERATOR } from './symbols';
export interface StreamListener<T> {
next(value: T): void;
throw(value: unknown): void;
return(value: T): void;
}
export interface Stream<T> {
__SEROVAL_STREAM__: true;
on(listener: StreamListener<T>): () => void;
next(value: T): void;
throw(value: unknown): void;
return(value: T): void;
}
export function isStream<T>(value: object): value is Stream<T> {
return '__SEROVAL_STREAM__' in value;
}
export function createStream<T>(): Stream<T> {
return STREAM_CONSTRUCTOR() as unknown as Stream<T>;
}
export function createStreamFromAsyncIterable<T>(
iterable: AsyncIterable<T>,
): Stream<T> {
const stream = createStream<T>();
const iterator = iterable[SYM_ASYNC_ITERATOR]();
async function push(): Promise<void> {
try {
const value = await iterator.next();
if (value.done) {
stream.return(value.value as T);
} else {
stream.next(value.value);
await push();
}
} catch (error) {
stream.throw(error);
}
}
push().catch(() => {
// no-op
});
return stream;
}
const createAsyncIterable = ASYNC_ITERATOR_CONSTRUCTOR(
SYM_ASYNC_ITERATOR,
PROMISE_CONSTRUCTOR,
);
export function streamToAsyncIterable<T>(
stream: Stream<T>,
): () => AsyncIterableIterator<T> {
return createAsyncIterable(
stream,
) as unknown as () => AsyncIterableIterator<T>;
}

View file

@ -0,0 +1,86 @@
import { NIL } from './constants';
export function serializeChar(str: string): string | undefined {
switch (str) {
case '"':
return '\\"';
case '\\':
return '\\\\';
case '\n':
return '\\n';
case '\r':
return '\\r';
case '\b':
return '\\b';
case '\t':
return '\\t';
case '\f':
return '\\f';
case '<':
return '\\x3C';
case '\u2028':
return '\\u2028';
case '\u2029':
return '\\u2029';
default:
return NIL;
}
}
// Written by https://github.com/DylanPiercey and is distributed under the MIT license.
// Creates a JavaScript double quoted string and escapes all characters
// not listed as DoubleStringCharacters on
// Also includes "<" to escape "</script>" and "\" to avoid invalid escapes in the output.
// http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
export function serializeString(str: string): string {
let result = '';
let lastPos = 0;
let replacement: string | undefined;
for (let i = 0, len = str.length; i < len; i++) {
replacement = serializeChar(str[i]);
if (replacement) {
result += str.slice(lastPos, i) + replacement;
lastPos = i + 1;
}
}
if (lastPos === 0) {
result = str;
} else {
result += str.slice(lastPos);
}
return result;
}
function deserializeReplacer(str: string): string {
switch (str) {
case '\\\\':
return '\\';
case '\\"':
return '"';
case '\\n':
return '\n';
case '\\r':
return '\r';
case '\\b':
return '\b';
case '\\t':
return '\t';
case '\\f':
return '\f';
case '\\x3C':
return '\x3C';
case '\\u2028':
return '\u2028';
case '\\u2029':
return '\u2029';
default:
return str;
}
}
export function deserializeString(str: string): string {
return str.replace(
/(\\\\|\\"|\\n|\\r|\\b|\\t|\\f|\\u2028|\\u2029|\\x3C)/g,
deserializeReplacer,
);
}

View file

@ -0,0 +1,18 @@
export const SYM_ASYNC_ITERATOR: typeof Symbol.asyncIterator = Symbol.asyncIterator;
export const SYM_HAS_INSTANCE: typeof Symbol.hasInstance = Symbol.hasInstance;
export const SYM_IS_CONCAT_SPREADABLE: typeof Symbol.isConcatSpreadable = Symbol.isConcatSpreadable;
export const SYM_ITERATOR: typeof Symbol.iterator = Symbol.iterator;
export const SYM_MATCH: typeof Symbol.match = Symbol.match;
export const SYM_MATCH_ALL: typeof Symbol.matchAll = Symbol.matchAll;
export const SYM_REPLACE: typeof Symbol.replace = Symbol.replace;
export const SYM_SEARCH: typeof Symbol.search = Symbol.search;
export const SYM_SPECIES: typeof Symbol.species = Symbol.species;
export const SYM_SPLIT: typeof Symbol.split = Symbol.split;
export const SYM_TO_PRIMITIVE: typeof Symbol.toPrimitive = Symbol.toPrimitive;
export const SYM_TO_STRING_TAG: typeof Symbol.toStringTag = Symbol.toStringTag;
export const SYM_UNSCOPABLES: typeof Symbol.unscopables = Symbol.unscopables;
// For the future
// export const SYM_DISPOSE = Symbol.dispose;
// export const SYM_ASYNC_DISPOSE = Symbol.asyncDispose;

View file

@ -0,0 +1,134 @@
import {
createAsyncParserContext,
parseTopAsync,
} from '../context/async-parser';
import {
createVanillaDeserializerContext,
deserializeTop,
} from '../context/deserializer';
import type { BaseParserContextOptions } from '../context/parser';
import {
createVanillaSerializerContext,
serializeTopVanilla,
} from '../context/serializer';
import { createSyncParserContext, parseTop } from '../context/sync-parser';
import {
type PluginAccessOptions,
resolvePlugins,
SerovalMode,
} from '../plugin';
import type { SerovalNode } from '../types';
import { ALL_ENABLED } from '../compat';
export type SyncParserContextOptions = Omit<BaseParserContextOptions, 'refs'>;
export type AsyncParserContextOptions = Omit<BaseParserContextOptions, 'refs'>;
export function serialize<T>(
source: T,
options: SyncParserContextOptions = {},
): string {
const plugins = resolvePlugins(options.plugins);
const ctx = createSyncParserContext(SerovalMode.Vanilla, {
plugins,
disabledFeatures: options.disabledFeatures,
});
const tree = parseTop(ctx, source);
const serial = createVanillaSerializerContext({
plugins,
features: ctx.base.features,
markedRefs: ctx.base.marked,
});
return serializeTopVanilla(serial, tree);
}
export async function serializeAsync<T>(
source: T,
options: AsyncParserContextOptions = {},
): Promise<string> {
const plugins = resolvePlugins(options.plugins);
const ctx = createAsyncParserContext(SerovalMode.Vanilla, {
plugins,
disabledFeatures: options.disabledFeatures,
});
const tree = await parseTopAsync(ctx, source);
const serial = createVanillaSerializerContext({
plugins,
features: ctx.base.features,
markedRefs: ctx.base.marked,
});
return serializeTopVanilla(serial, tree);
}
export function deserialize<T>(source: string): T {
return (0, eval)(source) as T;
}
export interface SerovalJSON {
t: SerovalNode;
f: number;
m: number[];
}
export interface FromJSONOptions extends PluginAccessOptions {
disabledFeatures?: number;
}
export function toJSON<T>(
source: T,
options: SyncParserContextOptions = {},
): SerovalJSON {
const plugins = resolvePlugins(options.plugins);
const ctx = createSyncParserContext(SerovalMode.Vanilla, {
plugins,
disabledFeatures: options.disabledFeatures,
});
return {
t: parseTop(ctx, source),
f: ctx.base.features,
m: Array.from(ctx.base.marked),
};
}
export async function toJSONAsync<T>(
source: T,
options: AsyncParserContextOptions = {},
): Promise<SerovalJSON> {
const plugins = resolvePlugins(options.plugins);
const ctx = createAsyncParserContext(SerovalMode.Vanilla, {
plugins,
disabledFeatures: options.disabledFeatures,
});
return {
t: await parseTopAsync(ctx, source),
f: ctx.base.features,
m: Array.from(ctx.base.marked),
};
}
export function compileJSON(
source: SerovalJSON,
options: PluginAccessOptions = {},
): string {
const plugins = resolvePlugins(options.plugins);
const ctx = createVanillaSerializerContext({
plugins,
features: source.f,
markedRefs: source.m,
});
return serializeTopVanilla(ctx, source.t);
}
export function fromJSON<T>(
source: SerovalJSON,
options: FromJSONOptions = {},
): T {
const plugins = resolvePlugins(options.plugins);
const disabledFeatures = options.disabledFeatures || 0;
const sourceFeatures = source.f ?? ALL_ENABLED;
const ctx = createVanillaDeserializerContext({
plugins,
markedRefs: source.m,
features: sourceFeatures & ~disabledFeatures,
disabledFeatures,
});
return deserializeTop(ctx, source.t) as T;
}

366
Frontend-Learner/node_modules/seroval/src/core/types.ts generated vendored Normal file
View file

@ -0,0 +1,366 @@
import type {
ErrorConstructorTag,
SerovalConstant,
SerovalNodeType,
SerovalObjectFlags,
Symbols,
} from './constants';
import type { SpecialReference } from './special-reference';
export interface SerovalBaseNode {
// Type of the node
t: SerovalNodeType;
// Reference ID
i: number | undefined;
// Serialized value
s: unknown;
// Constructor name / RegExp source
c: string | undefined;
// message/flags
m: string | undefined;
// properties (objects)
p: SerovalObjectRecordNode | undefined;
// entries (for Map, etc.)
e: SerovalMapRecordNode | undefined;
// array of nodes
a: (SerovalNode | 0)[] | undefined;
// fulfilled node
f: SerovalNode | undefined;
// byte offset/object flags
b: number | undefined;
// object flag
o: SerovalObjectFlags | undefined;
// length
l: number | undefined;
}
export type SerovalObjectRecordKey = string | SerovalNode;
export interface SerovalObjectRecordNode {
k: SerovalObjectRecordKey[];
v: SerovalNode[];
}
export interface SerovalMapRecordNode {
k: SerovalNode[];
v: SerovalNode[];
}
export interface SerovalNumberNode extends SerovalBaseNode {
t: SerovalNodeType.Number;
s: number;
}
export interface SerovalStringNode extends SerovalBaseNode {
t: SerovalNodeType.String;
s: string;
}
export interface SerovalConstantNode extends SerovalBaseNode {
t: SerovalNodeType.Constant;
s: SerovalConstant;
}
export type SerovalPrimitiveNode =
| SerovalNumberNode
| SerovalStringNode
| SerovalConstantNode;
export interface SerovalIndexedValueNode extends SerovalBaseNode {
t: SerovalNodeType.IndexedValue;
// id
i: number;
}
export interface SerovalBigIntNode extends SerovalBaseNode {
t: SerovalNodeType.BigInt;
// value in string
s: string;
}
export interface SerovalDateNode extends SerovalBaseNode {
t: SerovalNodeType.Date;
// id (Dates are stateful)
i: number;
// value in ISO string
s: string;
}
export interface SerovalRegExpNode extends SerovalBaseNode {
t: SerovalNodeType.RegExp;
// id (RegExp are stateful)
i: number;
// source
c: string;
// flags
m: string;
}
export interface SerovalArrayBufferNode extends SerovalBaseNode {
t: SerovalNodeType.ArrayBuffer;
// id
i: number;
// byte string
s: string;
// array buffer constructor
f: SerovalNodeWithID;
}
export interface SerovalTypedArrayNode extends SerovalBaseNode {
t: SerovalNodeType.TypedArray;
// id
i: number;
// TypedArray Constructor
c: string;
// ArrayBuffer reference
f: SerovalNode;
// Byte Offset
b: number;
// length
l: number;
}
export interface SerovalBigIntTypedArrayNode extends SerovalBaseNode {
t: SerovalNodeType.BigIntTypedArray;
i: number;
// TypedArray Constructor
c: string;
// ArrayBuffer reference
f: SerovalNode;
// Byte Offset
b: number;
// length
l: number;
}
export type SerovalSemiPrimitiveNode =
| SerovalBigIntNode
| SerovalDateNode
| SerovalRegExpNode
| SerovalTypedArrayNode
| SerovalBigIntTypedArrayNode;
export interface SerovalSetNode extends SerovalBaseNode {
t: SerovalNodeType.Set;
// id
i: number;
// Items in Set (as array)
a: SerovalNode[];
}
export interface SerovalMapNode extends SerovalBaseNode {
t: SerovalNodeType.Map;
i: number;
// key/value pairs
e: SerovalMapRecordNode;
f: SerovalNodeWithID;
}
export interface SerovalArrayNode extends SerovalBaseNode {
t: SerovalNodeType.Array;
// items
a: (SerovalNode | 0)[];
i: number;
o: SerovalObjectFlags;
}
export interface SerovalObjectNode extends SerovalBaseNode {
t: SerovalNodeType.Object;
// key/value pairs
p: SerovalObjectRecordNode;
i: number;
o: SerovalObjectFlags;
}
export interface SerovalNullConstructorNode extends SerovalBaseNode {
t: SerovalNodeType.NullConstructor;
// key/value pairs
p: SerovalObjectRecordNode;
i: number;
o: SerovalObjectFlags;
}
export interface SerovalPromiseNode extends SerovalBaseNode {
t: SerovalNodeType.Promise;
s: 0 | 1;
// resolved value
f: SerovalNode;
i: number;
}
export interface SerovalErrorNode extends SerovalBaseNode {
t: SerovalNodeType.Error;
// constructor name
s: ErrorConstructorTag;
// message
m: string;
// other properties
p: SerovalObjectRecordNode | undefined;
i: number;
}
export interface SerovalAggregateErrorNode extends SerovalBaseNode {
t: SerovalNodeType.AggregateError;
i: number;
// message
m: string;
// other properties
p: SerovalObjectRecordNode | undefined;
}
export interface SerovalWKSymbolNode extends SerovalBaseNode {
t: SerovalNodeType.WKSymbol;
i: number;
s: Symbols;
}
export interface SerovalReferenceNode extends SerovalBaseNode {
t: SerovalNodeType.Reference;
i: number;
// id of the reference in the map
s: string;
}
export interface SerovalDataViewNode extends SerovalBaseNode {
t: SerovalNodeType.DataView;
i: number;
// reference to array buffer
f: SerovalNode;
// byte offset
b: number;
// byte length
l: number;
}
export interface SerovalBoxedNode extends SerovalBaseNode {
t: SerovalNodeType.Boxed;
i: number;
f: SerovalNode;
}
export interface SerovalPromiseConstructorNode extends SerovalBaseNode {
t: SerovalNodeType.PromiseConstructor;
i: number;
s: number;
f: SerovalNodeWithID;
}
export interface SerovalPromiseResolveNode extends SerovalBaseNode {
t: SerovalNodeType.PromiseSuccess;
i: number;
a: [resolver: SerovalNodeWithID, resolved: SerovalNode];
}
export interface SerovalPromiseRejectNode extends SerovalBaseNode {
t: SerovalNodeType.PromiseFailure;
i: number;
a: [resolver: SerovalNodeWithID, resolved: SerovalNode];
}
export interface SerovalPluginNode extends SerovalBaseNode {
t: SerovalNodeType.Plugin;
i: number;
// value
s: unknown;
// tag name
c: string;
}
/**
* Represents special values as placeholders
*/
export interface SerovalSpecialReferenceNode extends SerovalBaseNode {
t: SerovalNodeType.SpecialReference;
i: number;
s: SpecialReference;
}
export interface SerovalIteratorFactoryNode extends SerovalBaseNode {
t: SerovalNodeType.IteratorFactory;
i: number;
f: SerovalNodeWithID;
}
export interface SerovalIteratorFactoryInstanceNode extends SerovalBaseNode {
t: SerovalNodeType.IteratorFactoryInstance;
a: [instance: SerovalNodeWithID, sequence: SerovalNode];
}
export interface SerovalAsyncIteratorFactoryNode extends SerovalBaseNode {
t: SerovalNodeType.AsyncIteratorFactory;
i: number;
a: [promise: SerovalNodeWithID, symbol: SerovalNodeWithID];
}
export interface SerovalAsyncIteratorFactoryInstanceNode
extends SerovalBaseNode {
t: SerovalNodeType.AsyncIteratorFactoryInstance;
a: [instance: SerovalNodeWithID, sequence: SerovalNode];
}
export interface SerovalStreamConstructorNode extends SerovalBaseNode {
t: SerovalNodeType.StreamConstructor;
i: number;
a: SerovalNode[];
// special reference to the constructor
f: SerovalNodeWithID;
}
export interface SerovalStreamNextNode extends SerovalBaseNode {
t: SerovalNodeType.StreamNext;
i: number;
// Next value
f: SerovalNode;
}
export interface SerovalStreamThrowNode extends SerovalBaseNode {
t: SerovalNodeType.StreamThrow;
i: number;
// Throw value
f: SerovalNode;
}
export interface SerovalStreamReturnNode extends SerovalBaseNode {
t: SerovalNodeType.StreamReturn;
i: number;
// Return value
f: SerovalNode;
}
export type SerovalSyncNode =
| SerovalPrimitiveNode
| SerovalIndexedValueNode
| SerovalSemiPrimitiveNode
| SerovalSetNode
| SerovalMapNode
| SerovalArrayNode
| SerovalObjectNode
| SerovalNullConstructorNode
| SerovalPromiseNode
| SerovalErrorNode
| SerovalAggregateErrorNode
| SerovalWKSymbolNode
| SerovalReferenceNode
| SerovalArrayBufferNode
| SerovalDataViewNode
| SerovalBoxedNode
| SerovalPluginNode
| SerovalSpecialReferenceNode
| SerovalIteratorFactoryNode
| SerovalIteratorFactoryInstanceNode
| SerovalAsyncIteratorFactoryNode
| SerovalAsyncIteratorFactoryInstanceNode;
export type SerovalAsyncNode =
| SerovalPromiseNode
| SerovalPromiseConstructorNode
| SerovalPromiseResolveNode
| SerovalPromiseRejectNode
| SerovalStreamConstructorNode
| SerovalStreamNextNode
| SerovalStreamThrowNode
| SerovalStreamReturnNode;
export type SerovalNode = SerovalSyncNode | SerovalAsyncNode;
export type SerovalNodeWithID = Extract<SerovalNode, { i: number }>;

Some files were not shown because too many files have changed in this diff Show more