@stackline/stable-stringify 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,728 @@
1
+ /*! @stackline/stable-stringify v1.0.0 | MIT */
2
+ var StacklineStableStringifyModule = (() => {
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.js
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ CanonicalizationError: () => CanonicalizationError,
25
+ StableStringifyLimitError: () => StableStringifyLimitError,
26
+ canonicalize: () => canonicalize,
27
+ canonicalizeBytes: () => canonicalizeBytes,
28
+ configure: () => configure,
29
+ default: () => index_default,
30
+ safeStringify: () => safeStringify,
31
+ stableStringify: () => stableStringify,
32
+ stringify: () => stringify
33
+ });
34
+ var hasOwn = Object.prototype.hasOwnProperty;
35
+ var propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
36
+ var objectToString = Object.prototype.toString;
37
+ var OMIT = /* @__PURE__ */ Symbol("omit");
38
+ var ROOT_PATH = null;
39
+ var SAFE_DEFAULTS = Object.freeze({
40
+ bigint: "string",
41
+ cycleValue: "[Circular]",
42
+ maxDepth: 100,
43
+ maxEntries: 1e5,
44
+ maxLength: 1e6,
45
+ onCycle: "marker"
46
+ });
47
+ var CANONICAL_DEFAULTS = Object.freeze({
48
+ maxDepth: 1e3,
49
+ maxEntries: 1e5,
50
+ maxLength: 16 * 1024 * 1024
51
+ });
52
+ var StableStringifyLimitError = class extends RangeError {
53
+ constructor(kind, limit, path) {
54
+ const location = formatPath(path);
55
+ super(`Stable stringify ${kind} limit of ${limit} exceeded at ${location}`);
56
+ this.name = "StableStringifyLimitError";
57
+ this.code = "ERR_STABLE_STRINGIFY_LIMIT";
58
+ this.kind = kind;
59
+ this.limit = limit;
60
+ this.path = location;
61
+ }
62
+ };
63
+ var CanonicalizationError = class extends TypeError {
64
+ constructor(reason, path) {
65
+ const location = formatPath(path);
66
+ super(`JSON canonicalization failed at ${location}: ${reason}`);
67
+ this.name = "CanonicalizationError";
68
+ this.code = "ERR_JSON_CANONICALIZATION";
69
+ this.path = location;
70
+ this.reason = reason;
71
+ }
72
+ };
73
+ function stableStringify(value, inputOptions) {
74
+ const options = normalizeStableOptions(inputOptions);
75
+ return serialize(value, options, false);
76
+ }
77
+ var stringify = stableStringify;
78
+ function configure(inputDefaults) {
79
+ const defaults = typeof inputDefaults === "function" ? { cmp: inputDefaults } : normalizeInputObject(inputDefaults);
80
+ normalizeStableOptions(defaults);
81
+ return function configuredStableStringify(value, inputOptions) {
82
+ const overrides = typeof inputOptions === "function" ? { cmp: inputOptions } : normalizeInputObject(inputOptions);
83
+ return stableStringify(value, { ...defaults, ...overrides });
84
+ };
85
+ }
86
+ function safeStringify(value, replacer, space, inputOptions) {
87
+ const options = normalizeInputObject(inputOptions);
88
+ const stableOptions = {
89
+ ...SAFE_DEFAULTS,
90
+ ...options,
91
+ maxDepth: options.maxDepth === void 0 ? options.depthLimit : options.maxDepth,
92
+ maxEntries: options.maxEntries === void 0 ? options.edgesLimit : options.maxEntries,
93
+ replacer: replacer === void 0 ? options.replacer : replacer,
94
+ space: space === void 0 ? options.space : space
95
+ };
96
+ if (stableOptions.maxDepth === void 0) {
97
+ stableOptions.maxDepth = SAFE_DEFAULTS.maxDepth;
98
+ }
99
+ if (stableOptions.maxEntries === void 0) {
100
+ stableOptions.maxEntries = SAFE_DEFAULTS.maxEntries;
101
+ }
102
+ try {
103
+ return stableStringify(value, stableOptions);
104
+ } catch (error) {
105
+ if (options.throwOnError === true) throw error;
106
+ let name = "UnknownError";
107
+ try {
108
+ if (error && typeof error.name === "string") {
109
+ name = error.name.slice(0, 80);
110
+ }
111
+ } catch (e) {
112
+ }
113
+ return JSON.stringify(`[Unable to serialize: ${name}]`);
114
+ }
115
+ }
116
+ function canonicalize(value, inputOptions) {
117
+ const options = normalizeCanonicalOptions(inputOptions);
118
+ return serialize(value, options, true);
119
+ }
120
+ function canonicalizeBytes(value, inputOptions) {
121
+ return encodeUtf8(canonicalize(value, inputOptions));
122
+ }
123
+ function serialize(rootValue, options, canonical) {
124
+ const state = {
125
+ ancestors: /* @__PURE__ */ new WeakMap(),
126
+ canonical,
127
+ chunks: [],
128
+ entries: 0,
129
+ length: 0,
130
+ options
131
+ };
132
+ const holder = { "": rootValue };
133
+ const prepared = prepareValue(rootValue, holder, "", ROOT_PATH, state);
134
+ if (prepared === OMIT) return void 0;
135
+ const tasks = [
136
+ {
137
+ depth: 0,
138
+ path: ROOT_PATH,
139
+ prepared,
140
+ type: "value"
141
+ }
142
+ ];
143
+ while (tasks.length > 0) {
144
+ const task = tasks.pop();
145
+ if (task.type === "value") {
146
+ processValueTask(task, tasks, state);
147
+ } else {
148
+ processContainerTask(task, tasks, state);
149
+ }
150
+ }
151
+ return state.chunks.join("");
152
+ }
153
+ function processValueTask(task, tasks, state) {
154
+ if (task.prepared.kind === "primitive") {
155
+ append(state, task.prepared.text, task.path);
156
+ return;
157
+ }
158
+ const value = task.prepared.value;
159
+ const previousPath = state.ancestors.get(value);
160
+ if (previousPath !== void 0 || state.ancestors.has(value)) {
161
+ appendCycle(state, previousPath, task.path);
162
+ return;
163
+ }
164
+ enforceDepth(state, task.depth, task.path);
165
+ const isArray = Array.isArray(value);
166
+ if (state.canonical && !isArray) validateCanonicalObject(value, task.path);
167
+ state.ancestors.set(value, task.path);
168
+ const frame = createContainerFrame(
169
+ value,
170
+ isArray,
171
+ task.depth,
172
+ task.path,
173
+ state
174
+ );
175
+ append(state, isArray ? "[" : "{", task.path);
176
+ if (frame.total === 0) {
177
+ append(state, isArray ? "]" : "}", task.path);
178
+ state.ancestors.delete(value);
179
+ return;
180
+ }
181
+ tasks.push(frame);
182
+ }
183
+ function processContainerTask(frame, tasks, state) {
184
+ if (frame.index >= frame.total) {
185
+ if (frame.emitted && state.options.gap !== "") {
186
+ append(state, `
187
+ ${frame.indent}`, frame.path);
188
+ }
189
+ append(state, frame.isArray ? "]" : "}", frame.path);
190
+ state.ancestors.delete(frame.value);
191
+ return;
192
+ }
193
+ if (frame.isArray) {
194
+ const index = frame.index;
195
+ frame.index += 1;
196
+ const path = createPath(frame.path, index);
197
+ consumeEntry(state, path);
198
+ const rawValue = readArrayValue(frame.value, index, path, state);
199
+ let prepared = prepareValue(
200
+ rawValue,
201
+ frame.value,
202
+ String(index),
203
+ path,
204
+ state
205
+ );
206
+ if (prepared === OMIT) prepared = primitive("null");
207
+ appendItemPrefix(frame, path, state);
208
+ tasks.push(frame);
209
+ tasks.push({
210
+ depth: frame.depth + 1,
211
+ path,
212
+ prepared,
213
+ type: "value"
214
+ });
215
+ return;
216
+ }
217
+ while (frame.index < frame.total) {
218
+ const key = frame.keys[frame.index];
219
+ frame.index += 1;
220
+ const path = createPath(frame.path, key);
221
+ consumeEntry(state, path);
222
+ const rawValue = readObjectValue(frame.value, key, path, state);
223
+ const prepared = prepareValue(rawValue, frame.value, key, path, state);
224
+ if (prepared === OMIT) continue;
225
+ appendItemPrefix(frame, path, state);
226
+ append(state, JSON.stringify(key), path);
227
+ append(state, state.options.gap === "" ? ":" : ": ", path);
228
+ tasks.push(frame);
229
+ tasks.push({
230
+ depth: frame.depth + 1,
231
+ path,
232
+ prepared,
233
+ type: "value"
234
+ });
235
+ return;
236
+ }
237
+ tasks.push(frame);
238
+ }
239
+ function createContainerFrame(value, isArray, depth, path, state) {
240
+ let keys;
241
+ let total;
242
+ if (isArray) {
243
+ total = value.length;
244
+ } else {
245
+ keys = getObjectKeys(value, path, state);
246
+ total = keys.length;
247
+ }
248
+ return {
249
+ depth,
250
+ emitted: false,
251
+ indent: state.options.gap === "" ? "" : state.options.gap.repeat(depth),
252
+ index: 0,
253
+ isArray,
254
+ keys,
255
+ path,
256
+ total,
257
+ type: "container",
258
+ value
259
+ };
260
+ }
261
+ function getObjectKeys(value, path, state) {
262
+ let keys;
263
+ if (state.canonical || state.options.propertyList === void 0) {
264
+ keys = Object.keys(value);
265
+ } else {
266
+ keys = state.options.propertyList.slice();
267
+ }
268
+ if (state.canonical) {
269
+ rejectEnumerableSymbols(value, path);
270
+ for (const key of keys) {
271
+ if (hasLoneSurrogate(key)) {
272
+ throw new CanonicalizationError(
273
+ "property names must not contain lone UTF-16 surrogates",
274
+ createPath(path, key)
275
+ );
276
+ }
277
+ }
278
+ return keys.sort();
279
+ }
280
+ if (state.options.accessors !== "invoke") {
281
+ keys = keys.filter((key) => {
282
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
283
+ if (!descriptor || !descriptor.get && !descriptor.set) return true;
284
+ if (state.options.accessors === "throw") {
285
+ throw new TypeError(
286
+ `Refusing to invoke accessor at ${formatPath(createPath(path, key))}`
287
+ );
288
+ }
289
+ return false;
290
+ });
291
+ }
292
+ if (state.options.cmp) {
293
+ const comparator = state.options.cmp;
294
+ keys.sort(
295
+ (left, right) => comparator(
296
+ { key: left, value: readForComparator(value, left, path, state) },
297
+ { key: right, value: readForComparator(value, right, path, state) }
298
+ )
299
+ );
300
+ } else {
301
+ keys.sort();
302
+ }
303
+ return keys;
304
+ }
305
+ function prepareValue(rawValue, holder, key, path, state) {
306
+ if (state.canonical) return prepareCanonicalValue(rawValue, path);
307
+ let value = rawValue;
308
+ if (state.options.toJSON && value !== null && value !== void 0) {
309
+ const method = value.toJSON;
310
+ if (typeof method === "function") value = method.call(value);
311
+ }
312
+ if (state.options.replacerFunction) {
313
+ value = state.options.replacerFunction.call(holder, key, value);
314
+ }
315
+ if (value === null) return primitive("null");
316
+ switch (typeof value) {
317
+ case "string":
318
+ return primitive(JSON.stringify(value));
319
+ case "number":
320
+ return primitive(Number.isFinite(value) ? String(value) : "null");
321
+ case "boolean":
322
+ return primitive(value ? "true" : "false");
323
+ case "bigint":
324
+ return prepareBigInt(value, state.options.bigint, path);
325
+ case "object":
326
+ return { kind: "object", value };
327
+ default:
328
+ return OMIT;
329
+ }
330
+ }
331
+ function prepareCanonicalValue(value, path) {
332
+ if (value === null) return primitive("null");
333
+ switch (typeof value) {
334
+ case "string":
335
+ if (hasLoneSurrogate(value)) {
336
+ throw new CanonicalizationError(
337
+ "strings must not contain lone UTF-16 surrogates",
338
+ path
339
+ );
340
+ }
341
+ return primitive(JSON.stringify(value));
342
+ case "number":
343
+ if (!Number.isFinite(value)) {
344
+ throw new CanonicalizationError(
345
+ "NaN and Infinity are not valid I-JSON numbers",
346
+ path
347
+ );
348
+ }
349
+ return primitive(JSON.stringify(value));
350
+ case "boolean":
351
+ return primitive(value ? "true" : "false");
352
+ case "object":
353
+ return { kind: "object", value };
354
+ case "bigint":
355
+ throw new CanonicalizationError(
356
+ "BigInt values must be represented as JSON strings",
357
+ path
358
+ );
359
+ default:
360
+ throw new CanonicalizationError(
361
+ `values of type ${typeof value} are not valid JSON data`,
362
+ path
363
+ );
364
+ }
365
+ }
366
+ function prepareBigInt(value, mode, path) {
367
+ if (mode === "string") return primitive(JSON.stringify(String(value)));
368
+ if (mode === "number") {
369
+ const number = Number(value);
370
+ if (!Number.isSafeInteger(number)) {
371
+ throw new RangeError(
372
+ `BigInt at ${formatPath(path)} cannot be represented as a safe JSON number`
373
+ );
374
+ }
375
+ return primitive(String(number));
376
+ }
377
+ throw new TypeError("Do not know how to serialize a BigInt");
378
+ }
379
+ function primitive(text) {
380
+ return { kind: "primitive", text };
381
+ }
382
+ function readArrayValue(array, index, path, state) {
383
+ if (state.canonical) {
384
+ if (!hasOwn.call(array, index)) {
385
+ throw new CanonicalizationError(
386
+ "sparse arrays are not valid I-JSON data",
387
+ path
388
+ );
389
+ }
390
+ return readCanonicalDescriptor(array, String(index), path);
391
+ }
392
+ return readStableProperty(array, String(index), path, state.options.accessors);
393
+ }
394
+ function readObjectValue(object, key, path, state) {
395
+ if (state.canonical) return readCanonicalDescriptor(object, key, path);
396
+ return readStableProperty(object, key, path, state.options.accessors);
397
+ }
398
+ function readCanonicalDescriptor(object, key, path) {
399
+ const descriptor = Object.getOwnPropertyDescriptor(object, key);
400
+ if (!descriptor || descriptor.get || descriptor.set) {
401
+ throw new CanonicalizationError(
402
+ "accessor properties are not valid canonical JSON input",
403
+ path
404
+ );
405
+ }
406
+ return descriptor.value;
407
+ }
408
+ function readStableProperty(object, key, path, accessors) {
409
+ if (accessors === "invoke") return object[key];
410
+ const seen = /* @__PURE__ */ new WeakSet();
411
+ let current = object;
412
+ while (current !== null && !seen.has(current)) {
413
+ seen.add(current);
414
+ const descriptor = Object.getOwnPropertyDescriptor(current, key);
415
+ if (descriptor) {
416
+ if (!descriptor.get && !descriptor.set) return descriptor.value;
417
+ if (accessors === "throw") {
418
+ throw new TypeError(`Refusing to invoke accessor at ${formatPath(path)}`);
419
+ }
420
+ return void 0;
421
+ }
422
+ current = Object.getPrototypeOf(current);
423
+ }
424
+ return void 0;
425
+ }
426
+ function readForComparator(object, key, path, state) {
427
+ return readStableProperty(
428
+ object,
429
+ key,
430
+ createPath(path, key),
431
+ state.options.accessors
432
+ );
433
+ }
434
+ function validateCanonicalObject(value, path) {
435
+ const prototype = Object.getPrototypeOf(value);
436
+ if (prototype !== null && objectToString.call(value) !== "[object Object]") {
437
+ throw new CanonicalizationError(
438
+ "only JSON objects and arrays can be canonicalized",
439
+ path
440
+ );
441
+ }
442
+ if (prototype !== null && Object.getPrototypeOf(prototype) !== null) {
443
+ throw new CanonicalizationError(
444
+ "class instances must be converted to plain JSON objects",
445
+ path
446
+ );
447
+ }
448
+ }
449
+ function rejectEnumerableSymbols(value, path) {
450
+ if (typeof Object.getOwnPropertySymbols !== "function") return;
451
+ const symbols = Object.getOwnPropertySymbols(value);
452
+ if (symbols.some((symbol) => propertyIsEnumerable.call(value, symbol))) {
453
+ throw new CanonicalizationError(
454
+ "symbol properties are not valid JSON object members",
455
+ path
456
+ );
457
+ }
458
+ }
459
+ function appendItemPrefix(frame, path, state) {
460
+ if (state.options.gap === "") {
461
+ if (frame.emitted) append(state, ",", path);
462
+ } else {
463
+ const indentation = state.options.gap.repeat(frame.depth + 1);
464
+ append(state, frame.emitted ? `,
465
+ ${indentation}` : `
466
+ ${indentation}`, path);
467
+ }
468
+ frame.emitted = true;
469
+ }
470
+ function appendCycle(state, previousPath, currentPath) {
471
+ if (state.canonical) {
472
+ throw new CanonicalizationError("circular references are not valid JSON", currentPath);
473
+ }
474
+ switch (state.options.onCycle) {
475
+ case "marker":
476
+ append(state, JSON.stringify(state.options.cycleValue), currentPath);
477
+ return;
478
+ case "path":
479
+ append(
480
+ state,
481
+ JSON.stringify(`[Circular ${formatPath(previousPath)}]`),
482
+ currentPath
483
+ );
484
+ return;
485
+ case "null":
486
+ append(state, "null", currentPath);
487
+ return;
488
+ default:
489
+ throw new TypeError("Converting circular structure to JSON");
490
+ }
491
+ }
492
+ function append(state, text, path) {
493
+ const nextLength = state.length + text.length;
494
+ if (nextLength > state.options.maxLength) {
495
+ throw new StableStringifyLimitError(
496
+ "length",
497
+ state.options.maxLength,
498
+ path
499
+ );
500
+ }
501
+ state.length = nextLength;
502
+ state.chunks.push(text);
503
+ }
504
+ function enforceDepth(state, depth, path) {
505
+ if (depth > state.options.maxDepth) {
506
+ throw new StableStringifyLimitError(
507
+ "depth",
508
+ state.options.maxDepth,
509
+ path
510
+ );
511
+ }
512
+ }
513
+ function consumeEntry(state, path) {
514
+ state.entries += 1;
515
+ if (state.entries > state.options.maxEntries) {
516
+ throw new StableStringifyLimitError(
517
+ "entry",
518
+ state.options.maxEntries,
519
+ path
520
+ );
521
+ }
522
+ }
523
+ function normalizeStableOptions(inputOptions) {
524
+ const input = typeof inputOptions === "function" ? { cmp: inputOptions } : normalizeInputObject(inputOptions);
525
+ if (input.cmp !== void 0 && typeof input.cmp !== "function") {
526
+ throw new TypeError("cmp must be a function");
527
+ }
528
+ if (input.cycles !== void 0 && typeof input.cycles !== "boolean") {
529
+ throw new TypeError("cycles must be a boolean");
530
+ }
531
+ if (input.replacer !== void 0 && input.replacer !== null && typeof input.replacer !== "function" && !Array.isArray(input.replacer)) {
532
+ throw new TypeError("replacer must be a function or an array");
533
+ }
534
+ const onCycle = input.onCycle === void 0 ? input.cycles === true ? "marker" : "throw" : input.onCycle;
535
+ if (!["throw", "marker", "path", "null"].includes(onCycle)) {
536
+ throw new TypeError(
537
+ "onCycle must be 'throw', 'marker', 'path', or 'null'"
538
+ );
539
+ }
540
+ const bigint = input.bigint === void 0 ? "throw" : input.bigint;
541
+ if (!["throw", "string", "number"].includes(bigint)) {
542
+ throw new TypeError("bigint must be 'throw', 'string', or 'number'");
543
+ }
544
+ const accessors = input.accessors === void 0 ? "invoke" : input.accessors;
545
+ if (!["invoke", "omit", "throw"].includes(accessors)) {
546
+ throw new TypeError("accessors must be 'invoke', 'omit', or 'throw'");
547
+ }
548
+ if (input.toJSON !== void 0 && typeof input.toJSON !== "boolean") {
549
+ throw new TypeError("toJSON must be a boolean");
550
+ }
551
+ if (input.cycleValue !== void 0 && typeof input.cycleValue !== "string") {
552
+ throw new TypeError("cycleValue must be a string");
553
+ }
554
+ return {
555
+ accessors,
556
+ bigint,
557
+ cmp: input.cmp,
558
+ cycleValue: input.cycleValue === void 0 ? "__cycle__" : input.cycleValue,
559
+ gap: normalizeGap(input.space),
560
+ maxDepth: normalizeLimit(input.maxDepth, Infinity, "maxDepth"),
561
+ maxEntries: normalizeLimit(input.maxEntries, Infinity, "maxEntries"),
562
+ maxLength: normalizeLimit(input.maxLength, Infinity, "maxLength"),
563
+ onCycle,
564
+ propertyList: Array.isArray(input.replacer) ? normalizePropertyList(input.replacer) : void 0,
565
+ replacerFunction: typeof input.replacer === "function" ? input.replacer : void 0,
566
+ toJSON: input.toJSON === void 0 ? true : input.toJSON
567
+ };
568
+ }
569
+ function normalizeCanonicalOptions(inputOptions) {
570
+ const input = normalizeInputObject(inputOptions);
571
+ return {
572
+ accessors: "throw",
573
+ bigint: "throw",
574
+ cmp: void 0,
575
+ cycleValue: "",
576
+ gap: "",
577
+ maxDepth: normalizeLimit(
578
+ input.maxDepth,
579
+ CANONICAL_DEFAULTS.maxDepth,
580
+ "maxDepth"
581
+ ),
582
+ maxEntries: normalizeLimit(
583
+ input.maxEntries,
584
+ CANONICAL_DEFAULTS.maxEntries,
585
+ "maxEntries"
586
+ ),
587
+ maxLength: normalizeLimit(
588
+ input.maxLength,
589
+ CANONICAL_DEFAULTS.maxLength,
590
+ "maxLength"
591
+ ),
592
+ onCycle: "throw",
593
+ propertyList: void 0,
594
+ replacerFunction: void 0,
595
+ toJSON: false
596
+ };
597
+ }
598
+ function normalizeInputObject(value) {
599
+ if (value === void 0 || value === null) return {};
600
+ if (typeof value !== "object") {
601
+ throw new TypeError("options must be an object when provided");
602
+ }
603
+ return { ...value };
604
+ }
605
+ function normalizeLimit(value, fallback, name) {
606
+ const resolved = value === void 0 ? fallback : value;
607
+ if (resolved === Infinity) return resolved;
608
+ if (!Number.isSafeInteger(resolved) || resolved < 0) {
609
+ throw new TypeError(
610
+ `${name} must be a non-negative safe integer or Infinity`
611
+ );
612
+ }
613
+ return resolved;
614
+ }
615
+ function normalizeGap(space) {
616
+ if (typeof space === "number") {
617
+ return " ".repeat(Math.min(10, Math.max(0, Math.trunc(space))));
618
+ }
619
+ if (typeof space === "string") return space.slice(0, 10);
620
+ return "";
621
+ }
622
+ function normalizePropertyList(input) {
623
+ const output = [];
624
+ const seen = /* @__PURE__ */ new Set();
625
+ for (const item of input) {
626
+ let key;
627
+ if (typeof item === "string" || typeof item === "number") {
628
+ key = String(item);
629
+ } else if (item && (objectToString.call(item) === "[object String]" || objectToString.call(item) === "[object Number]")) {
630
+ key = String(item);
631
+ }
632
+ if (key !== void 0 && !seen.has(key)) {
633
+ seen.add(key);
634
+ output.push(key);
635
+ }
636
+ }
637
+ return output;
638
+ }
639
+ function hasLoneSurrogate(value) {
640
+ for (let index = 0; index < value.length; index += 1) {
641
+ const code = value.charCodeAt(index);
642
+ if (code >= 55296 && code <= 56319) {
643
+ const next = value.charCodeAt(index + 1);
644
+ if (!(next >= 56320 && next <= 57343)) return true;
645
+ index += 1;
646
+ } else if (code >= 56320 && code <= 57343) {
647
+ return true;
648
+ }
649
+ }
650
+ return false;
651
+ }
652
+ function createPath(parent, key) {
653
+ return { key, parent };
654
+ }
655
+ function formatPath(path) {
656
+ if (path === ROOT_PATH) return "<root>";
657
+ const parts = [];
658
+ let current = path;
659
+ while (current !== ROOT_PATH) {
660
+ parts.push(current.key);
661
+ current = current.parent;
662
+ }
663
+ parts.reverse();
664
+ let output = "<root>";
665
+ for (const part of parts) {
666
+ if (typeof part === "number") {
667
+ output += `[${part}]`;
668
+ } else if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(part)) {
669
+ output += `.${part}`;
670
+ } else {
671
+ output += `[${JSON.stringify(part)}]`;
672
+ }
673
+ }
674
+ return output;
675
+ }
676
+ function encodeUtf8(value) {
677
+ if (typeof TextEncoder === "function") return new TextEncoder().encode(value);
678
+ const bytes = [];
679
+ for (let index = 0; index < value.length; index += 1) {
680
+ let code = value.charCodeAt(index);
681
+ if (code >= 55296 && code <= 56319) {
682
+ const next = value.charCodeAt(index + 1);
683
+ code = (code - 55296 << 10) + (next - 56320) + 65536;
684
+ index += 1;
685
+ }
686
+ if (code <= 127) {
687
+ bytes.push(code);
688
+ } else if (code <= 2047) {
689
+ bytes.push(192 | code >> 6, 128 | code & 63);
690
+ } else if (code <= 65535) {
691
+ bytes.push(
692
+ 224 | code >> 12,
693
+ 128 | code >> 6 & 63,
694
+ 128 | code & 63
695
+ );
696
+ } else {
697
+ bytes.push(
698
+ 240 | code >> 18,
699
+ 128 | code >> 12 & 63,
700
+ 128 | code >> 6 & 63,
701
+ 128 | code & 63
702
+ );
703
+ }
704
+ }
705
+ return Uint8Array.from(bytes);
706
+ }
707
+ Object.defineProperties(stableStringify, {
708
+ CanonicalizationError: { value: CanonicalizationError },
709
+ StableStringifyLimitError: { value: StableStringifyLimitError },
710
+ canonicalize: { value: canonicalize },
711
+ canonicalizeBytes: { value: canonicalizeBytes },
712
+ configure: { value: configure },
713
+ default: { value: stableStringify },
714
+ safeStringify: { value: safeStringify },
715
+ stable: { value: stableStringify },
716
+ stableStringify: { value: stableStringify },
717
+ stringify: { value: stableStringify }
718
+ });
719
+ Object.defineProperties(safeStringify, {
720
+ stable: { value: stableStringify },
721
+ stableStringify: { value: stableStringify }
722
+ });
723
+ var index_default = stableStringify;
724
+ return __toCommonJS(index_exports);
725
+ })();
726
+ var stableStringifyExport = StacklineStableStringifyModule.default;
727
+ module.exports = stableStringifyExport;
728
+ //# sourceMappingURL=index.cjs.map