json-6 1.1.4 → 1.1.6

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.mjs CHANGED
@@ -1,160 +1,279 @@
1
- function createCommonjsModule(fn, module) {
2
- return module = { exports: {} }, fn(module, module.exports), module.exports;
1
+ function getDefaultExportFromCjs (x) {
2
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
3
3
  }
4
4
 
5
- var json6 = createCommonjsModule(function (module, exports) {
6
-
7
- const version = "1.1.1";
8
- const VALUE_UNDEFINED = -1;
9
- const VALUE_UNSET = 0;
10
- const VALUE_NULL = 1;
11
- const VALUE_TRUE = 2;
12
- const VALUE_FALSE = 3;
13
- const VALUE_STRING = 4;
14
- const VALUE_NUMBER = 5;
15
- const VALUE_OBJECT = 6;
16
- const VALUE_ARRAY = 7;
17
- const VALUE_NEG_NAN = 8;
18
- const VALUE_NAN = 9;
19
- const VALUE_NEG_INFINITY = 10;
20
- const VALUE_INFINITY = 11; // const VALUE_DATE = 12 // unused yet
21
-
22
- const VALUE_EMPTY = 13; // [,] makes an array with 'empty item'
23
-
24
- const WORD_POS_RESET = 0;
25
- const WORD_POS_TRUE_1 = 1;
26
- const WORD_POS_TRUE_2 = 2;
27
- const WORD_POS_TRUE_3 = 3;
28
- const WORD_POS_FALSE_1 = 5;
29
- const WORD_POS_FALSE_2 = 6;
30
- const WORD_POS_FALSE_3 = 7;
31
- const WORD_POS_FALSE_4 = 8;
32
- const WORD_POS_NULL_1 = 9;
33
- const WORD_POS_NULL_2 = 10;
34
- const WORD_POS_NULL_3 = 11;
35
- const WORD_POS_UNDEFINED_1 = 12;
36
- const WORD_POS_UNDEFINED_2 = 13;
37
- const WORD_POS_UNDEFINED_3 = 14;
38
- const WORD_POS_UNDEFINED_4 = 15;
39
- const WORD_POS_UNDEFINED_5 = 16;
40
- const WORD_POS_UNDEFINED_6 = 17;
41
- const WORD_POS_UNDEFINED_7 = 18;
42
- const WORD_POS_UNDEFINED_8 = 19;
43
- const WORD_POS_NAN_1 = 20;
44
- const WORD_POS_NAN_2 = 21;
45
- const WORD_POS_INFINITY_1 = 22;
46
- const WORD_POS_INFINITY_2 = 23;
47
- const WORD_POS_INFINITY_3 = 24;
48
- const WORD_POS_INFINITY_4 = 25;
49
- const WORD_POS_INFINITY_5 = 26;
50
- const WORD_POS_INFINITY_6 = 27;
51
- const WORD_POS_INFINITY_7 = 28;
52
- const WORD_POS_FIELD = 29;
53
- const WORD_POS_AFTER_FIELD = 30;
54
- const WORD_POS_END = 31;
55
- const CONTEXT_UNKNOWN = 0;
56
- const CONTEXT_IN_ARRAY = 1; // const CONTEXT_IN_OBJECT = 2
57
-
58
- const CONTEXT_OBJECT_FIELD = 3;
59
- const CONTEXT_OBJECT_FIELD_VALUE = 4;
60
- const contexts = [];
61
-
62
- function getContext() {
63
- return contexts.pop() || {
64
- context: CONTEXT_UNKNOWN,
65
- elements: null,
66
- element_array: null
67
- };
68
- }
69
-
70
- function dropContext(ctx) {
71
- contexts.push(ctx);
72
- }
73
-
74
- const buffers = [];
75
-
76
- function getBuffer() {
77
- let buf = buffers.pop();
78
- if (!buf) buf = {
79
- buf: null,
80
- n: 0
81
- };else buf.n = 0;
82
- return buf;
83
- }
84
-
85
- function dropBuffer(buf) {
86
- buffers.push(buf);
87
- }
88
-
89
- const JSON6 = exports // istanbul ignore next
90
- ;
91
- /*
92
- let _DEBUG_LL = true;
93
- let _DEBUG_PARSING = true;
94
- let _DEBUG_PARSING_STACK = true;
95
-
96
- const log = function(type) {
97
- if (type === '_DEBUG_PARSING' && !_DEBUG_PARSING) {
98
- return;
99
- }
100
- if (type === '_DEBUG_PARSING_STACK' && !_DEBUG_PARSING_STACK) {
101
- return;
102
- }
103
- if (type === '_DEBUG_LL' && !_DEBUG_LL) {
104
- return;
105
- }
106
- console.log.apply(console, [].slice.call(arguments, 1));
107
- };
108
- */
109
-
110
- JSON6.escape = function (string) {
111
- let output = '';
112
- if (!string) return string;
113
-
114
- for (let n = 0; n < string.length; n++) {
115
- const ch = string[n];
5
+ var json6 = {exports: {}};
6
+
7
+ var hasRequiredJson6;
8
+ function requireJson6() {
9
+ if (hasRequiredJson6) return json6.exports;
10
+ hasRequiredJson6 = 1;
11
+ (function (module) {
12
+
13
+ const version = "1.1.6";
14
+ const VALUE_UNDEFINED = -1;
15
+ const VALUE_UNSET = 0;
16
+ const VALUE_NULL = 1;
17
+ const VALUE_TRUE = 2;
18
+ const VALUE_FALSE = 3;
19
+ const VALUE_STRING = 4;
20
+ const VALUE_NUMBER = 5;
21
+ const VALUE_OBJECT = 6;
22
+ const VALUE_ARRAY = 7;
23
+ const VALUE_NEG_NAN = 8;
24
+ const VALUE_NAN = 9;
25
+ const VALUE_NEG_INFINITY = 10;
26
+ const VALUE_INFINITY = 11;
27
+ // const VALUE_DATE = 12 // unused yet
28
+ const VALUE_EMPTY = 13; // [,] makes an array with 'empty item'
29
+
30
+ const WORD_POS_RESET = 0;
31
+ const WORD_POS_TRUE_1 = 1;
32
+ const WORD_POS_TRUE_2 = 2;
33
+ const WORD_POS_TRUE_3 = 3;
34
+ const WORD_POS_FALSE_1 = 5;
35
+ const WORD_POS_FALSE_2 = 6;
36
+ const WORD_POS_FALSE_3 = 7;
37
+ const WORD_POS_FALSE_4 = 8;
38
+ const WORD_POS_NULL_1 = 9;
39
+ const WORD_POS_NULL_2 = 10;
40
+ const WORD_POS_NULL_3 = 11;
41
+ const WORD_POS_UNDEFINED_1 = 12;
42
+ const WORD_POS_UNDEFINED_2 = 13;
43
+ const WORD_POS_UNDEFINED_3 = 14;
44
+ const WORD_POS_UNDEFINED_4 = 15;
45
+ const WORD_POS_UNDEFINED_5 = 16;
46
+ const WORD_POS_UNDEFINED_6 = 17;
47
+ const WORD_POS_UNDEFINED_7 = 18;
48
+ const WORD_POS_UNDEFINED_8 = 19;
49
+ const WORD_POS_NAN_1 = 20;
50
+ const WORD_POS_NAN_2 = 21;
51
+ const WORD_POS_INFINITY_1 = 22;
52
+ const WORD_POS_INFINITY_2 = 23;
53
+ const WORD_POS_INFINITY_3 = 24;
54
+ const WORD_POS_INFINITY_4 = 25;
55
+ const WORD_POS_INFINITY_5 = 26;
56
+ const WORD_POS_INFINITY_6 = 27;
57
+ const WORD_POS_INFINITY_7 = 28;
58
+ const WORD_POS_FIELD = 29;
59
+ const WORD_POS_AFTER_FIELD = 30;
60
+ const WORD_POS_END = 31;
61
+ const CONTEXT_UNKNOWN = 0;
62
+ const CONTEXT_IN_ARRAY = 1;
63
+ // const CONTEXT_IN_OBJECT = 2
64
+ const CONTEXT_OBJECT_FIELD = 3;
65
+ const CONTEXT_OBJECT_FIELD_VALUE = 4;
66
+
67
+ // Matches an ECMAScript `IdentifierName` (the production that may appear
68
+ // unquoted as an object-literal property key in JavaScript). Used only by the
69
+ // opt-in `esStrictCompatible` mode to reject unquoted keys JavaScript would
70
+ // not accept.
71
+ const ES_IDENTIFIER_NAME = /^[$_\p{ID_Start}][$_\p{ID_Continue}]*$/u;
72
+
73
+ // Matches a NumericLiteralSeparator ('_') only where it is legal: between two
74
+ // digits. Used only by `esStrictCompatible` to recognize unquoted numeric keys
75
+ // like `1_000` as valid JS -- `Number()` itself rejects the underscore.
76
+ const NUMERIC_SEPARATOR = /(\d)_(?=\d)/g;
77
+
78
+ /**
79
+ * @typedef {{
80
+ * n: number,
81
+ * buf: null|string
82
+ * }} Json6Node
83
+ */
84
+
85
+ /**
86
+ * Options accepted by {@link JSON6.parse} and {@link JSON6.begin}. All are
87
+ * off by default: with no options JSON6 accepts its full historical grammar.
88
+ *
89
+ * @typedef {object} Json6ParseOptions
90
+ * @property {boolean} [esStrictCompatible] When `true`, reject the JSON6
91
+ * extensions that are not valid in ECMAScript strict mode, so accepted
92
+ * input can be pasted into a module or `eval`'d unchanged: legacy-octal /
93
+ * leading-zero numbers (`0123`); legacy octal string escapes (`"\012"`,
94
+ * `"\1"`..`"\9"`); literal line terminators inside `'`/`"` strings
95
+ * (backtick strings still allow them); backtick-quoted object keys;
96
+ * unquoted object keys that are neither identifiers nor numbers; and two or
97
+ * more consecutive unary `+`/`-` signs. Defaults to `false`.
98
+ * @property {boolean} [forbidTemplateSubstitution] When `true`, reject an
99
+ * unescaped `${` inside a backtick-quoted string, so a document cannot
100
+ * silently turn into a template-literal substitution if later evaluated as
101
+ * JavaScript. Independent of `esStrictCompatible`. Defaults to `false`.
102
+ * @property {boolean} [warnWithCommentWithoutEOL] When `true`, a `//` comment
103
+ * that reaches the end of the document with no terminating line break logs
104
+ * a console warning. The input is accepted either way. Defaults to `false`.
105
+ * @property {boolean} [normalizeNumericKeys] When `true`, an unquoted object
106
+ * key that parses as a number is replaced with `String(Number(key))`, so
107
+ * `{1e3: true}` gets the key `"1000"` instead of the source text `"1e3"` --
108
+ * matching what a real JS object literal would produce. Independent of
109
+ * `esStrictCompatible` (does not require it). Note: `Number()` parses a
110
+ * leading-zero digit string like `"0123"` as decimal (123), while a real JS
111
+ * numeric literal `0123` is legacy octal (83) in sloppy mode; combine with
112
+ * `esStrictCompatible` (which forbids leading-zero numbers outright) for a
113
+ * guaranteed match. Defaults to `false`.
114
+ */
115
+
116
+ /**
117
+ * @template T
118
+ * @typedef {object} NodeInfo
119
+ * @property {T} node
120
+ * @property {NodeInfo<T>|null|undefined} next
121
+ * @property {NodeInfo<T>|null} prior
122
+ */
123
+
124
+ /**
125
+ * @typedef {object} Context
126
+ * @property {0|1|3|4} context
127
+ * @property {Record<string, unknown>|null|undefined} elements
128
+ * @property {unknown[]|null} element_array
129
+ * @property {string|null} name
130
+ */
131
+
132
+ /**
133
+ * @type {Context[]}
134
+ */
135
+ const contexts = [];
136
+ function getContext() {
137
+ return /** @type {Context} */contexts.pop() || (/** @type {Context} */{
138
+ context: CONTEXT_UNKNOWN,
139
+ elements: null,
140
+ element_array: null,
141
+ name: null
142
+ });
143
+ }
116
144
 
117
- if (ch == '"' || ch == '\\' || ch == '`' || ch == '\'') {
118
- output += '\\';
119
- }
145
+ /**
146
+ * @param {Context} ctx
147
+ */
148
+ function dropContext(ctx) {
149
+ contexts.push(ctx);
150
+ }
120
151
 
121
- output += ch;
152
+ /** @type {Json6Node[]} */
153
+ const buffers = [];
154
+ function getBuffer() {
155
+ /** @type {Json6Node|undefined} */
156
+ let buf = buffers.pop();
157
+ if (!buf) buf = {
158
+ buf: null,
159
+ n: 0
160
+ };else buf.n = 0;
161
+ return /** @type {Json6Node} */buf;
122
162
  }
123
163
 
124
- return output;
125
- };
164
+ /**
165
+ * @param {Json6Node} buf
166
+ */
167
+ function dropBuffer(buf) {
168
+ buffers.push(buf);
169
+ }
126
170
 
127
- JSON6.begin = function (cb, reviver) {
128
- const val = {
129
- name: null,
130
- // name of this value (if it's contained in an object)
131
- value_type: VALUE_UNSET,
132
- // value from above indiciating the type of this value
133
- string: '',
134
- // the string value of this value (strings and number types only)
135
- contains: null
171
+ /**
172
+ * @template T
173
+ * @param {T|undefined} value
174
+ * @param {string} [msg]
175
+ * @returns {T}
176
+ */
177
+ function ensureDefined(value, msg) {
178
+ /* istanbul ignore next -- every call site checks buf.length before consuming a code point, so codePointAt never actually returns undefined here */
179
+ if (value === undefined) throw new Error(msg || "Unexpected undefined value");
180
+ return value;
181
+ }
182
+ const JSON6 = {};
183
+
184
+ /*
185
+ let _DEBUG_LL = true;
186
+ let _DEBUG_PARSING = true;
187
+ let _DEBUG_PARSING_STACK = true;
188
+ const log = function(type) {
189
+ if (type === '_DEBUG_PARSING' && !_DEBUG_PARSING) {
190
+ return;
191
+ }
192
+ if (type === '_DEBUG_PARSING_STACK' && !_DEBUG_PARSING_STACK) {
193
+ return;
194
+ }
195
+ if (type === '_DEBUG_LL' && !_DEBUG_LL) {
196
+ return;
197
+ }
198
+ console.log.apply(console, [].slice.call(arguments, 1));
136
199
  };
137
- const pos = {
138
- line: 1,
139
- col: 1
200
+ */
201
+
202
+ /**
203
+ * @param {string} string
204
+ * @returns {string}
205
+ */
206
+ JSON6.escape = function (string) {
207
+ let output = '';
208
+ if (!string) return string;
209
+ for (let n = 0; n < string.length; n++) {
210
+ const ch = string[n];
211
+ if (ch == '"' || ch == '\\' || ch == '`' || ch == '\'') {
212
+ output += '\\';
213
+ }
214
+ output += ch;
215
+ }
216
+ return output;
140
217
  };
141
- let n = 0;
142
- let word = WORD_POS_RESET,
218
+
219
+ /**
220
+ * @callback Json6Reviver
221
+ * @param {string} key
222
+ * @param {unknown} value
223
+ * @returns {unknown}
224
+ */
225
+
226
+ /**
227
+ * @param {(value: unknown) => void} [cb]
228
+ * @param {Json6Reviver|undefined} [reviver]
229
+ * @param {Json6ParseOptions} [options]
230
+ */
231
+ JSON6.begin = function (cb, reviver, options) {
232
+ const beginOptions = options;
233
+ /** @type {boolean} */
234
+ let esStrictCompatible = !!(beginOptions && beginOptions.esStrictCompatible);
235
+ /** @type {boolean} */
236
+ let forbidTemplateSubstitution = !!(beginOptions && beginOptions.forbidTemplateSubstitution);
237
+ /** @type {boolean} */
238
+ let warnWithCommentWithoutEOL = !!(beginOptions && beginOptions.warnWithCommentWithoutEOL);
239
+ /** @type {boolean} */
240
+ let normalizeNumericKeys = !!(beginOptions && beginOptions.normalizeNumericKeys);
241
+ const val = /** @type {{ name: string|null, value_type: number, string: string, contains: unknown }} */{
242
+ name: null,
243
+ // name of this value (if it's contained in an object)
244
+ value_type: VALUE_UNSET,
245
+ // value from above indiciating the type of this value
246
+ string: '',
247
+ // the string value of this value (strings and number types only)
248
+ contains: null
249
+ };
250
+ // col is incremented as each character is taken, so it starts at 0 and the first
251
+ // character of a line reports as column 1.
252
+ const pos = /** @type {{ line: number, col: number }} */{
253
+ line: 1,
254
+ col: 0
255
+ };
256
+ /** @type {number} */
257
+ let n = 0;
258
+ /** @type {number} */
259
+ let word = WORD_POS_RESET,
143
260
  status = true,
144
261
  negative = false,
145
- result = null,
146
- elements = undefined,
147
- element_array = [],
148
- parse_context = CONTEXT_UNKNOWN,
262
+ /** @type {unknown} */result = null,
263
+ /** @type {Record<string, unknown>|null|undefined} */elements = undefined,
264
+ /** @type {unknown[]|null} */element_array = [],
265
+ /** @type {0|1|3|4} */parse_context = CONTEXT_UNKNOWN,
149
266
  comment = 0,
150
267
  fromHex = false,
151
268
  decimal = false,
152
269
  exponent = false,
153
270
  exponent_sign = false,
154
271
  exponent_digit = false,
155
- gatheringStringFirstChar = null,
272
+ /** @type {number|null} */gatheringStringFirstChar = null,
156
273
  gatheringString = false,
157
274
  gatheringNumber = false,
275
+ signSeen = false,
276
+ // '+' or '-' seen; no number or keyword has followed it yet
158
277
  stringEscape = false,
159
278
  cr_escaped = false,
160
279
  unicodeWide = false,
@@ -162,1622 +281,1594 @@ var json6 = createCommonjsModule(function (module, exports) {
162
281
  stringHex = false,
163
282
  hex_char = 0,
164
283
  hex_char_len = 0,
165
- completed = false;
166
- const context_stack = {
167
- first: null,
168
- last: null,
169
- saved: null,
170
-
171
- push(node) {
172
- let recover = this.saved;
173
-
174
- if (recover) {
175
- this.saved = recover.next;
176
- recover.node = node;
177
- recover.next = null;
178
- recover.prior = this.last;
179
- } else {
180
- recover = {
181
- node: node,
182
- next: null,
183
- prior: this.last
184
- };
284
+ completed = false,
285
+ dollarSeen = false;
286
+ const context_stack =
287
+ /** @type {{
288
+ first: NodeInfo<Context>|null,
289
+ last: NodeInfo<Context>|null,
290
+ saved: NodeInfo<Context>|null|undefined,
291
+ push: (node: Context) => void,
292
+ pop: () => Context
293
+ }} */
294
+ {
295
+ first: null,
296
+ last: null,
297
+ saved: null,
298
+ /**
299
+ * @param {Context} node
300
+ */
301
+ push(node) {
302
+ /** @type {NodeInfo<Context>|null|undefined} */
303
+ let recover = this.saved;
304
+ if (recover) {
305
+ this.saved = recover.next;
306
+ recover.node = node;
307
+ recover.next = null;
308
+ recover.prior = this.last;
309
+ } else {
310
+ recover = /** @type {NodeInfo<Context>} */{
311
+ node: node,
312
+ next: null,
313
+ prior: this.last
314
+ };
315
+ }
316
+ if (!this.last) this.first = recover;
317
+ this.last = recover;
318
+ },
319
+ pop() {
320
+ const resultNode = this.last;
321
+ /* istanbul ignore next -- pop() is only ever called from parse_context states that were entered via a matching push(), so the stack can never be empty here */
322
+ if (!resultNode) throw new Error("context stack underflow");
323
+ if (!(this.last = resultNode.prior)) this.first = null;
324
+ resultNode.next = this.saved;
325
+ this.saved = resultNode;
326
+ return resultNode.node;
185
327
  }
186
-
187
- if (!this.last) this.first = recover;
188
- this.last = recover;
189
- },
190
-
191
- pop() {
192
- const result = this.last;
193
- if (!(this.last = result.prior)) this.first = null;
194
- result.next = this.saved;
195
- this.saved = result;
196
- return result.node;
197
- }
198
-
199
- };
200
- const inQueue = {
201
- first: null,
202
- last: null,
203
- saved: null,
204
-
205
- push(node) {
206
- let recover = this.saved;
207
-
208
- if (recover) {
328
+ };
329
+ const inQueue =
330
+ /** @type {{
331
+ save: NodeInfo<Json6Node>|null|undefined,
332
+ first: NodeInfo<Json6Node>|null|undefined,
333
+ last: NodeInfo<Json6Node>|null,
334
+ saved: NodeInfo<Json6Node>|null|undefined,
335
+ push: (node: Json6Node) => void,
336
+ shift: () => Json6Node|null,
337
+ unshift: (node: Json6Node) => void
338
+ }} */
339
+ {
340
+ /** @type {NodeInfo<Json6Node>|null|undefined} */
341
+ save: undefined,
342
+ /** @type {NodeInfo<Json6Node>|null|undefined} */
343
+ first: null,
344
+ /** @type {NodeInfo<Json6Node>|null} */
345
+ last: null,
346
+ /** @type {NodeInfo<Json6Node>|null|undefined} */
347
+ saved: null,
348
+ /**
349
+ * @param {Json6Node} node
350
+ */
351
+ push(node) {
352
+ /** @type {NodeInfo<Json6Node>|null|undefined} */
353
+ let recover = this.saved;
354
+ if (recover) {
355
+ this.saved = recover.next;
356
+ recover.node = node;
357
+ recover.next = null;
358
+ recover.prior = this.last;
359
+ } else {
360
+ recover = /** @type {NodeInfo<Json6Node>} */{
361
+ node: node,
362
+ next: null,
363
+ prior: this.last
364
+ };
365
+ }
366
+ if (!this.last) this.first = recover;else this.last.next = recover;
367
+ this.last = recover;
368
+ },
369
+ shift() {
370
+ const resultNode = this.first;
371
+ if (!resultNode) return null;
372
+ this.first = resultNode.next;
373
+ if (!this.first) this.last = null;
374
+ resultNode.next = this.saved;
375
+ this.saved = resultNode;
376
+ // node is in saved...
377
+ return resultNode.node;
378
+ },
379
+ /**
380
+ * @param {Json6Node} node
381
+ */
382
+ unshift(node) {
383
+ // usage in this module, recover will ALWAYS have a saved to use.
384
+ const recover = /** @type {NodeInfo<Json6Node>} */this.saved;
209
385
  this.saved = recover.next;
210
386
  recover.node = node;
211
- recover.next = null;
212
- recover.prior = this.last;
213
- } else {
214
- recover = {
215
- node: node,
216
- next: null,
217
- prior: this.last
218
- };
387
+ recover.next = this.first;
388
+ recover.prior = null;
389
+ if (!this.first) this.last = recover;
390
+ this.first = recover;
219
391
  }
392
+ };
220
393
 
221
- if (!this.last) this.first = recover;else this.last.next = recover;
222
- this.last = recover;
223
- },
224
-
225
- shift() {
226
- const result = this.first;
227
- if (!result) return null;
228
- this.first = result.next;
229
- if (!this.first) this.last = null;
230
- result.next = this.saved;
231
- this.saved = result; // node is in saved...
232
-
233
- return result.node;
234
- },
235
-
236
- unshift(node) {
237
- // usage in this module, recover will ALWAYS have a saved to use.
238
- const recover = this.saved; //if( recover ) {
239
-
240
- this.saved = recover.next;
241
- recover.node = node;
242
- recover.next = this.first;
243
- recover.prior = null; //} else { recover = { node : node, next : this.first, prior : null }; }
244
-
245
- if (!this.first) this.last = recover;
246
- this.first = recover;
394
+ /**
395
+ * @param {string} leader
396
+ */
397
+ function throwEndError(leader /* , c */) {
398
+ throw new Error(`${leader} at ${n} [${pos.line}:${pos.col}]`);
247
399
  }
248
-
249
- };
250
-
251
- function throwEndError(leader
252
- /* , c */
253
- ) {
254
- throw new Error(`${leader} at ${n} [${pos.line}:${pos.col}]`);
255
- }
256
-
257
- return {
258
- finalError() {
259
- if (comment !== 0) {
260
- // most of the time everything's good.
261
- switch (comment) {
262
- case 1:
263
- return throwEndError("Comment began at end of document");
264
-
265
- case 2:
266
- console.log("Warning: '//' comment without end of line ended document");
267
- break;
268
-
269
- case 3:
270
- return throwEndError("Open comment '/*' is missing close at end of document");
271
-
272
- case 4:
273
- return throwEndError("Incomplete '/* *' close at end of document");
400
+ return {
401
+ finalError() {
402
+ if (comment !== 0) {
403
+ // most of the time everything's good.
404
+ switch (comment) {
405
+ case 1:
406
+ return throwEndError("Comment began at end of document");
407
+ case 2:
408
+ if (warnWithCommentWithoutEOL) console.log("Warning: '//' comment without end of line ended document");
409
+ break;
410
+ case 3:
411
+ return throwEndError("Open comment '/*' is missing close at end of document");
412
+ case 4:
413
+ return throwEndError("Incomplete '/* *' close at end of document");
414
+ }
274
415
  }
275
- }
276
-
277
- if (gatheringString) throwEndError("Incomplete string");
278
- },
279
-
280
- value() {
281
- this.finalError();
282
- const r = result;
283
- result = undefined;
284
- return r;
285
- },
286
-
287
- reset() {
288
- word = WORD_POS_RESET;
289
- status = true;
290
- if (inQueue.last) inQueue.last.next = inQueue.save;
291
- inQueue.save = inQueue.first;
292
- inQueue.first = inQueue.last = null;
293
- if (context_stack.last) context_stack.last.next = context_stack.save;
294
- context_stack.save = inQueue.first;
295
- context_stack.first = context_stack.last = null; //= [];
296
-
297
- element_array = null;
298
- elements = undefined;
299
- parse_context = CONTEXT_UNKNOWN;
300
- val.value_type = VALUE_UNSET;
301
- val.name = null;
302
- val.string = '';
303
- pos.line = 1;
304
- pos.col = 1;
305
- negative = false;
306
- comment = 0;
307
- completed = false;
308
- gatheringString = false;
309
- stringEscape = false; // string stringEscape intro
310
-
311
- cr_escaped = false; // carraige return escaped
312
- //stringUnicode = false; // reading \u
313
- //unicodeWide = false; // reading \u{} in string
314
- //stringHex = false; // reading \x in string
315
- },
316
-
317
- write(msg) {
318
- let retcode;
319
- if (msg !== undefined && typeof msg !== "string") msg = String(msg);
320
- if (!status) throw new Error("Parser is in an error state, please reset.");
321
-
322
- for (retcode = this._write(msg, false); retcode > 0; retcode = this._write()) {
416
+ if (gatheringString) throwEndError("Incomplete string");
417
+ },
418
+ value() {
323
419
  this.finalError();
324
- if (typeof reviver === 'function') (function walk(holder, key) {
325
- const value = holder[key];
326
-
327
- if (value && typeof value === 'object') {
328
- for (const k in value) {
329
- if (Object.prototype.hasOwnProperty.call(value, k)) {
330
- const v = walk(value, k);
331
-
332
- if (v !== undefined) {
333
- value[k] = v;
334
- } else {
335
- delete value[k];
336
- }
337
- }
338
- }
339
- }
340
-
341
- return reviver.call(holder, key, value);
342
- })({
343
- '': result
344
- }, '');
345
- cb(result);
420
+ const r = result;
346
421
  result = undefined;
347
- if (retcode < 2) break;
348
- }
349
-
350
- if (retcode) this.finalError();
351
- },
352
-
353
- _write(msg, complete_at_end) {
354
- let input;
355
- let buf;
356
- let retval = 0;
357
-
358
- function throwError(leader, c) {
359
- throw new Error(`${leader} '${String.fromCodePoint(c)}' unexpected at ${n} (near '${buf.substr(n > 4 ? n - 4 : 0, n > 4 ? 3 : n - 1)}[${String.fromCodePoint(c)}]${buf.substr(n, 10)}') [${pos.line}:${pos.col}]`);
360
- }
361
-
362
- function RESET_VAL() {
422
+ return r;
423
+ },
424
+ /**
425
+ * @param {Json6ParseOptions} [resetOptions] Options for the next parse.
426
+ * When omitted, the options passed to `begin()` (if any) stay in
427
+ * effect.
428
+ */
429
+ reset(resetOptions) {
430
+ const activeOptions = resetOptions === undefined ? beginOptions : resetOptions;
431
+ esStrictCompatible = !!(activeOptions && activeOptions.esStrictCompatible);
432
+ forbidTemplateSubstitution = !!(activeOptions && activeOptions.forbidTemplateSubstitution);
433
+ warnWithCommentWithoutEOL = !!(activeOptions && activeOptions.warnWithCommentWithoutEOL);
434
+ normalizeNumericKeys = !!(activeOptions && activeOptions.normalizeNumericKeys);
435
+ word = WORD_POS_RESET;
436
+ status = true;
437
+ if (inQueue.last) inQueue.last.next = inQueue.save;
438
+ inQueue.save = inQueue.first;
439
+ inQueue.first = inQueue.last = null;
440
+ if (context_stack.last) context_stack.last.next = context_stack.saved;
441
+ context_stack.saved = inQueue.first;
442
+ context_stack.first = context_stack.last = null; //= [];
443
+ element_array = null;
444
+ elements = undefined;
445
+ parse_context = CONTEXT_UNKNOWN;
363
446
  val.value_type = VALUE_UNSET;
447
+ val.name = null;
364
448
  val.string = '';
365
- }
366
-
367
- function arrayPush() {
368
- switch (val.value_type) {
369
- case VALUE_NUMBER:
370
- element_array.push((negative ? -1 : 1) * Number(val.string));
371
- break;
372
-
373
- case VALUE_STRING:
374
- element_array.push(val.string);
375
- break;
376
-
377
- case VALUE_TRUE:
378
- element_array.push(true);
379
- break;
380
-
381
- case VALUE_FALSE:
382
- element_array.push(false);
383
- break;
384
-
385
- case VALUE_NEG_NAN:
386
- element_array.push(-NaN);
387
- break;
388
-
389
- case VALUE_NAN:
390
- element_array.push(NaN);
391
- break;
392
-
393
- case VALUE_NEG_INFINITY:
394
- element_array.push(-Infinity);
395
- break;
396
-
397
- case VALUE_INFINITY:
398
- element_array.push(Infinity);
399
- break;
400
-
401
- case VALUE_NULL:
402
- element_array.push(null);
403
- break;
404
-
405
- case VALUE_UNDEFINED:
406
- element_array.push(undefined);
407
- break;
408
-
409
- case VALUE_EMPTY:
410
- element_array.push(undefined);
411
- delete element_array[element_array.length - 1];
412
- break;
413
-
414
- case VALUE_OBJECT:
415
- element_array.push(val.contains);
416
- break;
417
-
418
- case VALUE_ARRAY:
419
- element_array.push(val.contains);
420
- break;
421
- }
422
- }
423
-
424
- function objectPush() {
425
- switch (val.value_type) {
426
- case VALUE_NUMBER:
427
- elements[val.name] = (negative ? -1 : 1) * Number(val.string);
428
- break;
429
-
430
- case VALUE_STRING:
431
- elements[val.name] = val.string;
432
- break;
433
-
434
- case VALUE_TRUE:
435
- elements[val.name] = true;
436
- break;
437
-
438
- case VALUE_FALSE:
439
- elements[val.name] = false;
440
- break;
441
-
442
- case VALUE_NEG_NAN:
443
- elements[val.name] = -NaN;
444
- break;
445
-
446
- case VALUE_NAN:
447
- elements[val.name] = NaN;
448
- break;
449
-
450
- case VALUE_NEG_INFINITY:
451
- elements[val.name] = -Infinity;
452
- break;
453
-
454
- case VALUE_INFINITY:
455
- elements[val.name] = Infinity;
456
- break;
457
-
458
- case VALUE_NULL:
459
- elements[val.name] = null;
460
- break;
461
-
462
- case VALUE_UNDEFINED:
463
- elements[val.name] = undefined;
464
- break;
465
-
466
- case VALUE_OBJECT:
467
- elements[val.name] = val.contains;
468
- break;
469
-
470
- case VALUE_ARRAY:
471
- elements[val.name] = val.contains;
472
- break;
449
+ pos.line = 1;
450
+ pos.col = 0;
451
+ negative = false;
452
+ signSeen = false;
453
+ comment = 0;
454
+ completed = false;
455
+ signSeen = false;
456
+ dollarSeen = false;
457
+ gatheringStringFirstChar = null;
458
+ gatheringString = false;
459
+ stringEscape = false; // string stringEscape intro
460
+ cr_escaped = false; // carraige return escaped
461
+ unicodeWide = false;
462
+ stringUnicode = false;
463
+ stringHex = false;
464
+ hex_char = 0;
465
+ hex_char_len = 0;
466
+ //stringUnicode = false; // reading \u
467
+ //unicodeWide = false; // reading \u{} in string
468
+ //stringHex = false; // reading \x in string
469
+ },
470
+ /**
471
+ * @param {unknown} [msg]
472
+ */
473
+ write(msg) {
474
+ /** @type {number} */
475
+ let retcode;
476
+ // write() is the push interface; values only leave it through the callback.
477
+ // parse() drives the same parser through _write()/value() and needs no callback.
478
+ if (!cb) throw new Error("Callback function must be passed to begin, or you can't get values from the stream.");
479
+ if (msg !== undefined && typeof msg !== "string") msg = String(msg);
480
+ if (!status) throw new Error("Parser is in an error state, please reset.");
481
+ for (retcode = this._write(/** @type {string|undefined|null} */msg, false); retcode > 0; retcode = this._write()) {
482
+ this.finalError();
483
+ if (typeof reviver === 'function')
484
+ /**
485
+ * @param {Record<string, unknown>} holder
486
+ * @param {string} key
487
+ * @returns {unknown}
488
+ */
489
+ (function walk(holder, key) {
490
+ const value = holder[key];
491
+ if (value && typeof value === 'object') {
492
+ const record = /** @type {Record<string, unknown>} */value;
493
+ for (const k in record) {
494
+ if (Object.prototype.hasOwnProperty.call(record, k)) {
495
+ const v = walk(record, k);
496
+ if (v !== undefined) {
497
+ record[k] = v;
498
+ } else {
499
+ delete record[k];
500
+ }
501
+ }
502
+ }
503
+ }
504
+ return reviver.call(holder, key, value);
505
+ })({
506
+ '': result
507
+ }, '');
508
+ cb(result);
509
+ result = undefined;
510
+ if (retcode < 2) break;
473
511
  }
474
- }
475
-
476
- function gatherString(start_c) {
512
+ if (retcode) this.finalError();
513
+ },
514
+ /**
515
+ * @param {string|undefined|null} [msg]
516
+ * @param {boolean} [complete_at_end]
517
+ */
518
+ _write(msg, complete_at_end) {
519
+ /** @type {Json6Node|null} */
520
+ let input;
521
+ /** @type {string} */
522
+ let buf = "";
523
+ /** @type {number} */
477
524
  let retval = 0;
478
525
 
479
- while (retval == 0 && n < buf.length) {
480
- let str = buf.charAt(n);
481
- const cInt = buf.codePointAt(n++);
482
-
483
- if (cInt >= 0x10000) {
484
- str += buf.charAt(n);
485
- n++;
486
- } //console.log( "gathering....", stringEscape, str, cInt, unicodeWide, stringHex, stringUnicode, hex_char_len );
487
-
488
-
489
- pos.col++;
526
+ /**
527
+ * @param {string} leader
528
+ * @param {number} c
529
+ */
530
+ function throwError(leader, c) {
531
+ throw new Error(`${leader} '${String.fromCodePoint(c)}' unexpected at ${n} (near '${buf.substr(n > 4 ? n - 4 : 0, n > 4 ? 3 : n - 1)}[${String.fromCodePoint(c)}]${buf.substr(n, 10)}') [${pos.line}:${pos.col}]`);
532
+ }
490
533
 
491
- if (cInt == start_c) {
492
- //( cInt == 34/*'"'*/ ) || ( cInt == 39/*'\''*/ ) || ( cInt == 96/*'`'*/ ) )
493
- if (stringEscape) {
494
- if (stringHex) throwError("Incomplete hexidecimal sequence", cInt);else if (unicodeWide) throwError("Incomplete long unicode sequence", cInt);else if (stringUnicode) throwError("Incomplete unicode sequence", cInt);
534
+ // Line bookkeeping for a character that has just been taken (n is past it).
535
+ // CR, LF, LS and PS each end a line; a CR directly followed by LF counts once,
536
+ // at the LF. (A CR that ends one write() chunk with the LF in the next counts
537
+ // twice; that is the one case this does not see.) Column resets to 0 so the
538
+ // next character lands on column 1.
539
+ /**
540
+ * @param {number} cInt
541
+ */
542
+ function countLine(cInt) {
543
+ if (cInt === 13 /*'\r'*/) {
544
+ if (n < buf.length && buf.charCodeAt(n) === 10) return;
545
+ } else if (cInt !== 10 /*'\n'*/ && cInt !== 0x2028 && cInt !== 0x2029) return;
546
+ pos.line++;
547
+ pos.col = 0;
548
+ }
549
+ function RESET_VAL() {
550
+ val.value_type = VALUE_UNSET;
551
+ val.string = '';
552
+ signSeen = false;
553
+ }
495
554
 
496
- if (cr_escaped) {
497
- cr_escaped = false; // \\ \r ' :end string, the backslash was used for \r
555
+ // A delimiter, or the end of the document, arrived while a value was still
556
+ // being spelled out: 'tru', 'nul', or a sign with nothing after it. Without
557
+ // this, '[tru]' was [] and 'tru' alone was undefined.
558
+ /**
559
+ * @param {number} [cInt] the delimiter; omitted at end of document
560
+ */
561
+ function checkPartialValue(cInt) {
562
+ if (word > WORD_POS_RESET && word < WORD_POS_FIELD) {
563
+ if (cInt === undefined) throwEndError("Incomplete keyword");else throwError("Incomplete keyword", cInt);
564
+ }
565
+ if (signSeen && val.value_type == VALUE_UNSET) {
566
+ if (cInt === undefined) throwEndError("Sign with no number following");else throwError("Sign with no number following", cInt);
567
+ }
568
+ }
498
569
 
499
- retval = 1; // complete string.
500
- } else val.string += str; // escaped start quote
570
+ // A new value is starting; there must not already be a finished one waiting
571
+ // for a separator. Without this, '[1 2]' kept only the 2.
572
+ /**
573
+ * @param {number} cInt
574
+ */
575
+ function checkValueSeparator(cInt) {
576
+ if (val.value_type != VALUE_UNSET) throwError("Two values with no separator between them", cInt);
577
+ }
501
578
 
579
+ // collectNumber only admits digits, a sign, one '.', one 'e' and a radix
580
+ // prefix, so a token Number() cannot read is malformed: '1e', '.5.', '.e3', '0x'.
581
+ // These used to come back as NaN.
582
+ function checkNumber() {
583
+ if (Number.isNaN(Number(val.string))) {
584
+ status = false;
585
+ throw new Error(`Invalid number '${val.string}' at ${n} [${pos.line}:${pos.col}]`);
586
+ }
587
+ }
588
+ function arrayPush() {
589
+ // invariant: only called while parse_context is CONTEXT_IN_ARRAY, which is only
590
+ // entered after '[' sets element_array to a real array.
591
+ const arr = /** @type {unknown[]} */element_array;
592
+ switch (val.value_type) {
593
+ case VALUE_NUMBER:
594
+ arr.push((negative ? -1 : 1) * Number(val.string));
595
+ break;
596
+ case VALUE_STRING:
597
+ arr.push(val.string);
598
+ break;
599
+ case VALUE_TRUE:
600
+ arr.push(true);
601
+ break;
602
+ case VALUE_FALSE:
603
+ arr.push(false);
604
+ break;
605
+ case VALUE_NEG_NAN:
606
+ arr.push(-NaN);
607
+ break;
608
+ case VALUE_NAN:
609
+ arr.push(NaN);
610
+ break;
611
+ case VALUE_NEG_INFINITY:
612
+ arr.push(-Infinity);
613
+ break;
614
+ case VALUE_INFINITY:
615
+ arr.push(Infinity);
616
+ break;
617
+ case VALUE_NULL:
618
+ arr.push(null);
619
+ break;
620
+ case VALUE_UNDEFINED:
621
+ arr.push(undefined);
622
+ break;
623
+ case VALUE_EMPTY:
624
+ arr.push(undefined);
625
+ delete arr[arr.length - 1];
626
+ break;
627
+ case VALUE_OBJECT:
628
+ arr.push(val.contains);
629
+ break;
630
+ case VALUE_ARRAY:
631
+ arr.push(val.contains);
632
+ break;
633
+ }
634
+ }
635
+ function objectPush() {
636
+ // invariant: only called while parse_context is CONTEXT_OBJECT_FIELD_VALUE, which is
637
+ // only entered after '{' sets elements to a real object.
638
+ const obj = /** @type {Record<string, unknown>} */elements;
639
+ const name = /** @type {string} */val.name;
640
+ switch (val.value_type) {
641
+ case VALUE_NUMBER:
642
+ obj[name] = (negative ? -1 : 1) * Number(val.string);
643
+ break;
644
+ case VALUE_STRING:
645
+ obj[name] = val.string;
646
+ break;
647
+ case VALUE_TRUE:
648
+ obj[name] = true;
649
+ break;
650
+ case VALUE_FALSE:
651
+ obj[name] = false;
652
+ break;
653
+ case VALUE_NEG_NAN:
654
+ obj[name] = -NaN;
655
+ break;
656
+ case VALUE_NAN:
657
+ obj[name] = NaN;
658
+ break;
659
+ case VALUE_NEG_INFINITY:
660
+ obj[name] = -Infinity;
661
+ break;
662
+ case VALUE_INFINITY:
663
+ obj[name] = Infinity;
664
+ break;
665
+ case VALUE_NULL:
666
+ obj[name] = null;
667
+ break;
668
+ case VALUE_UNDEFINED:
669
+ obj[name] = undefined;
670
+ break;
671
+ case VALUE_OBJECT:
672
+ obj[name] = val.contains;
673
+ break;
674
+ case VALUE_ARRAY:
675
+ obj[name] = val.contains;
676
+ break;
677
+ }
678
+ }
502
679
 
503
- stringEscape = false;
504
- } else {
505
- // quote matches, not escaped, and not processing escape...
506
- retval = 1;
680
+ /**
681
+ * @param {number} start_c
682
+ */
683
+ function gatherString(start_c) {
684
+ let retval = 0;
685
+ // Hoisted out of the per-character loop: these are constant for
686
+ // the whole string, so the default (non-strict) path adds no
687
+ // work beyond one predictable branch.
688
+ const strictQuote = esStrictCompatible && start_c !== 96 /*'`'*/;
689
+ const trackTemplate = start_c === 96 /*'`'*/ && forbidTemplateSubstitution;
690
+ while (retval == 0 && n < buf.length) {
691
+ let str = buf.charAt(n);
692
+ const cInt = ensureDefined(buf.codePointAt(n++), "Unexpected end of string");
693
+ if (cInt >= 0x10000) {
694
+ str += buf.charAt(n);
695
+ n++;
507
696
  }
508
- } else if (stringEscape) {
509
- if (unicodeWide) {
510
- if (cInt == 125
511
- /*'}'*/
512
- ) {
697
+ //console.log( "gathering....", stringEscape, str, cInt, unicodeWide, stringHex, stringUnicode, hex_char_len );
698
+ pos.col++;
699
+ if (cInt == start_c) {
700
+ //( cInt == 34/*'"'*/ ) || ( cInt == 39/*'\''*/ ) || ( cInt == 96/*'`'*/ ) )
701
+ if (stringEscape) {
702
+ if (stringHex) throwError("Incomplete hexidecimal sequence", cInt);else if (unicodeWide) throwError("Incomplete long unicode sequence", cInt);else if (stringUnicode) throwError("Incomplete unicode sequence", cInt);
703
+ if (cr_escaped) {
704
+ cr_escaped = false; // \\ \r ' :end string, the backslash was used for \r
705
+ retval = 1; // complete string.
706
+ } else val.string += str; // escaped start quote
707
+ stringEscape = false;
708
+ } else {
709
+ // quote matches, not escaped, and not processing escape...
710
+ retval = 1;
711
+ }
712
+ } else if (stringEscape) {
713
+ if (unicodeWide) {
714
+ if (cInt == 125 /*'}'*/) {
513
715
  val.string += String.fromCodePoint(hex_char);
514
716
  unicodeWide = false;
515
717
  stringUnicode = false;
516
718
  stringEscape = false;
517
719
  continue;
518
720
  }
519
-
520
- hex_char *= 16;
521
- if (cInt >= 48
522
- /*'0'*/
523
- && cInt <= 57
524
- /*'9'*/
525
- ) hex_char += cInt - 0x30;else if (cInt >= 65
526
- /*'A'*/
527
- && cInt <= 70
528
- /*'F'*/
529
- ) hex_char += cInt - 65 + 10;else if (cInt >= 97
530
- /*'a'*/
531
- && cInt <= 102
532
- /*'f'*/
533
- ) hex_char += cInt - 97 + 10;else {
534
- throwError("(escaped character, parsing hex of \\u)", cInt);
535
- }
536
- continue;
537
- } else if (stringHex || stringUnicode) {
538
- if (hex_char_len === 0 && cInt === 123
539
- /*'{'*/
540
- ) {
721
+ hex_char *= 16;
722
+ if (cInt >= 48 /*'0'*/ && cInt <= 57 /*'9'*/) hex_char += cInt - 0x30;else if (cInt >= 65 /*'A'*/ && cInt <= 70 /*'F'*/) hex_char += cInt - 65 + 10;else if (cInt >= 97 /*'a'*/ && cInt <= 102 /*'f'*/) hex_char += cInt - 97 + 10;else {
723
+ throwError("(escaped character, parsing hex of \\u)", cInt);
724
+ }
725
+ continue;
726
+ } else if (stringHex || stringUnicode) {
727
+ if (hex_char_len === 0 && cInt === 123 /*'{'*/) {
541
728
  unicodeWide = true;
542
729
  continue;
543
730
  }
544
-
545
- hex_char *= 16;
546
- if (cInt >= 48
547
- /*'0'*/
548
- && cInt <= 57
549
- /*'9'*/
550
- ) hex_char += cInt - 0x30;else if (cInt >= 65
551
- /*'A'*/
552
- && cInt <= 70
553
- /*'F'*/
554
- ) hex_char += cInt - 65 + 10;else if (cInt >= 97
555
- /*'a'*/
556
- && cInt <= 102
557
- /*'f'*/
558
- ) hex_char += cInt - 97 + 10;else {
559
- throwError(stringUnicode ? "(escaped character, parsing hex of \\u)" : "(escaped character, parsing hex of \\x)", cInt);
560
- }
561
- hex_char_len++;
562
-
563
- if (stringUnicode) {
564
- if (hex_char_len == 4) {
731
+ hex_char *= 16;
732
+ if (cInt >= 48 /*'0'*/ && cInt <= 57 /*'9'*/) hex_char += cInt - 0x30;else if (cInt >= 65 /*'A'*/ && cInt <= 70 /*'F'*/) hex_char += cInt - 65 + 10;else if (cInt >= 97 /*'a'*/ && cInt <= 102 /*'f'*/) hex_char += cInt - 97 + 10;else {
733
+ throwError(stringUnicode ? "(escaped character, parsing hex of \\u)" : "(escaped character, parsing hex of \\x)", cInt);
734
+ }
735
+ hex_char_len++;
736
+ if (stringUnicode) {
737
+ if (hex_char_len == 4) {
738
+ val.string += String.fromCodePoint(hex_char);
739
+ stringUnicode = false;
740
+ stringEscape = false;
741
+ }
742
+ } else if (hex_char_len == 2) {
565
743
  val.string += String.fromCodePoint(hex_char);
566
- stringUnicode = false;
744
+ stringHex = false;
567
745
  stringEscape = false;
568
746
  }
569
- } else if (hex_char_len == 2) {
570
- val.string += String.fromCodePoint(hex_char);
571
- stringHex = false;
572
- stringEscape = false;
573
- }
574
-
575
- continue;
576
- }
577
-
578
- switch (cInt) {
579
- case 13
580
- /*'\r'*/
581
- :
582
- cr_escaped = true;
583
- pos.col = 1;
584
747
  continue;
585
-
586
- case 0x2028: // LS (Line separator)
587
-
588
- case 0x2029:
589
- // PS (paragraph separator)
590
- pos.col = 1;
591
- // no return to get newline reset, so reset line pos.
592
- // Fallthrough
593
-
594
- case 10
595
- /*'\n'*/
596
- :
597
- if (cr_escaped) {
598
- // \\ \r \n
748
+ }
749
+ switch (cInt) {
750
+ case 13 /*'\r'*/:
751
+ // \\ \r : a continuation; if \n follows it is counted there
752
+ cr_escaped = true;
753
+ countLine(cInt);
754
+ continue;
755
+ case 0x2028: // LS (Line separator)
756
+ case 0x2029: // PS (paragraph separator)
757
+ case 10 /*'\n'*/:
599
758
  cr_escaped = false;
600
- } else {
601
- // \\ \n
602
- pos.col = 1;
603
- }
604
-
605
- pos.line++;
606
- break;
607
-
608
- case 116
609
- /*'t'*/
610
- :
611
- val.string += '\t';
612
- break;
613
-
614
- case 98
615
- /*'b'*/
616
- :
617
- val.string += '\b';
618
- break;
619
-
620
- case 48
621
- /*'0'*/
622
- :
623
- val.string += '\0';
624
- break;
625
-
626
- case 110
627
- /*'n'*/
628
- :
629
- val.string += '\n';
630
- break;
631
-
632
- case 114
633
- /*'r'*/
634
- :
635
- val.string += '\r';
636
- break;
637
-
638
- case 102
639
- /*'f'*/
640
- :
641
- val.string += '\f';
642
- break;
643
-
644
- case 118
645
- /*'v'*/
646
- :
647
- val.string += '\v';
648
- break;
649
-
650
- case 120
651
- /*'x'*/
652
- :
653
- stringHex = true;
654
- hex_char_len = 0;
655
- hex_char = 0;
656
- continue;
657
-
658
- case 117
659
- /*'u'*/
660
- :
661
- stringUnicode = true;
662
- hex_char_len = 0;
663
- hex_char = 0;
664
- continue;
665
-
666
- default:
667
- val.string += str;
668
- break;
669
- } //console.log( "other..." );
670
-
671
-
672
- stringEscape = false;
673
- } else if (cInt === 92
674
- /*'\\'*/
675
- ) {
759
+ countLine(cInt);
760
+ break;
761
+ case 116 /*'t'*/:
762
+ val.string += '\t';
763
+ break;
764
+ case 98 /*'b'*/:
765
+ val.string += '\b';
766
+ break;
767
+ case 48 /*'0'*/:
768
+ if (esStrictCompatible && buf.charCodeAt(n) >= 48 /*'0'*/ && buf.charCodeAt(n) <= 57 /*'9'*/) throwError("Legacy octal string escapes are not allowed when the 'esStrictCompatible' option is set", buf.charCodeAt(n));
769
+ val.string += '\0';
770
+ break;
771
+ case 110 /*'n'*/:
772
+ val.string += '\n';
773
+ break;
774
+ case 114 /*'r'*/:
775
+ val.string += '\r';
776
+ break;
777
+ case 102 /*'f'*/:
778
+ val.string += '\f';
779
+ break;
780
+ case 118 /*'v'*/:
781
+ val.string += '\v';
782
+ break;
783
+ case 120 /*'x'*/:
784
+ stringHex = true;
785
+ hex_char_len = 0;
786
+ hex_char = 0;
787
+ continue;
788
+ case 117 /*'u'*/:
789
+ stringUnicode = true;
790
+ hex_char_len = 0;
791
+ hex_char = 0;
792
+ continue;
793
+ default:
794
+ if (esStrictCompatible && cInt >= 49 /*'1'*/ && cInt <= 57 /*'9'*/) throwError("Legacy octal string escapes are not allowed when the 'esStrictCompatible' option is set", cInt);
795
+ val.string += str;
796
+ break;
797
+ }
798
+ //console.log( "other..." );
799
+ stringEscape = false;
800
+ } else if (cInt === 92 /*'\\'*/) {
676
801
  stringEscape = true;
802
+ dollarSeen = false;
677
803
  } else {
678
- if (cr_escaped) {
679
- cr_escaped = false; // \\ \r <any other character>
680
-
681
- pos.line++;
682
- pos.col = 2; // newline, plus one character.
804
+ // U+2028/U+2029 are legal, unescaped, inside string literals since
805
+ // ES2019 (the JSON-superset proposal); only \n and \r are illegal.
806
+ if (strictQuote && (cInt === 10 /*'\n'*/ || cInt === 13 /*'\r'*/)) throwError("Literal line terminators inside single- or double-quoted strings require the 'esStrictCompatible' option to be off", cInt);
807
+ if (trackTemplate) {
808
+ if (dollarSeen && cInt === 123 /*'{'*/) throwError("Template substitution ${ } is not allowed when the 'forbidTemplateSubstitution' option is set", cInt);
809
+ dollarSeen = cInt === 36 /*'$'*/;
810
+ }
811
+ // \\ \r <any other character> : the CR was counted when seen
812
+ cr_escaped = false;
813
+ countLine(cInt);
814
+ val.string += str;
683
815
  }
684
-
685
- val.string += str;
686
816
  }
817
+ return retval;
687
818
  }
688
-
689
- return retval;
690
- }
691
-
692
- function collectNumber() {
693
- let _n;
694
-
695
- while ((_n = n) < buf.length) {
696
- const str = buf.charAt(_n);
697
- const cInt = buf.codePointAt(n++);
698
-
699
- if (cInt >= 0x10000) {
700
- throwError("fault while parsing number;", cInt);
701
- } //log('_DEBUG_PARSING', "in getting number:", n, cInt, String.fromCodePoint(cInt) );
702
-
703
-
704
- if (cInt == 95
705
- /*_*/
706
- ) continue;
707
- pos.col++; // leading zeros should be forbidden.
708
-
709
- if (cInt >= 48
710
- /*'0'*/
711
- && cInt <= 57
712
- /*'9'*/
713
- ) {
819
+ function collectNumber() {
820
+ let _n;
821
+ while ((_n = n) < buf.length) {
822
+ const str = buf.charAt(_n);
823
+ const cInt = ensureDefined(buf.codePointAt(n++), "Unexpected end of number");
824
+ if (cInt >= 0x10000) {
825
+ throwError("fault while parsing number;", cInt);
826
+ }
827
+ //log('_DEBUG_PARSING', "in getting number:", n, cInt, String.fromCodePoint(cInt) );
828
+ pos.col++;
829
+ if (cInt == 95 /*_*/) continue;
830
+ // leading zeros should be forbidden.
831
+ if (cInt >= 48 /*'0'*/ && cInt <= 57 /*'9'*/) {
832
+ if (esStrictCompatible && val.string === '0') throwError("Legacy octal / leading-zero numbers are not allowed when the 'esStrictCompatible' option is set", cInt);
714
833
  if (exponent) {
715
834
  exponent_digit = true;
716
835
  }
717
-
718
836
  val.string += str;
719
- } else if (cInt == 45
720
- /*'-'*/
721
- || cInt == 43
722
- /*'+'*/
723
- ) {
837
+ } else if (cInt == 45 /*'-'*/ || cInt == 43 /*'+'*/) {
724
838
  if (val.string.length == 0 || exponent && !exponent_sign && !exponent_digit) {
725
839
  val.string += str;
726
840
  exponent_sign = true;
727
841
  } else {
728
842
  status = false;
729
- throwError("fault while parsing number;", cInt); // break;
843
+ throwError("fault while parsing number;", cInt);
844
+ // break;
730
845
  }
731
- } else if (cInt == 46
732
- /*'.'*/
733
- ) {
846
+ } else if (cInt == 46 /*'.'*/) {
734
847
  if (!decimal && !fromHex && !exponent) {
735
848
  val.string += str;
736
849
  decimal = true;
737
850
  } else {
738
851
  status = false;
739
- throwError("fault while parsing number;", cInt); // break;
852
+ throwError("fault while parsing number;", cInt);
853
+ // break;
740
854
  }
741
- } else if (fromHex && (cInt >= 95
742
- /*'a'*/
743
- && cInt <= 102
744
- /*'f'*/
745
- || cInt >= 65
746
- /*'A'*/
747
- && cInt <= 70
748
- /*'F'*/
749
- )) {
750
- val.string += str;
751
- } else if (cInt == 120
752
- /*'x'*/
753
- || cInt == 98
754
- /*'b'*/
755
- || cInt == 111
756
- /*'o'*/
757
- || cInt == 88
758
- /*'X'*/
759
- || cInt == 66
760
- /*'B'*/
761
- || cInt == 79
762
- /*'O'*/
763
- ) {
855
+ } else if (fromHex && (cInt >= 95 /*'a'*/ && cInt <= 102 /*'f'*/ || cInt >= 65 /*'A'*/ && cInt <= 70 /*'F'*/)) {
856
+ val.string += str;
857
+ } else if (cInt == 120 /*'x'*/ || cInt == 98 /*'b'*/ || cInt == 111 /*'o'*/ || cInt == 88 /*'X'*/ || cInt == 66 /*'B'*/ || cInt == 79 /*'O'*/) {
764
858
  // hex conversion.
765
859
  if (!fromHex && val.string == '0') {
766
860
  fromHex = true;
767
861
  val.string += str;
768
862
  } else {
769
863
  status = false;
770
- throwError("fault while parsing number;", cInt); // break;
864
+ throwError("fault while parsing number;", cInt);
865
+ // break;
771
866
  }
772
- } else if (cInt == 101
773
- /*'e'*/
774
- || cInt == 69
775
- /*'E'*/
776
- ) {
777
- if (!exponent) {
778
- val.string += str;
779
- exponent = true;
780
- } else {
781
- status = false;
782
- throwError("fault while parsing number;", cInt); // break;
783
- }
784
- } else {
785
- if (cInt == 32
786
- /*' '*/
787
- || cInt == 160
788
- /* &nbsp */
789
- || cInt == 13 || cInt == 10 || cInt == 9 || cInt == 0xFEFF || cInt == 44
790
- /*','*/
791
- || cInt == 125
792
- /*'}'*/
793
- || cInt == 93
794
- /*']'*/
795
- || cInt == 58
796
- /*':'*/
797
- ) {
798
- break;
867
+ } else if (cInt == 101 /*'e'*/ || cInt == 69 /*'E'*/) {
868
+ if (!exponent) {
869
+ val.string += str;
870
+ exponent = true;
799
871
  } else {
800
- if (complete_at_end) {
801
872
  status = false;
802
873
  throwError("fault while parsing number;", cInt);
874
+ // break;
803
875
  }
804
-
805
- break;
806
- }
807
- }
808
- }
809
-
810
- n = _n;
811
-
812
- if (!complete_at_end && n == buf.length) {
813
- gatheringNumber = true;
814
- } else {
815
- gatheringNumber = false;
816
- val.value_type = VALUE_NUMBER;
817
-
818
- if (parse_context == CONTEXT_UNKNOWN) {
819
- completed = true;
876
+ } else {
877
+ if (cInt == 32 /*' '*/ || cInt == 160 /* &nbsp */ || cInt == 13 || cInt == 10 || cInt == 9 || cInt == 11 /*VT*/ || cInt == 12 /*FF*/ || cInt == 0x2028 /*LS*/ || cInt == 0x2029 /*PS*/ || cInt == 0xFEFF || cInt == 44 /*','*/ || cInt == 125 /*'}'*/ || cInt == 93 /*']'*/ || cInt == 58 /*':'*/) {
878
+ break;
879
+ } else {
880
+ if (complete_at_end) {
881
+ status = false;
882
+ throwError("fault while parsing number;", cInt);
883
+ }
884
+ break;
885
+ }
886
+ }
820
887
  }
821
- }
822
- }
823
-
824
- if (!status) return -1;
825
-
826
- if (msg && msg.length) {
827
- input = getBuffer();
828
- input.buf = msg;
829
- inQueue.push(input);
830
- } else {
831
- if (gatheringNumber) {
832
- //console.log( "Force completed.")
833
- gatheringNumber = false;
834
- val.value_type = VALUE_NUMBER;
835
-
836
- if (parse_context == CONTEXT_UNKNOWN) {
837
- completed = true;
888
+ // the character that ended the number was counted here and is handed back to
889
+ // the main loop, which counts it again.
890
+ if (n > _n) pos.col--;
891
+ n = _n;
892
+ if (!complete_at_end && n == buf.length) {
893
+ gatheringNumber = true;
838
894
  } else {
839
- throw new Error("context stack is not empty at flush");
895
+ gatheringNumber = false;
896
+ checkNumber();
897
+ val.value_type = VALUE_NUMBER;
898
+ if (parse_context == CONTEXT_UNKNOWN) {
899
+ completed = true;
900
+ }
840
901
  }
841
-
842
- retval = 1; // if returning buffers, then obviously there's more in this one.
843
902
  }
844
- }
845
-
846
- while (status && (input = inQueue.shift())) {
847
- n = input.n;
848
- buf = input.buf;
849
-
850
- if (gatheringString) {
851
- const string_status = gatherString(gatheringStringFirstChar);
852
-
853
- if (string_status > 0) {
854
- gatheringString = false;
855
- val.value_type = VALUE_STRING;
903
+ if (!status) return -1;
904
+ if (msg && msg.length) {
905
+ input = getBuffer();
906
+ input.buf = msg;
907
+ inQueue.push(input);
908
+ } else {
909
+ if (gatheringNumber) {
910
+ //console.log( "Force completed.")
911
+ gatheringNumber = false;
912
+ checkNumber();
913
+ val.value_type = VALUE_NUMBER;
914
+ if (parse_context == CONTEXT_UNKNOWN) {
915
+ completed = true;
916
+ } else {
917
+ throw new Error("context stack is not empty at flush");
918
+ }
919
+ retval = 1; // if returning buffers, then obviously there's more in this one.
856
920
  }
857
921
  }
858
-
859
- if (gatheringNumber) {
860
- collectNumber();
861
- }
862
-
863
- while (!completed && status && n < buf.length) {
864
- let str = buf.charAt(n);
865
- const cInt = buf.codePointAt(n++);
866
-
867
- if (cInt >= 0x10000) {
868
- str += buf.charAt(n);
869
- n++;
870
- } //// log('_DEBUG_PARSING', "parsing at ", cInt, str );
871
- //log('_DEBUG_LL', "processing: ", cInt, str, pos, comment, parse_context, word, val );
872
-
873
-
874
- pos.col++;
875
-
876
- if (comment) {
877
- // '/'
878
- if (comment == 1) {
922
+ while (status && (input = inQueue.shift())) {
923
+ n = input.n;
924
+ // invariant: queued buffers are always given a string via `input.buf = msg` before being pushed.
925
+ buf = /** @type {string} */input.buf;
926
+ if (gatheringString) {
927
+ /* istanbul ignore next -- gatheringString and gatheringStringFirstChar are always set/cleared together; this guards state that the public API can never actually produce */
928
+ if (gatheringStringFirstChar === null) {
929
+ throw new Error("Parser string start was unset");
930
+ }
931
+ const string_status = gatherString(gatheringStringFirstChar);
932
+ if (string_status > 0) {
933
+ gatheringString = false;
934
+ val.value_type = VALUE_STRING;
935
+ }
936
+ }
937
+ if (gatheringNumber) {
938
+ collectNumber();
939
+ }
940
+ while (!completed && status && n < buf.length) {
941
+ let str = buf.charAt(n);
942
+ const cInt = ensureDefined(buf.codePointAt(n++), "Unexpected end of input while parsing");
943
+ if (cInt >= 0x10000) {
944
+ str += buf.charAt(n);
945
+ n++;
946
+ }
947
+ //// log('_DEBUG_PARSING', "parsing at ", cInt, str );
948
+ //log('_DEBUG_LL', "processing: ", cInt, str, pos, comment, parse_context, word, val );
949
+ pos.col++;
950
+ if (comment) {
879
951
  // '/'
880
- if (cInt == 42
881
- /*'*'*/
882
- ) {
952
+ countLine(cInt);
953
+ if (comment == 1) {
954
+ // '/'
955
+ if (cInt == 42 /*'*'*/) {
883
956
  comment = 3;
884
957
  } // '/*'
885
- else if (cInt != 47
886
- /*'/'*/
887
- ) {
888
- // '//'(NOT)
889
- throwError("fault while parsing;", cInt);
890
- } else comment = 2; // '//' (valid)
891
-
892
- } else if (comment == 2) {
893
- // '// ...'
894
- if (cInt == 10
895
- /*'\n'*/
896
- || cInt == 13
897
- /*'\r'*/
898
- ) comment = 0;
899
- } else if (comment == 3) {
900
- // '/*... '
901
- if (cInt == 42
902
- /*'*'*/
903
- ) comment = 4;
904
- } else {
905
- // if( comment == 4 ) { // '/* ... *'
906
- if (cInt == 47
907
- /*'/'*/
908
- ) comment = 0;else comment = 3; // any other char, goto expect * to close */
909
- }
910
-
911
- continue;
912
- }
913
-
914
- switch (cInt) {
915
- case 47
916
- /*'/'*/
917
- :
918
- comment = 1;
919
- break;
920
-
921
- case 123
922
- /*'{'*/
923
- :
924
- if (word == WORD_POS_FIELD || word == WORD_POS_AFTER_FIELD || parse_context == CONTEXT_OBJECT_FIELD && word == WORD_POS_RESET) {
925
- throwError("fault while parsing; getting field name unexpected ", cInt); // break;
926
- }
927
-
928
- {
929
- const old_context = getContext(); //log('_DEBUG_PARSING', "Begin a new object; previously pushed into elements; but wait until trailing comma or close previously:%d", val.value_type );
930
-
931
- val.value_type = VALUE_OBJECT;
932
- const tmpobj = {};
933
- if (parse_context == CONTEXT_UNKNOWN) result = elements = tmpobj;
934
- old_context.context = parse_context;
935
- old_context.elements = elements;
936
- old_context.element_array = element_array;
937
- old_context.name = val.name;
938
- elements = tmpobj; //log('_DEBUG_PARSING_STACK',"push context (open object): ", context_stack.length );
939
-
940
- context_stack.push(old_context);
941
- RESET_VAL();
942
- parse_context = CONTEXT_OBJECT_FIELD;
943
- }
944
- break;
945
-
946
- case 91
947
- /*'['*/
948
- :
949
- if (parse_context == CONTEXT_OBJECT_FIELD || word == WORD_POS_FIELD || word == WORD_POS_AFTER_FIELD) {
950
- throwError("Fault while parsing; while getting field name unexpected", cInt); // break;
951
- }
952
-
953
- if (val.value_type == VALUE_UNSET || val.value_type == VALUE_UNDEFINED) {
954
- const old_context = getContext(); //log('_DEBUG_PARSING', "Begin a new array; previously pushed into elements; but wait until trailing comma or close previously:%d", val.value_type );
955
-
956
- val.value_type = VALUE_ARRAY;
957
- const tmparr = [];
958
- if (parse_context == CONTEXT_UNKNOWN) result = element_array = tmparr; //else if( parse_context == CONTEXT_IN_ARRAY )
959
- // element_array.push( tmparr );
960
- else if (parse_context == CONTEXT_OBJECT_FIELD_VALUE) elements[val.name] = tmparr;
961
- old_context.context = parse_context;
962
- old_context.elements = elements;
963
- old_context.element_array = element_array;
964
- old_context.name = val.name;
965
- element_array = tmparr; //log('_DEBUG_PARSING_STACK', "push context (open array): ", context_stack.length );
966
-
967
- context_stack.push(old_context);
968
- RESET_VAL();
969
- parse_context = CONTEXT_IN_ARRAY;
970
- } else {
971
- throwError("Unexpected array open after previous value", cInt);
972
- }
973
-
974
- break;
975
-
976
- case 58
977
- /*':'*/
978
- :
979
- ////log('_DEBUG_PARSING', "colon context:", parse_context );
980
- if (parse_context == CONTEXT_OBJECT_FIELD) {
981
- word = WORD_POS_RESET;
982
- val.name = val.string;
983
- val.string = '';
984
- parse_context = CONTEXT_OBJECT_FIELD_VALUE;
985
- val.value_type = VALUE_UNSET;
958
+ else if (cInt != 47 /*'/'*/) {
959
+ // '//'(NOT)
960
+ throwError("fault while parsing;", cInt);
961
+ } else comment = 2; // '//' (valid)
962
+ } else if (comment == 2) {
963
+ // '// ...'
964
+ if (cInt == 10 /*'\n'*/ || cInt == 13 /*'\r'*/ || cInt == 0x2028 /*LS*/ || cInt == 0x2029 /*PS*/) comment = 0;
965
+ } else if (comment == 3) {
966
+ // '/*... '
967
+ if (cInt == 42 /*'*'*/) comment = 4;
986
968
  } else {
987
- if (parse_context == CONTEXT_IN_ARRAY) throwError("(in array, got colon out of string):parsing fault;", cInt);else throwError("(outside any object, got colon out of string):parsing fault;", cInt);
969
+ // if( comment == 4 ) { // '/* ... *'
970
+ if (cInt == 47 /*'/'*/) comment = 0;else comment = 3; // any other char, goto expect * to close */
988
971
  }
989
-
990
- break;
991
-
992
- case 125
993
- /*'}'*/
994
- :
995
- ////log('_DEBUG_PARSING', "close bracket context:", word, parse_context );
996
- if (word == WORD_POS_END) {
997
- // allow starting a new word
998
- word = WORD_POS_RESET;
999
- } // coming back after pushing an array or sub-object will reset the context to FIELD, so an end with a field should still push value.
1000
-
1001
-
1002
- if (parse_context == CONTEXT_OBJECT_FIELD) {
1003
- //log('_DEBUG_PARSING', "close object; empty object %d", val.value_type );
1004
- //RESET_VAL();
1005
- val.value_type = VALUE_OBJECT;
1006
- val.contains = elements;
1007
- const old_context = context_stack.pop(); //log('_DEBUG_PARSING_STACK',"object pop stack (close obj)", context_stack.length, old_context );
1008
-
1009
- val.name = old_context.name;
1010
- parse_context = old_context.context; // this will restore as IN_ARRAY or OBJECT_FIELD
1011
-
1012
- elements = old_context.elements;
1013
- element_array = old_context.element_array;
1014
- dropContext(old_context);
1015
-
1016
- if (parse_context == CONTEXT_UNKNOWN) {
1017
- completed = true;
972
+ continue;
973
+ }
974
+ switch (cInt) {
975
+ case 47 /*'/'*/:
976
+ comment = 1;
977
+ break;
978
+ case 123 /*'{'*/:
979
+ if (word == WORD_POS_FIELD || word == WORD_POS_AFTER_FIELD || parse_context == CONTEXT_OBJECT_FIELD && word == WORD_POS_RESET) {
980
+ throwError("fault while parsing; getting field name unexpected ", cInt);
981
+ // break;
1018
982
  }
1019
- } else if (parse_context == CONTEXT_OBJECT_FIELD_VALUE) {
1020
- // first, add the last value
1021
- //log('_DEBUG_PARSING', "close object; push item '%s' %d", val.name, val.value_type );
1022
- if (val.value_type != VALUE_UNSET) {
1023
- objectPush();
983
+ checkValueSeparator(cInt);
984
+ {
985
+ const old_context = getContext();
986
+ //log('_DEBUG_PARSING', "Begin a new object; previously pushed into elements; but wait until trailing comma or close previously:%d", val.value_type );
987
+
988
+ val.value_type = VALUE_OBJECT;
989
+ const tmpobj = {};
990
+ if (parse_context == CONTEXT_UNKNOWN) result = elements = tmpobj;
991
+ old_context.context = parse_context;
992
+ old_context.elements = elements;
993
+ old_context.element_array = element_array;
994
+ old_context.name = val.name;
995
+ elements = tmpobj;
996
+ //log('_DEBUG_PARSING_STACK',"push context (open object): ", context_stack.length );
997
+ context_stack.push(old_context);
998
+ RESET_VAL();
999
+ parse_context = CONTEXT_OBJECT_FIELD;
1000
+ }
1001
+ break;
1002
+ case 91 /*'['*/:
1003
+ if (parse_context == CONTEXT_OBJECT_FIELD || word == WORD_POS_FIELD || word == WORD_POS_AFTER_FIELD) {
1004
+ throwError("Fault while parsing; while getting field name unexpected", cInt);
1005
+ // break;
1006
+ }
1007
+ if (val.value_type == VALUE_UNSET || val.value_type == VALUE_UNDEFINED) {
1008
+ const old_context = getContext();
1009
+ //log('_DEBUG_PARSING', "Begin a new array; previously pushed into elements; but wait until trailing comma or close previously:%d", val.value_type );
1010
+
1011
+ val.value_type = VALUE_ARRAY;
1012
+ /** @type {unknown[]} */
1013
+ const tmparr = [];
1014
+ if (parse_context == CONTEXT_UNKNOWN) result = element_array = tmparr;
1015
+ //else if( parse_context == CONTEXT_IN_ARRAY )
1016
+ // element_array.push( tmparr );
1017
+ else if (parse_context == CONTEXT_OBJECT_FIELD_VALUE)
1018
+ // invariant: CONTEXT_OBJECT_FIELD_VALUE means elements/val.name were set by ':'.
1019
+ /** @type {Record<string, unknown>} */
1020
+ elements[(/** @type {string} */val.name)] = tmparr;
1021
+ old_context.context = parse_context;
1022
+ old_context.elements = elements;
1023
+ old_context.element_array = element_array;
1024
+ old_context.name = val.name;
1025
+ element_array = tmparr;
1026
+ //log('_DEBUG_PARSING_STACK', "push context (open array): ", context_stack.length );
1027
+ context_stack.push(old_context);
1028
+ RESET_VAL();
1029
+ parse_context = CONTEXT_IN_ARRAY;
1024
1030
  } else {
1025
- throwError("Fault while parsing field value, close with no value", cInt);
1031
+ throwError("Unexpected array open after previous value", cInt);
1026
1032
  }
1027
-
1028
- val.value_type = VALUE_OBJECT;
1029
- val.contains = elements;
1030
- const old_context = context_stack.pop(); //log('_DEBUG_PARSING_STACK',"object pop stack (close object)", context_stack.length, old_context );
1031
-
1032
- val.name = old_context.name;
1033
- parse_context = old_context.context; // this will restore as IN_ARRAY or OBJECT_FIELD
1034
-
1035
- elements = old_context.elements;
1036
- element_array = old_context.element_array;
1037
- dropContext(old_context);
1038
-
1039
- if (parse_context == CONTEXT_UNKNOWN) {
1040
- completed = true;
1033
+ break;
1034
+ case 58 /*':'*/:
1035
+ ////log('_DEBUG_PARSING', "colon context:", parse_context );
1036
+ if (parse_context == CONTEXT_OBJECT_FIELD) {
1037
+ word = WORD_POS_RESET;
1038
+ if (esStrictCompatible && val.value_type !== VALUE_STRING && !ES_IDENTIFIER_NAME.test(val.string) && Number.isNaN(Number(val.string.replace(NUMERIC_SEPARATOR, '$1')))) throwError("Unquoted keys must be valid identifiers when the 'esStrictCompatible' option is set", cInt);
1039
+ if (normalizeNumericKeys && val.value_type !== VALUE_STRING && val.string !== '') {
1040
+ const numericKey = Number(val.string.replace(NUMERIC_SEPARATOR, '$1'));
1041
+ if (!Number.isNaN(numericKey)) val.string = String(numericKey);
1042
+ }
1043
+ val.name = val.string;
1044
+ val.string = '';
1045
+ parse_context = CONTEXT_OBJECT_FIELD_VALUE;
1046
+ val.value_type = VALUE_UNSET;
1047
+ } else {
1048
+ if (parse_context == CONTEXT_IN_ARRAY) throwError("(in array, got colon out of string):parsing fault;", cInt);else throwError("(outside any object, got colon out of string):parsing fault;", cInt);
1041
1049
  }
1042
- } else {
1043
- throwError("Fault while parsing; unexpected", cInt);
1044
- }
1045
-
1046
- negative = false;
1047
- break;
1048
-
1049
- case 93
1050
- /*']'*/
1051
- :
1052
- if (word == WORD_POS_END) word = WORD_POS_RESET;
1053
-
1054
- if (parse_context == CONTEXT_IN_ARRAY) {
1055
- //log('_DEBUG_PARSING', "close array, push last element: %d", val.value_type );
1056
- if (val.value_type != VALUE_UNSET) {
1057
- arrayPush();
1050
+ break;
1051
+ case 125 /*'}'*/:
1052
+ ////log('_DEBUG_PARSING', "close bracket context:", word, parse_context );
1053
+ if (word == WORD_POS_END) {
1054
+ // allow starting a new word
1055
+ word = WORD_POS_RESET;
1058
1056
  }
1059
-
1060
- val.value_type = VALUE_ARRAY;
1061
- val.contains = element_array;
1062
- {
1063
- const old_context = context_stack.pop(); //log('_DEBUG_PARSING_STACK',"object pop stack (close array)", context_stack.length );
1064
-
1057
+ checkPartialValue(cInt);
1058
+ // coming back after pushing an array or sub-object will reset the context to FIELD, so an end with a field should still push value.
1059
+ if (parse_context == CONTEXT_OBJECT_FIELD) {
1060
+ // a field name was collected but no ':' followed it: '{a}', '{a }', '{"a"}'.
1061
+ // This used to silently produce {}.
1062
+ if (word == WORD_POS_FIELD || word == WORD_POS_AFTER_FIELD || val.value_type == VALUE_STRING) throwError("Object field name with no value", cInt);
1063
+ //log('_DEBUG_PARSING', "close object; empty object %d", val.value_type );
1064
+ //RESET_VAL();
1065
+ val.value_type = VALUE_OBJECT;
1066
+ val.contains = elements;
1067
+ const old_context = context_stack.pop();
1068
+ //log('_DEBUG_PARSING_STACK',"object pop stack (close obj)", context_stack.length, old_context );
1065
1069
  val.name = old_context.name;
1066
- parse_context = old_context.context;
1070
+ parse_context = old_context.context; // this will restore as IN_ARRAY or OBJECT_FIELD
1067
1071
  elements = old_context.elements;
1068
1072
  element_array = old_context.element_array;
1069
1073
  dropContext(old_context);
1074
+ if (parse_context == CONTEXT_UNKNOWN) {
1075
+ completed = true;
1076
+ }
1077
+ } else if (parse_context == CONTEXT_OBJECT_FIELD_VALUE) {
1078
+ // first, add the last value
1079
+ //log('_DEBUG_PARSING', "close object; push item '%s' %d", val.name, val.value_type );
1080
+ if (val.value_type != VALUE_UNSET) {
1081
+ objectPush();
1082
+ } else {
1083
+ throwError("Fault while parsing field value, close with no value", cInt);
1084
+ }
1085
+ val.value_type = VALUE_OBJECT;
1086
+ val.contains = elements;
1087
+ const old_context = context_stack.pop();
1088
+ //log('_DEBUG_PARSING_STACK',"object pop stack (close object)", context_stack.length, old_context );
1089
+ val.name = old_context.name;
1090
+ parse_context = old_context.context; // this will restore as IN_ARRAY or OBJECT_FIELD
1091
+ elements = old_context.elements;
1092
+ element_array = old_context.element_array;
1093
+ dropContext(old_context);
1094
+ if (parse_context == CONTEXT_UNKNOWN) {
1095
+ completed = true;
1096
+ }
1097
+ } else {
1098
+ throwError("Fault while parsing; unexpected", cInt);
1070
1099
  }
1071
-
1072
- if (parse_context == CONTEXT_UNKNOWN) {
1073
- completed = true;
1100
+ negative = false;
1101
+ signSeen = false;
1102
+ break;
1103
+ case 93 /*']'*/:
1104
+ if (word == WORD_POS_END) word = WORD_POS_RESET;
1105
+ checkPartialValue(cInt);
1106
+ if (parse_context == CONTEXT_IN_ARRAY) {
1107
+ //log('_DEBUG_PARSING', "close array, push last element: %d", val.value_type );
1108
+ if (val.value_type != VALUE_UNSET) {
1109
+ arrayPush();
1110
+ }
1111
+ val.value_type = VALUE_ARRAY;
1112
+ val.contains = element_array;
1113
+ {
1114
+ const old_context = context_stack.pop();
1115
+ //log('_DEBUG_PARSING_STACK',"object pop stack (close array)", context_stack.length );
1116
+ val.name = old_context.name;
1117
+ parse_context = old_context.context;
1118
+ elements = old_context.elements;
1119
+ element_array = old_context.element_array;
1120
+ dropContext(old_context);
1121
+ }
1122
+ if (parse_context == CONTEXT_UNKNOWN) {
1123
+ completed = true;
1124
+ }
1125
+ } else {
1126
+ throwError(`bad context ${parse_context}; fault while parsing`, cInt); // fault
1074
1127
  }
1075
- } else {
1076
- throwError(`bad context ${parse_context}; fault while parsing`, cInt); // fault
1077
- }
1078
-
1079
- negative = false;
1080
- break;
1081
-
1082
- case 44
1083
- /*','*/
1084
- :
1085
- if (word == WORD_POS_END) word = WORD_POS_RESET; // allow collect new keyword
1086
- //log('_DEBUG_PARSING', "comma context:", parse_context, val );
1087
-
1088
- if (parse_context == CONTEXT_IN_ARRAY) {
1089
- if (val.value_type == VALUE_UNSET) val.value_type = VALUE_EMPTY; // in an array, elements after a comma should init as undefined...
1090
- //log('_DEBUG_PARSING', "back in array; push item %d", val.value_type );
1091
-
1092
- arrayPush();
1093
- RESET_VAL(); // undefined allows [,,,] to be 4 values and [1,2,3,] to be 4 values with an undefined at end.
1094
- } else if (parse_context == CONTEXT_OBJECT_FIELD_VALUE) {
1095
- // after an array value, it will have returned to OBJECT_FIELD anyway
1096
- //log('_DEBUG_PARSING', "comma after field value, push field to object: %s", val.name );
1097
- parse_context = CONTEXT_OBJECT_FIELD;
1098
-
1099
- if (val.value_type != VALUE_UNSET) {
1100
- objectPush();
1128
+ negative = false;
1129
+ signSeen = false;
1130
+ break;
1131
+ case 44 /*','*/:
1132
+ if (word == WORD_POS_END) word = WORD_POS_RESET; // allow collect new keyword
1133
+ checkPartialValue(cInt);
1134
+ //log('_DEBUG_PARSING', "comma context:", parse_context, val );
1135
+ if (parse_context == CONTEXT_IN_ARRAY) {
1136
+ if (val.value_type == VALUE_UNSET) val.value_type = VALUE_EMPTY; // in an array, elements after a comma should init as undefined...
1137
+
1138
+ //log('_DEBUG_PARSING', "back in array; push item %d", val.value_type );
1139
+ arrayPush();
1101
1140
  RESET_VAL();
1102
- } else throwError("Unexpected comma after object field name", cInt);
1103
- } else {
1104
- status = false;
1105
- throwError("bad context; excessive commas while parsing;", cInt); // fault
1106
- }
1107
-
1108
- negative = false;
1109
- break;
1110
-
1111
- default:
1112
- if (parse_context == CONTEXT_OBJECT_FIELD) {
1113
- switch (cInt) {
1141
+ // undefined allows [,,,] to be 4 values and [1,2,3,] to be 4 values with an undefined at end.
1142
+ } else if (parse_context == CONTEXT_OBJECT_FIELD_VALUE) {
1143
+ // after an array value, it will have returned to OBJECT_FIELD anyway
1144
+ //log('_DEBUG_PARSING', "comma after field value, push field to object: %s", val.name );
1145
+ parse_context = CONTEXT_OBJECT_FIELD;
1146
+ if (val.value_type != VALUE_UNSET) {
1147
+ objectPush();
1148
+ RESET_VAL();
1149
+ } else throwError("Unexpected comma after object field name", cInt);
1150
+ } else {
1151
+ status = false;
1152
+ throwError("bad context; excessive commas while parsing;", cInt); // fault
1153
+ }
1154
+ negative = false;
1155
+ signSeen = false;
1156
+ break;
1157
+ default:
1158
+ if (parse_context == CONTEXT_OBJECT_FIELD) {
1159
+ switch (cInt) {
1160
+ case 96:
1161
+ //'`':
1162
+ if (esStrictCompatible) throwError("Backtick-quoted keys are not allowed when the 'esStrictCompatible' option is set", cInt);
1163
+ // falls through
1164
+ case 34: //'"':
1165
+ case 39:
1166
+ //'\'':
1167
+ if (word == WORD_POS_RESET) {
1168
+ if (val.value_type != VALUE_UNSET) throwError("String begin after previous value", cInt);
1169
+ const string_status = gatherString(cInt);
1170
+ //log('_DEBUG_PARSING', "string gather for object field name :", val.string, string_status );
1171
+ if (string_status) {
1172
+ val.value_type = VALUE_STRING;
1173
+ } else {
1174
+ gatheringStringFirstChar = cInt;
1175
+ gatheringString = true;
1176
+ }
1177
+ } else {
1178
+ throwError("fault while parsing; quote not at start of field name", cInt);
1179
+ }
1180
+ break;
1181
+ case 10: //'\n':
1182
+ case 13: //'\r':
1183
+ case 32: //' ':
1184
+ case 160: //&nbsp:
1185
+ case 9: //'\t':
1186
+ case 11: //VT
1187
+ case 12: //FF
1188
+ case 0x2028: //LS
1189
+ case 0x2029: //PS
1190
+ case 0xFEFF:
1191
+ // ZWNBS is WS though
1192
+ countLine(cInt);
1193
+ if (word == WORD_POS_END) {
1194
+ // allow collect new keyword
1195
+ word = WORD_POS_RESET;
1196
+ } else if (word == WORD_POS_FIELD) {
1197
+ word = WORD_POS_AFTER_FIELD;
1198
+ }
1199
+ // skip whitespace
1200
+ break;
1201
+ default:
1202
+ if (word == WORD_POS_AFTER_FIELD) {
1203
+ status = false;
1204
+ throwError("fault while parsing; character unexpected", cInt);
1205
+ }
1206
+ if (word == WORD_POS_RESET) word = WORD_POS_FIELD;
1207
+ val.string += str;
1208
+ break;
1209
+ // default
1210
+ }
1211
+ } else switch (cInt) {
1114
1212
  case 96: //'`':
1115
-
1116
1213
  case 34: //'"':
1117
-
1118
1214
  case 39:
1119
- //'\'':
1120
- if (word == WORD_POS_RESET) {
1121
- if (val.value_type != VALUE_UNSET) throwError("String begin after previous value", cInt);
1122
- const string_status = gatherString(cInt); //log('_DEBUG_PARSING', "string gather for object field name :", val.string, string_status );
1123
-
1124
- if (string_status) {
1125
- val.value_type = VALUE_STRING;
1126
- } else {
1127
- gatheringStringFirstChar = cInt;
1128
- gatheringString = true;
1129
- }
1130
- } else {
1131
- throwError("fault while parsing; quote not at start of field name", cInt);
1215
+ {
1216
+ //'\'':
1217
+ if (val.value_type === VALUE_UNSET) {
1218
+ const string_status = gatherString(cInt);
1219
+ //log('_DEBUG_PARSING', "string gather for object field value :", val.string, string_status, completed, input.n, buf.length );
1220
+ if (string_status) {
1221
+ val.value_type = VALUE_STRING;
1222
+ word = WORD_POS_END;
1223
+ } else {
1224
+ gatheringStringFirstChar = cInt;
1225
+ gatheringString = true;
1226
+ }
1227
+ } else throwError("String unexpected", cInt);
1228
+ break;
1132
1229
  }
1133
-
1134
- break;
1135
-
1136
- case 10:
1137
- //'\n':
1138
- pos.line++;
1139
- pos.col = 1;
1140
- // fall through to normal space handling - just updated line/col position
1141
-
1142
- case 13: //'\r':
1143
-
1230
+ case 10: //'\n':
1144
1231
  case 32: //' ':
1145
-
1146
- case 160: //&nbsp:
1147
-
1232
+ case 160: // &nbsp
1148
1233
  case 9: //'\t':
1149
-
1234
+ case 13: //'\r':
1235
+ case 11: //VT
1236
+ case 12: //FF
1237
+ case 0x2028: //LS
1238
+ case 0x2029: //PS
1150
1239
  case 0xFEFF:
1151
- // ZWNBS is WS though
1240
+ //'\uFEFF':
1241
+ countLine(cInt);
1152
1242
  if (word == WORD_POS_END) {
1153
- // allow collect new keyword
1154
1243
  word = WORD_POS_RESET;
1155
- } else if (word == WORD_POS_FIELD) {
1156
- word = WORD_POS_AFTER_FIELD;
1157
- } // skip whitespace
1158
-
1159
-
1244
+ signSeen = false;
1245
+ if (parse_context == CONTEXT_UNKNOWN) {
1246
+ completed = true;
1247
+ }
1248
+ break;
1249
+ }
1250
+ if (word !== WORD_POS_RESET) {
1251
+ // breaking in the middle of gathering a keyword.
1252
+ status = false;
1253
+ throwError("fault parsing whitespace", cInt);
1254
+ }
1160
1255
  break;
1161
-
1256
+ //----------------------------------------------------------
1257
+ // catch characters for true/false/null/undefined which are values outside of quotes
1258
+ case 116:
1259
+ //'t':
1260
+ if (word == WORD_POS_RESET) {
1261
+ checkValueSeparator(cInt);
1262
+ word = WORD_POS_TRUE_1;
1263
+ } else if (word == WORD_POS_INFINITY_6) word = WORD_POS_INFINITY_7;else {
1264
+ status = false;
1265
+ throwError("fault parsing", cInt);
1266
+ } // fault
1267
+ break;
1268
+ case 114:
1269
+ //'r':
1270
+ if (word == WORD_POS_TRUE_1) word = WORD_POS_TRUE_2;else {
1271
+ status = false;
1272
+ throwError("fault parsing", cInt);
1273
+ } // fault
1274
+ break;
1275
+ case 117:
1276
+ //'u':
1277
+ if (word == WORD_POS_TRUE_2) word = WORD_POS_TRUE_3;else if (word == WORD_POS_NULL_1) word = WORD_POS_NULL_2;else if (word == WORD_POS_RESET) {
1278
+ checkValueSeparator(cInt);
1279
+ word = WORD_POS_UNDEFINED_1;
1280
+ } else {
1281
+ status = false;
1282
+ throwError("fault parsing", cInt);
1283
+ } // fault
1284
+ break;
1285
+ case 101:
1286
+ //'e':
1287
+ if (word == WORD_POS_TRUE_3) {
1288
+ val.value_type = VALUE_TRUE;
1289
+ word = WORD_POS_END;
1290
+ } else if (word == WORD_POS_FALSE_4) {
1291
+ val.value_type = VALUE_FALSE;
1292
+ word = WORD_POS_END;
1293
+ } else if (word == WORD_POS_UNDEFINED_3) word = WORD_POS_UNDEFINED_4;else if (word == WORD_POS_UNDEFINED_7) word = WORD_POS_UNDEFINED_8;else {
1294
+ status = false;
1295
+ throwError("fault parsing", cInt);
1296
+ } // fault
1297
+ break;
1298
+ case 110:
1299
+ //'n':
1300
+ if (word == WORD_POS_RESET) {
1301
+ checkValueSeparator(cInt);
1302
+ word = WORD_POS_NULL_1;
1303
+ } else if (word == WORD_POS_UNDEFINED_1) word = WORD_POS_UNDEFINED_2;else if (word == WORD_POS_UNDEFINED_6) word = WORD_POS_UNDEFINED_7;else if (word == WORD_POS_INFINITY_1) word = WORD_POS_INFINITY_2;else if (word == WORD_POS_INFINITY_4) word = WORD_POS_INFINITY_5;else {
1304
+ status = false;
1305
+ throwError("fault parsing", cInt);
1306
+ } // fault
1307
+ break;
1308
+ case 100:
1309
+ //'d':
1310
+ if (word == WORD_POS_UNDEFINED_2) word = WORD_POS_UNDEFINED_3;else if (word == WORD_POS_UNDEFINED_8) {
1311
+ val.value_type = VALUE_UNDEFINED;
1312
+ word = WORD_POS_END;
1313
+ } else {
1314
+ status = false;
1315
+ throwError("fault parsing", cInt);
1316
+ } // fault
1317
+ break;
1318
+ case 105:
1319
+ //'i':
1320
+ if (word == WORD_POS_UNDEFINED_5) word = WORD_POS_UNDEFINED_6;else if (word == WORD_POS_INFINITY_3) word = WORD_POS_INFINITY_4;else if (word == WORD_POS_INFINITY_5) word = WORD_POS_INFINITY_6;else {
1321
+ status = false;
1322
+ throwError("fault parsing", cInt);
1323
+ } // fault
1324
+ break;
1325
+ case 108:
1326
+ //'l':
1327
+ if (word == WORD_POS_NULL_2) word = WORD_POS_NULL_3;else if (word == WORD_POS_NULL_3) {
1328
+ val.value_type = VALUE_NULL;
1329
+ word = WORD_POS_END;
1330
+ } else if (word == WORD_POS_FALSE_2) word = WORD_POS_FALSE_3;else {
1331
+ status = false;
1332
+ throwError("fault parsing", cInt);
1333
+ } // fault
1334
+ break;
1335
+ case 102:
1336
+ //'f':
1337
+ if (word == WORD_POS_RESET) {
1338
+ checkValueSeparator(cInt);
1339
+ word = WORD_POS_FALSE_1;
1340
+ } else if (word == WORD_POS_UNDEFINED_4) word = WORD_POS_UNDEFINED_5;else if (word == WORD_POS_INFINITY_2) word = WORD_POS_INFINITY_3;else {
1341
+ status = false;
1342
+ throwError("fault parsing", cInt);
1343
+ } // fault
1344
+ break;
1345
+ case 97:
1346
+ //'a':
1347
+ if (word == WORD_POS_FALSE_1) word = WORD_POS_FALSE_2;else if (word == WORD_POS_NAN_1) word = WORD_POS_NAN_2;else {
1348
+ status = false;
1349
+ throwError("fault parsing", cInt);
1350
+ } // fault
1351
+ break;
1352
+ case 115:
1353
+ //'s':
1354
+ if (word == WORD_POS_FALSE_3) word = WORD_POS_FALSE_4;else {
1355
+ status = false;
1356
+ throwError("fault parsing", cInt);
1357
+ } // fault
1358
+ break;
1359
+ case 73:
1360
+ //'I':
1361
+ if (word == WORD_POS_RESET) {
1362
+ checkValueSeparator(cInt);
1363
+ word = WORD_POS_INFINITY_1;
1364
+ } else {
1365
+ status = false;
1366
+ throwError("fault parsing", cInt);
1367
+ } // fault
1368
+ break;
1369
+ case 78:
1370
+ //'N':
1371
+ if (word == WORD_POS_RESET) {
1372
+ checkValueSeparator(cInt);
1373
+ word = WORD_POS_NAN_1;
1374
+ } else if (word == WORD_POS_NAN_2) {
1375
+ val.value_type = negative ? VALUE_NEG_NAN : VALUE_NAN;
1376
+ negative = false;
1377
+ word = WORD_POS_END;
1378
+ } else {
1379
+ status = false;
1380
+ throwError("fault parsing", cInt);
1381
+ } // fault
1382
+ break;
1383
+ case 121:
1384
+ //'y':
1385
+ if (word == WORD_POS_INFINITY_7) {
1386
+ val.value_type = negative ? VALUE_NEG_INFINITY : VALUE_INFINITY;
1387
+ negative = false;
1388
+ word = WORD_POS_END;
1389
+ } else {
1390
+ status = false;
1391
+ throwError("fault parsing", cInt);
1392
+ } // fault
1393
+ break;
1394
+ case 45:
1395
+ //'-':
1396
+ if (word == WORD_POS_RESET) {
1397
+ checkValueSeparator(cInt);
1398
+ if (esStrictCompatible && signSeen) throwError("Multiple consecutive signs are not allowed when the 'esStrictCompatible' option is set", cInt);
1399
+ signSeen = true;
1400
+ negative = !negative;
1401
+ } else {
1402
+ status = false;
1403
+ throwError("fault parsing", cInt);
1404
+ } // fault
1405
+ break;
1406
+ case 43:
1407
+ //'+':
1408
+ if (word !== WORD_POS_RESET) {
1409
+ status = false;
1410
+ throwError("fault parsing", cInt);
1411
+ } // fault
1412
+ else {
1413
+ checkValueSeparator(cInt);
1414
+ if (esStrictCompatible && signSeen) throwError("Multiple consecutive signs are not allowed when the 'esStrictCompatible' option is set", cInt);
1415
+ signSeen = true;
1416
+ }
1417
+ break;
1418
+ //
1419
+ //----------------------------------------------------------
1162
1420
  default:
1163
- if (word == WORD_POS_AFTER_FIELD) {
1421
+ if (cInt >= 48 /*'0'*/ && cInt <= 57 /*'9'*/ || cInt == 43 /*'+'*/ || cInt == 46 /*'.'*/ || cInt == 45 /*'-'*/) {
1422
+ checkValueSeparator(cInt);
1423
+ fromHex = false;
1424
+ exponent = false;
1425
+ exponent_sign = false;
1426
+ exponent_digit = false;
1427
+ decimal = false;
1428
+ signSeen = false;
1429
+ val.string = str;
1430
+ input.n = n;
1431
+ collectNumber();
1432
+ } else {
1164
1433
  status = false;
1165
- throwError("fault while parsing; character unexpected", cInt);
1434
+ throwError("fault parsing", cInt);
1166
1435
  }
1167
-
1168
- if (word == WORD_POS_RESET) word = WORD_POS_FIELD;
1169
- val.string += str;
1170
1436
  break;
1171
1437
  // default
1172
1438
  }
1173
- } else switch (cInt) {
1174
- case 96: //'`':
1175
-
1176
- case 34: //'"':
1177
-
1178
- case 39:
1179
- {
1180
- //'\'':
1181
- if (val.value_type === VALUE_UNSET) {
1182
- const string_status = gatherString(cInt); //log('_DEBUG_PARSING', "string gather for object field value :", val.string, string_status, completed, input.n, buf.length );
1183
-
1184
- if (string_status) {
1185
- val.value_type = VALUE_STRING;
1186
- word = WORD_POS_END;
1187
- } else {
1188
- gatheringStringFirstChar = cInt;
1189
- gatheringString = true;
1190
- }
1191
- } else throwError("String unexpected", cInt);
1192
-
1193
- break;
1194
- }
1195
-
1196
- case 10:
1197
- //'\n':
1198
- pos.line++;
1199
- pos.col = 1;
1200
- // Fallthrough
1201
-
1202
- case 32: //' ':
1203
-
1204
- case 160: // &nbsp
1205
-
1206
- case 9: //'\t':
1207
-
1208
- case 13: //'\r':
1209
-
1210
- case 0xFEFF:
1211
- //'\uFEFF':
1212
- if (word == WORD_POS_END) {
1213
- word = WORD_POS_RESET;
1214
-
1215
- if (parse_context == CONTEXT_UNKNOWN) {
1216
- completed = true;
1217
- }
1218
-
1219
- break;
1220
- }
1221
-
1222
- if (word !== WORD_POS_RESET) {
1223
- // breaking in the middle of gathering a keyword.
1224
- status = false;
1225
- throwError("fault parsing whitespace", cInt);
1226
- }
1227
-
1228
- break;
1229
- //----------------------------------------------------------
1230
- // catch characters for true/false/null/undefined which are values outside of quotes
1231
-
1232
- case 116:
1233
- //'t':
1234
- if (word == WORD_POS_RESET) word = WORD_POS_TRUE_1;else if (word == WORD_POS_INFINITY_6) word = WORD_POS_INFINITY_7;else {
1235
- status = false;
1236
- throwError("fault parsing", cInt);
1237
- } // fault
1238
-
1239
- break;
1240
-
1241
- case 114:
1242
- //'r':
1243
- if (word == WORD_POS_TRUE_1) word = WORD_POS_TRUE_2;else {
1244
- status = false;
1245
- throwError("fault parsing", cInt);
1246
- } // fault
1247
-
1248
- break;
1249
-
1250
- case 117:
1251
- //'u':
1252
- if (word == WORD_POS_TRUE_2) word = WORD_POS_TRUE_3;else if (word == WORD_POS_NULL_1) word = WORD_POS_NULL_2;else if (word == WORD_POS_RESET) word = WORD_POS_UNDEFINED_1;else {
1253
- status = false;
1254
- throwError("fault parsing", cInt);
1255
- } // fault
1256
-
1257
- break;
1258
-
1259
- case 101:
1260
- //'e':
1261
- if (word == WORD_POS_TRUE_3) {
1262
- val.value_type = VALUE_TRUE;
1263
- word = WORD_POS_END;
1264
- } else if (word == WORD_POS_FALSE_4) {
1265
- val.value_type = VALUE_FALSE;
1266
- word = WORD_POS_END;
1267
- } else if (word == WORD_POS_UNDEFINED_3) word = WORD_POS_UNDEFINED_4;else if (word == WORD_POS_UNDEFINED_7) word = WORD_POS_UNDEFINED_8;else {
1268
- status = false;
1269
- throwError("fault parsing", cInt);
1270
- } // fault
1271
-
1272
-
1273
- break;
1274
-
1275
- case 110:
1276
- //'n':
1277
- if (word == WORD_POS_RESET) word = WORD_POS_NULL_1;else if (word == WORD_POS_UNDEFINED_1) word = WORD_POS_UNDEFINED_2;else if (word == WORD_POS_UNDEFINED_6) word = WORD_POS_UNDEFINED_7;else if (word == WORD_POS_INFINITY_1) word = WORD_POS_INFINITY_2;else if (word == WORD_POS_INFINITY_4) word = WORD_POS_INFINITY_5;else {
1278
- status = false;
1279
- throwError("fault parsing", cInt);
1280
- } // fault
1281
-
1282
- break;
1283
-
1284
- case 100:
1285
- //'d':
1286
- if (word == WORD_POS_UNDEFINED_2) word = WORD_POS_UNDEFINED_3;else if (word == WORD_POS_UNDEFINED_8) {
1287
- val.value_type = VALUE_UNDEFINED;
1288
- word = WORD_POS_END;
1289
- } else {
1290
- status = false;
1291
- throwError("fault parsing", cInt);
1292
- } // fault
1293
-
1294
- break;
1295
-
1296
- case 105:
1297
- //'i':
1298
- if (word == WORD_POS_UNDEFINED_5) word = WORD_POS_UNDEFINED_6;else if (word == WORD_POS_INFINITY_3) word = WORD_POS_INFINITY_4;else if (word == WORD_POS_INFINITY_5) word = WORD_POS_INFINITY_6;else {
1299
- status = false;
1300
- throwError("fault parsing", cInt);
1301
- } // fault
1302
-
1303
- break;
1304
-
1305
- case 108:
1306
- //'l':
1307
- if (word == WORD_POS_NULL_2) word = WORD_POS_NULL_3;else if (word == WORD_POS_NULL_3) {
1308
- val.value_type = VALUE_NULL;
1309
- word = WORD_POS_END;
1310
- } else if (word == WORD_POS_FALSE_2) word = WORD_POS_FALSE_3;else {
1311
- status = false;
1312
- throwError("fault parsing", cInt);
1313
- } // fault
1314
-
1315
- break;
1316
-
1317
- case 102:
1318
- //'f':
1319
- if (word == WORD_POS_RESET) word = WORD_POS_FALSE_1;else if (word == WORD_POS_UNDEFINED_4) word = WORD_POS_UNDEFINED_5;else if (word == WORD_POS_INFINITY_2) word = WORD_POS_INFINITY_3;else {
1320
- status = false;
1321
- throwError("fault parsing", cInt);
1322
- } // fault
1323
-
1324
- break;
1325
-
1326
- case 97:
1327
- //'a':
1328
- if (word == WORD_POS_FALSE_1) word = WORD_POS_FALSE_2;else if (word == WORD_POS_NAN_1) word = WORD_POS_NAN_2;else {
1329
- status = false;
1330
- throwError("fault parsing", cInt);
1331
- } // fault
1332
-
1333
- break;
1334
-
1335
- case 115:
1336
- //'s':
1337
- if (word == WORD_POS_FALSE_3) word = WORD_POS_FALSE_4;else {
1338
- status = false;
1339
- throwError("fault parsing", cInt);
1340
- } // fault
1341
-
1342
- break;
1343
-
1344
- case 73:
1345
- //'I':
1346
- if (word == WORD_POS_RESET) word = WORD_POS_INFINITY_1;else {
1347
- status = false;
1348
- throwError("fault parsing", cInt);
1349
- } // fault
1350
-
1351
- break;
1352
-
1353
- case 78:
1354
- //'N':
1355
- if (word == WORD_POS_RESET) word = WORD_POS_NAN_1;else if (word == WORD_POS_NAN_2) {
1356
- val.value_type = negative ? VALUE_NEG_NAN : VALUE_NAN;
1357
- negative = false;
1358
- word = WORD_POS_END;
1359
- } else {
1360
- status = false;
1361
- throwError("fault parsing", cInt);
1362
- } // fault
1363
-
1364
- break;
1365
-
1366
- case 121:
1367
- //'y':
1368
- if (word == WORD_POS_INFINITY_7) {
1369
- val.value_type = negative ? VALUE_NEG_INFINITY : VALUE_INFINITY;
1370
- negative = false;
1371
- word = WORD_POS_END;
1372
- } else {
1373
- status = false;
1374
- throwError("fault parsing", cInt);
1375
- } // fault
1376
-
1377
-
1378
- break;
1379
-
1380
- case 45:
1381
- //'-':
1382
- if (word == WORD_POS_RESET) negative = !negative;else {
1383
- status = false;
1384
- throwError("fault parsing", cInt);
1385
- } // fault
1386
-
1387
- break;
1388
-
1389
- case 43:
1390
- //'+':
1391
- if (word !== WORD_POS_RESET) {
1392
- status = false;
1393
- throwError("fault parsing", cInt);
1394
- } // fault
1395
-
1396
-
1397
- break;
1398
- //
1399
- //----------------------------------------------------------
1400
-
1401
- default:
1402
- if (cInt >= 48
1403
- /*'0'*/
1404
- && cInt <= 57
1405
- /*'9'*/
1406
- || cInt == 43
1407
- /*'+'*/
1408
- || cInt == 46
1409
- /*'.'*/
1410
- || cInt == 45
1411
- /*'-'*/
1412
- ) {
1413
- fromHex = false;
1414
- exponent = false;
1415
- exponent_sign = false;
1416
- exponent_digit = false;
1417
- decimal = false;
1418
- val.string = str;
1419
- input.n = n;
1420
- collectNumber();
1421
- } else {
1422
- status = false;
1423
- throwError("fault parsing", cInt);
1424
- }
1425
-
1426
- break;
1427
- // default
1439
+ break;
1440
+ // default of high level switch
1441
+ }
1442
+ if (completed) {
1443
+ if (word == WORD_POS_END) {
1444
+ word = WORD_POS_RESET;
1428
1445
  }
1429
-
1430
1446
  break;
1431
- // default of high level switch
1432
- }
1433
-
1434
- if (completed) {
1435
- if (word == WORD_POS_END) {
1436
- word = WORD_POS_RESET;
1437
1447
  }
1438
-
1439
- break;
1440
1448
  }
1441
- }
1442
-
1443
- if (n == buf.length) {
1444
- dropBuffer(input);
1445
-
1446
- if (gatheringString || gatheringNumber || parse_context == CONTEXT_OBJECT_FIELD) {
1447
- retval = 0;
1448
- } else {
1449
- if (parse_context == CONTEXT_UNKNOWN && (val.value_type != VALUE_UNSET || result)) {
1450
- completed = true;
1451
- retval = 1;
1449
+ if (n == buf.length) {
1450
+ dropBuffer(input);
1451
+ if (complete_at_end) checkPartialValue();
1452
+ if (gatheringString || gatheringNumber || parse_context == CONTEXT_OBJECT_FIELD) {
1453
+ retval = 0;
1454
+ } else {
1455
+ if (parse_context == CONTEXT_UNKNOWN && (val.value_type != VALUE_UNSET || result)) {
1456
+ completed = true;
1457
+ retval = 1;
1458
+ }
1452
1459
  }
1460
+ } else {
1461
+ // put these back into the stack.
1462
+ input.n = n;
1463
+ inQueue.unshift(input);
1464
+ retval = 2; // if returning buffers, then obviously there's more in this one.
1453
1465
  }
1454
- } else {
1455
- // put these back into the stack.
1456
- input.n = n;
1457
- inQueue.unshift(input);
1458
- retval = 2; // if returning buffers, then obviously there's more in this one.
1466
+ if (completed) break;
1459
1467
  }
1460
-
1461
- if (completed) break;
1462
- }
1463
-
1464
- if (completed && val.value_type != VALUE_UNSET) {
1465
- switch (val.value_type) {
1466
- case VALUE_NUMBER:
1467
- result = (negative ? -1 : 1) * Number(val.string);
1468
- break;
1469
-
1470
- case VALUE_STRING:
1471
- result = val.string;
1472
- break;
1473
-
1474
- case VALUE_TRUE:
1475
- result = true;
1476
- break;
1477
-
1478
- case VALUE_FALSE:
1479
- result = false;
1480
- break;
1481
-
1482
- case VALUE_NULL:
1483
- result = null;
1484
- break;
1485
-
1486
- case VALUE_UNDEFINED:
1487
- result = undefined;
1488
- break;
1489
-
1490
- case VALUE_NAN:
1491
- result = NaN;
1492
- break;
1493
-
1494
- case VALUE_NEG_NAN:
1495
- result = -NaN;
1496
- break;
1497
-
1498
- case VALUE_INFINITY:
1499
- result = Infinity;
1500
- break;
1501
-
1502
- case VALUE_NEG_INFINITY:
1503
- result = -Infinity;
1504
- break;
1505
-
1506
- case VALUE_OBJECT:
1507
- // never happens
1508
- result = val.contains;
1509
- break;
1510
-
1511
- case VALUE_ARRAY:
1512
- // never happens
1513
- result = val.contains;
1514
- break;
1468
+ if (completed && val.value_type != VALUE_UNSET) {
1469
+ switch (val.value_type) {
1470
+ case VALUE_NUMBER:
1471
+ result = (negative ? -1 : 1) * Number(val.string);
1472
+ break;
1473
+ case VALUE_STRING:
1474
+ result = val.string;
1475
+ break;
1476
+ case VALUE_TRUE:
1477
+ result = true;
1478
+ break;
1479
+ case VALUE_FALSE:
1480
+ result = false;
1481
+ break;
1482
+ case VALUE_NULL:
1483
+ result = null;
1484
+ break;
1485
+ case VALUE_UNDEFINED:
1486
+ result = undefined;
1487
+ break;
1488
+ case VALUE_NAN:
1489
+ result = NaN;
1490
+ break;
1491
+ case VALUE_NEG_NAN:
1492
+ result = -NaN;
1493
+ break;
1494
+ case VALUE_INFINITY:
1495
+ result = Infinity;
1496
+ break;
1497
+ case VALUE_NEG_INFINITY:
1498
+ result = -Infinity;
1499
+ break;
1500
+ case VALUE_OBJECT:
1501
+ // never happens
1502
+ result = val.contains;
1503
+ break;
1504
+ case VALUE_ARRAY:
1505
+ // never happens
1506
+ result = val.contains;
1507
+ break;
1508
+ }
1509
+ negative = false;
1510
+ val.string = '';
1511
+ val.value_type = VALUE_UNSET;
1515
1512
  }
1516
-
1517
- negative = false;
1518
- val.string = '';
1519
- val.value_type = VALUE_UNSET;
1513
+ completed = false;
1514
+ return retval;
1520
1515
  }
1521
-
1522
- completed = false;
1523
- return retval;
1524
- }
1525
-
1516
+ };
1526
1517
  };
1527
- };
1528
-
1529
- const _parser = [Object.freeze(JSON6.begin())];
1530
- let _parse_level = 0;
1531
-
1532
- JSON6.parse = function (msg, reviver) {
1533
- //var parser = JSON6.begin();
1534
- const parse_level = _parse_level++;
1535
- if (_parser.length <= parse_level) _parser.push(Object.freeze(JSON6.begin()));
1536
- const parser = _parser[parse_level];
1537
- if (typeof msg !== "string") msg = String(msg);
1538
- parser.reset();
1539
-
1540
- if (parser._write(msg, true) > 0) {
1541
- const result = parser.value();
1542
- if (typeof reviver === 'function') (function walk(holder, key) {
1543
- const value = holder[key];
1544
-
1545
- if (value && typeof value === 'object') {
1546
- for (const k in value) {
1547
- if (Object.prototype.hasOwnProperty.call(value, k)) {
1548
- const v = walk(value, k);
1549
-
1550
- if (v !== undefined) {
1551
- value[k] = v;
1552
- } else {
1553
- delete value[k];
1518
+ const _parser = [Object.freeze(JSON6.begin())];
1519
+ let _parse_level = 0;
1520
+
1521
+ /**
1522
+ * @param {unknown} msg
1523
+ * @param {Json6Reviver} [reviver]
1524
+ * @param {Json6ParseOptions} [options]
1525
+ */
1526
+ JSON6.parse = function (msg, reviver, options) {
1527
+ //var parser = JSON6.begin();
1528
+ const parse_level = _parse_level++;
1529
+ if (_parser.length <= parse_level) _parser.push(Object.freeze(JSON6.begin()));
1530
+ const parser = _parser[parse_level];
1531
+ if (typeof msg !== "string") msg = String(msg);
1532
+ parser.reset(options);
1533
+ try {
1534
+ if (parser._write(/** @type {string} */msg, true) <= 0) {
1535
+ // nothing completed: empty document, whitespace, or only comments.
1536
+ parser.finalError();
1537
+ throw new Error("No value found in document");
1538
+ }
1539
+ const result = parser.value();
1540
+ if (typeof reviver === 'function')
1541
+ /**
1542
+ * @param {Record<string, unknown>} holder
1543
+ * @param {string} key
1544
+ * @returns {unknown}
1545
+ */
1546
+ (function walk(holder, key) {
1547
+ const value = holder[key];
1548
+ if (value && typeof value === 'object') {
1549
+ const record = /** @type {Record<string, unknown>} */value;
1550
+ for (const k in record) {
1551
+ if (Object.prototype.hasOwnProperty.call(record, k)) {
1552
+ const v = walk(record, k);
1553
+ if (v !== undefined) {
1554
+ record[k] = v;
1555
+ } else {
1556
+ delete record[k];
1557
+ }
1554
1558
  }
1555
1559
  }
1556
1560
  }
1557
- }
1558
-
1559
- return reviver.call(holder, key, value);
1560
- })({
1561
- '': result
1562
- }, '');
1563
- _parse_level--;
1564
- return result;
1565
- } else parser.finalError();
1566
-
1567
- return undefined;
1568
- };
1569
-
1570
- JSON6.stringify = JSON.stringify; //---------------------------------------------------------------------------
1571
- // Stringify
1572
- //---------------------------------------------------------------------------
1573
-
1574
- JSON6.stringifierActive = null;
1575
-
1576
- JSON6.stringifier = function () {
1577
- const keywords = {
1578
- ["true"]: true,
1579
- ["false"]: false,
1580
- ["null"]: null,
1581
- ["NaN"]: NaN,
1582
- ["Infinity"]: Infinity,
1583
- ["undefined"]: undefined
1584
- };
1585
- let useQuote = '"';
1586
- let ignoreNonEnumerable = false;
1587
- return {
1588
- stringify(o, r, s, as) {
1589
- return stringify(this, o, r, s, as);
1590
- },
1591
-
1592
- setQuote(q) {
1593
- useQuote = q;
1594
- },
1595
-
1596
- get ignoreNonEnumerable() {
1597
- return ignoreNonEnumerable;
1598
- },
1599
-
1600
- set ignoreNonEnumerable(val) {
1601
- ignoreNonEnumerable = val;
1561
+ return reviver.call(holder, key, value);
1562
+ })({
1563
+ '': result
1564
+ }, '');
1565
+ return result;
1566
+ } finally {
1567
+ _parse_level--;
1602
1568
  }
1603
-
1604
1569
  };
1605
1570
 
1606
- function getIdentifier(s) {
1607
- if ("number" === typeof s && !isNaN(s)) {
1608
- return ["'", s.toString(), "'"].join();
1609
- }
1610
-
1611
- if (!s.length) return useQuote + useQuote; // should check also for if any non ident in string...
1612
-
1613
- return s in keywords
1614
- /* [ "true","false","null","NaN","Infinity","undefined"].find( keyword=>keyword===s )*/
1615
- || /([0-9-])/.test(s[0]) || /((\n|\r|\t)|[ #{}()<>!+\-*/.:,])/.test(s) ? useQuote + JSON6.escape(s) + useQuote : s;
1616
- }
1617
-
1618
- function stringify(stringifier, object, replacer, space, asField) {
1619
- if (object === undefined) return "undefined";
1620
- if (object === null) return "null";
1621
- let gap;
1622
- let indent;
1623
- let i;
1624
- const spaceType = typeof space;
1625
- const repType = typeof replacer;
1626
- gap = "";
1627
- indent = "";
1628
- const stringifier_ = JSON6.stringifierActive;
1629
- JSON6.stringifierActive = stringifier;
1630
-
1631
- if (!asField) {
1632
- asField = "";
1633
- } // If the space parameter is a number, make an indent string containing that
1634
- // many spaces.
1635
-
1636
-
1637
- if (spaceType === "number") {
1638
- for (i = 0; i < space; i += 1) {
1639
- indent += " ";
1640
- } // If the space parameter is a string, it will be used as the indent string.
1641
-
1642
- } else if (spaceType === "string") {
1643
- indent = space;
1644
- } // If there is a replacer, it must be a function or an array.
1645
- // Otherwise, throw an error.
1646
-
1647
-
1648
- const rep = replacer;
1649
-
1650
- if (replacer && repType !== "function" && (repType !== "object" || typeof replacer.length !== "number")) {
1651
- throw new Error("JSON6.stringify unknown replacer type.");
1571
+ //---------------------------------------------------------------------------
1572
+ // Stringify
1573
+ //---------------------------------------------------------------------------
1574
+
1575
+ /**
1576
+ * @typedef {((key: string, value: unknown) => unknown) | Array<string|number> | null} Json6Replacer
1577
+ */
1578
+
1579
+ /**
1580
+ * @typedef {object} Json6Stringifier
1581
+ * @property {(o?: unknown, r?: Json6Replacer, s?: string|number|null, as?: string) => string|undefined} stringify
1582
+ * @property {(q: string) => void} setQuote
1583
+ * @property {boolean} ignoreNonEnumerable
1584
+ * @property {boolean} sortKeys
1585
+ */
1586
+
1587
+ /** @type {Json6Stringifier|null} */
1588
+ JSON6.stringifierActive = null;
1589
+ JSON6.stringifier = function () {
1590
+ const keywords = {
1591
+ ["true"]: true,
1592
+ ["false"]: false,
1593
+ ["null"]: null,
1594
+ ["NaN"]: NaN,
1595
+ ["Infinity"]: Infinity,
1596
+ ["undefined"]: undefined
1597
+ };
1598
+ let useQuote = '"';
1599
+ let ignoreNonEnumerable = false;
1600
+ // preserves the historical (sorted) output by default; set to `false` to
1601
+ // emit keys in their own enumeration order instead.
1602
+ let sortKeys = true;
1603
+ return {
1604
+ /**
1605
+ * @param {unknown} [o]
1606
+ * @param {Json6Replacer} [r]
1607
+ * @param {string|number|null} [s]
1608
+ * @param {string} [as]
1609
+ * @returns {string|undefined}
1610
+ */
1611
+ stringify(o, r, s, as) {
1612
+ return stringify(this, o, r, s, as);
1613
+ },
1614
+ /**
1615
+ * @param {string} q
1616
+ */
1617
+ setQuote(q) {
1618
+ useQuote = q;
1619
+ },
1620
+ get ignoreNonEnumerable() {
1621
+ return ignoreNonEnumerable;
1622
+ },
1623
+ set ignoreNonEnumerable(val) {
1624
+ ignoreNonEnumerable = val;
1625
+ },
1626
+ get sortKeys() {
1627
+ return sortKeys;
1628
+ },
1629
+ set sortKeys(val) {
1630
+ sortKeys = val;
1631
+ }
1632
+ };
1633
+
1634
+ /**
1635
+ * @param {string} s
1636
+ */
1637
+ function getIdentifier(s) {
1638
+ if (!s.length) return useQuote + useQuote;
1639
+ // should check also for if any non ident in string...
1640
+ return s in keywords /* [ "true","false","null","NaN","Infinity","undefined"].find( keyword=>keyword===s )*/ || /([0-9-])/.test(s[0]) || /((\n|\r|\t)|[ #{}()<>!+\-*/.:,])/.test(s) ? useQuote + JSON6.escape(s) + useQuote : s;
1652
1641
  }
1653
1642
 
1654
- const r = str(asField, {
1655
- [asField]: object
1656
- });
1657
- JSON6.stringifierActive = stringifier_; //DEBUG_STRINGIFY_OUTPUT && console.trace( "Stringify Result:", r );
1658
-
1659
- return r; // from https://github.com/douglascrockford/JSON-js/blob/master/json2.js#L181
1660
-
1661
- function str(key, holder) {
1662
- // Produce a string from holder[key].
1663
- let i; // The loop counter.
1664
-
1665
- let k; // The member key.
1666
-
1667
- let v; // The member value.
1668
-
1669
- let length;
1670
- const mind = gap;
1671
- let partial;
1672
- let value = holder[key];
1673
- if ("string" === typeof value) value = getIdentifier(value);
1674
-
1675
- if (value !== undefined && value !== null && typeof value === "object" && typeof toJSOX === "function") {
1676
- // is encoding?
1677
- gap += indent;
1678
- gap = mind;
1679
- } // If we were called with a replacer function, then call the replacer to
1680
- // obtain a replacement value.
1681
-
1682
-
1683
- if (typeof rep === "function") {
1684
- value = rep.call(holder, key, value);
1685
- } // What happens next depends on the value's type.
1686
-
1687
-
1688
- switch (typeof value) {
1689
- case "string":
1690
- return value;
1691
-
1692
- case "number":
1693
- return '' + value;
1694
- //useQuote+JSOX.escape( value )+useQuote;
1643
+ /**
1644
+ * @param {Json6Stringifier} stringifier
1645
+ * @param {unknown} object
1646
+ * @param {Json6Replacer} [replacer]
1647
+ * @param {string|number|null} [space]
1648
+ * @param {string} [asField]
1649
+ * @returns {string|undefined}
1650
+ */
1651
+ function stringify(stringifier, object, replacer, space, asField) {
1652
+ if (object === undefined) return "undefined";
1653
+ if (object === null) return "null";
1654
+ /** @type {string} */
1655
+ let gap = "";
1656
+ /** @type {string} */
1657
+ let indent = "";
1658
+ const stringifier_ = JSON6.stringifierActive;
1659
+ JSON6.stringifierActive = stringifier;
1660
+ if (!asField) {
1661
+ asField = "";
1662
+ }
1695
1663
 
1696
- case "boolean":
1697
- return String(value);
1664
+ // If the space parameter is a number, make an indent string containing that
1665
+ // many spaces.
1666
+ if (typeof space === "number") {
1667
+ for (let i = 0; i < space; i += 1) {
1668
+ indent += " ";
1669
+ }
1698
1670
 
1699
- case "object":
1700
- //_DEBUG_STRINGIFY && console.log( "ENTERING OBJECT EMISSION WITH:", v );
1701
- //if( v ) return v;
1702
- // Due to a specification blunder in ECMAScript, typeof null is "object",
1703
- // so watch out for that case.
1704
- if (!value) {
1705
- return "null";
1706
- } // Make an array to hold the partial results of stringifying this object value.
1671
+ // If the space parameter is a string, it will be used as the indent string.
1672
+ } else if (typeof space === "string") {
1673
+ indent = space;
1674
+ }
1707
1675
 
1676
+ // If there is a replacer, it must be a function or an array.
1677
+ // Otherwise, throw an error.
1678
+ const rep = replacer;
1679
+ if (replacer && typeof replacer !== "function" && (typeof replacer !== "object" || typeof replacer.length !== "number")) {
1680
+ throw new Error("JSON6.stringify unknown replacer type.");
1681
+ }
1682
+ const r = str(asField, {
1683
+ [asField]: object
1684
+ });
1685
+ JSON6.stringifierActive = stringifier_;
1686
+ //DEBUG_STRINGIFY_OUTPUT && console.trace( "Stringify Result:", r );
1687
+ return r;
1708
1688
 
1689
+ // from https://github.com/douglascrockford/JSON-js/blob/master/json2.js#L181
1690
+ /**
1691
+ * @param {string} key
1692
+ * @param {Record<string, unknown>} holder
1693
+ * @returns {string|undefined}
1694
+ */
1695
+ function str(key, holder) {
1696
+ // Produce a string from holder[key].
1697
+ const mind = gap;
1698
+ /** @type {unknown} */
1699
+ let value = holder[key];
1700
+ // A string *value* must always be quoted: unlike an object key,
1701
+ // a bareword here would parse back as an identifier/variable
1702
+ // reference rather than as the string itself, so `getIdentifier`
1703
+ // (which intentionally leaves identifier-shaped keys unquoted)
1704
+ // is not applicable to values. Using it here previously emitted
1705
+ // invalid, non-reparseable output for any identifier-shaped
1706
+ // string value (e.g. `"hello"` became the bare word `hello`).
1707
+ if ("string" === typeof value) {
1708
+ value = useQuote + JSON6.escape(value) + useQuote;
1709
+ }
1710
+ if (value !== undefined && value !== null && typeof value === "object" && typeof toJSOX === "function") {
1711
+ // is encoding?
1709
1712
  gap += indent;
1710
- partial = []; // If the replacer is an array, use it to select the members to be stringified.
1711
-
1712
- if (rep && typeof rep === "object") {
1713
- length = rep.length; //_DEBUG_STRINGIFY && console.log( "Working through replacer" );
1713
+ gap = mind;
1714
+ }
1715
+ // If we were called with a replacer function, then call the replacer to
1716
+ // obtain a replacement value.
1714
1717
 
1715
- for (i = 0; i < length; i += 1) {
1716
- if (typeof rep[i] === "string") {
1717
- k = rep[i];
1718
- v = str(k, value);
1718
+ if (typeof rep === "function") {
1719
+ value = rep.call(holder, key, value);
1720
+ }
1719
1721
 
1720
- if (v) {
1721
- partial.push(getIdentifier(k) + (gap ? ": " : ":") + v);
1722
- }
1722
+ // What happens next depends on the value's type.
1723
+ switch (typeof value) {
1724
+ case "string":
1725
+ return value;
1726
+ case "number":
1727
+ return '' + value;
1728
+ //useQuote+JSOX.escape( value )+useQuote;
1729
+ case "boolean":
1730
+ return String(value);
1731
+ case "object":
1732
+ {
1733
+ //_DEBUG_STRINGIFY && console.log( "ENTERING OBJECT EMISSION WITH:", v );
1734
+ //if( v ) return v;
1735
+
1736
+ // Due to a specification blunder in ECMAScript, typeof null is "object",
1737
+ // so watch out for that case.
1738
+ if (!value) {
1739
+ return "null";
1723
1740
  }
1724
- }
1725
- } else {
1726
- // Otherwise, iterate through all of the keys in the object.
1727
- const keys = []; //_DEBUG_STRINGIFY && console.log( "is something in something?", k, value );
1728
-
1729
- for (k in value) {
1730
- if (ignoreNonEnumerable) if (!Object.prototype.propertyIsEnumerable.call(value, k)) {
1731
- //_DEBUG_STRINGIFY && console.log( "skipping non-enuerable?", k );
1732
- continue;
1733
- } // sort properties into keys.
1734
-
1735
- if (Object.prototype.hasOwnProperty.call(value, k)) {
1736
- let n;
1737
-
1738
- for (n = 0; n < keys.length; n++) if (keys[n] > k) {
1739
- keys.splice(n, 0, k);
1740
- break;
1741
+ if (Array.isArray(value)) {
1742
+ // Arrays used to fall through to the object path below and come out
1743
+ // as {"0":..,"1":..}. Holes stay holes ( [1,,3] ) and undefined stays
1744
+ // undefined; both are JSON6 syntax and both parse back to what they were.
1745
+ const arr = /** @type {unknown[]} */value;
1746
+ const holder_ = /** @type {Record<string, unknown>} */ /** @type {unknown} */arr;
1747
+ gap += indent;
1748
+ /** @type {string[]} */
1749
+ const items = [];
1750
+ for (let i = 0; i < arr.length; i++) {
1751
+ if (!(i in arr)) {
1752
+ items.push("");
1753
+ continue;
1754
+ }
1755
+ const v = str(String(i), holder_);
1756
+ items.push(v === undefined ? "undefined" : v);
1741
1757
  }
1742
-
1743
- if (n === keys.length) keys.push(k);
1758
+ // a trailing hole needs its own comma, since "[1,]" parses as [1].
1759
+ const trailingHole = arr.length > 0 && !(arr.length - 1 in arr);
1760
+ const v = items.length === 0 ? "[]" : gap ? "[\n" + gap + items.join(",\n" + gap) + (trailingHole ? "," : "") + "\n" + mind + "]" : "[" + items.join(",") + (trailingHole ? "," : "") + "]";
1761
+ gap = mind;
1762
+ return v;
1744
1763
  }
1745
- } //_DEBUG_STRINGIFY && console.log( "Expanding object keys:", v, keys );
1746
-
1747
-
1748
- for (let n = 0; n < keys.length; n++) {
1749
- k = keys[n];
1750
-
1751
- if (Object.prototype.hasOwnProperty.call(value, k)) {
1752
- v = str(k, value);
1753
-
1754
- if (v) {
1755
- partial.push(getIdentifier(k) + (gap ? ": " : ":") + v);
1764
+ const record = /** @type {Record<string, unknown>} */value;
1765
+
1766
+ // Make an array to hold the partial results of stringifying this object value.
1767
+
1768
+ gap += indent;
1769
+ /** @type {string[]} */
1770
+ const partial = [];
1771
+
1772
+ // If the replacer is an array, use it to select the members to be stringified.
1773
+ if (rep && typeof rep === "object") {
1774
+ const length = rep.length;
1775
+ //_DEBUG_STRINGIFY && console.log( "Working through replacer" );
1776
+ for (let i = 0; i < length; i += 1) {
1777
+ if (typeof rep[i] === "string") {
1778
+ const k = /** @type {string} */rep[i];
1779
+ const v = str(k, record);
1780
+ if (v) {
1781
+ partial.push(getIdentifier(k) + (gap ? ": " : ":") + v);
1782
+ }
1783
+ }
1784
+ }
1785
+ } else {
1786
+ // Otherwise, iterate through all of the keys in the object.
1787
+ /** @type {string[]} */
1788
+ const keys = [];
1789
+ //_DEBUG_STRINGIFY && console.log( "is something in something?", k, value );
1790
+ for (const k in record) {
1791
+ if (ignoreNonEnumerable) if (!Object.prototype.propertyIsEnumerable.call(record, k)) {
1792
+ //_DEBUG_STRINGIFY && console.log( "skipping non-enuerable?", k );
1793
+ continue;
1794
+ }
1795
+ if (Object.prototype.hasOwnProperty.call(record, k)) {
1796
+ if (sortKeys) {
1797
+ // sort properties into keys.
1798
+ let n;
1799
+ for (n = 0; n < keys.length; n++) if (keys[n] > k) {
1800
+ keys.splice(n, 0, k);
1801
+ break;
1802
+ }
1803
+ if (n === keys.length) keys.push(k);
1804
+ } else {
1805
+ keys.push(k);
1806
+ }
1807
+ }
1808
+ }
1809
+ //_DEBUG_STRINGIFY && console.log( "Expanding object keys:", v, keys );
1810
+ for (let n = 0; n < keys.length; n++) {
1811
+ const k = keys[n];
1812
+ if (Object.prototype.hasOwnProperty.call(record, k)) {
1813
+ const v = str(k, record);
1814
+ if (v) {
1815
+ partial.push(getIdentifier(k) + (gap ? ": " : ":") + v);
1816
+ }
1817
+ }
1756
1818
  }
1757
1819
  }
1758
- }
1759
- } // Join all of the member texts together, separated with commas,
1760
- // and wrap them in braces.
1761
- //_DEBUG_STRINGIFY && console.log( "partial:", partial, protoConverter )
1762
1820
 
1763
-
1764
- v = '' + (partial.length === 0 ? "{}" : gap ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" : "{" + partial.join(",") + "}");
1765
- gap = mind; //_DEBUG_STRINGIFY && console.log(" Resulting phrase from this part is:", v );
1766
-
1767
- return v;
1821
+ // Join all of the member texts together, separated with commas,
1822
+ // and wrap them in braces.
1823
+ //_DEBUG_STRINGIFY && console.log( "partial:", partial, protoConverter )
1824
+ const v = '' + (partial.length === 0 ? "{}" : gap ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" : "{" + partial.join(",") + "}");
1825
+ gap = mind;
1826
+ //_DEBUG_STRINGIFY && console.log(" Resulting phrase from this part is:", v );
1827
+ return v;
1828
+ }
1829
+ }
1768
1830
  }
1769
1831
  }
1770
- }
1771
- };
1832
+ };
1772
1833
 
1773
- JSON6.stringify = function (object, replacer, space) {
1774
- const stringifier = JSON6.stringifier();
1775
- return stringifier.stringify(object, replacer, space);
1776
- };
1834
+ /**
1835
+ * @typedef {object} Json6StringifyOptions
1836
+ * @property {boolean} [sortKeys] When `false`, object keys are emitted in their
1837
+ * own enumeration order instead of sorted. Defaults to `true`.
1838
+ */
1839
+
1840
+ /**
1841
+ * @param {unknown} object
1842
+ * @param {Json6Replacer} [replacer]
1843
+ * @param {string|number} [space]
1844
+ * @param {Json6StringifyOptions} [options]
1845
+ * @returns {string|undefined}
1846
+ */
1847
+ JSON6.stringify = function (object, replacer, space, options) {
1848
+ const stringifier = JSON6.stringifier();
1849
+ if (options && options.sortKeys === false) stringifier.sortKeys = false;
1850
+ return stringifier.stringify(object, replacer, space);
1851
+ };
1852
+ JSON6.version = version;
1853
+
1854
+ // CommonJS export; guarded so lib/json6.js can also be loaded directly with a
1855
+ // <script> tag, where JSON6 is simply left as a global.
1856
+ /* istanbul ignore next -- the non-CommonJS branch is only reachable from a browser <script> tag */
1857
+ if (module && module.exports) module.exports = JSON6;
1858
+ })(json6);
1859
+ return json6.exports;
1860
+ }
1777
1861
 
1778
- JSON6.version = version;
1779
- });
1862
+ var lib;
1863
+ var hasRequiredLib;
1864
+ function requireLib() {
1865
+ if (hasRequiredLib) return lib;
1866
+ hasRequiredLib = 1;
1867
+ lib = requireJson6();
1868
+ return lib;
1869
+ }
1780
1870
 
1781
- var lib = json6;
1871
+ var libExports = requireLib();
1872
+ var index = /*@__PURE__*/getDefaultExportFromCjs(libExports);
1782
1873
 
1783
- export default lib;
1874
+ export { index as default };