devalue
Version:
Gets the job done when JSON.stringify can't
515 lines (472 loc) • 19.2 kB
TypeScript
declare module 'devalue' {
export type StringValueTag = StringValueTag_1;
export type ViewTag = ViewTag_1;
export type StringifyOperations = StringifyOperations_1;
export type DefaultStringifyOperations = DefaultStringifyOperations_1;
export type StringifyOptions = StringifyOptions_1;
export type ParseOperations = ParseOperations_1;
export type DefaultParseOperations = DefaultParseOperations_1;
export type ParseOptions = ParseOptions_1;
/**
* Turn a value into the JavaScript that creates an equivalent value
*
*/
export function uneval(value: any, replacer?: (value: any, uneval: (value: any) => string) => string | void): string;
type StringValueTag_1 =
| 'URL'
| 'URLSearchParams'
| 'Temporal.Duration'
| 'Temporal.Instant'
| 'Temporal.PlainDate'
| 'Temporal.PlainTime'
| 'Temporal.PlainDateTime'
| 'Temporal.PlainMonthDay'
| 'Temporal.PlainYearMonth'
| 'Temporal.ZonedDateTime';
type ViewTag_1 =
| 'Int8Array'
| 'Uint8Array'
| 'Uint8ClampedArray'
| 'Int16Array'
| 'Uint16Array'
| 'Float16Array'
| 'Int32Array'
| 'Uint32Array'
| 'Float32Array'
| 'Float64Array'
| 'BigInt64Array'
| 'BigUint64Array'
| 'DataView';
type TypedArray =
| Int8Array
| Uint8Array
| Uint8ClampedArray
| Int16Array
| Uint16Array
| Float16Array
| Int32Array
| Uint32Array
| Float32Array
| Float64Array
| BigInt64Array
| BigUint64Array;
/**
* The introspection/extraction operations `stringify` performs on the value
* being serialized. Every dynamic operation — property reads, prototype
* method calls, iteration, type classification — goes through this
* interface, so overriding members lets you control exactly how values are
* inspected.
*
* Use cases:
* - **Side-effect-free serialization**: replace operations that can execute
* user code (getters, proxy traps, patched prototypes, `Symbol.toStringTag`
* accessors) with implementations based on captured intrinsics, internal
* slots, or property descriptors.
* - **Foreign-runtime serialization**: serialize values that live in another
* JavaScript runtime (a `node:vm` context, a WASM-hosted engine, a remote
* process) by implementing the operations over handle objects. The
* `stringify` algorithm never touches the value directly, so "value" can
* be any opaque token as long as the operations agree on what it means.
*
* All members are optional when passed to `stringify` — omitted members fall
* back to the defaults (native behavior, exported as
* `defaultStringifyOperations`).
*
* Members are named by what they do with the value:
* - `isXxx`/`hasXxx` — predicates returning booleans
* - `toXxx` — conversions whose whole result crosses into host JavaScript
* (`toPrimitive`, `toISOString`) or into a native container (`toPromise`)
* - `xxxOf` — queries returning host data *about* the value (`typeOf`,
* `tagOf`, `lengthOf`) or its constituents, which remain in value space
* (`valuesOf`, `entriesOf`)
* - `xxxInfo` — multi-field descriptors mixing host data and constituent
* values (`viewInfo`, `regExpInfo`)
* - bare verbs (`get`, `unbox`, `identify`) — accessors whose results remain
* in value space
*
* (`toStringValue` and `unbox` deliberately avoid the names `toString` and
* `valueOf`, which would shadow `Object.prototype` methods on the operations
* object.)
*/
interface StringifyOperations_1 {
/**
* Returns the key used for deduplication and cycle detection (compared
* with `Map` key semantics). Two values that represent the same logical
* object must return the same key. Default: the value itself.
*
* Override this when serializing through handles, where two distinct
* handle objects may refer to the same underlying value.
*
* Keys are compared across *every* value in the payload, including
* primitives, so an implementation that derives keys for objects must
* make sure they cannot collide with a primitive that appears in the
* same payload — returning e.g. the string `'42'` as an object's key
* would alias it to the string `'42'` elsewhere in the payload and emit
* a wrong back-reference. Prefer keys that are unforgeable, such as the
* underlying object itself, a symbol, or a wrapper object.
*/
identify(value: any): unknown;
/**
* Classifies a value. Same contract as the `typeof` operator, except
* `null` must be reported as `'null'` (not `'object'`).
*/
typeOf(value: any):
| 'undefined'
| 'null'
| 'boolean'
| 'number'
| 'bigint'
| 'string'
| 'symbol'
| 'function'
| 'object';
/**
* Extracts the host-JavaScript primitive from a value whose `typeOf` is
* `'null'`, `'boolean'`, `'number'`, `'bigint'` or `'string'`.
* Default: the value itself (it already is the primitive).
*/
toPrimitive(value: any): undefined | null | boolean | number | bigint | string;
/**
* Returns the brand of an object value — the strings produced by
* `Object.prototype.toString` without the wrapping (`'Date'`, `'Array'`,
* `'Map'`, `'Object'`, `'Temporal.Instant'`, …). This decides which
* serialization strategy is used, so hardened implementations should use
* engine-level brand checks rather than (spoofable, getter-invoking)
* `Symbol.toStringTag` lookups.
*/
tagOf(value: any): string;
/** Returns true if the object value should be treated as a thenable. */
isThenable(value: any): boolean;
/**
* Converts a thenable into a native promise, whose settled value is then
* serialized. The returned promise may reject, in which case
* `stringifyAsync` rejects. Only called from `stringifyAsync`, for values
* where `isThenable` returned true.
*/
toPromise(thenable: any): Promise<any>;
/**
* Extracts the inner value of a boxed primitive (`Number`, `String`,
* `Boolean`, `BigInt` objects). Equivalent to `boxed.valueOf()`. The
* result is serialized recursively, so it may be a foreign value/handle.
*/
unbox(boxed: any): any;
/**
* Returns the ISO string for a `Date` value, or `''` for an invalid
* date. Equivalent to `date.toISOString()`.
*/
toISOString(date: any): string;
/**
* Returns the string form of a `URL`, `URLSearchParams` or `Temporal.*`
* value. Equivalent to `value.toString()`.
*/
toStringValue(value: any): string;
/** Returns the source and flags of a `RegExp` value. */
regExpInfo(regexp: any): { source: string; flags: string };
/**
* Returns an iterable over the elements of a `Set` value. The iterable
* is consumed on the host; elements may be foreign values/handles.
*/
valuesOf(set: any): Iterable<any>;
/**
* Returns an iterable over the `[key, value]` entries of a `Map` value.
* The iterable is consumed on the host; keys/values may be foreign
* values/handles.
*/
entriesOf(map: any): Iterable<[any, any]>;
/**
* Returns the view metadata of a typed array or `DataView` value.
* `length` is only meaningful for typed arrays. `buffer` is serialized
* recursively, so it may be a foreign value/handle.
*/
viewInfo(view: any): {
buffer: any;
byteOffset: number;
byteLength: number;
length?: number;
bufferByteLength: number;
};
/**
* Returns a host `ArrayBuffer` with the bytes of an `ArrayBuffer` value.
* Default: the value itself. Foreign-runtime implementations should copy
* the bytes into a host buffer.
*/
toArrayBuffer(buffer: any): ArrayBuffer;
/** Returns the length of an `Array` value. */
lengthOf(array: any): number;
/**
* Returns true if a value has an own property at `key`. Same contract as
* `Object.hasOwn(value, key)`.
*/
hasOwn(value: any, key: string | number): boolean;
/**
* Returns the populated indices of a (sparse) `Array` value as strings,
* in ascending order.
*
* Implementations that already have the value's own enumerable string
* keys — as a foreign-runtime implementation typically does — should pass
* them through the exported `filterArrayIndices` helper rather than
* reimplementing the filtering, which encodes the sparse-array heuristic.
*
* Equivalent to `Object.keys(array)` filtered to
* valid array indices.
*/
indicesOf(array: any): string[];
/**
* Classifies a plain-object candidate:
* - `{ kind: 'plain' | 'null-proto', keys }` — a serializable POJO and
* its own enumerable string keys
* - `{ kind: 'not-plain' }` — a non-POJO (stringify throws)
* - `{ kind: 'symbol-keys' }` — a POJO with enumerable symbol keys
* (stringify throws)
*/
shapeOf(
value: any
):
| { kind: 'plain' | 'null-proto'; keys: string[] }
| { kind: 'not-plain' }
| { kind: 'symbol-keys' };
/**
* Reads a property from an `Array` or plain-object value. Equivalent to
* `value[key]`. Hardened implementations can read through property
* descriptors to control what happens for accessor properties.
*/
get(value: any, key: string | number): any;
}
/** The native JavaScript implementation exported as `defaultStringifyOperations`. */
interface DefaultStringifyOperations_1 extends StringifyOperations_1 {
identify(value: any): any;
toPrimitive(
value: undefined | null | boolean | number | bigint | string
): undefined | null | boolean | number | bigint | string;
toISOString(date: Date): string;
regExpInfo(regexp: RegExp): { source: string; flags: string };
valuesOf(set: Set<any>): Set<any>;
entriesOf(map: Map<any, any>): Map<any, any>;
viewInfo(view: any): {
buffer: ArrayBufferLike;
byteOffset: number;
byteLength: number;
length?: number;
bufferByteLength: number;
};
toArrayBuffer(buffer: ArrayBuffer): ArrayBuffer;
lengthOf(array: any[]): number;
indicesOf(array: any[]): string[];
}
/** Options for `stringify` and `stringifyAsync`. */
interface StringifyOptions_1 {
/**
* Overrides for the introspection/extraction operations used while
* serializing. Omitted members fall back to `defaultStringifyOperations`.
*/
operations?: Partial<StringifyOperations_1>;
}
/**
* The construction operations `parse` and `unflatten` perform while reviving
* a value. Every value the algorithm creates — primitives, built-in
* instances, containers — and every mutation it performs to populate those
* containers goes through this interface, so overriding members lets you
* control exactly what gets built.
*
* Use cases:
* - **Cross-realm revival**: construct values from the intrinsics of a
* different realm (e.g. a `node:vm` context) so that the result passes
* `instanceof` checks inside that realm.
* - **Foreign-runtime revival**: build values inside another JavaScript
* runtime (a WASM-hosted engine, a remote process) by implementing the
* operations over handle objects. The algorithm never inspects the values
* it creates — it only passes them back into other operations — so
* "value" can be any opaque token.
*
* The naming follows the same scheme as `StringifyOperations`, with the
* host/value-space boundary running the other way:
*
* - `fromXxx` — conversions whose input is entirely host data and whose
* result crosses into value space; each is the inverse of the
* corresponding `toXxx` (`fromPrimitive` / `toPrimitive`,
* `fromISOString` / `toISOString`, `fromStringValue` / `toStringValue`,
* `fromArrayBuffer` / `toArrayBuffer`).
* - `fromXxxInfo` — construction from a multi-field descriptor, the inverse
* of the corresponding `xxxInfo` (`fromRegExpInfo` / `regExpInfo`,
* `fromViewInfo` / `viewInfo`).
* - `createXxx` — empty value-space containers, populated afterwards by the
* mutators. That ordering is what makes cyclic values possible: the empty
* container is cached before its contents are revived.
* - bare verbs — value-space operations whose operands and results stay in
* value space (`box` inverts `unbox`, `set` inverts `get`, `addValue`
* inverts `valuesOf`, `addEntry` inverts `entriesOf`).
*
* All members are optional when passed to `parse`/`unflatten` — omitted
* members fall back to the defaults (native behavior, exported as
* `defaultParseOperations`).
*/
interface ParseOperations_1 {
/**
* Wraps a host primitive (`string`, `number`, `boolean`, `bigint`,
* `null`, `undefined`, and the special values `NaN`, `±Infinity`, `-0`)
* into the representation the other operations expect. The inverse of
* `toPrimitive`. Default: the value itself.
*/
fromPrimitive(
primitive: string | number | boolean | bigint | null | undefined
): any;
/**
* Creates a `Date` from an ISO string. The inverse of `toISOString`.
* An empty string represents an invalid date (as produced for
* `new Date(NaN)`).
*/
fromISOString(iso: string): any;
/**
* Creates a `URL`, `URLSearchParams` or `Temporal.*` value from its
* string form — the same tags `toStringValue` serializes, and its
* inverse. `tag` distinguishes them (e.g. `'URL'`,
* `'Temporal.Instant'`).
*/
fromStringValue(tag: StringValueTag_1, text: string): any;
/**
* Creates an `ArrayBuffer` from a host `ArrayBuffer` holding the decoded
* bytes. The inverse of `toArrayBuffer`. Default: the buffer itself.
* Foreign-runtime implementations should copy the bytes into the target
* runtime.
*/
fromArrayBuffer(buffer: ArrayBuffer): any;
/**
* Creates a `RegExp` from its source and flags. The inverse of
* `regExpInfo`. `flags` is `undefined` when the pattern had no flags.
*/
fromRegExpInfo(source: string, flags: string | undefined): any;
/**
* Creates a typed array or `DataView` over an already-revived buffer.
* The inverse of `viewInfo`. `tag` is the constructor name (e.g.
* `'Uint8Array'`, `'DataView'`). `byteOffset` and `length` are
* `undefined` when the view spans the whole buffer; otherwise `length`
* is the element count for typed arrays and the byte length for
* `DataView`, matching the constructor signatures.
*/
fromViewInfo(
tag: ViewTag_1,
buffer: any,
byteOffset: number | undefined,
length: number | undefined
): any;
/**
* Creates a boxed primitive object (`Number`, `String`, `Boolean`,
* `BigInt` wrapper) around an already-revived inner primitive. The
* inverse of `unbox`. Equivalent to `Object(value)`.
*/
box(value: any): any;
/**
* Creates an array of the given length, to be populated with `set`.
* The length is bounded by the size of the input, so it is safe to
* allocate eagerly. Indices that are never set must remain holes.
*/
createArray(length: number): any;
/**
* Creates a sparse array of the given length, to be populated with
* `set`. Unlike `createArray`, the length comes from the input rather
* than being bounded by it, so implementations must not allocate
* storage proportional to it.
*/
createSparseArray(length: number): any;
/** Creates an empty object, to be populated with `set`. */
createObject(): any;
/**
* Creates an empty null-prototype object, to be populated with `set`.
* Equivalent to `Object.create(null)`.
*/
createNullPrototypeObject(): any;
/** Creates an empty `Set`, to be populated with `addValue`. */
createSet(): any;
/** Creates an empty `Map`, to be populated with `addEntry`. */
createMap(): any;
/**
* Sets an element or property on a value created by `createArray`,
* `createSparseArray`, `createObject` or `createNullPrototypeObject`.
* The inverse of `get`, which likewise serves both arrays and objects.
*/
set(target: any, key: string | number, value: any): void;
/** Adds a value to a `Set` created by `createSet`. The inverse of `valuesOf`. */
addValue(set: any, value: any): void;
/** Adds an entry to a `Map` created by `createMap`. The inverse of `entriesOf`. */
addEntry(map: any, key: any, value: any): void;
}
/** The native JavaScript implementation exported as `defaultParseOperations`. */
interface DefaultParseOperations_1 extends ParseOperations_1 {
fromPrimitive(
primitive: string | number | boolean | bigint | null | undefined
): string | number | boolean | bigint | null | undefined;
fromISOString(iso: string): Date;
fromStringValue(tag: StringValueTag_1, text: string): URL | URLSearchParams | object;
fromArrayBuffer(buffer: ArrayBuffer): ArrayBuffer;
fromRegExpInfo(source: string, flags: string | undefined): RegExp;
fromViewInfo(
tag: ViewTag_1,
buffer: ArrayBufferLike,
byteOffset: number | undefined,
length: number | undefined
): TypedArray | DataView;
box(value: any): object;
createArray(length: number): any[];
createSparseArray(length: number): any[];
createObject(): Record<string, any>;
createNullPrototypeObject(): Record<string, any>;
createSet(): Set<any>;
createMap(): Map<any, any>;
addValue(set: Set<any>, value: any): void;
addEntry(map: Map<any, any>, key: any, value: any): void;
}
/** Options for `parse` and `unflatten`. */
interface ParseOptions_1 {
/**
* Overrides for the construction operations used while reviving.
* Omitted members fall back to `defaultParseOperations`.
*/
operations?: Partial<ParseOperations_1>;
}
/**
* Revive a value serialized with `devalue.stringify`
*
*/
export function parse(serialized: string, revivers?: Record<string, (value: any) => any>, options?: ParseOptions_1): any;
/**
* Revive a value flattened with `devalue.stringify`
*
*/
export function unflatten(parsed: number | any[], revivers?: Record<string, (value: any) => any>, options?: ParseOptions_1): any;
/**
* Turn a value into a JSON string that can be parsed with `devalue.parse`
*
*/
export function stringify(value: any, reducers?: Record<string, (value: any) => any>, options?: StringifyOptions_1): string;
/**
* Turn a value into a JSON string that can be parsed with `devalue.parse`
*
*/
export function stringifyAsync(value: any, reducers?: Record<string, (value: any) => any>, options?: StringifyOptions_1): Promise<string>;
export const defaultStringifyOperations: Readonly<DefaultStringifyOperations_1>;
export const defaultParseOperations: Readonly<DefaultParseOperations_1>;
/**
* Given the own enumerable string keys of an array-like value, in property
* order, returns the leading run of them that are valid array indices.
*
* This is the filtering half of the `indicesOf` stringify operation,
* exposed so that custom operations — which typically already have the keys
* in hand, e.g. from a foreign runtime — don't have to reimplement it.
*
* Does not modify `keys`.
*
* */
export function filterArrayIndices(keys: readonly string[]): string[];
export class DevalueError extends Error {
/**
* @param value - The value that failed to be serialized
* @param root - The root value being serialized
*/
constructor(message: string, keys: string[], value?: any, root?: any);
path: string;
value: any;
root: any;
}
export {};
}
//# sourceMappingURL=index.d.ts.map