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/README.md +222 -21
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/import.d.mts +2 -0
- package/dist/import.d.mts.map +1 -0
- package/dist/index-esm.d.mts +3 -0
- package/dist/index-esm.d.mts.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3283 -2120
- package/dist/index.min.js +1 -1
- package/dist/index.min.mjs +1 -1
- package/dist/index.mjs +1706 -1615
- package/dist/json6.d.ts +157 -0
- package/dist/json6.d.ts.map +1 -0
- package/dist/register.d.mts +2 -0
- package/dist/register.d.mts.map +1 -0
- package/dist/require.d.ts +3 -0
- package/dist/require.d.ts.map +1 -0
- package/lib/globals.d.ts +7 -0
- package/lib/import.mjs +30 -82
- package/lib/index-esm.mjs +3 -0
- package/lib/json6.js +665 -222
- package/lib/register.mjs +11 -0
- package/lib/require.js +6 -0
- package/package.json +53 -9
package/dist/index.mjs
CHANGED
|
@@ -1,160 +1,279 @@
|
|
|
1
|
-
function
|
|
2
|
-
return
|
|
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 =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
145
|
+
/**
|
|
146
|
+
* @param {Context} ctx
|
|
147
|
+
*/
|
|
148
|
+
function dropContext(ctx) {
|
|
149
|
+
contexts.push(ctx);
|
|
150
|
+
}
|
|
120
151
|
|
|
121
|
-
|
|
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
|
-
|
|
125
|
-
|
|
164
|
+
/**
|
|
165
|
+
* @param {Json6Node} buf
|
|
166
|
+
*/
|
|
167
|
+
function dropBuffer(buf) {
|
|
168
|
+
buffers.push(buf);
|
|
169
|
+
}
|
|
126
170
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
142
|
-
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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 =
|
|
212
|
-
recover.prior =
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
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
|
-
|
|
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
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
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
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
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
|
-
|
|
497
|
-
|
|
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
|
-
|
|
500
|
-
|
|
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
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
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
|
-
|
|
509
|
-
|
|
510
|
-
|
|
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
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
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
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
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
|
-
|
|
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
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
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
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
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
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
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
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
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);
|
|
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);
|
|
852
|
+
throwError("fault while parsing number;", cInt);
|
|
853
|
+
// break;
|
|
740
854
|
}
|
|
741
|
-
} else if (fromHex && (cInt >= 95
|
|
742
|
-
|
|
743
|
-
|
|
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);
|
|
864
|
+
throwError("fault while parsing number;", cInt);
|
|
865
|
+
// break;
|
|
771
866
|
}
|
|
772
|
-
} else if (cInt == 101
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
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
|
-
/*   */
|
|
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
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
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 /*   */ || 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
|
-
|
|
825
|
-
|
|
826
|
-
|
|
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
|
-
|
|
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
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
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
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
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
|
-
|
|
881
|
-
|
|
882
|
-
|
|
952
|
+
countLine(cInt);
|
|
953
|
+
if (comment == 1) {
|
|
954
|
+
// '/'
|
|
955
|
+
if (cInt == 42 /*'*'*/) {
|
|
883
956
|
comment = 3;
|
|
884
957
|
} // '/*'
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
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
|
|
969
|
+
// if( comment == 4 ) { // '/* ... *'
|
|
970
|
+
if (cInt == 47 /*'/'*/) comment = 0;else comment = 3; // any other char, goto expect * to close */
|
|
988
971
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
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
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
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("
|
|
1031
|
+
throwError("Unexpected array open after previous value", cInt);
|
|
1026
1032
|
}
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
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
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
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
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
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
|
-
|
|
1073
|
-
|
|
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
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
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
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
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: // :
|
|
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
|
-
|
|
1121
|
-
if (val.value_type
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
throwError("
|
|
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: // :
|
|
1147
|
-
|
|
1232
|
+
case 160: //  
|
|
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
|
-
//
|
|
1240
|
+
//'\uFEFF':
|
|
1241
|
+
countLine(cInt);
|
|
1152
1242
|
if (word == WORD_POS_END) {
|
|
1153
|
-
// allow collect new keyword
|
|
1154
1243
|
word = WORD_POS_RESET;
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
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 (
|
|
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
|
|
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
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
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: //  
|
|
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
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
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
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
}
|
|
1563
|
-
|
|
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
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
const
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
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
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
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
|
-
|
|
1697
|
-
|
|
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
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
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
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
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
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
v = str(k, value);
|
|
1718
|
+
if (typeof rep === "function") {
|
|
1719
|
+
value = rep.call(holder, key, value);
|
|
1720
|
+
}
|
|
1719
1721
|
|
|
1720
|
-
|
|
1721
|
-
|
|
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
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
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
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
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
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
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
|
-
|
|
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
|
|
1871
|
+
var libExports = requireLib();
|
|
1872
|
+
var index = /*@__PURE__*/getDefaultExportFromCjs(libExports);
|
|
1782
1873
|
|
|
1783
|
-
export default
|
|
1874
|
+
export { index as default };
|