// src/compat.ts
var Feature = /* @__PURE__ */ ((Feature2) => {
  Feature2[Feature2["AggregateError"] = 1] = "AggregateError";
  Feature2[Feature2["ArrayPrototypeValues"] = 2] = "ArrayPrototypeValues";
  Feature2[Feature2["ArrowFunction"] = 4] = "ArrowFunction";
  Feature2[Feature2["BigInt"] = 8] = "BigInt";
  Feature2[Feature2["ErrorPrototypeStack"] = 16] = "ErrorPrototypeStack";
  Feature2[Feature2["Map"] = 32] = "Map";
  Feature2[Feature2["MethodShorthand"] = 64] = "MethodShorthand";
  Feature2[Feature2["ObjectAssign"] = 128] = "ObjectAssign";
  Feature2[Feature2["Promise"] = 256] = "Promise";
  Feature2[Feature2["Set"] = 512] = "Set";
  Feature2[Feature2["Symbol"] = 1024] = "Symbol";
  Feature2[Feature2["TypedArray"] = 2048] = "TypedArray";
  Feature2[Feature2["BigIntTypedArray"] = 4096] = "BigIntTypedArray";
  return Feature2;
})(Feature || {});
var ALL_ENABLED = 8191;

// src/get-identifier.ts
var REF_START_CHARS = "hjkmoquxzABCDEFGHIJKLNPQRTUVWXYZ$_";
var REF_START_CHARS_LEN = REF_START_CHARS.length;
var REF_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$_";
var REF_CHARS_LEN = REF_CHARS.length;
function getIdentifier(index) {
  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;
}

// src/context.ts
var DEFAULT_OPTIONS = {
  disabledFeatures: 0
};
function createParserContext(options = {}) {
  const result = Object.assign({}, DEFAULT_OPTIONS, options || {});
  return {
    markedRefs: /* @__PURE__ */ new Set(),
    refs: /* @__PURE__ */ new Map(),
    features: ALL_ENABLED ^ result.disabledFeatures
  };
}
function createSerializationContext(options) {
  return {
    stack: [],
    vars: [],
    assignments: [],
    validRefs: [],
    refSize: 0,
    features: options.features,
    markedRefs: new Set(options.markedRefs),
    valueMap: /* @__PURE__ */ new Map()
  };
}
function markRef(ctx, current) {
  ctx.markedRefs.add(current);
}
function getRefParam(ctx, index) {
  let actualIndex = ctx.validRefs[index];
  if (actualIndex == null) {
    actualIndex = ctx.refSize++;
    ctx.validRefs[index] = actualIndex;
  }
  let identifier = ctx.vars[actualIndex];
  if (identifier == null) {
    identifier = getIdentifier(actualIndex);
    ctx.vars[actualIndex] = identifier;
  }
  return identifier;
}
function getRootID(ctx, current) {
  const ref = ctx.refs.get(current);
  if (ref == null) {
    return ctx.refs.size;
  }
  return ref;
}
function createRef(ctx, current) {
  const ref = ctx.refs.get(current);
  if (ref == null) {
    const id = ctx.refs.size;
    ctx.refs.set(current, id);
    return id;
  }
  markRef(ctx, ref);
  return ref;
}

// src/assert.ts
function assert(cond, error) {
  if (!cond) {
    throw new Error(error);
  }
}

// src/quote.ts
function quote(str) {
  let result = "";
  let lastPos = 0;
  for (let i = 0, len = str.length; i < len; i++) {
    let replacement;
    switch (str[i]) {
      case '"':
        replacement = '\\"';
        break;
      case "\\":
        replacement = "\\\\";
        break;
      case "<":
        replacement = "\\x3C";
        break;
      case "\n":
        replacement = "\\n";
        break;
      case "\r":
        replacement = "\\r";
        break;
      case "\u2028":
        replacement = "\\u2028";
        break;
      case "\u2029":
        replacement = "\\u2029";
        break;
      default:
        continue;
    }
    result += str.slice(lastPos, i) + replacement;
    lastPos = i + 1;
  }
  if (lastPos === 0) {
    result = str;
  } else {
    result += str.slice(lastPos);
  }
  return result;
}
function invQuote(str) {
  return str.replace(/\\"/g, '"').replace(/\\\\/g, "\\").replace(/\\x3C/g, "<").replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\u2028/g, "\u2028").replace(/\\u2029/g, "\u2029");
}

// src/tree/symbols.ts
var SYMBOL_STRING = {
  [0 /* AsyncIterator */]: "Symbol.asyncIterator",
  [1 /* HasInstance */]: "Symbol.hasInstance",
  [2 /* IsConcatSpreadable */]: "Symbol.isConcatSpreadable",
  [3 /* Iterator */]: "Symbol.iterator",
  [4 /* Match */]: "Symbol.match",
  [5 /* MatchAll */]: "Symbol.matchAll",
  [6 /* Replace */]: "Symbol.replace",
  [7 /* Search */]: "Symbol.search",
  [8 /* Species */]: "Symbol.species",
  [9 /* Split */]: "Symbol.split",
  [10 /* ToPrimitive */]: "Symbol.toPrimitive",
  [11 /* ToStringTag */]: "Symbol.toStringTag",
  [12 /* Unscopables */]: "Symbol.unscopables"
};
var INV_SYMBOL_REF = {
  [Symbol.asyncIterator]: 0 /* AsyncIterator */,
  [Symbol.hasInstance]: 1 /* HasInstance */,
  [Symbol.isConcatSpreadable]: 2 /* IsConcatSpreadable */,
  [Symbol.iterator]: 3 /* Iterator */,
  [Symbol.match]: 4 /* Match */,
  [Symbol.matchAll]: 5 /* MatchAll */,
  [Symbol.replace]: 6 /* Replace */,
  [Symbol.search]: 7 /* Search */,
  [Symbol.species]: 8 /* Species */,
  [Symbol.split]: 9 /* Split */,
  [Symbol.toPrimitive]: 10 /* ToPrimitive */,
  [Symbol.toStringTag]: 11 /* ToStringTag */,
  [Symbol.unscopables]: 12 /* Unscopables */
};
var SYMBOL_REF = {
  [0 /* AsyncIterator */]: Symbol.asyncIterator,
  [1 /* HasInstance */]: Symbol.hasInstance,
  [2 /* IsConcatSpreadable */]: Symbol.isConcatSpreadable,
  [3 /* Iterator */]: Symbol.iterator,
  [4 /* Match */]: Symbol.match,
  [5 /* MatchAll */]: Symbol.matchAll,
  [6 /* Replace */]: Symbol.replace,
  [7 /* Search */]: Symbol.search,
  [8 /* Species */]: Symbol.species,
  [9 /* Split */]: Symbol.split,
  [10 /* ToPrimitive */]: Symbol.toPrimitive,
  [11 /* ToStringTag */]: Symbol.toStringTag,
  [12 /* Unscopables */]: Symbol.unscopables
};

// src/tree/primitives.ts
var TRUE_NODE = {
  t: 2 /* Boolean */,
  i: void 0,
  s: true,
  l: void 0,
  c: void 0,
  m: void 0,
  d: void 0,
  a: void 0,
  f: void 0
};
var FALSE_NODE = {
  t: 2 /* Boolean */,
  i: void 0,
  s: false,
  l: void 0,
  c: void 0,
  m: void 0,
  d: void 0,
  a: void 0,
  f: void 0
};
var UNDEFINED_NODE = {
  t: 4 /* Undefined */,
  i: void 0,
  s: void 0,
  l: void 0,
  c: void 0,
  m: void 0,
  d: void 0,
  a: void 0,
  f: void 0
};
var NULL_NODE = {
  t: 3 /* Null */,
  i: void 0,
  s: void 0,
  l: void 0,
  c: void 0,
  m: void 0,
  d: void 0,
  a: void 0,
  f: void 0
};
var NEG_ZERO_NODE = {
  t: 5 /* NegativeZero */,
  i: void 0,
  s: void 0,
  l: void 0,
  c: void 0,
  m: void 0,
  d: void 0,
  a: void 0,
  f: void 0
};
var INFINITY_NODE = {
  t: 6 /* Infinity */,
  i: void 0,
  s: void 0,
  l: void 0,
  c: void 0,
  m: void 0,
  d: void 0,
  a: void 0,
  f: void 0
};
var NEG_INFINITY_NODE = {
  t: 7 /* NegativeInfinity */,
  i: void 0,
  s: void 0,
  l: void 0,
  c: void 0,
  m: void 0,
  d: void 0,
  a: void 0,
  f: void 0
};
var NAN_NODE = {
  t: 8 /* NaN */,
  i: void 0,
  s: void 0,
  l: void 0,
  c: void 0,
  m: void 0,
  d: void 0,
  a: void 0,
  f: void 0
};
function createNumberNode(value) {
  return {
    t: 0 /* Number */,
    i: void 0,
    s: value,
    l: void 0,
    c: void 0,
    m: void 0,
    d: void 0,
    a: void 0,
    f: void 0
  };
}
function createStringNode(value) {
  return {
    t: 1 /* String */,
    i: void 0,
    s: quote(value),
    l: void 0,
    c: void 0,
    m: void 0,
    d: void 0,
    a: void 0,
    f: void 0
  };
}
function createBigIntNode(ctx, current) {
  assert(ctx.features & 8 /* BigInt */, 'Unsupported type "BigInt"');
  return {
    t: 9 /* BigInt */,
    i: void 0,
    s: "" + current,
    l: void 0,
    c: void 0,
    m: void 0,
    d: void 0,
    a: void 0,
    f: void 0
  };
}
function createReferenceNode(id) {
  return {
    t: 10 /* Reference */,
    i: id,
    s: void 0,
    l: void 0,
    c: void 0,
    m: void 0,
    d: void 0,
    a: void 0,
    f: void 0
  };
}
function createDateNode(id, current) {
  return {
    t: 11 /* Date */,
    i: id,
    s: current.toISOString(),
    l: void 0,
    c: void 0,
    m: void 0,
    d: void 0,
    f: void 0,
    a: void 0
  };
}
function createRegExpNode(id, current) {
  return {
    t: 12 /* RegExp */,
    i: id,
    s: void 0,
    l: void 0,
    c: current.source,
    m: current.flags,
    d: void 0,
    a: void 0,
    f: void 0
  };
}
function createTypedArrayNode(ctx, id, current) {
  const constructor = current.constructor.name;
  assert(ctx.features & 2048 /* TypedArray */, `Unsupported value type "${constructor}"`);
  const len = current.length;
  const values = new Array(len);
  for (let i = 0; i < len; i++) {
    values[i] = "" + current[i];
  }
  return {
    t: 22 /* TypedArray */,
    i: id,
    s: values,
    l: current.byteOffset,
    c: constructor,
    m: void 0,
    d: void 0,
    a: void 0,
    f: void 0
  };
}
var BIGINT_FLAG = 4096 /* BigIntTypedArray */ | 8 /* BigInt */;
function createBigIntTypedArrayNode(ctx, id, current) {
  const constructor = current.constructor.name;
  assert(
    (ctx.features & BIGINT_FLAG) === BIGINT_FLAG,
    `Unsupported value type "${constructor}"`
  );
  const len = current.length;
  const values = new Array(len);
  for (let i = 0; i < len; i++) {
    values[i] = "" + current[i];
  }
  return {
    t: 23 /* BigIntTypedArray */,
    i: id,
    s: values,
    l: current.byteOffset,
    c: constructor,
    m: void 0,
    d: void 0,
    a: void 0,
    f: void 0
  };
}
function createWKSymbolNode(current) {
  return {
    t: 24 /* WKSymbol */,
    i: void 0,
    s: INV_SYMBOL_REF[current],
    l: void 0,
    c: void 0,
    m: void 0,
    d: void 0,
    a: void 0,
    f: void 0
  };
}

// src/tree/shared.ts
function getErrorConstructorName(error) {
  if (error instanceof EvalError) {
    return "EvalError";
  }
  if (error instanceof RangeError) {
    return "RangeError";
  }
  if (error instanceof ReferenceError) {
    return "ReferenceError";
  }
  if (error instanceof SyntaxError) {
    return "SyntaxError";
  }
  if (error instanceof TypeError) {
    return "TypeError";
  }
  if (error instanceof URIError) {
    return "URIError";
  }
  return "Error";
}
function getErrorConstructor(errorName) {
  switch (errorName) {
    case "Error":
      return Error;
    case "EvalError":
      return EvalError;
    case "RangeError":
      return RangeError;
    case "ReferenceError":
      return ReferenceError;
    case "SyntaxError":
      return SyntaxError;
    case "TypeError":
      return TypeError;
    case "URIError":
      return URIError;
    default:
      throw new Error(`Unknown Error constructor "${errorName}"`);
  }
}
function getErrorOptions(ctx, error) {
  let options;
  const constructor = getErrorConstructorName(error);
  if (error.name !== constructor) {
    options = { name: error.name };
  } else if (error.constructor.name !== constructor) {
    options = { name: error.constructor.name };
  }
  const names = Object.getOwnPropertyNames(error);
  for (const name of names) {
    if (name !== "name" && name !== "message") {
      if (name === "stack") {
        if (ctx.features & 16 /* ErrorPrototypeStack */) {
          options = options || {};
          options[name] = error[name];
        }
      } else {
        options = options || {};
        options[name] = error[name];
      }
    }
  }
  return options;
}
function getIterableOptions(obj) {
  const names = Object.getOwnPropertyNames(obj);
  if (names.length) {
    const options = {};
    for (const name of names) {
      options[name] = obj[name];
    }
    return options;
  }
  return void 0;
}
function isIterable(value) {
  if (!value || typeof value !== "object") {
    return false;
  }
  if (Array.isArray(value)) {
    return false;
  }
  switch (value.constructor) {
    case Map:
    case Set:
    case Int8Array:
    case Int16Array:
    case Int32Array:
    case Uint8Array:
    case Uint16Array:
    case Uint32Array:
    case Uint8ClampedArray:
    case Float32Array:
    case Float64Array:
    case BigInt64Array:
    case BigUint64Array:
      return false;
    default:
      break;
  }
  return Symbol.iterator in value;
}
function getTypedArrayConstructor(name) {
  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 Error(`Unknown TypedArray "${name}"`);
  }
}
var IDENTIFIER_CHECK = /^[$A-Z_][0-9A-Z_$]*$/i;
function isValidIdentifier(name) {
  const char = name[0];
  return (char === "$" || char === "_" || char >= "A" && char <= "Z" || char >= "a" && char <= "z") && IDENTIFIER_CHECK.test(name);
}

// src/tree/async.ts
async function generateNodeList(ctx, current) {
  const size = current.length;
  const nodes = new Array(size);
  const deferred = new Array(size);
  let item;
  for (let i = 0; i < size; i++) {
    if (i in current) {
      item = current[i];
      if (isIterable(item)) {
        deferred[i] = item;
      } else {
        nodes[i] = await parse(ctx, item);
      }
    }
  }
  for (let i = 0; i < size; i++) {
    if (i in deferred) {
      nodes[i] = await parse(ctx, deferred[i]);
    }
  }
  return nodes;
}
async function generateArrayNode(ctx, id, current) {
  return {
    t: 15 /* Array */,
    i: id,
    s: void 0,
    l: current.length,
    c: void 0,
    m: void 0,
    d: void 0,
    a: await generateNodeList(ctx, current),
    f: void 0
  };
}
async function generateMapNode(ctx, id, current) {
  assert(ctx.features & 32 /* Map */, 'Unsupported type "Map"');
  const len = current.size;
  const keyNodes = new Array(len);
  const valueNodes = new Array(len);
  const deferredKey = new Array(len);
  const deferredValue = new Array(len);
  let deferredSize = 0;
  let nodeSize = 0;
  for (const [key, value] of current.entries()) {
    if (isIterable(key) || isIterable(value)) {
      deferredKey[deferredSize] = key;
      deferredValue[deferredSize] = value;
      deferredSize++;
    } else {
      keyNodes[nodeSize] = await parse(ctx, key);
      valueNodes[nodeSize] = await parse(ctx, value);
      nodeSize++;
    }
  }
  for (let i = 0; i < deferredSize; i++) {
    keyNodes[nodeSize + i] = await parse(ctx, deferredKey[i]);
    valueNodes[nodeSize + i] = await parse(ctx, deferredValue[i]);
  }
  return {
    t: 14 /* Map */,
    i: id,
    s: void 0,
    l: void 0,
    c: void 0,
    m: void 0,
    d: { k: keyNodes, v: valueNodes, s: len },
    a: void 0,
    f: void 0
  };
}
async function generateSetNode(ctx, id, current) {
  assert(ctx.features & 512 /* Set */, 'Unsupported type "Set"');
  const len = current.size;
  const nodes = new Array(len);
  const deferred = new Array(len);
  let deferredSize = 0;
  let nodeSize = 0;
  for (const item of current.keys()) {
    if (isIterable(item)) {
      deferred[deferredSize++] = item;
    } else {
      nodes[nodeSize++] = await parse(ctx, item);
    }
  }
  for (let i = 0; i < deferredSize; i++) {
    nodes[nodeSize + i] = await parse(ctx, deferred[i]);
  }
  return {
    t: 13 /* Set */,
    i: id,
    s: void 0,
    l: len,
    c: void 0,
    m: void 0,
    d: void 0,
    a: nodes,
    f: void 0
  };
}
async function generateProperties(ctx, properties) {
  const keys = Object.keys(properties);
  const size = keys.length;
  const keyNodes = new Array(size);
  const valueNodes = new Array(size);
  const deferredKeys = new Array(size);
  const deferredValues = new Array(size);
  let deferredSize = 0;
  let nodesSize = 0;
  let item;
  for (const key of keys) {
    item = properties[key];
    if (isIterable(item)) {
      deferredKeys[deferredSize] = key;
      deferredValues[deferredSize] = item;
      deferredSize++;
    } else {
      keyNodes[nodesSize] = key;
      valueNodes[nodesSize] = await parse(ctx, item);
      nodesSize++;
    }
  }
  for (let i = 0; i < deferredSize; i++) {
    keyNodes[nodesSize + i] = deferredKeys[i];
    valueNodes[nodesSize + i] = await parse(ctx, deferredValues[i]);
  }
  return {
    k: keyNodes,
    v: valueNodes,
    s: size
  };
}
async function generateIterableNode(ctx, id, current) {
  assert(ctx.features & 1024 /* Symbol */, 'Unsupported type "Iterable"');
  const options = getIterableOptions(current);
  const array = Array.from(current);
  return {
    t: 21 /* Iterable */,
    i: id,
    s: void 0,
    l: array.length,
    c: void 0,
    m: void 0,
    // Parse options first before the items
    d: options ? await generateProperties(ctx, options) : void 0,
    a: await generateNodeList(ctx, array),
    f: void 0
  };
}
async function generatePromiseNode(ctx, id, current) {
  assert(ctx.features & 256 /* Promise */, 'Unsupported type "Promise"');
  return current.then(async (value) => ({
    t: 18 /* Promise */,
    i: id,
    s: void 0,
    l: void 0,
    c: void 0,
    m: void 0,
    // Parse options first before the items
    d: void 0,
    a: void 0,
    f: await parse(ctx, value)
  }));
}
async function generateObjectNode(ctx, id, current, empty) {
  if (Symbol.iterator in current) {
    return generateIterableNode(ctx, id, current);
  }
  if ("then" in current && typeof current.then === "function") {
    return generatePromiseNode(ctx, id, current);
  }
  return {
    t: empty ? 17 /* NullConstructor */ : 16 /* Object */,
    i: id,
    s: void 0,
    l: void 0,
    c: void 0,
    m: void 0,
    d: await generateProperties(ctx, current),
    a: void 0,
    f: void 0
  };
}
async function generateAggregateErrorNode(ctx, id, current) {
  const options = getErrorOptions(ctx, current);
  const optionsNode = options ? await generateProperties(ctx, options) : void 0;
  return {
    t: 20 /* AggregateError */,
    i: id,
    s: void 0,
    l: current.errors.length,
    c: void 0,
    m: current.message,
    d: optionsNode,
    a: await generateNodeList(ctx, current.errors),
    f: void 0
  };
}
async function generateErrorNode(ctx, id, current) {
  const options = getErrorOptions(ctx, current);
  const optionsNode = options ? await generateProperties(ctx, options) : void 0;
  return {
    t: 19 /* Error */,
    i: id,
    s: void 0,
    l: void 0,
    c: getErrorConstructorName(current),
    m: current.message,
    d: optionsNode,
    a: void 0,
    f: void 0
  };
}
async function parse(ctx, current) {
  switch (typeof current) {
    case "boolean":
      return current ? TRUE_NODE : FALSE_NODE;
    case "undefined":
      return UNDEFINED_NODE;
    case "string":
      return createStringNode(current);
    case "number":
      switch (current) {
        case Infinity:
          return INFINITY_NODE;
        case -Infinity:
          return NEG_INFINITY_NODE;
        default:
          break;
      }
      if (current !== current) {
        return NAN_NODE;
      }
      if (Object.is(current, -0)) {
        return NEG_ZERO_NODE;
      }
      return createNumberNode(current);
    case "bigint":
      return createBigIntNode(ctx, current);
    case "object": {
      if (!current) {
        return NULL_NODE;
      }
      const id = createRef(ctx, current);
      if (ctx.markedRefs.has(id)) {
        return createReferenceNode(id);
      }
      if (Array.isArray(current)) {
        return generateArrayNode(ctx, id, current);
      }
      switch (current.constructor) {
        case Date:
          return createDateNode(id, current);
        case RegExp:
          return createRegExpNode(id, current);
        case Promise:
          return generatePromiseNode(ctx, id, current);
        case Int8Array:
        case Int16Array:
        case Int32Array:
        case Uint8Array:
        case Uint16Array:
        case Uint32Array:
        case Uint8ClampedArray:
        case Float32Array:
        case Float64Array:
          return createTypedArrayNode(ctx, id, current);
        case BigInt64Array:
        case BigUint64Array:
          return createBigIntTypedArrayNode(ctx, id, current);
        case Map:
          return generateMapNode(
            ctx,
            id,
            current
          );
        case Set:
          return generateSetNode(
            ctx,
            id,
            current
          );
        case Object:
          return generateObjectNode(
            ctx,
            id,
            current,
            false
          );
        case void 0:
          return generateObjectNode(
            ctx,
            id,
            current,
            true
          );
        case AggregateError:
          if (ctx.features & 1 /* AggregateError */) {
            return generateAggregateErrorNode(ctx, id, current);
          }
          return generateErrorNode(ctx, id, current);
        case Error:
        case EvalError:
        case RangeError:
        case ReferenceError:
        case SyntaxError:
        case TypeError:
        case URIError:
          return generateErrorNode(ctx, id, current);
        default:
          break;
      }
      if (current instanceof AggregateError) {
        if (ctx.features & 1 /* AggregateError */) {
          return generateAggregateErrorNode(ctx, id, current);
        }
        return generateErrorNode(ctx, id, current);
      }
      if (current instanceof Error) {
        return generateErrorNode(ctx, id, current);
      }
      if (current instanceof Promise) {
        return generatePromiseNode(ctx, id, current);
      }
      if (Symbol.iterator in current) {
        return generateIterableNode(ctx, id, current);
      }
      if ("then" in current && typeof current.then === "function") {
        return generatePromiseNode(ctx, id, current);
      }
      throw new Error("Unsupported type");
    }
    case "symbol":
      assert(ctx.features & 1024 /* Symbol */, 'Unsupported type "symbol"');
      assert(current in INV_SYMBOL_REF, "seroval only supports well-known symbols");
      return createWKSymbolNode(current);
    default:
      throw new Error("Unsupported type");
  }
}
async function parseAsync(ctx, current) {
  const result = await parse(ctx, current);
  const isObject = result.t === 16 /* Object */ || result.t === 21 /* Iterable */;
  return [result, getRootID(ctx, current), isObject];
}

// src/tree/deserialize.ts
function assignRef(ctx, index, value) {
  ctx.valueMap.set(index, value);
  return value;
}
function deserializeNodeList(ctx, node, result) {
  let item;
  for (let i = 0, len = node.a.length; i < len; i++) {
    item = node.a[i];
    if (item) {
      result[i] = deserializeTree(ctx, item);
    }
  }
  return result;
}
function deserializeArray(ctx, node) {
  const result = assignRef(
    ctx,
    node.i,
    new Array(node.l)
  );
  ctx.stack.push(node.i);
  deserializeNodeList(ctx, node, result);
  ctx.stack.pop();
  return result;
}
function deserializeProperties(ctx, node, result) {
  if (node.s === 0) {
    return {};
  }
  for (let i = 0; i < node.s; i++) {
    result[node.k[i]] = deserializeTree(ctx, node.v[i]);
  }
  return result;
}
function deserializeNullConstructor(ctx, node) {
  const result = assignRef(ctx, node.i, /* @__PURE__ */ Object.create(null));
  ctx.stack.push(node.i);
  deserializeProperties(ctx, node.d, result);
  ctx.stack.pop();
  return result;
}
function deserializeObject(ctx, node) {
  const result = assignRef(ctx, node.i, {});
  ctx.stack.push(node.i);
  deserializeProperties(ctx, node.d, result);
  ctx.stack.pop();
  return result;
}
function deserializeSet(ctx, node) {
  const result = assignRef(ctx, node.i, /* @__PURE__ */ new Set());
  ctx.stack.push(node.i);
  for (let i = 0, len = node.a.length; i < len; i++) {
    result.add(deserializeTree(ctx, node.a[i]));
  }
  ctx.stack.pop();
  return result;
}
function deserializeMap(ctx, node) {
  const result = assignRef(
    ctx,
    node.i,
    /* @__PURE__ */ new Map()
  );
  ctx.stack.push(node.i);
  for (let i = 0; i < node.d.s; i++) {
    result.set(
      deserializeTree(ctx, node.d.k[i]),
      deserializeTree(ctx, node.d.v[i])
    );
  }
  ctx.stack.pop();
  return result;
}
function deserializeDictionary(ctx, node, result) {
  if (node.d) {
    ctx.stack.push(node.i);
    const fields = deserializeProperties(ctx, node.d, {});
    ctx.stack.pop();
    Object.assign(result, fields);
  }
  return result;
}
function deserializeAggregateError(ctx, node) {
  const result = assignRef(ctx, node.i, new AggregateError([], node.m));
  ctx.stack.push(node.i);
  result.errors = deserializeNodeList(ctx, node, new Array(node.l));
  ctx.stack.pop();
  return deserializeDictionary(ctx, node, result);
}
function deserializeError(ctx, node) {
  const ErrorConstructor = getErrorConstructor(node.c);
  const result = assignRef(ctx, node.i, new ErrorConstructor(node.m));
  return deserializeDictionary(ctx, node, result);
}
function createDeferred() {
  let resolver;
  return {
    resolve(v) {
      resolver(v);
    },
    promise: new Promise((res) => {
      resolver = res;
    })
  };
}
function deserializePromise(ctx, node) {
  const deferred = createDeferred();
  const result = assignRef(ctx, node.i, deferred.promise);
  deferred.resolve(deserializeTree(ctx, node.f));
  return result;
}
function deserializeTypedArray(ctx, node) {
  const TypedArray = getTypedArrayConstructor(node.c);
  const dummy = new TypedArray();
  const result = assignRef(ctx, node.i, new TypedArray(
    dummy.buffer,
    node.l
  ));
  for (let i = 0, len = node.s.length; i < len; i++) {
    result[i] = node.t === 23 /* BigIntTypedArray */ ? BigInt(node.s[i]) : Number(node.s[i]);
  }
  return result;
}
function deserializeIterable(ctx, node) {
  const values = [];
  deserializeNodeList(ctx, node, values);
  const result = assignRef(ctx, node.i, {
    [Symbol.iterator]: () => values.values()
  });
  return deserializeDictionary(ctx, node, result);
}
function deserializeTree(ctx, node) {
  switch (node.t) {
    case 0 /* Number */:
    case 2 /* Boolean */:
      return node.s;
    case 1 /* String */:
      return invQuote(node.s);
    case 4 /* Undefined */:
      return void 0;
    case 3 /* Null */:
      return null;
    case 5 /* NegativeZero */:
      return -0;
    case 6 /* Infinity */:
      return Infinity;
    case 7 /* NegativeInfinity */:
      return -Infinity;
    case 8 /* NaN */:
      return NaN;
    case 9 /* BigInt */:
      return BigInt(node.s);
    case 10 /* Reference */:
      return ctx.valueMap.get(node.i);
    case 15 /* Array */:
      return deserializeArray(ctx, node);
    case 16 /* Object */:
      return deserializeObject(ctx, node);
    case 17 /* NullConstructor */:
      return deserializeNullConstructor(ctx, node);
    case 11 /* Date */:
      return assignRef(ctx, node.i, new Date(node.s));
    case 12 /* RegExp */:
      return assignRef(ctx, node.i, new RegExp(node.c, node.m));
    case 13 /* Set */:
      return deserializeSet(ctx, node);
    case 14 /* Map */:
      return deserializeMap(ctx, node);
    case 23 /* BigIntTypedArray */:
    case 22 /* TypedArray */:
      return deserializeTypedArray(ctx, node);
    case 20 /* AggregateError */:
      return deserializeAggregateError(ctx, node);
    case 19 /* Error */:
      return deserializeError(ctx, node);
    case 21 /* Iterable */:
      return deserializeIterable(ctx, node);
    case 18 /* Promise */:
      return deserializePromise(ctx, node);
    case 24 /* WKSymbol */:
      return SYMBOL_REF[node.s];
    default:
      throw new Error("Unsupported type");
  }
}

// src/tree/serialize.ts
function getAssignmentExpression(assignment) {
  switch (assignment.t) {
    case "index":
      return assignment.s + "=" + assignment.v;
    case "map":
      return assignment.s + ".set(" + assignment.k + "," + assignment.v + ")";
    case "set":
      return assignment.s + ".add(" + assignment.v + ")";
    default:
      return "";
  }
}
function mergeAssignments(assignments) {
  const newAssignments = [];
  let current = assignments[0];
  let prev = current;
  let item;
  for (let i = 1, len = assignments.length; i < len; i++) {
    item = assignments[i];
    if (item.t === prev.t) {
      switch (item.t) {
        case "index":
          if (item.v === prev.v) {
            current = {
              t: "index",
              s: item.s,
              k: void 0,
              v: getAssignmentExpression(current)
            };
          } else {
            newAssignments.push(current);
            current = item;
          }
          break;
        case "map":
          if (item.s === prev.s) {
            current = {
              t: "map",
              s: getAssignmentExpression(current),
              k: item.k,
              v: item.v
            };
          } else {
            newAssignments.push(current);
            current = item;
          }
          break;
        case "set":
          if (item.s === prev.s) {
            current = {
              t: "set",
              s: getAssignmentExpression(current),
              k: void 0,
              v: item.v
            };
          } else {
            newAssignments.push(current);
            current = item;
          }
          break;
        default:
          break;
      }
    } else {
      newAssignments.push(current);
      current = item;
    }
    prev = item;
  }
  newAssignments.push(current);
  return newAssignments;
}
function resolveAssignments(assignments) {
  if (assignments.length) {
    let result = "";
    const merged = mergeAssignments(assignments);
    for (let i = 0, len = merged.length; i < len; i++) {
      result += getAssignmentExpression(merged[i]) + ",";
    }
    return result;
  }
  return void 0;
}
function resolvePatches(ctx) {
  return resolveAssignments(ctx.assignments);
}
function createAssignment(ctx, source, value) {
  ctx.assignments.push({
    t: "index",
    s: source,
    k: void 0,
    v: value
  });
}
function createSetAdd(ctx, ref, value) {
  markRef(ctx, ref);
  ctx.assignments.push({
    t: "set",
    s: getRefParam(ctx, ref),
    k: void 0,
    v: value
  });
}
function createMapSet(ctx, ref, key, value) {
  markRef(ctx, ref);
  ctx.assignments.push({
    t: "map",
    s: getRefParam(ctx, ref),
    k: key,
    v: value
  });
}
function createArrayAssign(ctx, ref, index, value) {
  markRef(ctx, ref);
  createAssignment(ctx, getRefParam(ctx, ref) + "[" + index + "]", value);
}
function createObjectAssign(ctx, ref, key, value) {
  markRef(ctx, ref);
  createAssignment(ctx, getRefParam(ctx, ref) + "." + key, value);
}
function assignRef2(ctx, index, value) {
  if (ctx.markedRefs.has(index)) {
    return getRefParam(ctx, index) + "=" + value;
  }
  return value;
}
function isReferenceInStack(ctx, node) {
  return node.t === 10 /* Reference */ && ctx.stack.includes(node.i);
}
function serializeNodeList(ctx, node) {
  const size = node.l;
  let values = "";
  let item;
  let isHoley = false;
  for (let i = 0; i < size; i++) {
    if (i !== 0) {
      values += ",";
    }
    item = node.a[i];
    if (item) {
      if (isReferenceInStack(ctx, item)) {
        createArrayAssign(ctx, node.i, i, getRefParam(ctx, item.i));
        isHoley = true;
      } else {
        values += serializeTree(ctx, item);
        isHoley = false;
      }
    } else {
      isHoley = true;
    }
  }
  return "[" + values + (isHoley ? ",]" : "]");
}
function serializeArray(ctx, node) {
  ctx.stack.push(node.i);
  const result = serializeNodeList(ctx, node);
  ctx.stack.pop();
  return assignRef2(ctx, node.i, result);
}
function serializeProperties(ctx, sourceID, node) {
  if (node.s === 0) {
    return "{}";
  }
  let result = "";
  ctx.stack.push(sourceID);
  let key;
  let val;
  let check;
  let isIdentifier;
  let refParam;
  let hasPrev = false;
  for (let i = 0; i < node.s; i++) {
    key = node.k[i];
    val = node.v[i];
    check = Number(key);
    isIdentifier = check >= 0 || isValidIdentifier(key);
    if (isReferenceInStack(ctx, val)) {
      refParam = getRefParam(ctx, val.i);
      if (isIdentifier && Number.isNaN(check)) {
        createObjectAssign(ctx, sourceID, key, refParam);
      } else {
        createArrayAssign(ctx, sourceID, isIdentifier ? key : '"' + quote(key) + '"', refParam);
      }
    } else {
      result += (hasPrev ? "," : "") + (isIdentifier ? key : '"' + quote(key) + '"') + ":" + serializeTree(ctx, val);
      hasPrev = true;
    }
  }
  ctx.stack.pop();
  return "{" + result + "}";
}
function serializeWithObjectAssign(ctx, value, id, serialized) {
  const fields = serializeProperties(ctx, id, value);
  if (fields !== "{}") {
    return "Object.assign(" + serialized + "," + fields + ")";
  }
  return serialized;
}
function serializeAssignments(ctx, sourceID, node) {
  ctx.stack.push(sourceID);
  const mainAssignments = [];
  let parentStack;
  let refParam;
  let key;
  let check;
  let parentAssignment;
  let isIdentifier;
  for (let i = 0; i < node.s; i++) {
    parentStack = ctx.stack;
    ctx.stack = [];
    refParam = serializeTree(ctx, node.v[i]);
    ctx.stack = parentStack;
    key = node.k[i];
    check = Number(key);
    parentAssignment = ctx.assignments;
    ctx.assignments = mainAssignments;
    isIdentifier = check >= 0 || isValidIdentifier(key);
    if (isIdentifier && Number.isNaN(check)) {
      createObjectAssign(ctx, sourceID, key, refParam);
    } else {
      createArrayAssign(ctx, sourceID, isIdentifier ? key : '"' + quote(key) + '"', refParam);
    }
    ctx.assignments = parentAssignment;
  }
  ctx.stack.pop();
  return resolveAssignments(mainAssignments);
}
function serializeDictionary(ctx, i, d, init) {
  if (d) {
    if (ctx.features & 128 /* ObjectAssign */) {
      init = serializeWithObjectAssign(ctx, d, i, init);
    } else {
      markRef(ctx, i);
      const assignments = serializeAssignments(ctx, i, d);
      if (assignments) {
        return "(" + assignRef2(ctx, i, init) + "," + assignments + getRefParam(ctx, i) + ")";
      }
    }
  }
  return assignRef2(ctx, i, init);
}
function serializeNullConstructor(ctx, node) {
  return serializeDictionary(ctx, node.i, node.d, "Object.create(null)");
}
function serializeObject(ctx, node) {
  return assignRef2(ctx, node.i, serializeProperties(ctx, node.i, node.d));
}
function serializeSet(ctx, node) {
  let serialized = "new Set";
  const size = node.l;
  if (size) {
    let result = "";
    ctx.stack.push(node.i);
    let item;
    let hasPrev = false;
    for (let i = 0; i < size; i++) {
      item = node.a[i];
      if (isReferenceInStack(ctx, item)) {
        createSetAdd(ctx, node.i, getRefParam(ctx, item.i));
      } else {
        result += (hasPrev ? "," : "") + serializeTree(ctx, item);
        hasPrev = true;
      }
    }
    ctx.stack.pop();
    if (result) {
      serialized += "([" + result + "])";
    }
  }
  return assignRef2(ctx, node.i, serialized);
}
function serializeMap(ctx, node) {
  let serialized = "new Map";
  if (node.d.s) {
    let result = "";
    ctx.stack.push(node.i);
    let key;
    let val;
    let keyRef;
    let valueRef;
    let parent;
    let hasPrev = false;
    for (let i = 0; i < node.d.s; i++) {
      key = node.d.k[i];
      val = node.d.v[i];
      if (isReferenceInStack(ctx, key)) {
        keyRef = getRefParam(ctx, key.i);
        if (isReferenceInStack(ctx, val)) {
          valueRef = getRefParam(ctx, val.i);
          createMapSet(ctx, node.i, keyRef, valueRef);
        } else {
          parent = ctx.stack;
          ctx.stack = [];
          createMapSet(ctx, node.i, keyRef, serializeTree(ctx, val));
          ctx.stack = parent;
        }
      } else if (isReferenceInStack(ctx, val)) {
        valueRef = getRefParam(ctx, val.i);
        parent = ctx.stack;
        ctx.stack = [];
        createMapSet(ctx, node.i, serializeTree(ctx, key), valueRef);
        ctx.stack = parent;
      } else {
        result += (hasPrev ? ",[" : "[") + serializeTree(ctx, key) + "," + serializeTree(ctx, val) + "]";
        hasPrev = true;
      }
    }
    ctx.stack.pop();
    if (result) {
      serialized += "([" + result + "])";
    }
  }
  return assignRef2(ctx, node.i, serialized);
}
function serializeAggregateError(ctx, node) {
  ctx.stack.push(node.i);
  const serialized = "new AggregateError(" + serializeNodeList(ctx, node) + ',"' + quote(node.m) + '")';
  ctx.stack.pop();
  return serializeDictionary(ctx, node.i, node.d, serialized);
}
function serializeError(ctx, node) {
  const serialized = "new " + node.c + '("' + quote(node.m) + '")';
  return serializeDictionary(ctx, node.i, node.d, serialized);
}
function serializePromise(ctx, node) {
  let serialized;
  if (isReferenceInStack(ctx, node.f)) {
    const ref = getRefParam(ctx, node.f.i);
    if (ctx.features & 4 /* ArrowFunction */) {
      serialized = "Promise.resolve().then(()=>" + ref + ")";
    } else {
      serialized = "Promise.resolve().then(function(){return " + ref + "})";
    }
  } else {
    ctx.stack.push(node.i);
    const result = serializeTree(ctx, node.f);
    ctx.stack.pop();
    serialized = "Promise.resolve(" + result + ")";
  }
  return assignRef2(ctx, node.i, serialized);
}
function serializeTypedArray(ctx, node) {
  let result = "";
  const isBigInt = node.t === 23 /* BigIntTypedArray */;
  for (let i = 0, len = node.s.length; i < len; i++) {
    result += (i !== 0 ? "," : "") + node.s[i] + (isBigInt ? "n" : "");
  }
  const args = "[" + result + "]" + (node.l !== 0 ? "," + node.l : "");
  return assignRef2(ctx, node.i, "new " + node.c + "(" + args + ")");
}
function serializeIterable(ctx, node) {
  const parent = ctx.stack;
  ctx.stack = [];
  const values = serializeNodeList(ctx, node);
  ctx.stack = parent;
  let serialized = values;
  if (ctx.features & 2 /* ArrayPrototypeValues */) {
    serialized += ".values()";
  } else {
    serialized += "[Symbol.iterator]()";
  }
  if (ctx.features & 4 /* ArrowFunction */) {
    serialized = "{[Symbol.iterator]:()=>" + serialized + "}";
  } else if (ctx.features & 64 /* MethodShorthand */) {
    serialized = "{[Symbol.iterator](){return " + serialized + "}}";
  } else {
    serialized = "{[Symbol.iterator]:function(){return " + serialized + "}}";
  }
  return serializeDictionary(ctx, node.i, node.d, serialized);
}
function serializeTree(ctx, node) {
  switch (node.t) {
    case 0 /* Number */:
      return "" + node.s;
    case 1 /* String */:
      return '"' + node.s + '"';
    case 2 /* Boolean */:
      return node.s ? "!0" : "!1";
    case 4 /* Undefined */:
      return "void 0";
    case 3 /* Null */:
      return "null";
    case 5 /* NegativeZero */:
      return "-0";
    case 6 /* Infinity */:
      return "1/0";
    case 7 /* NegativeInfinity */:
      return "-1/0";
    case 8 /* NaN */:
      return "NaN";
    case 9 /* BigInt */:
      return node.s + "n";
    case 10 /* Reference */:
      return getRefParam(ctx, node.i);
    case 15 /* Array */:
      return serializeArray(ctx, node);
    case 16 /* Object */:
      return serializeObject(ctx, node);
    case 17 /* NullConstructor */:
      return serializeNullConstructor(ctx, node);
    case 11 /* Date */:
      return assignRef2(ctx, node.i, 'new Date("' + node.s + '")');
    case 12 /* RegExp */:
      return assignRef2(ctx, node.i, "/" + node.c + "/" + node.m);
    case 13 /* Set */:
      return serializeSet(ctx, node);
    case 14 /* Map */:
      return serializeMap(ctx, node);
    case 23 /* BigIntTypedArray */:
    case 22 /* TypedArray */:
      return serializeTypedArray(ctx, node);
    case 20 /* AggregateError */:
      return serializeAggregateError(ctx, node);
    case 19 /* Error */:
      return serializeError(ctx, node);
    case 21 /* Iterable */:
      return serializeIterable(ctx, node);
    case 18 /* Promise */:
      return serializePromise(ctx, node);
    case 24 /* WKSymbol */:
      return SYMBOL_STRING[node.s];
    default:
      throw new Error("Unsupported type");
  }
}

// src/tree/sync.ts
function generateNodeList2(ctx, current) {
  const size = current.length;
  const nodes = new Array(size);
  const deferred = new Array(size);
  let item;
  for (let i = 0; i < size; i++) {
    if (i in current) {
      item = current[i];
      if (isIterable(item)) {
        deferred[i] = item;
      } else {
        nodes[i] = parse2(ctx, item);
      }
    }
  }
  for (let i = 0; i < size; i++) {
    if (i in deferred) {
      nodes[i] = parse2(ctx, deferred[i]);
    }
  }
  return nodes;
}
function generateArrayNode2(ctx, id, current) {
  return {
    t: 15 /* Array */,
    i: id,
    s: void 0,
    l: current.length,
    c: void 0,
    m: void 0,
    d: void 0,
    a: generateNodeList2(ctx, current),
    f: void 0
  };
}
function generateMapNode2(ctx, id, current) {
  assert(ctx.features & 32 /* Map */, 'Unsupported type "Map"');
  const len = current.size;
  const keyNodes = new Array(len);
  const valueNodes = new Array(len);
  const deferredKey = new Array(len);
  const deferredValue = new Array(len);
  let deferredSize = 0;
  let nodeSize = 0;
  for (const [key, value] of current.entries()) {
    if (isIterable(key) || isIterable(value)) {
      deferredKey[deferredSize] = key;
      deferredValue[deferredSize] = value;
      deferredSize++;
    } else {
      keyNodes[nodeSize] = parse2(ctx, key);
      valueNodes[nodeSize] = parse2(ctx, value);
      nodeSize++;
    }
  }
  for (let i = 0; i < deferredSize; i++) {
    keyNodes[nodeSize + i] = parse2(ctx, deferredKey[i]);
    valueNodes[nodeSize + i] = parse2(ctx, deferredValue[i]);
  }
  return {
    t: 14 /* Map */,
    i: id,
    s: void 0,
    l: void 0,
    c: void 0,
    m: void 0,
    d: { k: keyNodes, v: valueNodes, s: len },
    a: void 0,
    f: void 0
  };
}
function generateSetNode2(ctx, id, current) {
  assert(ctx.features & 512 /* Set */, 'Unsupported type "Set"');
  const len = current.size;
  const nodes = new Array(len);
  const deferred = new Array(len);
  let deferredSize = 0;
  let nodeSize = 0;
  for (const item of current.keys()) {
    if (isIterable(item)) {
      deferred[deferredSize++] = item;
    } else {
      nodes[nodeSize++] = parse2(ctx, item);
    }
  }
  for (let i = 0; i < deferredSize; i++) {
    nodes[nodeSize + i] = parse2(ctx, deferred[i]);
  }
  return {
    t: 13 /* Set */,
    i: id,
    s: void 0,
    l: len,
    c: void 0,
    m: void 0,
    d: void 0,
    a: nodes,
    f: void 0
  };
}
function generateProperties2(ctx, properties) {
  const keys = Object.keys(properties);
  const size = keys.length;
  const keyNodes = new Array(size);
  const valueNodes = new Array(size);
  const deferredKeys = new Array(size);
  const deferredValues = new Array(size);
  let deferredSize = 0;
  let nodesSize = 0;
  let item;
  for (const key of keys) {
    item = properties[key];
    if (isIterable(item)) {
      deferredKeys[deferredSize] = key;
      deferredValues[deferredSize] = item;
      deferredSize++;
    } else {
      keyNodes[nodesSize] = key;
      valueNodes[nodesSize] = parse2(ctx, item);
      nodesSize++;
    }
  }
  for (let i = 0; i < deferredSize; i++) {
    keyNodes[nodesSize + i] = deferredKeys[i];
    valueNodes[nodesSize + i] = parse2(ctx, deferredValues[i]);
  }
  return {
    k: keyNodes,
    v: valueNodes,
    s: size
  };
}
function generateIterableNode2(ctx, id, current) {
  assert(ctx.features & 1024 /* Symbol */, 'Unsupported type "Iterable"');
  const options = getIterableOptions(current);
  const array = Array.from(current);
  return {
    t: 21 /* Iterable */,
    i: id,
    s: void 0,
    l: array.length,
    c: void 0,
    m: void 0,
    // Parse options first before the items
    d: options ? generateProperties2(ctx, options) : void 0,
    a: generateNodeList2(ctx, array),
    f: void 0
  };
}
function generateObjectNode2(ctx, id, current, empty) {
  if (Symbol.iterator in current) {
    return generateIterableNode2(ctx, id, current);
  }
  return {
    t: empty ? 17 /* NullConstructor */ : 16 /* Object */,
    i: id,
    s: void 0,
    l: void 0,
    c: void 0,
    m: void 0,
    d: generateProperties2(ctx, current),
    a: void 0,
    f: void 0
  };
}
function generateAggregateErrorNode2(ctx, id, current) {
  const options = getErrorOptions(ctx, current);
  const optionsNode = options ? generateProperties2(ctx, options) : void 0;
  return {
    t: 20 /* AggregateError */,
    i: id,
    s: void 0,
    l: current.errors.length,
    c: void 0,
    m: current.message,
    d: optionsNode,
    a: generateNodeList2(ctx, current.errors),
    f: void 0
  };
}
function generateErrorNode2(ctx, id, current) {
  const options = getErrorOptions(ctx, current);
  const optionsNode = options ? generateProperties2(ctx, options) : void 0;
  return {
    t: 19 /* Error */,
    i: id,
    s: void 0,
    l: void 0,
    c: getErrorConstructorName(current),
    m: current.message,
    d: optionsNode,
    a: void 0,
    f: void 0
  };
}
function parse2(ctx, current) {
  switch (typeof current) {
    case "boolean":
      return current ? TRUE_NODE : FALSE_NODE;
    case "undefined":
      return UNDEFINED_NODE;
    case "string":
      return createStringNode(current);
    case "number":
      switch (current) {
        case Infinity:
          return INFINITY_NODE;
        case -Infinity:
          return NEG_INFINITY_NODE;
        default:
          break;
      }
      if (current !== current) {
        return NAN_NODE;
      }
      if (Object.is(current, -0)) {
        return NEG_ZERO_NODE;
      }
      return createNumberNode(current);
    case "bigint":
      return createBigIntNode(ctx, current);
    case "object": {
      if (!current) {
        return NULL_NODE;
      }
      const id = createRef(ctx, current);
      if (ctx.markedRefs.has(id)) {
        return createReferenceNode(id);
      }
      if (Array.isArray(current)) {
        return generateArrayNode2(ctx, id, current);
      }
      switch (current.constructor) {
        case Date:
          return createDateNode(id, current);
        case RegExp:
          return createRegExpNode(id, current);
        case Int8Array:
        case Int16Array:
        case Int32Array:
        case Uint8Array:
        case Uint16Array:
        case Uint32Array:
        case Uint8ClampedArray:
        case Float32Array:
        case Float64Array:
          return createTypedArrayNode(ctx, id, current);
        case BigInt64Array:
        case BigUint64Array:
          return createBigIntTypedArrayNode(ctx, id, current);
        case Map:
          return generateMapNode2(ctx, id, current);
        case Set:
          return generateSetNode2(ctx, id, current);
        case Object:
          return generateObjectNode2(ctx, id, current, false);
        case void 0:
          return generateObjectNode2(ctx, id, current, true);
        case AggregateError:
          if (ctx.features & 1 /* AggregateError */) {
            return generateAggregateErrorNode2(ctx, id, current);
          }
          return generateErrorNode2(ctx, id, current);
        case Error:
        case EvalError:
        case RangeError:
        case ReferenceError:
        case SyntaxError:
        case TypeError:
        case URIError:
          return generateErrorNode2(ctx, id, current);
        default:
          break;
      }
      if (current instanceof AggregateError) {
        if (ctx.features & 1 /* AggregateError */) {
          return generateAggregateErrorNode2(ctx, id, current);
        }
        return generateErrorNode2(ctx, id, current);
      }
      if (current instanceof Error) {
        return generateErrorNode2(ctx, id, current);
      }
      if (Symbol.iterator in current) {
        return generateIterableNode2(ctx, id, current);
      }
      throw new Error("Unsupported type");
    }
    case "symbol":
      assert(ctx.features & 1024 /* Symbol */, 'Unsupported type "symbol"');
      assert(current in INV_SYMBOL_REF, "seroval only supports well-known symbols");
      return createWKSymbolNode(current);
    default:
      throw new Error("Unsupported type");
  }
}
function parseSync(ctx, current) {
  const result = parse2(ctx, current);
  const isObject = result.t === 16 /* Object */ || result.t === 21 /* Iterable */;
  return [result, getRootID(ctx, current), isObject];
}

// src/index.ts
function finalize(ctx, rootID, isObject, result) {
  if (ctx.vars.length) {
    const patches = resolvePatches(ctx);
    let body = result;
    if (patches) {
      const index = getRefParam(ctx, rootID);
      body = result + "," + patches + index;
      if (!result.startsWith(index + "=")) {
        body = index + "=" + body;
      }
    }
    let params = ctx.vars.length > 1 ? ctx.vars.join(",") : ctx.vars[0];
    if (ctx.features & 4 /* ArrowFunction */) {
      params = ctx.vars.length > 1 || ctx.vars.length === 0 ? "(" + params + ")" : params;
      return "(" + params + "=>(" + body + "))()";
    }
    return "(function(" + params + "){return " + body + "})()";
  }
  if (isObject) {
    return "(" + result + ")";
  }
  return result;
}
function serialize(source, options) {
  const ctx = createParserContext(options);
  const [tree, rootID, isObject] = parseSync(ctx, source);
  const serial = createSerializationContext(ctx);
  const result = serializeTree(serial, tree);
  return finalize(serial, rootID, isObject, result);
}
async function serializeAsync(source, options) {
  const ctx = createParserContext(options);
  const [tree, rootID, isObject] = await parseAsync(ctx, source);
  const serial = createSerializationContext(ctx);
  const result = serializeTree(serial, tree);
  return finalize(serial, rootID, isObject, result);
}
function deserialize(source) {
  return (0, eval)(source);
}
function toJSON(source, options) {
  const ctx = createParserContext(options);
  const [tree, root, isObject] = parseSync(ctx, source);
  return {
    t: tree,
    r: root,
    i: isObject,
    f: ctx.features,
    m: Array.from(ctx.markedRefs)
  };
}
async function toJSONAsync(source, options) {
  const ctx = createParserContext(options);
  const [tree, root, isObject] = await parseAsync(ctx, source);
  return {
    t: tree,
    r: root,
    i: isObject,
    f: ctx.features,
    m: Array.from(ctx.markedRefs)
  };
}
function compileJSON(source) {
  const serial = createSerializationContext({
    features: source.f,
    markedRefs: source.m
  });
  const result = serializeTree(serial, source.t);
  return finalize(serial, source.r, source.i, result);
}
function fromJSON(source) {
  const serial = createSerializationContext({
    features: source.f,
    markedRefs: source.m
  });
  return deserializeTree(serial, source.t);
}
var src_default = serialize;
export {
  Feature,
  compileJSON,
  src_default as default,
  deserialize,
  fromJSON,
  serialize,
  serializeAsync,
  toJSON,
  toJSONAsync
};
//# sourceMappingURL=index.mjs.map
