Website Structure
This commit is contained in:
parent
62812f2090
commit
71f0676a62
22365 changed files with 4265753 additions and 791 deletions
119
Frontend-Learner/node_modules/seroval/src/core/Serializer.ts
generated
vendored
Normal file
119
Frontend-Learner/node_modules/seroval/src/core/Serializer.ts
generated
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
514
Frontend-Learner/node_modules/seroval/src/core/base-primitives.ts
generated
vendored
Normal file
514
Frontend-Learner/node_modules/seroval/src/core/base-primitives.ts
generated
vendored
Normal 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,
|
||||
);
|
||||
}
|
||||
23
Frontend-Learner/node_modules/seroval/src/core/compat.ts
generated
vendored
Normal file
23
Frontend-Learner/node_modules/seroval/src/core/compat.ts
generated
vendored
Normal 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;
|
||||
201
Frontend-Learner/node_modules/seroval/src/core/constants.ts
generated
vendored
Normal file
201
Frontend-Learner/node_modules/seroval/src/core/constants.ts
generated
vendored
Normal 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,
|
||||
};
|
||||
270
Frontend-Learner/node_modules/seroval/src/core/constructors.ts
generated
vendored
Normal file
270
Frontend-Learner/node_modules/seroval/src/core/constructors.ts
generated
vendored
Normal 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();
|
||||
638
Frontend-Learner/node_modules/seroval/src/core/context/async-parser.ts
generated
vendored
Normal file
638
Frontend-Learner/node_modules/seroval/src/core/context/async-parser.ts
generated
vendored
Normal 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);
|
||||
}
|
||||
}
|
||||
810
Frontend-Learner/node_modules/seroval/src/core/context/deserializer.ts
generated
vendored
Normal file
810
Frontend-Learner/node_modules/seroval/src/core/context/deserializer.ts
generated
vendored
Normal 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);
|
||||
}
|
||||
}
|
||||
335
Frontend-Learner/node_modules/seroval/src/core/context/parser.ts
generated
vendored
Normal file
335
Frontend-Learner/node_modules/seroval/src/core/context/parser.ts
generated
vendored
Normal 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,
|
||||
);
|
||||
}
|
||||
1406
Frontend-Learner/node_modules/seroval/src/core/context/serializer.ts
generated
vendored
Normal file
1406
Frontend-Learner/node_modules/seroval/src/core/context/serializer.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
907
Frontend-Learner/node_modules/seroval/src/core/context/sync-parser.ts
generated
vendored
Normal file
907
Frontend-Learner/node_modules/seroval/src/core/context/sync-parser.ts
generated
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
188
Frontend-Learner/node_modules/seroval/src/core/cross/index.ts
generated
vendored
Normal file
188
Frontend-Learner/node_modules/seroval/src/core/cross/index.ts
generated
vendored
Normal 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;
|
||||
}
|
||||
196
Frontend-Learner/node_modules/seroval/src/core/errors.ts
generated
vendored
Normal file
196
Frontend-Learner/node_modules/seroval/src/core/errors.ts
generated
vendored
Normal 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',
|
||||
);
|
||||
}
|
||||
}
|
||||
32
Frontend-Learner/node_modules/seroval/src/core/function-string.ts
generated
vendored
Normal file
32
Frontend-Learner/node_modules/seroval/src/core/function-string.ts
generated
vendored
Normal 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
17
Frontend-Learner/node_modules/seroval/src/core/keys.ts
generated
vendored
Normal 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,
|
||||
)}"]=[]`;
|
||||
}
|
||||
43
Frontend-Learner/node_modules/seroval/src/core/literals.ts
generated
vendored
Normal file
43
Frontend-Learner/node_modules/seroval/src/core/literals.ts
generated
vendored
Normal 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
40
Frontend-Learner/node_modules/seroval/src/core/node.ts
generated
vendored
Normal 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;
|
||||
}
|
||||
9
Frontend-Learner/node_modules/seroval/src/core/opaque-reference.ts
generated
vendored
Normal file
9
Frontend-Learner/node_modules/seroval/src/core/opaque-reference.ts
generated
vendored
Normal 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,
|
||||
) {}
|
||||
}
|
||||
100
Frontend-Learner/node_modules/seroval/src/core/plugin.ts
generated
vendored
Normal file
100
Frontend-Learner/node_modules/seroval/src/core/plugin.ts
generated
vendored
Normal 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;
|
||||
}
|
||||
66
Frontend-Learner/node_modules/seroval/src/core/reference.ts
generated
vendored
Normal file
66
Frontend-Learner/node_modules/seroval/src/core/reference.ts
generated
vendored
Normal 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,
|
||||
});
|
||||
}
|
||||
42
Frontend-Learner/node_modules/seroval/src/core/special-reference.ts
generated
vendored
Normal file
42
Frontend-Learner/node_modules/seroval/src/core/special-reference.ts
generated
vendored
Normal 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,
|
||||
};
|
||||
71
Frontend-Learner/node_modules/seroval/src/core/stream.ts
generated
vendored
Normal file
71
Frontend-Learner/node_modules/seroval/src/core/stream.ts
generated
vendored
Normal 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>;
|
||||
}
|
||||
86
Frontend-Learner/node_modules/seroval/src/core/string.ts
generated
vendored
Normal file
86
Frontend-Learner/node_modules/seroval/src/core/string.ts
generated
vendored
Normal 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,
|
||||
);
|
||||
}
|
||||
18
Frontend-Learner/node_modules/seroval/src/core/symbols.ts
generated
vendored
Normal file
18
Frontend-Learner/node_modules/seroval/src/core/symbols.ts
generated
vendored
Normal 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;
|
||||
134
Frontend-Learner/node_modules/seroval/src/core/tree/index.ts
generated
vendored
Normal file
134
Frontend-Learner/node_modules/seroval/src/core/tree/index.ts
generated
vendored
Normal 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
366
Frontend-Learner/node_modules/seroval/src/core/types.ts
generated
vendored
Normal 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 }>;
|
||||
73
Frontend-Learner/node_modules/seroval/src/core/utils/error.ts
generated
vendored
Normal file
73
Frontend-Learner/node_modules/seroval/src/core/utils/error.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import { Feature } from '../compat';
|
||||
import { ERROR_CONSTRUCTOR_STRING, ErrorConstructorTag } from '../constants';
|
||||
|
||||
type ErrorValue =
|
||||
| Error
|
||||
| AggregateError
|
||||
| EvalError
|
||||
| RangeError
|
||||
| ReferenceError
|
||||
| TypeError
|
||||
| SyntaxError
|
||||
| URIError;
|
||||
|
||||
export function getErrorConstructor(error: ErrorValue): ErrorConstructorTag {
|
||||
if (error instanceof EvalError) {
|
||||
return ErrorConstructorTag.EvalError;
|
||||
}
|
||||
if (error instanceof RangeError) {
|
||||
return ErrorConstructorTag.RangeError;
|
||||
}
|
||||
if (error instanceof ReferenceError) {
|
||||
return ErrorConstructorTag.ReferenceError;
|
||||
}
|
||||
if (error instanceof SyntaxError) {
|
||||
return ErrorConstructorTag.SyntaxError;
|
||||
}
|
||||
if (error instanceof TypeError) {
|
||||
return ErrorConstructorTag.TypeError;
|
||||
}
|
||||
if (error instanceof URIError) {
|
||||
return ErrorConstructorTag.URIError;
|
||||
}
|
||||
return ErrorConstructorTag.Error;
|
||||
}
|
||||
|
||||
function getInitialErrorOptions(
|
||||
error: Error,
|
||||
): Record<string, unknown> | undefined {
|
||||
const construct = ERROR_CONSTRUCTOR_STRING[getErrorConstructor(error)];
|
||||
// Name has been modified
|
||||
if (error.name !== construct) {
|
||||
return { name: error.name };
|
||||
}
|
||||
if (error.constructor.name !== construct) {
|
||||
// Otherwise, name is overriden because
|
||||
// the Error class is extended
|
||||
return { name: error.constructor.name };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
export function getErrorOptions(
|
||||
error: Error,
|
||||
features: number,
|
||||
): Record<string, unknown> | undefined {
|
||||
let options = getInitialErrorOptions(error);
|
||||
const names = Object.getOwnPropertyNames(error);
|
||||
for (let i = 0, len = names.length, name: string; i < len; i++) {
|
||||
name = names[i];
|
||||
if (name !== 'name' && name !== 'message') {
|
||||
if (name === 'stack') {
|
||||
if (features & Feature.ErrorPrototypeStack) {
|
||||
options = options || {};
|
||||
options[name] = error[name as keyof Error];
|
||||
}
|
||||
} else {
|
||||
options = options || {};
|
||||
options[name] = error[name as keyof Error];
|
||||
}
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
18
Frontend-Learner/node_modules/seroval/src/core/utils/get-identifier.ts
generated
vendored
Normal file
18
Frontend-Learner/node_modules/seroval/src/core/utils/get-identifier.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Written by https://github.com/DylanPiercey and is distributed under the MIT license.
|
||||
const REF_START_CHARS = /* @__PURE__ */ 'hjkmoquxzABCDEFGHIJKLNPQRTUVWXYZ$_'; // Avoids chars that could evaluate to a reserved word.
|
||||
const REF_START_CHARS_LEN = /* @__PURE__ */ REF_START_CHARS.length;
|
||||
const REF_CHARS =
|
||||
/* @__PURE__ */ 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$_';
|
||||
const REF_CHARS_LEN = /* @__PURE__ */ REF_CHARS.length;
|
||||
|
||||
export default function getIdentifier(index: number): string {
|
||||
let mod = index % REF_START_CHARS_LEN;
|
||||
let ref = REF_START_CHARS[mod];
|
||||
index = (index - mod) / REF_START_CHARS_LEN;
|
||||
while (index > 0) {
|
||||
mod = index % REF_CHARS_LEN;
|
||||
ref += REF_CHARS[mod];
|
||||
index = (index - mod) / REF_CHARS_LEN;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
14
Frontend-Learner/node_modules/seroval/src/core/utils/get-object-flag.ts
generated
vendored
Normal file
14
Frontend-Learner/node_modules/seroval/src/core/utils/get-object-flag.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { SerovalObjectFlags } from '../constants';
|
||||
|
||||
export function getObjectFlag(obj: unknown): SerovalObjectFlags {
|
||||
if (Object.isFrozen(obj)) {
|
||||
return SerovalObjectFlags.Frozen;
|
||||
}
|
||||
if (Object.isSealed(obj)) {
|
||||
return SerovalObjectFlags.Sealed;
|
||||
}
|
||||
if (Object.isExtensible(obj)) {
|
||||
return SerovalObjectFlags.None;
|
||||
}
|
||||
return SerovalObjectFlags.NonExtensible;
|
||||
}
|
||||
12
Frontend-Learner/node_modules/seroval/src/core/utils/is-valid-identifier.ts
generated
vendored
Normal file
12
Frontend-Learner/node_modules/seroval/src/core/utils/is-valid-identifier.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
const IDENTIFIER_CHECK = /^[$A-Z_][0-9A-Z_$]*$/i;
|
||||
|
||||
export function isValidIdentifier(name: string): boolean {
|
||||
const char = name[0];
|
||||
return (
|
||||
(char === '$' ||
|
||||
char === '_' ||
|
||||
(char >= 'A' && char <= 'Z') ||
|
||||
(char >= 'a' && char <= 'z')) &&
|
||||
IDENTIFIER_CHECK.test(name)
|
||||
);
|
||||
}
|
||||
44
Frontend-Learner/node_modules/seroval/src/core/utils/iterator-to-sequence.ts
generated
vendored
Normal file
44
Frontend-Learner/node_modules/seroval/src/core/utils/iterator-to-sequence.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import { ITERATOR_CONSTRUCTOR } from '../constructors';
|
||||
import { SYM_ITERATOR } from '../symbols';
|
||||
|
||||
export interface Sequence {
|
||||
v: unknown[];
|
||||
t: number;
|
||||
d: number;
|
||||
}
|
||||
|
||||
export function iteratorToSequence<T>(source: Iterable<T>): Sequence {
|
||||
const values: unknown[] = [];
|
||||
let throwsAt = -1;
|
||||
let doneAt = -1;
|
||||
|
||||
const iterator = source[SYM_ITERATOR]();
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
const value = iterator.next();
|
||||
values.push(value.value);
|
||||
if (value.done) {
|
||||
doneAt = values.length - 1;
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
throwsAt = values.length;
|
||||
values.push(error);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
v: values,
|
||||
t: throwsAt,
|
||||
d: doneAt,
|
||||
};
|
||||
}
|
||||
|
||||
const createIterator = ITERATOR_CONSTRUCTOR(SYM_ITERATOR);
|
||||
|
||||
export function sequenceToIterator<T>(
|
||||
sequence: Sequence,
|
||||
): () => IterableIterator<T> {
|
||||
return createIterator(sequence) as unknown as () => IterableIterator<T>;
|
||||
}
|
||||
9
Frontend-Learner/node_modules/seroval/src/core/utils/promise-to-result.ts
generated
vendored
Normal file
9
Frontend-Learner/node_modules/seroval/src/core/utils/promise-to-result.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
export default async function promiseToResult(
|
||||
current: Promise<unknown>,
|
||||
): Promise<[0 | 1, unknown]> {
|
||||
try {
|
||||
return [1, await current];
|
||||
} catch (e) {
|
||||
return [0, e];
|
||||
}
|
||||
}
|
||||
56
Frontend-Learner/node_modules/seroval/src/core/utils/typed-array.ts
generated
vendored
Normal file
56
Frontend-Learner/node_modules/seroval/src/core/utils/typed-array.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import { SerovalUnknownTypedArrayError } from '../errors';
|
||||
|
||||
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 function getTypedArrayConstructor(name: string): TypedArrayConstructor {
|
||||
switch (name) {
|
||||
case 'Int8Array':
|
||||
return Int8Array;
|
||||
case 'Int16Array':
|
||||
return Int16Array;
|
||||
case 'Int32Array':
|
||||
return Int32Array;
|
||||
case 'Uint8Array':
|
||||
return Uint8Array;
|
||||
case 'Uint16Array':
|
||||
return Uint16Array;
|
||||
case 'Uint32Array':
|
||||
return Uint32Array;
|
||||
case 'Uint8ClampedArray':
|
||||
return Uint8ClampedArray;
|
||||
case 'Float32Array':
|
||||
return Float32Array;
|
||||
case 'Float64Array':
|
||||
return Float64Array;
|
||||
case 'BigInt64Array':
|
||||
return BigInt64Array;
|
||||
case 'BigUint64Array':
|
||||
return BigUint64Array;
|
||||
default:
|
||||
throw new SerovalUnknownTypedArrayError(name);
|
||||
}
|
||||
}
|
||||
36
Frontend-Learner/node_modules/seroval/src/index.ts
generated
vendored
Normal file
36
Frontend-Learner/node_modules/seroval/src/index.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
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';
|
||||
Loading…
Add table
Add a link
Reference in a new issue