valueSource

tcmts.loader.valueSource · #7g76j57t · term · runs anywhere

A value as code that makes it again (new globalThis.Map([[1, "a"]])), for a pure constant evaluated once: plain data (numbers, strings, bigints, arrays, plain objects, Maps, Sets, Dates, RegExps). Undefined if it can't be made again the same: a function, a class's instance, a frozen object, an object found twice in it or among others (what other definitions hold: a copy would be a different object), or more than most characters of code.

export function valueSource(
  value: unknown,
  others: Set<unknown> = new Set(),
  most = 256 * 1024,
): string | undefined {
  const fail = Symbol("not kept");
  const seen = new Set<unknown>();
  const go = (v: unknown, root: boolean): string => {
    switch (typeof v) {
      case "undefined":
        return "undefined";
      case "boolean":
        return String(v);
      case "number":
        return Object.is(v, -0) ? "-0" : String(v);
      case "bigint":
        return `${v}n`;
      case "string":
        return JSON.stringify(v);
      case "object":
        break;
      default:
        throw fail;
    }
    if (v === null) return "null";
    if (seen.has(v) || (!root && others.has(v)) || !Object.isExtensible(v)) throw fail;
    seen.add(v);
    const proto = Object.getPrototypeOf(v);
    const own = Reflect.ownKeys(v);
    if (Array.isArray(v) && proto === Array.prototype) {
      // (no holes, nothing but its elements)
      if (own.length !== v.length + 1) throw fail;
      return `[${v.map((x) => go(x, false)).join(",")}]`;
    }
    if (proto === Map.prototype && !own.length)
      return `new globalThis.Map([${[...(v as Map<unknown, unknown>)].map(([k, x]) => `[${go(k, false)},${go(x, false)}]`).join(",")}])`;
    if (proto === Set.prototype && !own.length)
      return `new globalThis.Set([${[...(v as Set<unknown>)].map((x) => go(x, false)).join(",")}])`;
    if (proto === Date.prototype && !own.length)
      return `new globalThis.Date(${go((v as Date).getTime(), false)})`;
    if (proto === RegExp.prototype && own.length === 1 && (v as RegExp).lastIndex === 0)
      return `new globalThis.RegExp(${JSON.stringify((v as RegExp).source)},${JSON.stringify((v as RegExp).flags)})`;
    if (proto !== Object.prototype) throw fail;
    const parts: string[] = [];
    for (const k of own) {
      const d = Object.getOwnPropertyDescriptor(v, k)!;
      if (
        typeof k !== "string" ||
        !("value" in d) ||
        !d.enumerable ||
        !d.writable ||
        !d.configurable
      )
        throw fail;
      parts.push(
        `${k === "__proto__" ? '["__proto__"]' : JSON.stringify(k)}:${go(d.value, false)}`,
      );
    }
    return `{${parts.join(",")}}`;
  };
  try {
    const s = go(value, true);
    return s.length <= most ? s : undefined;
  } catch (e) {
    if (e === fail) return undefined;
    throw e;
  }
}

used by