UNPKG

5.98 kBJavaScriptView Raw
1/**
2 * react-router v8.0.0
3 *
4 * Copyright (c) Remix Software Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE.md file in the root directory of this source tree.
8 *
9 * @license MIT
10 */
11//#region vendor/turbo-stream-v2/flatten.ts
12const TIME_LIMIT_MS = 1;
13const getNow = () => Date.now();
14const yieldToMain = () => new Promise((resolve) => setTimeout(resolve, 0));
15async function flatten(input) {
16 const { indices } = this;
17 const existing = indices.get(input);
18 if (existing) return [existing];
19 if (input === void 0) return -7;
20 if (input === null) return -5;
21 if (Number.isNaN(input)) return -2;
22 if (input === Number.POSITIVE_INFINITY) return -6;
23 if (input === Number.NEGATIVE_INFINITY) return -3;
24 if (input === 0 && 1 / input < 0) return -4;
25 const index = this.index++;
26 indices.set(input, index);
27 const stack = [[input, index]];
28 await stringify.call(this, stack);
29 return index;
30}
31async function stringify(stack) {
32 const { deferred, indices, plugins, postPlugins } = this;
33 const str = this.stringified;
34 let lastYieldTime = getNow();
35 const flattenValue = (value) => {
36 const existing = indices.get(value);
37 if (existing) return [existing];
38 if (value === void 0) return -7;
39 if (value === null) return -5;
40 if (Number.isNaN(value)) return -2;
41 if (value === Number.POSITIVE_INFINITY) return -6;
42 if (value === Number.NEGATIVE_INFINITY) return -3;
43 if (value === 0 && 1 / value < 0) return -4;
44 const index = this.index++;
45 indices.set(value, index);
46 stack.push([value, index]);
47 return index;
48 };
49 let i = 0;
50 while (stack.length > 0) {
51 const now = getNow();
52 if (++i % 6e3 === 0 && now - lastYieldTime >= TIME_LIMIT_MS) {
53 await yieldToMain();
54 lastYieldTime = getNow();
55 }
56 const [input, index] = stack.pop();
57 const partsForObj = (obj) => Object.keys(obj).map((k) => `"_${flattenValue(k)}":${flattenValue(obj[k])}`).join(",");
58 let error = null;
59 switch (typeof input) {
60 case "boolean":
61 case "number":
62 case "string":
63 str[index] = JSON.stringify(input);
64 break;
65 case "bigint":
66 str[index] = `["B","${input}"]`;
67 break;
68 case "symbol": {
69 const keyFor = Symbol.keyFor(input);
70 if (!keyFor) error = /* @__PURE__ */ new Error("Cannot encode symbol unless created with Symbol.for()");
71 else str[index] = `["Y",${JSON.stringify(keyFor)}]`;
72 break;
73 }
74 case "object": {
75 if (!input) {
76 str[index] = `-5`;
77 break;
78 }
79 const isArray = Array.isArray(input);
80 let pluginHandled = false;
81 if (!isArray && plugins) for (const plugin of plugins) {
82 const pluginResult = plugin(input);
83 if (Array.isArray(pluginResult)) {
84 pluginHandled = true;
85 const [pluginIdentifier, ...rest] = pluginResult;
86 str[index] = `[${JSON.stringify(pluginIdentifier)}`;
87 if (rest.length > 0) str[index] += `,${rest.map((v) => flattenValue(v)).join(",")}`;
88 str[index] += "]";
89 break;
90 }
91 }
92 if (!pluginHandled) {
93 let result = isArray ? "[" : "{";
94 if (isArray) {
95 for (let i = 0; i < input.length; i++) result += (i ? "," : "") + (i in input ? flattenValue(input[i]) : -1);
96 str[index] = `${result}]`;
97 } else if (input instanceof Date) {
98 const dateTime = input.getTime();
99 str[index] = `["D",${Number.isNaN(dateTime) ? JSON.stringify("invalid") : dateTime}]`;
100 } else if (input instanceof URL) str[index] = `["U",${JSON.stringify(input.href)}]`;
101 else if (input instanceof RegExp) str[index] = `["R",${JSON.stringify(input.source)},${JSON.stringify(input.flags)}]`;
102 else if (input instanceof Set) if (input.size > 0) str[index] = `["S",${[...input].map((val) => flattenValue(val)).join(",")}]`;
103 else str[index] = `["S"]`;
104 else if (input instanceof Map) if (input.size > 0) str[index] = `["M",${[...input].flatMap(([k, v]) => [flattenValue(k), flattenValue(v)]).join(",")}]`;
105 else str[index] = `["M"]`;
106 else if (input instanceof Promise) {
107 str[index] = `["P",${index}]`;
108 deferred[index] = input;
109 } else if (input instanceof Error) {
110 str[index] = `["E",${JSON.stringify(input.message)}`;
111 if (input.name !== "Error") str[index] += `,${JSON.stringify(input.name)}`;
112 str[index] += "]";
113 } else if (Object.getPrototypeOf(input) === null) str[index] = `["N",{${partsForObj(input)}}]`;
114 else if (isPlainObject(input)) str[index] = `{${partsForObj(input)}}`;
115 else error = /* @__PURE__ */ new Error("Cannot encode object with prototype");
116 }
117 break;
118 }
119 default: {
120 const isArray = Array.isArray(input);
121 let pluginHandled = false;
122 if (!isArray && plugins) for (const plugin of plugins) {
123 const pluginResult = plugin(input);
124 if (Array.isArray(pluginResult)) {
125 pluginHandled = true;
126 const [pluginIdentifier, ...rest] = pluginResult;
127 str[index] = `[${JSON.stringify(pluginIdentifier)}`;
128 if (rest.length > 0) str[index] += `,${rest.map((v) => flattenValue(v)).join(",")}`;
129 str[index] += "]";
130 break;
131 }
132 }
133 if (!pluginHandled) error = /* @__PURE__ */ new Error("Cannot encode function or unexpected type");
134 }
135 }
136 if (error) {
137 let pluginHandled = false;
138 if (postPlugins) for (const plugin of postPlugins) {
139 const pluginResult = plugin(input);
140 if (Array.isArray(pluginResult)) {
141 pluginHandled = true;
142 const [pluginIdentifier, ...rest] = pluginResult;
143 str[index] = `[${JSON.stringify(pluginIdentifier)}`;
144 if (rest.length > 0) str[index] += `,${rest.map((v) => flattenValue(v)).join(",")}`;
145 str[index] += "]";
146 break;
147 }
148 }
149 if (!pluginHandled) throw error;
150 }
151 }
152}
153const objectProtoNames = Object.getOwnPropertyNames(Object.prototype).sort().join("\0");
154function isPlainObject(thing) {
155 const proto = Object.getPrototypeOf(thing);
156 return proto === Object.prototype || proto === null || Object.getOwnPropertyNames(proto).sort().join("\0") === objectProtoNames;
157}
158//#endregion
159export { flatten };