sqlmath 2026.4.30 → 2026.6.30

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/jslint.mjs CHANGED
@@ -90,50 +90,312 @@
90
90
 
91
91
  // WARNING: JSLint will hurt your feelings.
92
92
 
93
- /*jslint beta, node*/
93
+ /*jslint beta, node, trace*/
94
94
  /*property
95
- JSLINT_BETA, NODE_V8_COVERAGE, a, all, argv, arity, artifact,
96
- assertErrorThrownAsync, assertJsonEqual, assertOrThrow, assign, async, b,
97
- beta, bitwise, block, body, browser, c, calls, catch, catch_list,
98
- catch_stack, causes, char, children, clear, closer, closure, code, column,
99
- concat, consoleError, console_error, console_log, constant, context,
100
- convert, count, coverageDir, create, cwd, d, dead, debugInline, default,
101
- delta, devel, directive, directive_ignore_line, directive_list, directives,
102
- dirname, disrupt, dot, edition, elem_list, ellipsis, else, end, endOffset,
103
- endsWith, entries, env, error, eval, every, example_list, excludeList, exec,
104
- execArgv, exit, exitCode, export_dict, exports, expression, extra, fart,
105
- file, fileList, fileURLToPath, filter, finally, flag, floor, for, forEach,
106
- formatted_message, free, freeze, from, froms, fsWriteFileWithParents,
107
- fud_stmt, functionName, function_list, function_stack, functions, get,
108
- getset, github_repo, globExclude, global, global_dict, global_list,
109
- holeList, htmlEscape, id, identifier, ignoreLine, import, import_list,
110
- import_meta_url, inc, includeList, indent2, index, indexOf, init, initial,
111
- isArray, isBlockCoverage, isHole, isNaN, is_equal, is_weird, join, jslint,
112
- jslint_apidoc, jslint_assert, jslint_charset_ascii, jslint_cli,
113
- jslint_edition, jslint_phase1_split, jslint_phase2_lex, jslint_phase3_parse,
114
- jslint_phase4_walk, jslint_phase5_whitage, jslint_report, json,
115
- jstestDescribe, jstestIt, jstestOnExit, keys, label, lbp, led_infix, length,
116
- level, line, lineList, line_list, line_offset, line_source, lines,
117
- linesCovered, linesTotal, live, log, long, loop, m, map, margin, match, max,
118
- message, meta, min, mkdir, modeCoverageIgnoreFile, modeIndex, mode_cli,
119
- mode_conditional, mode_json, mode_module, mode_noop, mode_property,
120
- mode_shebang, mode_stop, module, moduleFsInit, moduleName, module_list,
121
- name, names, node, nomen, noop, now, nr, nud_prefix,
122
- objectDeepCopyWithKeysSorted, ok, on, open, opening, option, option_dict,
123
- order, package_name, padEnd, padStart, parameters, parent, parentIi, parse,
124
- pathname, pathnameList, platform, pop, processArgv, process_argv,
125
- process_env, process_exit, promises, property, property_dict, push, quote,
126
- ranges, readFile, readdir, readonly, recursive, reduce, repeat, replace,
127
- resolve, result, reverse, role, round, scriptId, search, set, shebang,
128
- shell, shift, signature, single, slice, some, sort, source, spawn, splice,
129
- split, stack, stack_trace, start, startOffset, startsWith, statement,
130
- statement_prv, stdio, stop, stop_at, stringify, subscript, switch,
131
- syntax_dict, tenure, test, test_cause, test_internal_error, this, thru,
132
- toLocaleString, toString, token, token_global, token_list, token_nxt,
133
- token_tree, tokens, trace, tree, trim, trimEnd, trimRight, try, type,
134
- unlink, unordered, unshift, url, used, v8CoverageListMerge,
135
- v8CoverageReportCreate, value, variable, version, versions, warn, warn_at,
136
- warning, warning_list, warnings, white, wrapped, writeFile
95
+ JSLINT_BETA,
96
+ NODE_V8_COVERAGE,
97
+ a,
98
+ all,
99
+ argv,
100
+ arity,
101
+ artifact,
102
+ assertErrorThrownAsync,
103
+ assertJsonEqual,
104
+ assertOrThrow,
105
+ assign,
106
+ assignment,
107
+ async,
108
+ b,
109
+ beta,
110
+ bitwise,
111
+ block,
112
+ body,
113
+ browser,
114
+ c,
115
+ calls,
116
+ catch,
117
+ catch_list,
118
+ catch_stack,
119
+ causes,
120
+ char,
121
+ children,
122
+ clear,
123
+ closer,
124
+ closure,
125
+ code,
126
+ column,
127
+ concat,
128
+ consoleError,
129
+ console_error,
130
+ console_log,
131
+ constant,
132
+ context,
133
+ convert,
134
+ count,
135
+ coverageDir,
136
+ create,
137
+ cwd,
138
+ d,
139
+ dead,
140
+ debugInline,
141
+ default,
142
+ delta,
143
+ devel,
144
+ directive,
145
+ directive_ignore_line,
146
+ directive_list,
147
+ directives,
148
+ dirname,
149
+ disrupt,
150
+ dot,
151
+ edition,
152
+ elem_list,
153
+ ellipsis,
154
+ else,
155
+ end,
156
+ endOffset,
157
+ endsWith,
158
+ entries,
159
+ env,
160
+ error,
161
+ eval,
162
+ every,
163
+ example_list,
164
+ excludeList,
165
+ exec,
166
+ execArgv,
167
+ exit,
168
+ exitCode,
169
+ export_dict,
170
+ exports,
171
+ expression,
172
+ extra,
173
+ fart,
174
+ file,
175
+ fileList,
176
+ fileURLToPath,
177
+ filter,
178
+ finally,
179
+ flag,
180
+ floor,
181
+ for,
182
+ forEach,
183
+ formatted_message,
184
+ free,
185
+ freeze,
186
+ from,
187
+ froms,
188
+ fsWriteFileWithParents,
189
+ fud_stmt,
190
+ functionName,
191
+ function_list,
192
+ function_stack,
193
+ functions,
194
+ get,
195
+ getset,
196
+ github_repo,
197
+ globExclude,
198
+ global,
199
+ global_dict,
200
+ global_list,
201
+ holeList,
202
+ htmlEscape,
203
+ id,
204
+ identifier,
205
+ ignoreLine,
206
+ import,
207
+ import_list,
208
+ import_meta_url,
209
+ inc,
210
+ includeList,
211
+ indent2,
212
+ indent_method,
213
+ index,
214
+ indexOf,
215
+ init,
216
+ initial,
217
+ isArray,
218
+ isBlockCoverage,
219
+ isHole,
220
+ isNaN,
221
+ is_equal,
222
+ is_weird,
223
+ join,
224
+ jslint,
225
+ jslint_apidoc,
226
+ jslint_assert,
227
+ jslint_charset_ascii,
228
+ jslint_cli,
229
+ jslint_edition,
230
+ jslint_phase1_split,
231
+ jslint_phase2_lex,
232
+ jslint_phase3_parse,
233
+ jslint_phase4_walk,
234
+ jslint_phase5_whitage,
235
+ jslint_report,
236
+ json,
237
+ jstestDescribe,
238
+ jstestIt,
239
+ jstestOnExit,
240
+ keys,
241
+ label,
242
+ lbp,
243
+ led_infix,
244
+ length,
245
+ level,
246
+ line,
247
+ lineList,
248
+ line_list,
249
+ line_offset,
250
+ line_source,
251
+ lines,
252
+ linesCovered,
253
+ linesTotal,
254
+ live_list,
255
+ log,
256
+ long,
257
+ loop,
258
+ m,
259
+ map,
260
+ margin,
261
+ match,
262
+ max,
263
+ message,
264
+ meta,
265
+ min,
266
+ mkdir,
267
+ modeCoverageIgnoreFile,
268
+ modeIndex,
269
+ mode_cli,
270
+ mode_conditional,
271
+ mode_json,
272
+ mode_module,
273
+ mode_noop,
274
+ mode_property,
275
+ mode_shebang,
276
+ mode_stop,
277
+ module,
278
+ moduleFsInit,
279
+ moduleName,
280
+ module_list,
281
+ name,
282
+ name_list,
283
+ node,
284
+ nomen,
285
+ noop,
286
+ now,
287
+ nr,
288
+ nud_prefix,
289
+ objectDeepCopyWithKeysSorted,
290
+ ok,
291
+ on,
292
+ open,
293
+ opening,
294
+ option,
295
+ option_dict,
296
+ order,
297
+ package_name,
298
+ padEnd,
299
+ padStart,
300
+ parameter_count,
301
+ parent,
302
+ parentIi,
303
+ parse,
304
+ pathname,
305
+ pathnameList,
306
+ platform,
307
+ pop,
308
+ processArgv,
309
+ process_argv,
310
+ process_env,
311
+ process_exit,
312
+ promises,
313
+ property,
314
+ property_dict,
315
+ push,
316
+ quote,
317
+ ranges,
318
+ readFile,
319
+ readdir,
320
+ readonly,
321
+ recursive,
322
+ reduce,
323
+ repeat,
324
+ replace,
325
+ resolve,
326
+ result,
327
+ reverse,
328
+ role,
329
+ round,
330
+ scriptId,
331
+ search,
332
+ set,
333
+ shebang,
334
+ shell,
335
+ shift,
336
+ signature,
337
+ single,
338
+ slice,
339
+ some,
340
+ sort,
341
+ source,
342
+ spawn,
343
+ splice,
344
+ split,
345
+ stack,
346
+ stack_trace,
347
+ start,
348
+ startOffset,
349
+ startsWith,
350
+ statement,
351
+ statement_prv,
352
+ stdio,
353
+ stop,
354
+ stop_at,
355
+ stringify,
356
+ subscript,
357
+ switch,
358
+ syntax_dict,
359
+ tenure,
360
+ test,
361
+ test_cause,
362
+ test_internal_error,
363
+ this,
364
+ thru,
365
+ toLocaleString,
366
+ toString,
367
+ token,
368
+ token_global,
369
+ token_list,
370
+ token_nxt,
371
+ token_tree,
372
+ tokens,
373
+ trace,
374
+ tree,
375
+ trim,
376
+ trimEnd,
377
+ trimRight,
378
+ try,
379
+ type,
380
+ unlink,
381
+ unordered,
382
+ unshift,
383
+ url,
384
+ used,
385
+ v8CoverageListMerge,
386
+ v8CoverageReportCreate,
387
+ value,
388
+ variable,
389
+ version,
390
+ versions,
391
+ warn,
392
+ warn_at,
393
+ warning,
394
+ warning_list,
395
+ warnings,
396
+ white,
397
+ wrapped,
398
+ writeFile
137
399
  */
138
400
 
139
401
  // init debugInline
@@ -141,14 +403,14 @@ let debugInline = (function () {
141
403
  let __consoleError = function () {
142
404
  return;
143
405
  };
144
- function debug(...argv) {
406
+ function debug(...argList) {
145
407
 
146
- // This function will print <argv> to stderr and then return <argv>[0].
408
+ // This function will print <argList> to stderr and then return <argList>[0].
147
409
 
148
410
  __consoleError("\n\ndebugInline");
149
- __consoleError(...argv);
411
+ __consoleError(...argList);
150
412
  __consoleError("\n");
151
- return argv[0];
413
+ return argList[0];
152
414
  }
153
415
  debug(); // Coverage-hack.
154
416
  __consoleError = console.error; //jslint-ignore-line
@@ -163,7 +425,7 @@ let jslint_charset_ascii = (
163
425
  + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
164
426
  + "`abcdefghijklmnopqrstuvwxyz{|}~\u007f"
165
427
  );
166
- let jslint_edition = "v2026.4.30";
428
+ let jslint_edition = "v2026.7.1-beta";
167
429
  let jslint_export; // The jslint object to be exported.
168
430
  let jslint_fudge = 1; // Fudge starting line and starting
169
431
  // ... column to 1.
@@ -187,7 +449,7 @@ let jslint_rgx_digits_octals = (
187
449
  /^[0-7_]*/
188
450
  );
189
451
  let jslint_rgx_directive = (
190
- /^(jslint|property|global)\s+(.*)$/
452
+ /^(jslint|property|global)\s+?(\S.*?)$/
191
453
  );
192
454
  let jslint_rgx_directive_part = (
193
455
  /([a-zA-Z$_][a-zA-Z0-9$_]*)(?::\s*(true|false))?,?\s*|$/g
@@ -228,6 +490,7 @@ let jslint_rgx_token = new RegExp(
228
490
  + "(\\s+)"
229
491
  + "|([a-zA-Z_$][a-zA-Z0-9_$]*)"
230
492
  + "|[(){}\\[\\],:;'\"~\\`]"
493
+ + "|\\?\\?="
231
494
  + "|\\?[?.]?"
232
495
  + "|=(?:==?|>)?"
233
496
  + "|\\.+"
@@ -236,9 +499,10 @@ let jslint_rgx_token = new RegExp(
236
499
  + "|\\+[=+]?"
237
500
  + "|-[=\\-]?"
238
501
  + "|[\\^%]=?"
502
+ + "|&&="
239
503
  + "|&[&=]?"
240
- + "|\\"
241
- + "|[|=]?"
504
+ + "|\\|\\|="
505
+ + "|\\|[|=]?"
242
506
  + "|>{1,3}=?"
243
507
  + "|<<?=?"
244
508
  + "|!(?:!|==?)?"
@@ -575,13 +839,10 @@ function htmlEscape(str) {
575
839
 
576
840
  // This function will make <str> html-safe by escaping & < >.
577
841
 
578
- return String(str).replace((
579
- /&/g
580
- ), "&amp;").replace((
581
- /</g
582
- ), "&lt;").replace((
583
- />/g
584
- ), "&gt;");
842
+ return String(str)
843
+ .replace((/&/g), "&amp;")
844
+ .replace((/</g), "&lt;")
845
+ .replace((/>/g), "&gt;");
585
846
  }
586
847
 
587
848
  function jslint(
@@ -632,7 +893,7 @@ function jslint(
632
893
  id: "(global)",
633
894
  level: 0,
634
895
  line: jslint_fudge,
635
- live: [],
896
+ live_list: [],
636
897
  loop: 0,
637
898
  switch: 0,
638
899
  thru: 0,
@@ -822,22 +1083,24 @@ function jslint(
822
1083
  // This function will instrument <cause> to <cause_dict> for test-purposes.
823
1084
 
824
1085
  if (option_dict.test_cause) {
825
- cause_dict[JSON.stringify([
826
- String(new Error().stack).replace((
827
- /^ at (?:file|stop|stop_at|test_cause|warn|warn_at)\b.*?\n/gm
828
- ), "").match(
829
- /\n at ((?:Object\.\w+?_)?\w+?) /
830
- )[1].replace((
831
- /^Object\./
832
- ), ""),
833
- code,
834
- String(
835
- (aa === undefined || aa === token_global)
836
- ? ""
837
- : aa
838
- ),
839
- column || 0
840
- ])] = true;
1086
+ cause_dict[
1087
+ JSON.stringify([
1088
+ String(new Error().stack)
1089
+ .replace(
1090
+ (/^ at (?:file|stop|stop_at|test_cause|warn|warn_at)\b.*?\n/gm),
1091
+ ""
1092
+ )
1093
+ .match(/\n at ((?:Object\.\w+?_)?\w+?) /)[1]
1094
+ .replace((/^Object\./), ""),
1095
+ code,
1096
+ String(
1097
+ (aa === undefined || aa === token_global)
1098
+ ? ""
1099
+ : aa
1100
+ ),
1101
+ column || 0
1102
+ ])
1103
+ ] = true;
841
1104
  }
842
1105
  }
843
1106
 
@@ -1006,7 +1269,7 @@ function jslint(
1006
1269
  case "infix_in":
1007
1270
  mm = (
1008
1271
  `Unexpected 'in'. Compare with undefined,`
1009
- + ` or use the hasOwnProperty method instead.`
1272
+ + ` or use Object.hasOwn() instead.`
1010
1273
  );
1011
1274
  break;
1012
1275
  case "label_a":
@@ -1157,15 +1420,6 @@ function jslint(
1157
1420
  case "use_double":
1158
1421
  mm = `Use double quotes, not single quotes.`;
1159
1422
  break;
1160
-
1161
- // PR-386 - Fix issue #382 - Make fart-related warnings more readable.
1162
-
1163
- case "use_function_not_fart":
1164
- mm = (
1165
- `Use 'function (...)', not '(...) =>' when arrow functions`
1166
- + ` become too complex.`
1167
- );
1168
- break;
1169
1423
  case "use_open":
1170
1424
  mm = (
1171
1425
  `Wrap a ternary expression in parens,`
@@ -1479,13 +1733,10 @@ ${name}
1479
1733
  /(\([\S\s]*?\)) \{/
1480
1734
  ), function (match0, match1) {
1481
1735
  signature = htmlEscape(
1482
- match1.replace((
1483
- / *?\/\*[\S\s]*?\*\/ */g
1484
- ), "").replace((
1485
- / *?\/\/.*/g
1486
- ), "").replace((
1487
- /\n{2,}/g
1488
- ), "\n")
1736
+ match1
1737
+ .replace((/ *?\/\*[\S\s]*?\*\/ */g), "")
1738
+ .replace((/ *?\/\/.*/g), "")
1739
+ .replace((/\n{2,}/g), "\n")
1489
1740
  );
1490
1741
  return match0;
1491
1742
  });
@@ -1760,16 +2011,22 @@ function jslint_assert(condition, message) {
1760
2011
 
1761
2012
  // This function will throw <message> if <condition> is falsy.
1762
2013
 
2014
+ let error;
1763
2015
  if (condition) {
1764
- return condition;
2016
+ return;
1765
2017
  }
1766
- throw new Error(
2018
+ error = new Error(
1767
2019
  `This was caused by a bug in JSLint.
1768
2020
  Please open an issue with this stack-trace (and possible example-code) at
1769
2021
  https://github.com/jslint-org/jslint/issues.
1770
2022
  edition = "${jslint_edition}";
1771
2023
  ${String(message).slice(0, 2000)}`
1772
2024
  );
2025
+ if (message === "test_internal_error") {
2026
+ error = {};
2027
+ }
2028
+ console.error(error);
2029
+ throw error;
1773
2030
  }
1774
2031
 
1775
2032
  async function jslint_cli({
@@ -2183,9 +2440,8 @@ function jslint_phase2_lex(state) {
2183
2440
  // ... literal.
2184
2441
  let mode_regexp; // true if regular expression literal seen on
2185
2442
  // ... this line.
2186
- let paren_backtrack_list = []; // List of most recent "(" tokens at any
2187
- // ... paren-depth.
2188
- let paren_depth = 0; // Keeps track of current paren-depth.
2443
+ let opener_popped = empty(); // Last token popped from opener_stack.
2444
+ let opener_stack = []; // Stack of opener tokens: (, [.
2189
2445
  let snippet = ""; // A piece of string.
2190
2446
  let token_1; // The first token.
2191
2447
  let token_prv = token_global; // The previous token including
@@ -2279,7 +2535,13 @@ function jslint_phase2_lex(state) {
2279
2535
  // test_cause:
2280
2536
  // ["\"\\u{12345\"", "char_after_escape", "expected_a_before_b", "\"", 10]
2281
2537
 
2282
- stop_at("expected_a_before_b", line, column, "}", char);
2538
+ return stop_at(
2539
+ "expected_a_before_b",
2540
+ line,
2541
+ column,
2542
+ "}",
2543
+ char
2544
+ );
2283
2545
  }
2284
2546
  return char_after();
2285
2547
  }
@@ -2430,9 +2692,14 @@ function jslint_phase2_lex(state) {
2430
2692
 
2431
2693
  // Lex directives in comment.
2432
2694
 
2433
- [
2434
- the_comment.directive, body
2435
- ] = Array.from(snippet.match(jslint_rgx_directive) || []).slice(1);
2695
+ snippet.replace(jslint_rgx_directive, function (
2696
+ ignore,
2697
+ match1,
2698
+ match2
2699
+ ) {
2700
+ the_comment.directive = match1;
2701
+ body = match2;
2702
+ });
2436
2703
  if (the_comment.directive === undefined) {
2437
2704
  return the_comment;
2438
2705
  }
@@ -2825,14 +3092,55 @@ function jslint_phase2_lex(state) {
2825
3092
  case "?":
2826
3093
  char_after("?");
2827
3094
  switch (char) {
3095
+
3096
+ // ES1999-feature Negative lookahead assertion.
3097
+
2828
3098
  case "!":
2829
3099
 
2830
3100
  // PR-437 - Add grammar for regexp-named-capture-group.
2831
3101
 
2832
3102
  case "<":
3103
+
3104
+ // ES1999-feature Positive lookahead assertion.
3105
+
2833
3106
  case "=":
2834
3107
  char_after();
2835
3108
  break;
3109
+
3110
+ // PR-499 - Add ES2025-feature RegExp Modifiers.
3111
+
3112
+ case "-":
3113
+ case "i":
3114
+ case "m":
3115
+ case "s":
3116
+ char_after();
3117
+ while (true) {
3118
+ if (char === ":" && snippet.slice(-1) !== "-") {
3119
+ char_after();
3120
+ break;
3121
+ }
3122
+ switch (char) {
3123
+ case "-":
3124
+ case "i":
3125
+ case "m":
3126
+ case "s":
3127
+ char_after();
3128
+ break;
3129
+ default:
3130
+
3131
+ // test_cause:
3132
+ // ["aa=/(?-.", "lex_regexp_group", "unexpected_a_after_b", "(?-", 8]
3133
+
3134
+ return stop_at(
3135
+ "unexpected_a_after_b",
3136
+ line,
3137
+ column,
3138
+ snippet.slice(-1),
3139
+ snippet.slice(0, -1)
3140
+ );
3141
+ }
3142
+ }
3143
+ break;
2836
3144
  default:
2837
3145
  char_after(":");
2838
3146
  }
@@ -2993,14 +3301,29 @@ function jslint_phase2_lex(state) {
2993
3301
  // Process dangling flag letters.
2994
3302
 
2995
3303
  switch (!flag[char] && char) {
3304
+
3305
+ // PR-499 - Add ES2022-feature RegExp Match Indices.
3306
+
3307
+ case "d":
3308
+ break;
2996
3309
  case "g":
2997
3310
  break;
2998
3311
  case "i":
2999
3312
  break;
3000
3313
  case "m":
3001
3314
  break;
3315
+
3316
+ // PR-499 - Add ES2018-feature s (dotall) flag for regular expressions.
3317
+
3318
+ case "s":
3319
+ break;
3002
3320
  case "u":
3003
3321
  break;
3322
+
3323
+ // PR-499 - Add ES2024-feature RegExp v flag with set-notation + str-properties.
3324
+
3325
+ case "v":
3326
+ break;
3004
3327
  case "y":
3005
3328
 
3006
3329
  // test_cause:
@@ -3487,9 +3810,9 @@ import https from "https";
3487
3810
  });
3488
3811
  });
3489
3812
  result.replace((
3490
- /\n- \{\{JSxRef\("(?:Global_Objects\/)?([^"\/]+?)"/g
3813
+ /\n- \{\{jsxref\("(?:global_objects\/)?([^"]+?)"/ig
3491
3814
  ), function (ignore, key) {
3492
- if (globalThis.hasOwnProperty(key)) {
3815
+ if (Object.hasOwn(globalThis, key)) {
3493
3816
  dict[key] = true;
3494
3817
  }
3495
3818
  return "";
@@ -3513,6 +3836,7 @@ import https from "https";
3513
3836
  "Date",
3514
3837
  "Error",
3515
3838
  "EvalError",
3839
+ "Float16Array",
3516
3840
  "Float32Array",
3517
3841
  "Float64Array",
3518
3842
  "Function",
@@ -3534,10 +3858,12 @@ import https from "https";
3534
3858
  "Reflect",
3535
3859
  "RegExp",
3536
3860
  "Set",
3861
+ "ShadowRealm",
3537
3862
  "SharedArrayBuffer",
3538
3863
  "String",
3539
3864
  "Symbol",
3540
3865
  "SyntaxError",
3866
+ "Temporal",
3541
3867
  "TypeError",
3542
3868
  "URIError",
3543
3869
  "Uint16Array",
@@ -3545,6 +3871,7 @@ import https from "https";
3545
3871
  "Uint8Array",
3546
3872
  "Uint8ClampedArray",
3547
3873
  "WeakMap",
3874
+ "WeakRef",
3548
3875
  "WeakSet",
3549
3876
  "WebAssembly",
3550
3877
  "decodeURI",
@@ -3729,7 +4056,7 @@ import moduleHttps from "https";
3729
4056
  // test_cause:
3730
4057
  // ["/*jslint-enable*/", "read_line", "unopened_enable", "", 1]
3731
4058
 
3732
- stop_at("unopened_enable", line);
4059
+ return stop_at("unopened_enable", line);
3733
4060
  }
3734
4061
  line_disable = undefined;
3735
4062
  } else if (
@@ -3833,21 +4160,34 @@ import moduleHttps from "https";
3833
4160
 
3834
4161
  switch (id) {
3835
4162
  case "(":
3836
- paren_backtrack_list[paren_depth] = the_token;
3837
- paren_depth += 1;
4163
+ case "[":
4164
+ opener_stack.push(the_token);
3838
4165
  break;
3839
4166
  case ")":
3840
- paren_depth -= 1;
3841
- break;
3842
- case "=>":
3843
- if (
3844
- token_prv_expr.id === ")"
3845
- && paren_backtrack_list[paren_depth]
3846
- ) {
3847
- paren_backtrack_list[paren_depth].fart = the_token;
4167
+ case "]":
4168
+ opener_popped = opener_stack.pop();
4169
+ if (noop(
4170
+ id === ")"
4171
+ ? opener_popped.id !== "("
4172
+ : opener_popped.id !== "["
4173
+ )) {
4174
+
4175
+ // test_cause:
4176
+ // [";(]", "token_create", "unexpected_a", "]", 3]
4177
+ // [";[)", "token_create", "unexpected_a", ")", 3]
4178
+
4179
+ return stop("unexpected_a", the_token);
3848
4180
  }
3849
4181
  break;
3850
4182
  }
4183
+ switch (token_prv_expr.id + " " + id) {
4184
+ case ") =>":
4185
+ opener_popped.fart = the_token;
4186
+ break;
4187
+ case "] =":
4188
+ opener_popped.assignment = the_token;
4189
+ break;
4190
+ }
3851
4191
 
3852
4192
  // The previous token is used to detect adjacency problems.
3853
4193
 
@@ -3938,6 +4278,7 @@ function jslint_phase3_parse(state) {
3938
4278
  // ... the parse.
3939
4279
  let token_nxt = token_global; // The next token to be examined in
3940
4280
  // ... <token_list>.
4281
+ let token_prv = token_global; // The previous token examined.
3941
4282
 
3942
4283
  function advance(id, match) {
3943
4284
 
@@ -3985,6 +4326,7 @@ function jslint_phase3_parse(state) {
3985
4326
 
3986
4327
  // Promote the tokens, skipping comments.
3987
4328
 
4329
+ token_prv = token_now;
3988
4330
  token_now = token_nxt;
3989
4331
  while (true) {
3990
4332
  token_nxt = token_list[token_ii];
@@ -4020,7 +4362,15 @@ function jslint_phase3_parse(state) {
4020
4362
  the_token.arity = "assignment";
4021
4363
  right = parse_expression(20 - 1);
4022
4364
  if (id === "=" && left.arity === "variable") {
4023
- the_token.names = left;
4365
+ the_token.name_list = []; // 1. name_list for "aa = ..."
4366
+ name_push(
4367
+ the_token.name_list, // name_list
4368
+ false, // enroll
4369
+ left, // name
4370
+ "variable", // role
4371
+ false, // readonly
4372
+ true // init
4373
+ );
4024
4374
  the_token.expression = right;
4025
4375
  } else {
4026
4376
  the_token.expression = [left, right];
@@ -4067,7 +4417,7 @@ function jslint_phase3_parse(state) {
4067
4417
  ) {
4068
4418
  token_nxt.statement = true;
4069
4419
  advance("(string)");
4070
- advance(";");
4420
+ semicolon();
4071
4421
  }
4072
4422
  stmts = parse_statements();
4073
4423
  the_block.block = stmts;
@@ -4100,6 +4450,10 @@ function jslint_phase3_parse(state) {
4100
4450
  const id = left.id;
4101
4451
  if (
4102
4452
  !left.identifier
4453
+
4454
+ // PR-xxx - Relax warning for ((...) => {...}());
4455
+
4456
+ && left.id !== "=>"
4103
4457
  && (
4104
4458
  left.arity !== "ternary"
4105
4459
  || (
@@ -4162,13 +4516,20 @@ function jslint_phase3_parse(state) {
4162
4516
 
4163
4517
  // This function will warn if <token_list> is unordered.
4164
4518
 
4165
- token_list.reduce(function (aa, token) {
4166
- const bb = artifact(token);
4167
- if (!option_dict.unordered && aa > bb) {
4168
- warn("expected_a_b_before_c_d", token, type, bb, type, aa);
4169
- }
4170
- return bb;
4171
- }, "");
4519
+ token_list
4520
+ .filter(function (token) {
4521
+
4522
+ // Issue #401 - Regression - Ignore tokens prefixed by ellipsis for sorting.
4523
+
4524
+ return token && !token.ellipsis;
4525
+ })
4526
+ .reduce(function (aa, token) {
4527
+ const bb = artifact(token);
4528
+ if (!option_dict.unordered && aa > bb) {
4529
+ warn("expected_a_b_before_c_d", token, type, bb, type, aa);
4530
+ }
4531
+ return bb;
4532
+ }, "");
4172
4533
  }
4173
4534
 
4174
4535
  function check_ordered_case(case_list) {
@@ -4430,95 +4791,6 @@ function jslint_phase3_parse(state) {
4430
4791
  return token_now;
4431
4792
  }
4432
4793
 
4433
- function enroll(name, role, readonly) {
4434
-
4435
- // Enroll a name into the current function context. The role can be exception,
4436
- // function, label, parameter, or variable. We look for variable redefinition
4437
- // because it causes confusion.
4438
-
4439
- let earlier;
4440
- let id = name.id;
4441
-
4442
- // Reserved words may not be enrolled.
4443
-
4444
- if (syntax_dict[id] !== undefined && id !== "ignore") {
4445
-
4446
- // test_cause:
4447
- // ["let undefined", "enroll", "reserved_a", "undefined", 5]
4448
-
4449
- warn("reserved_a", name);
4450
- return;
4451
- }
4452
-
4453
- // Has the name been enrolled in this context?
4454
-
4455
- earlier = functionage.context[id] || catchage.context[id];
4456
- if (earlier) {
4457
-
4458
- // test_cause:
4459
- // ["let aa;let aa", "enroll", "redefinition_a_b", "1", 12]
4460
-
4461
- warn("redefinition_a_b", name, id, earlier.line);
4462
- return;
4463
- }
4464
-
4465
- // Has the name been enrolled in an outer context?
4466
-
4467
- function_stack.forEach(function ({
4468
- context
4469
- }) {
4470
- earlier = context[id] || earlier;
4471
- });
4472
- if (earlier && id === "ignore") {
4473
- if (earlier.role === "variable") {
4474
-
4475
- // test_cause:
4476
- // ["let ignore;function aa(ignore){}", "enroll", "redefinition_a_b", "1", 24]
4477
-
4478
- warn("redefinition_a_b", name, id, earlier.line);
4479
- }
4480
- } else if (
4481
- earlier
4482
- && role !== "parameter" && role !== "function"
4483
- && (role !== "exception" || earlier.role !== "exception")
4484
- ) {
4485
-
4486
- // test_cause:
4487
- // ["
4488
- // function aa(){try{aa();}catch(aa){aa();}}
4489
- // ", "enroll", "redefinition_a_b", "1", 31]
4490
- // ["function aa(){var aa;}", "enroll", "redefinition_a_b", "1", 19]
4491
-
4492
- warn("redefinition_a_b", name, id, earlier.line);
4493
- } else if (
4494
- option_dict.beta
4495
- && global_dict[id]
4496
- && role !== "parameter"
4497
- ) {
4498
-
4499
- // test_cause:
4500
- // ["let Array", "enroll", "redefinition_global_a_b", "Array", 5]
4501
-
4502
- warn("redefinition_global_a_b", name, global_dict[id], id);
4503
- }
4504
-
4505
- // Enroll it.
4506
-
4507
- Object.assign(name, {
4508
- dead: true,
4509
- init: false,
4510
- parent: (
4511
- role === "exception"
4512
- ? catchage
4513
- : functionage
4514
- ),
4515
- readonly,
4516
- role,
4517
- used: 0
4518
- });
4519
- name.parent.context[id] = name;
4520
- }
4521
-
4522
4794
  function infix(bp, id, f) {
4523
4795
 
4524
4796
  // Create an infix operator.
@@ -4527,7 +4799,7 @@ function jslint_phase3_parse(state) {
4527
4799
  the_symbol.led_infix = function (left) {
4528
4800
  const the_token = token_now;
4529
4801
  the_token.arity = "binary";
4530
- if (f !== undefined) {
4802
+ if (f) {
4531
4803
  return f(left);
4532
4804
  }
4533
4805
  the_token.expression = [left, parse_expression(bp)];
@@ -4542,17 +4814,39 @@ function jslint_phase3_parse(state) {
4542
4814
  if (
4543
4815
  (
4544
4816
  left.id !== "(string)"
4545
- || (name.id !== "indexOf" && name.id !== "repeat")
4817
+ || (
4818
+ name.id !== "at"
4819
+ && name.id !== "charCodeAt"
4820
+ && name.id !== "includes"
4821
+ && name.id !== "indexOf"
4822
+ && name.id !== "isWellFormed"
4823
+ && name.id !== "match"
4824
+ && name.id !== "repeat"
4825
+ && name.id !== "replace"
4826
+ && name.id !== "toLowerCase"
4827
+ && name.id !== "toUpperCase"
4828
+ && name.id !== "toWellFormed"
4829
+ )
4546
4830
  )
4547
4831
  && (
4548
4832
  left.id !== "["
4549
4833
  || (
4550
- name.id !== "concat"
4834
+ name.id !== "at"
4835
+ && name.id !== "concat"
4836
+ && name.id !== "every"
4837
+ && name.id !== "filter"
4838
+ && name.id !== "find"
4839
+ && name.id !== "findIndex"
4551
4840
  && name.id !== "flat"
4552
4841
  && name.id !== "flatMap"
4553
4842
  && name.id !== "forEach"
4843
+ && name.id !== "includes"
4554
4844
  && name.id !== "join"
4555
4845
  && name.id !== "map"
4846
+ && name.id !== "reduce"
4847
+ && name.id !== "some"
4848
+ && name.id !== "toReversed"
4849
+ && name.id !== "toSorted"
4556
4850
  )
4557
4851
  )
4558
4852
  && (left.id !== "+" || name.id !== "slice")
@@ -4563,16 +4857,36 @@ function jslint_phase3_parse(state) {
4563
4857
  ) {
4564
4858
 
4565
4859
  // test_cause:
4860
+ // ["(/./)?.0", "check_left", "unexpected_a", "?.", 6]
4566
4861
  // ["\"\".aa", "check_left", "unexpected_a", ".", 3]
4862
+ // ["\"aa\"?.0", "check_left", "unexpected_a", "?.", 5]
4863
+ // ["aa=[]?.aa", "check_left", "unexpected_a", "?.", 6]
4567
4864
 
4568
4865
  check_left(left, the_token);
4569
4866
  }
4867
+
4868
+ // Issue #468 - Fix optional dynamic-property/function-call not recognized.
4869
+
4870
+ if (
4871
+ the_token.id === "?."
4872
+ && (name.id === "[" || name.id === "(")
4873
+ ) {
4874
+
4875
+ // test_cause:
4876
+ // ["aa?.(bb)", "infix_dot", "dyn_prop_or_call", "", 0]
4877
+ // ["aa?.[bb]", "infix_dot", "dyn_prop_or_call", "", 0]
4878
+
4879
+ test_cause("dyn_prop_or_call");
4880
+ return left;
4881
+ }
4570
4882
  if (!name.identifier) {
4571
4883
 
4572
4884
  // test_cause:
4885
+ // ["(0+0)?.0", "infix_dot", "expected_identifier_a", "0", 8]
4573
4886
  // ["aa.0", "infix_dot", "expected_identifier_a", "0", 4]
4887
+ // ["aa?.0", "infix_dot", "expected_identifier_a", "0", 5]
4574
4888
 
4575
- stop("expected_identifier_a");
4889
+ return stop("expected_identifier_a", name);
4576
4890
  }
4577
4891
  advance();
4578
4892
  survey(name);
@@ -4585,11 +4899,22 @@ function jslint_phase3_parse(state) {
4585
4899
  }
4586
4900
 
4587
4901
  function infix_fart_unwrapped() {
4902
+ if (!token_prv.identifier) {
4903
+
4904
+ // test_cause:
4905
+ // ["0=>0", "infix_fart_unwrapped", "expected_identifier_a", "0", 1]
4906
+
4907
+ return stop("expected_identifier_a", token_prv);
4908
+ }
4909
+
4910
+ // PR-499 - Update ES2015-feature arrow, to continue parsing unwrapped-form
4911
+ // with warning, instead of stopping.
4588
4912
 
4589
4913
  // test_cause:
4590
4914
  // ["aa=>0", "infix_fart_unwrapped", "wrap_fart_parameter", "=>", 3]
4591
4915
 
4592
- return stop("wrap_fart_parameter", token_now);
4916
+ warn("wrap_fart_parameter", token_now);
4917
+ return prefix_function(token_now, true, true);
4593
4918
  }
4594
4919
 
4595
4920
  function infix_grave(left) {
@@ -4632,7 +4957,6 @@ function jslint_phase3_parse(state) {
4632
4957
 
4633
4958
  function infix_lparen(left) {
4634
4959
  const the_paren = token_now;
4635
- let ellipsis;
4636
4960
  let the_argument;
4637
4961
  if (left.id !== "function") {
4638
4962
 
@@ -4652,12 +4976,14 @@ function jslint_phase3_parse(state) {
4652
4976
 
4653
4977
  while (true) {
4654
4978
  if (token_nxt.id === "...") {
4655
- ellipsis = true;
4656
- advance("...");
4657
- }
4658
- the_argument = parse_expression(10);
4659
- if (ellipsis) {
4660
- the_argument.ellipsis = true;
4979
+
4980
+ // test_cause:
4981
+ // ["aa(...aa)", "infix_lparen", "aa(...aa)", "", 0]
4982
+
4983
+ test_cause("aa(...aa)");
4984
+ the_argument = prefix_ellipsis();
4985
+ } else {
4986
+ the_argument = parse_expression(10);
4661
4987
  }
4662
4988
  the_paren.expression.push(the_argument);
4663
4989
  if (token_nxt.id !== ",") {
@@ -4702,88 +5028,134 @@ function jslint_phase3_parse(state) {
4702
5028
  return the_paren;
4703
5029
  }
4704
5030
 
4705
- function infix_option_chain(left) {
4706
- const the_token = token_now;
4707
- let name = token_nxt;
4708
- if (
4709
- (
4710
- left.id !== "(string)"
4711
- || (name.id !== "indexOf" && name.id !== "repeat")
4712
- )
4713
- && (
4714
- left.id !== "["
4715
- || (
4716
- name.id !== "concat"
4717
- && name.id !== "forEach"
4718
- && name.id !== "join"
4719
- && name.id !== "map"
4720
- )
4721
- )
5031
+ function infixr(bp, id) {
4722
5032
 
4723
- // test_cause:
4724
- // ["(0+0)?.0", "infix_option_chain", "check_left", "", 0]
5033
+ // Create a right associative infix operator.
4725
5034
 
4726
- && (left.id !== "+" || name.id !== "slice")
4727
- && (
4728
- left.id !== "(regexp)"
4729
- || (name.id !== "exec" && name.id !== "test")
4730
- )
4731
- ) {
4732
- test_cause("check_left");
5035
+ const the_symbol = symbol(id, bp);
5036
+ the_symbol.led_infix = function parse_infixr_led(left) {
5037
+ const the_token = token_now;
4733
5038
 
4734
5039
  // test_cause:
4735
- // ["(/./)?.0", "check_left", "unexpected_a", "?.", 6]
4736
- // ["\"aa\"?.0", "check_left", "unexpected_a", "?.", 5]
4737
- // ["aa=[]?.aa", "check_left", "unexpected_a", "?.", 6]
5040
+ // ["0**0", "parse_infixr_led", "led_infix", "", 0]
4738
5041
 
4739
- check_left(left, the_token);
4740
- }
5042
+ test_cause("led_infix");
5043
+ the_token.arity = "binary";
5044
+ the_token.expression = [left, parse_expression(bp - 1)];
5045
+ return the_token;
5046
+ };
5047
+ return the_symbol;
5048
+ }
4741
5049
 
4742
- // Issue #468 - Fix optional dynamic-property/function-call not recognized.
5050
+ function name_enroll(name, role, readonly) {
4743
5051
 
4744
- if (name.id === "[" || name.id === "(") {
4745
- test_cause("dyn_prop_or_call");
5052
+ // Enroll a name into the current function context. The role can be exception,
5053
+ // function, label, parameter, or variable. We look for variable redefinition
5054
+ // because it causes confusion.
5055
+
5056
+ let earlier;
5057
+ let id = name.id;
5058
+
5059
+ // Reserved words may not be enrolled.
5060
+
5061
+ if (syntax_dict[id] !== undefined && id !== "ignore") {
4746
5062
 
4747
5063
  // test_cause:
4748
- // ["aa?.(bb)", "infix_option_chain", "dyn_prop_or_call", "", 0]
4749
- // ["aa?.[bb]", "infix_option_chain", "dyn_prop_or_call", "", 0]
5064
+ // ["let undefined", "name_enroll", "reserved_a", "undefined", 5]
4750
5065
 
4751
- return left;
5066
+ warn("reserved_a", name);
5067
+ return;
4752
5068
  }
4753
- if (!name.identifier) {
5069
+
5070
+ // Has the name been enrolled in this context?
5071
+
5072
+ earlier = functionage.context[id] || catchage.context[id];
5073
+ if (earlier) {
4754
5074
 
4755
5075
  // test_cause:
4756
- // ["aa?.0", "infix_option_chain", "expected_identifier_a", "0", 5]
5076
+ // ["let aa;let aa", "name_enroll", "redefinition_a_b", "1", 12]
4757
5077
 
4758
- stop("expected_identifier_a");
5078
+ warn("redefinition_a_b", name, id, earlier.line);
5079
+ return;
4759
5080
  }
4760
- advance();
4761
- survey(name);
4762
5081
 
4763
- // The property name is not an expression.
5082
+ // Has the name been enrolled in an outer context?
4764
5083
 
4765
- the_token.name = name;
4766
- the_token.expression = left;
4767
- return the_token;
4768
- }
5084
+ function_stack.forEach(function ({
5085
+ context
5086
+ }) {
5087
+ earlier = context[id] || earlier;
5088
+ });
5089
+ if (earlier && id === "ignore") {
5090
+ if (earlier.role === "variable") {
4769
5091
 
4770
- function infixr(bp, id) {
5092
+ // test_cause:
5093
+ // ["let ignore;(ignore)=>0", "name_enroll", "redefinition_a_b", "1", 13]
4771
5094
 
4772
- // Create a right associative infix operator.
5095
+ warn("redefinition_a_b", name, id, earlier.line);
5096
+ }
5097
+ } else if (
5098
+ earlier
5099
+ && role !== "parameter" && role !== "function"
5100
+ && (role !== "exception" || earlier.role !== "exception")
5101
+ ) {
4773
5102
 
4774
- const the_symbol = symbol(id, bp);
4775
- the_symbol.led_infix = function parse_infixr_led(left) {
4776
- const the_token = token_now;
5103
+ // test_cause:
5104
+ // ["
5105
+ // function aa(){try{aa();}catch(aa){aa();}}
5106
+ // ", "name_enroll", "redefinition_a_b", "1", 31]
5107
+ // ["function aa(){var aa;}", "name_enroll", "redefinition_a_b", "1", 19]
5108
+
5109
+ warn("redefinition_a_b", name, id, earlier.line);
5110
+ } else if (
5111
+ option_dict.beta
5112
+ && global_dict[id]
5113
+ && role !== "parameter"
5114
+ ) {
4777
5115
 
4778
5116
  // test_cause:
4779
- // ["0**0", "parse_infixr_led", "led_infix", "", 0]
5117
+ // ["let Array", "name_enroll", "redefinition_global_a_b", "Array", 5]
4780
5118
 
4781
- test_cause("led_infix");
4782
- the_token.arity = "binary";
4783
- the_token.expression = [left, parse_expression(bp - 1)];
4784
- return the_token;
4785
- };
4786
- return the_symbol;
5119
+ warn("redefinition_global_a_b", name, global_dict[id], id);
5120
+ }
5121
+
5122
+ // Enroll it.
5123
+
5124
+ Object.assign(name, {
5125
+
5126
+ // 1z. Mark as dead, the variable, during variable-initialization.
5127
+
5128
+ dead: true,
5129
+ parent: (
5130
+ role === "exception"
5131
+ ? catchage
5132
+ : functionage
5133
+ ),
5134
+ readonly,
5135
+ role,
5136
+ used: 0
5137
+ });
5138
+ name.parent.context[id] = name;
5139
+ }
5140
+
5141
+ // PR-xxx - Unify name_list.push() logic with helper-function name_push().
5142
+
5143
+ function name_push(name_list, enroll, name, role, readonly, init) {
5144
+
5145
+ // This function will:
5146
+ // 1. Push variable or function-parameter <name> to <name_list>.
5147
+ // 2. Enroll <name> if its either a declared-variable or function-parameter.
5148
+ // 3. Set <name>.init = true, if its either an assigned-variable or
5149
+ // function-parameter.
5150
+
5151
+ name_list.push(name);
5152
+ if (enroll) {
5153
+ name_enroll(name, role, readonly);
5154
+ }
5155
+ if (role === "variable") {
5156
+ name.arity = "variable";
5157
+ }
5158
+ name.init = init;
4787
5159
  }
4788
5160
 
4789
5161
  function parse_expression(rbp, initial) {
@@ -4800,7 +5172,10 @@ function jslint_phase3_parse(state) {
4800
5172
  // .led_infix Left denotation. The infix/postfix handler.
4801
5173
  // lbp Left binding power of infix operator. It tells us how strongly
4802
5174
  // the operator binds to the argument at its left.
4803
- // rbp Right binding power.
5175
+ // rbp Right binding power. Parser will continue consuming tokens while
5176
+ // next token's lbp > rbp.
5177
+ // initial Whether first token has already been advanced. If falsy,
5178
+ // immediately calls advance().
4804
5179
 
4805
5180
  // It processes a nud_prefix (variable, constant, prefix operator). It will then
4806
5181
  // process leds (infix operators) until the bind powers cause it to stop (it
@@ -4903,78 +5278,6 @@ function jslint_phase3_parse(state) {
4903
5278
  return left;
4904
5279
  }
4905
5280
 
4906
- function parse_fart(the_fart) {
4907
-
4908
- // Give the function properties storing its names and for observing the depth
4909
- // of loops and switches.
4910
-
4911
- Object.assign(the_fart, {
4912
- arity: "binary",
4913
- context: empty(),
4914
- finally: 0,
4915
- level: functionage.level + 1,
4916
- loop: 0,
4917
- name: anon,
4918
- switch: 0,
4919
- try: 0
4920
- });
4921
-
4922
- // PR-384 - Relax warning "function_in_loop".
4923
- //
4924
- // if (functionage.loop > 0) {
4925
-
4926
- // // test_cause:
4927
- // // ["while(0){aa.map(()=>0);}", "parse_fart", "function_in_loop", "=>", 19]
4928
- //
4929
- // warn("function_in_loop", the_fart);
4930
- // }
4931
-
4932
- // Push the current function context and establish a new one.
4933
-
4934
- function_list.push(the_fart);
4935
- function_stack.push(functionage);
4936
- functionage = the_fart;
4937
-
4938
- // Parse the parameter list.
4939
-
4940
- prefix_function_parameter(the_fart);
4941
- advance("=>");
4942
-
4943
- // The function's body is a block.
4944
-
4945
- if (token_nxt.id === "{") {
4946
- if (!option_dict.fart) {
4947
-
4948
- // test_cause:
4949
- // ["()=>{}", "parse_fart", "use_function_not_fart", "=>", 3]
4950
-
4951
- warn("use_function_not_fart", the_fart);
4952
- }
4953
- the_fart.block = block("body");
4954
- } else if (
4955
- syntax_dict[token_nxt.id] !== undefined
4956
- && syntax_dict[token_nxt.id].fud_stmt !== undefined
4957
- ) {
4958
-
4959
- // PR-384 - Bugfix - Fixes issue #379 - warn against naked-statement in fart.
4960
-
4961
- // test_cause:
4962
- // ["()=>delete aa", "parse_fart", "unexpected_a_after_b", "=>", 5]
4963
-
4964
- stop("unexpected_a_after_b", token_nxt, token_nxt.id, "=>");
4965
-
4966
- // The function's body is an expression.
4967
-
4968
- } else {
4969
- the_fart.expression = parse_expression(0);
4970
- }
4971
-
4972
- // Restore the previous context.
4973
-
4974
- functionage = function_stack.pop();
4975
- return the_fart;
4976
- }
4977
-
4978
5281
  function parse_json() {
4979
5282
  let container;
4980
5283
  let is_dup;
@@ -4987,8 +5290,10 @@ function jslint_phase3_parse(state) {
4987
5290
  // test_cause:
4988
5291
  // ["[-.0]", "parse_json", "unexpected_a", ".", 3]
4989
5292
  // ["[-0x0]", "parse_json", "unexpected_a", "0x0", 3]
5293
+ // ["[...]", "parse_json", "unexpected_a", "...", 2]
4990
5294
  // ["[.0]", "parse_json", "unexpected_a", ".", 2]
4991
5295
  // ["[0x0]", "parse_json", "unexpected_a", "0x0", 2]
5296
+ // ["{...}", "parse_json", "unexpected_a", "...", 2]
4992
5297
 
4993
5298
  warn("unexpected_a");
4994
5299
  }
@@ -5029,11 +5334,6 @@ function jslint_phase3_parse(state) {
5029
5334
 
5030
5335
  container.expression.push(parse_json());
5031
5336
  if (token_nxt.id !== ",") {
5032
-
5033
- // test_cause:
5034
- // ["[0,0]", "parse_json", "comma", "", 0]
5035
-
5036
- test_cause("comma");
5037
5337
  break;
5038
5338
  }
5039
5339
  advance(",");
@@ -5122,7 +5422,7 @@ function jslint_phase3_parse(state) {
5122
5422
  // test_cause:
5123
5423
  // ["[undefined]", "parse_json", "unexpected_a", "undefined", 2]
5124
5424
 
5125
- stop("unexpected_a");
5425
+ return stop("unexpected_a");
5126
5426
  }
5127
5427
  }
5128
5428
 
@@ -5160,12 +5460,21 @@ function jslint_phase3_parse(state) {
5160
5460
  // ["aa:while{}", "parse_statement", "the_statement_label", "while", 0]
5161
5461
 
5162
5462
  test_cause("the_statement_label", token_nxt.id);
5163
- enroll(the_label, "label", true);
5463
+ name_push(
5464
+ [], // name_list
5465
+ true, // enroll
5466
+ the_label, // name
5467
+ "label", // role
5468
+ true, // readonly
5469
+ true // init
5470
+ );
5471
+
5472
+ // 2a. Mark not dead, the label-statement, before control-flow-block.
5473
+
5164
5474
  the_label.dead = false;
5165
- the_label.init = true;
5166
5475
  the_statement = parse_statement();
5167
5476
 
5168
- // Issue #458 - Regression - Warn about variable usage before initialization.
5477
+ // 2z. Mark as dead, the label-statement, after control-flow-block.
5169
5478
 
5170
5479
  the_label.dead = true;
5171
5480
  functionage.statement_prv = the_statement;
@@ -5214,13 +5523,6 @@ function jslint_phase3_parse(state) {
5214
5523
  }
5215
5524
  semicolon();
5216
5525
  }
5217
-
5218
- // Issue #458 - Regression - Warn about variable usage before initialization.
5219
-
5220
- // if (the_label !== undefined) {
5221
- // the_label.dead = true;
5222
- // }
5223
-
5224
5526
  return the_statement;
5225
5527
  }
5226
5528
 
@@ -5303,7 +5605,7 @@ function jslint_phase3_parse(state) {
5303
5605
  the_symbol.nud_prefix = function () {
5304
5606
  const the_token = token_now;
5305
5607
  the_token.arity = "unary";
5306
- if (typeof f === "function") {
5608
+ if (f) {
5307
5609
  return f();
5308
5610
  }
5309
5611
  the_token.expression = parse_expression(150);
@@ -5317,7 +5619,7 @@ function jslint_phase3_parse(state) {
5317
5619
  // test_cause:
5318
5620
  // ["/=", "prefix_assign_divide", "expected_a_b", "/=", 1]
5319
5621
 
5320
- stop("expected_a_b", token_now, "/\\=", "/=");
5622
+ return stop("expected_a_b", token_now, "/\\=", "/=");
5321
5623
  }
5322
5624
 
5323
5625
  function prefix_async() {
@@ -5332,13 +5634,6 @@ function jslint_phase3_parse(state) {
5332
5634
  the_function = Object.assign(token_now.fart, {
5333
5635
  async: 1
5334
5636
  });
5335
- if (!option_dict.fart) {
5336
-
5337
- // test_cause:
5338
- // ["async()=>0", "prefix_async", "use_function_not_fart", "=>", 8]
5339
-
5340
- warn("use_function_not_fart", the_function);
5341
- }
5342
5637
  prefix_lparen();
5343
5638
 
5344
5639
  // Parse async function.
@@ -5389,6 +5684,218 @@ function jslint_phase3_parse(state) {
5389
5684
  return the_await;
5390
5685
  }
5391
5686
 
5687
+ function prefix_destructure(
5688
+ enroll,
5689
+ role,
5690
+ readonly,
5691
+ name_list,
5692
+ the_function,
5693
+ the_function_toplevel
5694
+ ) {
5695
+ const is_lbrace = token_now.id === "{";
5696
+ const sub_list = [];
5697
+ const the_destructure = token_now;
5698
+ let optional;
5699
+ function advance_and_signature_push(id) {
5700
+ advance(id);
5701
+ if (the_function?.signature) {
5702
+ the_function.signature.push(id);
5703
+ switch (id) {
5704
+ case ",":
5705
+ case ":":
5706
+ the_function.signature.push(" ");
5707
+ break;
5708
+ }
5709
+ }
5710
+ }
5711
+ function name_parse() {
5712
+ let name = token_nxt;
5713
+ switch (name.id) {
5714
+ case "...":
5715
+ advance_and_signature_push("...");
5716
+ name = token_nxt;
5717
+ name.ellipsis = true;
5718
+ if (name.id === "...") {
5719
+
5720
+ // test_cause:
5721
+ // ["let[... ...]=0", "name_parse", "unexpected_a_after_b", "...", 9]
5722
+
5723
+ return stop("unexpected_a_after_b", name, name.id, "...");
5724
+ }
5725
+ if (optional) {
5726
+
5727
+ // test_cause:
5728
+ // ["function aa(aa=0,...){}", "name_parse", "required_a_optional_b", "aa", 21]
5729
+
5730
+ warn("required_a_optional_b", name, name.id, optional.id);
5731
+ }
5732
+
5733
+ // test_cause:
5734
+ // ["let[...aa]=0", "name_parse", "recurse_ellipsis", "", 0]
5735
+ // ["let{...aa}=0", "name_parse", "recurse_ellipsis", "", 0]
5736
+
5737
+ test_cause("recurse_ellipsis");
5738
+ name_parse();
5739
+ return true;
5740
+ case "[":
5741
+ case "{":
5742
+ if (optional) {
5743
+
5744
+ // test_cause:
5745
+ // ["function aa(aa=0,[]){}", "name_parse", "required_a_optional_b", "aa", 18]
5746
+ // ["function aa(aa=0,{}){}", "name_parse", "required_a_optional_b", "aa", 18]
5747
+
5748
+ warn("required_a_optional_b", name, name.id, optional.id);
5749
+ }
5750
+
5751
+ // test_cause:
5752
+ // ["let[[aa]]=0", "name_parse", "recurse_element", "", 0]
5753
+ // ["let[{aa}]=0", "name_parse", "recurse_element", "", 0]
5754
+
5755
+ test_cause("recurse_element");
5756
+ advance_and_signature_push(token_nxt.id);
5757
+ prefix_destructure(
5758
+ enroll, // enroll
5759
+ role, // role
5760
+ readonly, // readonly
5761
+ name_list, // name_list
5762
+ the_function, // the_function
5763
+ false // the_function_toplevel
5764
+ );
5765
+ return;
5766
+ }
5767
+ if (!name.identifier) {
5768
+
5769
+ // test_cause:
5770
+ // ["function aa(...0){}", "name_parse", "expected_identifier_a", "0", 16]
5771
+ // ["function aa(0){}", "name_parse", "expected_identifier_a", "0", 13]
5772
+ // ["function aa([0]){}", "name_parse", "expected_identifier_a", "0", 14]
5773
+ // ["function aa({0}){}", "name_parse", "expected_identifier_a", "0", 14]
5774
+ // ["function aa({aa:0}){}", "name_parse", "expected_identifier_a", "0", 17]
5775
+ // ["let[...0]=0", "name_parse", "expected_identifier_a", "0", 8]
5776
+ // ["let[0]=0", "name_parse", "expected_identifier_a", "0", 5]
5777
+ // ["let{0}=0", "name_parse", "expected_identifier_a", "0", 5]
5778
+
5779
+ return stop("expected_identifier_a", name);
5780
+ }
5781
+ if (is_lbrace) {
5782
+ survey(name);
5783
+ }
5784
+ advance_and_signature_push(token_nxt.id);
5785
+ if (is_lbrace && token_nxt.id === ":") {
5786
+ advance_and_signature_push(":");
5787
+ if (!the_function_toplevel) {
5788
+ the_destructure.open = true;
5789
+ }
5790
+ if (token_nxt.id === "...") {
5791
+
5792
+ // test_cause:
5793
+ // ["let{aa:...aa}=0", "name_parse", "unexpected_a", "...", 8]
5794
+
5795
+ return stop("unexpected_a", token_nxt);
5796
+ }
5797
+ if (!token_nxt.identifier) {
5798
+
5799
+ // test_cause:
5800
+ // ["let{aa:[aa]}=0", "name_parse", "recurse_property", "", 0]
5801
+ // ["let{aa:{aa}}=0", "name_parse", "recurse_property", "", 0]
5802
+
5803
+ test_cause("recurse_property");
5804
+ name_parse();
5805
+ return;
5806
+ }
5807
+ token_nxt.label = name;
5808
+ name = token_nxt;
5809
+ name_push(sub_list, enroll, name, role, readonly, true);
5810
+ advance_and_signature_push(token_nxt.id);
5811
+ return;
5812
+ }
5813
+ name_push(sub_list, enroll, name, role, readonly, true);
5814
+ if (token_nxt.id === "=") {
5815
+ optional = the_function_toplevel && token_now;
5816
+ advance_and_signature_push("=");
5817
+ if (!the_function_toplevel) {
5818
+ the_destructure.open = true;
5819
+ }
5820
+ name.expression = parse_expression(0);
5821
+
5822
+ // test_cause:
5823
+ // ["function aa([aa=aa]){}", "name_lookup", "out_of_scope_a", "aa", 17]
5824
+ // ["function aa([aa=aa]){}", "name_parse", "optional", "aa", 0]
5825
+ // ["function aa({aa=aa}){}", "name_lookup", "out_of_scope_a", "aa", 17]
5826
+ // ["function aa({aa=aa}){}", "name_parse", "optional", "aa", 0]
5827
+ // ["let[aa=bb]=0;let bb", "name_lookup", "out_of_scope_a", "bb", 8]
5828
+ // ["let[aa=bb]=0;let bb", "name_parse", "optional", "aa", 0]
5829
+ // ["let{aa=bb}=0;let bb", "name_lookup", "out_of_scope_a", "bb", 8]
5830
+ // ["let{aa=bb}=0;let bb", "name_parse", "optional", "aa", 0]
5831
+
5832
+ test_cause("optional", name.id);
5833
+ return;
5834
+ }
5835
+ if (optional) {
5836
+
5837
+ // test_cause:
5838
+ // ["function aa(aa=0,bb){}", "name_parse", "required_a_optional_b", "aa", 18]
5839
+
5840
+ warn("required_a_optional_b", name, name.id, optional.id);
5841
+ }
5842
+ }
5843
+ while (true) {
5844
+ if (!is_lbrace && !the_function_toplevel && token_nxt.id === ",") {
5845
+
5846
+ // test_cause:
5847
+ // ["(,aa)=>0", "name_parse", "expected_identifier_a", ",", 2]
5848
+ // ["([,aa])=>0", "prefix_destructure", "ignore", "", 0]
5849
+ // [";[,aa]=0", "prefix_destructure", "ignore", "", 0]
5850
+ // ["let[,aa]=0", "prefix_destructure", "ignore", "", 0]
5851
+
5852
+ test_cause("ignore");
5853
+ advance_and_signature_push(",");
5854
+ }
5855
+ if (the_function_toplevel) {
5856
+ the_function.parameter_count += 1;
5857
+ }
5858
+ if (name_parse()) {
5859
+
5860
+ // Break early from ellipsis.
5861
+
5862
+ break;
5863
+ }
5864
+ if (token_nxt.id !== ",") {
5865
+ break;
5866
+ }
5867
+ advance_and_signature_push(",");
5868
+ }
5869
+ name_list.push(...sub_list);
5870
+ if (the_function_toplevel) {
5871
+ return the_destructure;
5872
+ }
5873
+ if (is_lbrace) {
5874
+
5875
+ // test_cause:
5876
+ // ["
5877
+ // function aa({bb,aa}){}
5878
+ // ", "check_ordered", "expected_a_b_before_c_d", "aa", 17]
5879
+ // ["let{bb,aa}=0", "check_ordered", "expected_a_b_before_c_d", "aa", 8]
5880
+
5881
+ // PR-xxx - Fix false-warning about ordering in nested-object-destructuring.
5882
+
5883
+ check_ordered(role, sub_list);
5884
+ advance_and_signature_push("}");
5885
+ return the_destructure;
5886
+ }
5887
+ advance_and_signature_push("]");
5888
+ return the_destructure;
5889
+ }
5890
+
5891
+ function prefix_ellipsis() {
5892
+ let after_ellipsis;
5893
+ advance("...");
5894
+ after_ellipsis = parse_expression(0);
5895
+ after_ellipsis.ellipsis = true;
5896
+ return after_ellipsis;
5897
+ }
5898
+
5392
5899
  function prefix_fart() {
5393
5900
 
5394
5901
  // test_cause:
@@ -5397,66 +5904,58 @@ function jslint_phase3_parse(state) {
5397
5904
  return stop("expected_a_before_b", token_now, "()", "=>");
5398
5905
  }
5399
5906
 
5400
- function prefix_function(the_function) {
5401
- let name = the_function && the_function.name;
5402
- if (the_function === undefined) {
5403
- the_function = token_now;
5907
+ function prefix_function(the_function, mode_fart, mode_fart_infix) {
5908
+ let name;
5909
+ let role = "function";
5910
+ the_function = the_function || token_now;
5911
+ if (mode_fart) {
5912
+ the_function.arity = "binary";
5404
5913
 
5405
5914
  // A function statement must have a name that will be in the parent's scope.
5406
5915
 
5407
- if (the_function.arity === "statement") {
5408
- if (!token_nxt.identifier) {
5916
+ } else if (the_function.arity === "statement") {
5917
+ if (!token_nxt.identifier) {
5409
5918
 
5410
5919
  // test_cause:
5411
5920
  // ["function(){}", "prefix_function", "expected_identifier_a", "(", 9]
5412
5921
  // ["function*aa(){}", "prefix_function", "expected_identifier_a", "*", 9]
5413
5922
 
5414
- return stop("expected_identifier_a");
5415
- }
5416
- name = token_nxt;
5417
- enroll(name, "variable", true);
5418
- the_function.name = Object.assign(name, {
5419
- calls: empty(),
5420
-
5421
- // PR-331 - Bugfix - Fixes issue #272 - function hoisting not allowed.
5422
-
5423
- dead: false,
5424
- init: true
5425
- });
5426
- advance();
5427
- } else if (name === undefined) {
5923
+ return stop("expected_identifier_a", token_nxt);
5924
+ }
5925
+ name = token_nxt;
5926
+ name.calls = empty();
5927
+ role = "variable";
5928
+ advance();
5929
+ } else if (token_nxt.identifier) {
5428
5930
 
5429
5931
  // A function expression may have an optional name.
5430
5932
 
5431
- the_function.name = anon;
5432
- if (token_nxt.identifier) {
5433
- name = token_nxt;
5434
- the_function.name = name;
5435
- advance();
5436
- }
5437
- }
5933
+ // test_cause:
5934
+ // ["(function bb(){}())", "prefix_function", "expression", "bb", 0]
5935
+ // ["aa=function bb(){}", "prefix_function", "expression", "bb", 0]
5936
+
5937
+ test_cause("expression", token_nxt.id);
5938
+ name = token_nxt;
5939
+ advance();
5438
5940
  }
5941
+ if (name) {
5942
+ name_push(
5943
+ [], // name_list
5944
+ true, // enroll
5945
+ name, // name
5946
+ role, // role
5947
+ false, // readonly
5948
+ true // init
5949
+ );
5950
+ if (the_function.arity === "statement") {
5439
5951
 
5440
- // Probably deadcode.
5441
- // if (mode_mega) {
5442
- // warn("unexpected_a", the_function);
5443
- // }
5444
- // jslint_assert(!mode_mega, `Expected !mode_mega.`);
5952
+ // 3a. Mark not dead, the function-name, in function-statement.
5445
5953
 
5446
- // PR-378 - Relax warning "function_in_loop".
5447
- //
5448
- // // Don't create functions in loops. It is inefficient, and it can lead to
5449
- // // scoping errors.
5450
- //
5451
- // if (functionage.loop > 0) {
5452
- //
5453
- // // test_cause:
5454
- // // ["
5455
- // // while(0){aa.map(function(){});}
5456
- // // ", "prefix_function", "function_in_loop", "function", 17]
5457
- //
5458
- // warn("function_in_loop", the_function);
5459
- // }
5954
+ name.dead = false;
5955
+ } else {
5956
+ name.used += 1;
5957
+ }
5958
+ }
5460
5959
 
5461
5960
  // Give the function properties for storing its names and for observing the
5462
5961
  // depth of loops and switches.
@@ -5467,23 +5966,34 @@ function jslint_phase3_parse(state) {
5467
5966
  finally: 0,
5468
5967
  level: functionage.level + 1,
5469
5968
  loop: 0,
5969
+ name: (
5970
+ name || (
5971
+ mode_fart_infix
5972
+ ? "anonymous"
5973
+ : anon
5974
+ )
5975
+ ),
5976
+ parameter_count: Number(Boolean(mode_fart_infix)),
5977
+ signature: (
5978
+ mode_fart_infix
5979
+ ? token_prv.id
5980
+ : ["("]
5981
+ ),
5470
5982
  statement_prv: undefined,
5471
5983
  switch: 0,
5472
5984
  try: 0
5473
5985
  });
5474
- if (the_function.arity !== "statement" && typeof name === "object") {
5475
5986
 
5476
- // test_cause:
5477
- // ["let aa=function bb(){return;};", "prefix_function", "expression", "bb", 0]
5987
+ // PR-384 - Relax warning "function_in_loop".
5988
+ //
5989
+ // if (functionage.loop > 0) {
5478
5990
 
5479
- test_cause("expression", name.id);
5480
- enroll(name, "function", true);
5481
- name.dead = false;
5482
- name.init = true;
5483
- name.used = 1;
5484
- }
5991
+ // // test_cause:
5992
+ // // ["while(0){aa.map(()=>0);}", "parse_fart", "function_in_loop", "=>", 19]
5993
+ //
5994
+ // warn("function_in_loop", the_function);
5995
+ // }
5485
5996
 
5486
- // PR-334 - Bugfix - fix function-redefinition not warned inside function-call.
5487
5997
  // Push the current function context and establish a new one.
5488
5998
 
5489
5999
  function_list.push(the_function);
@@ -5492,54 +6002,110 @@ function jslint_phase3_parse(state) {
5492
6002
 
5493
6003
  // Parse the parameter list.
5494
6004
 
5495
- advance("(");
5496
- token_now.arity = "function";
5497
- prefix_function_parameter(the_function);
6005
+ if (!mode_fart) {
6006
+ advance("(");
6007
+ token_now.arity = "function";
6008
+ }
6009
+ the_function.name_list = []; // 2. name_list for "function (aa)"
6010
+ if (mode_fart_infix) {
6011
+ name_push(
6012
+ the_function.name_list, // name_list
6013
+ true, // enroll
6014
+ token_prv, // name
6015
+ "parameter", // role
6016
+ false, // readonly
6017
+ true // init
6018
+ );
6019
+ } else {
6020
+ token_now.free = false;
6021
+ if (token_nxt.id !== ")" && token_nxt.id !== "(end)") {
6022
+
6023
+ // PR-500 - Unify ES2015-destructure-logic. - function ([aa]) {...}
6024
+
6025
+ prefix_destructure(
6026
+ true, // enroll
6027
+ "parameter", // role
6028
+ false, // readonly
6029
+ the_function.name_list, // name_list
6030
+ the_function, // the_function
6031
+ true // the_function_toplevel
6032
+ );
6033
+ }
6034
+ advance(")");
6035
+ the_function.signature = the_function.signature.join("") + ")";
6036
+ }
6037
+ if (mode_fart && !mode_fart_infix) {
6038
+ advance("=>");
6039
+ }
6040
+ if (mode_fart && token_nxt.id !== "{") {
6041
+
6042
+ // The function's body is an expression.
6043
+
6044
+ // PR-384 - Bugfix - Fixes issue #379 - warn against naked-statement in fart.
6045
+
6046
+ if (
6047
+ syntax_dict[token_nxt.id]
6048
+ && syntax_dict[token_nxt.id].fud_stmt
6049
+ ) {
6050
+
6051
+ // test_cause:
6052
+ // ["()=>delete aa", "prefix_function", "unexpected_a_after_b", "=>", 5]
6053
+
6054
+ return stop(
6055
+ "unexpected_a_after_b",
6056
+ token_nxt,
6057
+ token_nxt.id,
6058
+ "=>"
6059
+ );
6060
+ }
6061
+ the_function.expression = parse_expression(0);
6062
+ } else {
5498
6063
 
5499
6064
  // The function's body is a block.
5500
6065
 
5501
- the_function.block = block("body");
5502
- if (
5503
- the_function.arity === "statement"
5504
- && token_nxt.line === token_now.line
5505
- ) {
6066
+ the_function.block = block("body");
6067
+ if (
6068
+ the_function.arity === "statement"
6069
+ && token_nxt.line === token_now.line
6070
+ ) {
5506
6071
 
5507
6072
  // test_cause:
5508
6073
  // ["function aa(){}0", "prefix_function", "unexpected_a", "0", 16]
5509
6074
 
5510
- return stop("unexpected_a");
5511
- }
5512
- if (
5513
- token_nxt.id === "."
5514
- || token_nxt.id === "?."
6075
+ return stop("unexpected_a");
6076
+ }
6077
+ if (
6078
+ token_nxt.id === "."
6079
+ || token_nxt.id === "?."
5515
6080
 
5516
6081
  // PR-459 - Allow destructuring-assignment after function-definition.
5517
6082
 
5518
- // || token_nxt.id === "["
5519
- ) {
6083
+ // || token_nxt.id === "["
6084
+ ) {
5520
6085
 
5521
6086
  // test_cause:
5522
6087
  // ["function aa(){}\n.aa", "prefix_function", "unexpected_a", ".", 1]
5523
6088
  // ["function aa(){}\n?.aa", "prefix_function", "unexpected_a", "?.", 1]
5524
6089
 
5525
- warn("unexpected_a");
5526
- }
6090
+ warn("unexpected_a");
6091
+ }
5527
6092
 
5528
6093
  // Check functions are ordered.
5529
6094
 
5530
- check_ordered(
5531
- "function",
5532
- function_list.slice(
5533
- function_list.indexOf(the_function) + 1
5534
- ).map(function ({
5535
- level,
5536
- name
5537
- }) {
5538
- return (level === the_function.level + 1) && name;
5539
- }).filter(function (name) {
5540
- return option_dict.beta && name && name.id;
5541
- })
5542
- );
6095
+ check_ordered(
6096
+ "function",
6097
+ function_list.slice(
6098
+ function_list.indexOf(the_function) + 1
6099
+ ).map(function ({
6100
+ level,
6101
+ name
6102
+ }) {
6103
+ return (level === the_function.level + 1) && name;
6104
+ }).filter(function (name) {
6105
+ return option_dict.beta && name && name.id;
6106
+ })
6107
+ );
6108
+ }
5543
6109
 
5544
6110
  // Restore the previous context.
5545
6111
 
@@ -5547,379 +6113,151 @@ function jslint_phase3_parse(state) {
5547
6113
  return the_function;
5548
6114
  }
5549
6115
 
5550
- function prefix_function_parameter(the_function) {
5551
-
5552
- // This function will parse input <parameters> at beginning of <the_function>
5553
-
5554
- let optional;
5555
- let parameters = [];
5556
- let signature = ["("];
5557
- let subparam;
5558
- function param_enroll(name) {
5559
- if (name.identifier) {
5560
- enroll(name, "parameter", false);
5561
- } else {
6116
+ function prefix_lbrace() {
6117
+ const seen = empty();
6118
+ const the_brace = token_now;
6119
+ function property_parse() {
6120
+ let extra;
6121
+ let full;
6122
+ let id;
6123
+ let name = token_nxt;
6124
+ let the_colon;
6125
+ let value;
6126
+ if (!name.identifier && name.id === "`") {
5562
6127
 
5563
6128
  // test_cause:
5564
- // ["([aa])=>0", "param_enroll", "use_function_not_fart", "=>", 7]
5565
- // ["({aa})=>0", "param_enroll", "use_function_not_fart", "=>", 7]
5566
-
5567
- if (the_function.id === "=>" && !option_dict.fart) {
5568
- warn("use_function_not_fart", the_function);
5569
- }
6129
+ // ["aa={`aa`:0}", "property_parse", "unexpected_a", "`", 5]
5570
6130
 
5571
- // Recurse param_enroll().
5572
-
5573
- name.names.forEach(param_enroll);
6131
+ return stop("unexpected_a", name);
5574
6132
  }
5575
- }
5576
- function param_parse() {
5577
- let ellipsis = false;
5578
- let param;
5579
- if (token_nxt.id === "{") {
5580
- if (optional !== undefined) {
5581
-
5582
- // test_cause:
5583
- // ["function aa(aa=0,{}){}", "param_parse", "required_a_optional_b", "aa", 18]
5584
-
5585
- warn(
5586
- "required_a_optional_b",
5587
- token_nxt,
5588
- token_nxt.id,
5589
- optional.id
5590
- );
5591
- }
5592
- param = token_nxt;
5593
- param.names = [];
5594
- advance("{");
5595
- signature.push("{");
5596
- while (true) {
5597
- subparam = token_nxt;
5598
- if (!subparam.identifier) {
5599
6133
 
5600
- // test_cause:
5601
- // ["function aa(aa=0,{}){}", "param_parse", "expected_identifier_a", "}", 19]
5602
- // ["function aa({0}){}", "param_parse", "expected_identifier_a", "0", 14]
6134
+ // Issue #401 - Add ES2018-syntax for object-literal-spread-operator.
5603
6135
 
5604
- return stop("expected_identifier_a");
5605
- }
5606
- survey(subparam);
5607
- advance();
5608
- signature.push(subparam.id);
5609
- if (token_nxt.id === ":") {
5610
- advance(":");
5611
- advance();
5612
- token_now.label = subparam;
5613
- subparam = token_now;
5614
- if (!subparam.identifier) {
6136
+ if (!name.identifier && token_nxt.id === "...") {
5615
6137
 
5616
6138
  // test_cause:
5617
- // ["function aa({aa:0}){}", "param_parse", "expected_identifier_a", "}", 18]
6139
+ // ["aa={...aa}", "property_parse", "ellipsis", "", 0]
5618
6140
 
5619
- return stop(
5620
- "expected_identifier_a",
5621
- token_nxt
5622
- );
5623
- }
5624
- }
6141
+ test_cause("ellipsis");
6142
+ value = prefix_ellipsis();
6143
+ return value;
6144
+ }
6145
+ advance();
6146
+ if (
6147
+ (name.id === "get" || name.id === "set")
6148
+ && token_nxt.identifier
6149
+ ) {
6150
+ if (!option_dict.getset) {
5625
6151
 
5626
6152
  // test_cause:
5627
- // ["function aa({aa=aa},aa){}", "param_parse", "equal", "", 0]
6153
+ // ["aa={get aa(){}}", "property_parse", "unexpected_a", "get", 5]
5628
6154
 
5629
- test_cause("equal");
5630
- if (token_nxt.id === "=") {
5631
- advance("=");
5632
- subparam.expression = parse_expression();
5633
- param.open = true;
5634
- }
5635
- param.names.push(subparam);
5636
- if (token_nxt.id === ",") {
5637
- advance(",");
5638
- signature.push(", ");
5639
- } else {
5640
- break;
5641
- }
6155
+ warn("unexpected_a", name);
5642
6156
  }
5643
- parameters.push(param);
6157
+ extra = name.id;
6158
+ full = extra + " " + token_nxt.id;
6159
+ name = token_nxt;
6160
+ advance();
6161
+ id = survey(name);
6162
+ if (seen[full] === true || seen[id] === true) {
5644
6163
 
5645
6164
  // test_cause:
5646
- // ["
5647
- // function aa({bb,aa}){}
5648
- // ", "check_ordered", "expected_a_b_before_c_d", "aa", 17]
6165
+ // ["aa={get aa(){},get aa(){}}", "property_parse", "duplicate_a", "aa", 20]
5649
6166
 
5650
- check_ordered("parameter", param.names);
5651
- advance("}");
5652
- signature.push("}");
5653
- if (token_nxt.id === ",") {
5654
- advance(",");
5655
- signature.push(", ");
5656
- param_parse();
5657
- return;
6167
+ warn("duplicate_a", name);
5658
6168
  }
5659
- } else if (token_nxt.id === "[") {
5660
- if (optional !== undefined) {
6169
+ seen[id] = false;
6170
+ seen[full] = true;
6171
+ } else {
6172
+ id = survey(name);
6173
+ if (typeof seen[id] === "boolean") {
5661
6174
 
5662
6175
  // test_cause:
5663
- // ["function aa(aa=0,[]){}", "param_parse", "required_a_optional_b", "aa", 18]
6176
+ // ["aa={aa,aa}", "property_parse", "duplicate_a", "aa", 8]
5664
6177
 
5665
- warn(
5666
- "required_a_optional_b",
5667
- token_nxt,
5668
- token_nxt.id,
5669
- optional.id
5670
- );
6178
+ warn("duplicate_a", name);
5671
6179
  }
5672
- param = token_nxt;
5673
- param.names = [];
5674
- advance("[");
5675
- signature.push("[]");
5676
- while (true) {
5677
- subparam = token_nxt;
5678
- if (!subparam.identifier) {
6180
+ seen[id] = true;
6181
+ }
6182
+ if (!name.identifier) {
5679
6183
 
5680
6184
  // test_cause:
5681
- // ["function aa(aa=0,[]){}", "param_parse", "expected_identifier_a", "]", 19]
6185
+ // ["aa={\"aa\":0}", "property_parse", "colon", "", 0]
5682
6186
 
5683
- return stop("expected_identifier_a");
5684
- }
5685
- advance();
5686
- param.names.push(subparam);
6187
+ test_cause("colon");
6188
+ advance(":");
6189
+ value = parse_expression(0);
6190
+ value.label = name;
6191
+ return value;
6192
+ }
6193
+ if (token_nxt.id === "}" || token_nxt.id === ",") {
6194
+ if (typeof extra === "string") {
5687
6195
 
5688
6196
  // test_cause:
5689
- // ["function aa([aa=aa],aa){}", "param_parse", "id", "", 0]
6197
+ // ["aa={get aa}", "property_parse", "closer", "", 0]
5690
6198
 
5691
- test_cause("id");
5692
- if (token_nxt.id === "=") {
5693
- advance("=");
5694
- subparam.expression = parse_expression();
5695
- param.open = true;
5696
- }
5697
- if (token_nxt.id === ",") {
5698
- advance(",");
5699
- } else {
5700
- break;
5701
- }
5702
- }
5703
- parameters.push(param);
5704
- advance("]");
5705
- if (token_nxt.id === ",") {
5706
- advance(",");
5707
- signature.push(", ");
5708
- param_parse();
5709
- return;
6199
+ test_cause("closer");
6200
+ advance("(");
5710
6201
  }
6202
+ value = parse_expression(Infinity, true);
6203
+ } else if (token_nxt.id === "(") {
6204
+
6205
+ // test_cause:
6206
+ // ["aa={aa()}", "property_parse", "paren", "", 0]
6207
+ // ["aa={get aa(){}}", "property_parse", "paren", "", 0]
6208
+
6209
+ test_cause("paren");
6210
+ value = prefix_function({
6211
+ arity: "unary",
6212
+ from: name.from,
6213
+ id: "function",
6214
+ line: name.line,
6215
+ name: (
6216
+ typeof extra === "string"
6217
+ ? extra
6218
+ : id
6219
+ ),
6220
+ thru: name.from
6221
+ });
5711
6222
  } else {
5712
- if (token_nxt.id === "...") {
5713
- ellipsis = true;
5714
- signature.push("...");
5715
- advance("...");
5716
- if (optional !== undefined) {
5717
-
5718
- // test_cause:
5719
- // ["function aa(aa=0,...){}", "param_parse", "required_a_optional_b", "aa", 21]
5720
-
5721
- warn(
5722
- "required_a_optional_b",
5723
- token_nxt,
5724
- token_nxt.id,
5725
- optional.id
5726
- );
5727
- }
5728
- }
5729
- if (!token_nxt.identifier) {
6223
+ if (typeof extra === "string") {
5730
6224
 
5731
6225
  // test_cause:
5732
- // ["function aa(0){}", "param_parse", "expected_identifier_a", "0", 13]
6226
+ // ["aa={get aa.aa}", "property_parse", "paren", "", 0]
5733
6227
 
5734
- return stop("expected_identifier_a");
6228
+ test_cause("paren");
6229
+ advance("(");
5735
6230
  }
5736
- param = token_nxt;
5737
- parameters.push(param);
5738
- advance();
5739
- signature.push(param.id);
5740
- if (ellipsis) {
5741
- param.ellipsis = true;
5742
- } else {
5743
- if (token_nxt.id === "=") {
5744
- optional = param;
5745
- advance("=");
5746
- param.expression = parse_expression(0);
5747
- } else {
5748
- if (optional !== undefined) {
6231
+ the_colon = token_nxt;
6232
+ advance(":");
6233
+ value = parse_expression(0);
6234
+ if (
6235
+ value.id === name.id
6236
+ && value.id !== "function"
6237
+ ) {
5749
6238
 
5750
6239
  // test_cause:
5751
- // ["function aa(aa=0,bb){}", "param_parse", "required_a_optional_b", "aa", 18]
6240
+ // ["aa={aa:aa}", "property_parse", "unexpected_a", ": aa", 7]
5752
6241
 
5753
- warn(
5754
- "required_a_optional_b",
5755
- param,
5756
- param.id,
5757
- optional.id
5758
- );
5759
- }
5760
- }
5761
- if (token_nxt.id === ",") {
5762
- advance(",");
5763
- signature.push(", ");
5764
- param_parse();
5765
- return;
5766
- }
6242
+ warn("unexpected_a", the_colon, ": " + name.id);
5767
6243
  }
5768
6244
  }
6245
+ value.label = name;
6246
+ if (typeof extra === "string") {
6247
+ value.extra = extra;
6248
+ }
6249
+ return value;
5769
6250
  }
5770
-
5771
- // test_cause:
5772
- // ["function aa(){}", "prefix_function_parameter", "opener", "(", 0]
5773
-
5774
- test_cause("opener", token_now.id);
5775
- token_now.free = false;
5776
- if (token_nxt.id !== ")" && token_nxt.id !== "(end)") {
5777
- param_parse();
5778
- }
5779
- advance(")");
5780
- signature.push(")");
5781
- parameters.forEach(param_enroll);
5782
- the_function.parameters = parameters;
5783
- the_function.signature = signature.join("");
5784
- }
5785
-
5786
- function prefix_lbrace() {
5787
- const seen = empty();
5788
- const the_brace = token_now;
5789
- let extra;
5790
- let full;
5791
- let id;
5792
- let name;
5793
- let the_colon;
5794
- let value;
5795
6251
  the_brace.expression = [];
5796
6252
  if (token_nxt.id !== "}") {
5797
6253
 
5798
6254
  // Parse/loop through each property in {...}.
5799
6255
 
5800
6256
  while (true) {
5801
- name = token_nxt;
5802
- advance();
5803
- if (
5804
- (name.id === "get" || name.id === "set")
5805
- && token_nxt.identifier
5806
- ) {
5807
- if (!option_dict.getset) {
5808
-
5809
- // test_cause:
5810
- // ["aa={get aa(){}}", "prefix_lbrace", "unexpected_a", "get", 5]
5811
-
5812
- warn("unexpected_a", name);
5813
- }
5814
- extra = name.id;
5815
- full = extra + " " + token_nxt.id;
5816
- name = token_nxt;
5817
- advance();
5818
- id = survey(name);
5819
- if (seen[full] === true || seen[id] === true) {
5820
-
5821
- // test_cause:
5822
- // ["aa={get aa(){},get aa(){}}", "prefix_lbrace", "duplicate_a", "aa", 20]
5823
-
5824
- warn("duplicate_a", name);
5825
- }
5826
- seen[id] = false;
5827
- seen[full] = true;
5828
- } else if (name.id === "`") {
5829
-
5830
- // test_cause:
5831
- // ["aa={`aa`:0}", "prefix_lbrace", "unexpected_a", "`", 5]
5832
-
5833
- stop("unexpected_a", name);
5834
-
5835
- } else {
5836
- id = survey(name);
5837
- if (typeof seen[id] === "boolean") {
5838
-
5839
- // test_cause:
5840
- // ["aa={aa,aa}", "prefix_lbrace", "duplicate_a", "aa", 8]
5841
-
5842
- warn("duplicate_a", name);
5843
- }
5844
- seen[id] = true;
5845
- }
5846
- if (name.identifier) {
5847
- if (token_nxt.id === "}" || token_nxt.id === ",") {
5848
- if (typeof extra === "string") {
5849
-
5850
- // test_cause:
5851
- // ["aa={get aa}", "prefix_lbrace", "closer", "", 0]
5852
-
5853
- test_cause("closer");
5854
- advance("(");
5855
- }
5856
- value = parse_expression(Infinity, true);
5857
- } else if (token_nxt.id === "(") {
5858
-
5859
- // test_cause:
5860
- // ["aa={aa()}", "prefix_lbrace", "paren", "", 0]
5861
- // ["aa={get aa(){}}", "prefix_lbrace", "paren", "", 0]
5862
-
5863
- test_cause("paren");
5864
- value = prefix_function({
5865
- arity: "unary",
5866
- from: name.from,
5867
- id: "function",
5868
- line: name.line,
5869
- name: (
5870
- typeof extra === "string"
5871
- ? extra
5872
- : id
5873
- ),
5874
- thru: name.from
5875
- });
5876
- } else {
5877
- if (typeof extra === "string") {
5878
-
5879
- // test_cause:
5880
- // ["aa={get aa.aa}", "prefix_lbrace", "paren", "", 0]
5881
-
5882
- test_cause("paren");
5883
- advance("(");
5884
- }
5885
- the_colon = token_nxt;
5886
- advance(":");
5887
- value = parse_expression(0);
5888
- if (
5889
- value.id === name.id
5890
- && value.id !== "function"
5891
- ) {
5892
-
5893
- // test_cause:
5894
- // ["aa={aa:aa}", "prefix_lbrace", "unexpected_a", ": aa", 7]
5895
-
5896
- warn("unexpected_a", the_colon, ": " + name.id);
5897
- }
5898
- }
5899
- value.label = name;
5900
- if (typeof extra === "string") {
5901
- value.extra = extra;
5902
- }
5903
- the_brace.expression.push(value);
5904
- } else {
5905
-
5906
- // test_cause:
5907
- // ["aa={\"aa\":0}", "prefix_lbrace", "colon", "", 0]
5908
-
5909
- test_cause("colon");
5910
- advance(":");
5911
- value = parse_expression(0);
5912
- value.label = name;
5913
- the_brace.expression.push(value);
5914
- }
6257
+ the_brace.expression.push(property_parse());
5915
6258
  if (token_nxt.id !== ",") {
5916
6259
  break;
5917
6260
  }
5918
-
5919
- // test_cause:
5920
- // ["aa={\"aa\":0,\"bb\":0}", "prefix_lbrace", "comma", "", 0]
5921
-
5922
- test_cause("comma");
5923
6261
  advance(",");
5924
6262
  if (token_nxt.id === "}") {
5925
6263
 
@@ -5948,25 +6286,45 @@ function jslint_phase3_parse(state) {
5948
6286
  }
5949
6287
 
5950
6288
  function prefix_lbracket() {
5951
- const the_token = token_now;
5952
6289
  let element;
5953
- let ellipsis;
6290
+ let the_token = token_now;
5954
6291
  the_token.expression = [];
6292
+ if (the_token.assignment) {
6293
+ the_token = token_now.assignment;
6294
+ the_token.name_list = []; // 3. name_list for "[aa] = ..."
6295
+
6296
+ // PR-500 - Unify ES2015-destructure-logic. - [aa] = ...;
6297
+
6298
+ element = prefix_destructure(
6299
+ false, // enroll
6300
+ "variable", // role
6301
+ false, // readonly
6302
+ the_token.name_list, // name_list
6303
+ undefined, // the_function
6304
+ false // the_function_toplevel
6305
+ );
6306
+ advance("=");
6307
+ symbol("=").led_infix(element);
6308
+ return the_token;
6309
+ }
5955
6310
  if (token_nxt.id !== "]") {
5956
6311
 
5957
6312
  // Parse/loop through each element in [...].
5958
6313
 
5959
6314
  while (true) {
5960
- ellipsis = false;
5961
- if (token_nxt.id === "...") {
5962
- ellipsis = true;
5963
- advance("...");
5964
- }
5965
- element = parse_expression(10);
5966
- if (ellipsis) {
5967
- element.ellipsis = true;
6315
+ if (!state.mode_json && token_nxt.id === "...") {
6316
+
6317
+ // test_cause:
6318
+ // ["aa=[...aa]", "prefix_lbracket", "ellipsis", "...", 0]
6319
+
6320
+ test_cause("ellipsis", token_nxt.id);
6321
+ the_token.expression.push(prefix_ellipsis());
6322
+
6323
+ // Issue #401 - Regression - Allow multiple-ellipsis in array-literal.
6324
+
6325
+ } else {
6326
+ the_token.expression.push(parse_expression(10));
5968
6327
  }
5969
- the_token.expression.push(element);
5970
6328
  if (token_nxt.id !== ",") {
5971
6329
  break;
5972
6330
  }
@@ -5974,7 +6332,7 @@ function jslint_phase3_parse(state) {
5974
6332
  if (token_nxt.id === "]") {
5975
6333
 
5976
6334
  // test_cause:
5977
- // ["let aa=[0,]", "prefix_lbracket", "unexpected_a", ",", 10]
6335
+ // ["aa=[0,]", "prefix_lbracket", "unexpected_a", ",", 6]
5978
6336
 
5979
6337
  warn("unexpected_a", token_now);
5980
6338
  break;
@@ -5992,7 +6350,7 @@ function jslint_phase3_parse(state) {
5992
6350
  // PR-385 - Bugfix - Fixes issue #382 - failure to detect destructured fart.
5993
6351
 
5994
6352
  if (token_now.fart) {
5995
- return parse_fart(token_now.fart);
6353
+ return prefix_function(token_now.fart, true, false);
5996
6354
  }
5997
6355
 
5998
6356
  // test_cause:
@@ -6139,7 +6497,7 @@ function jslint_phase3_parse(state) {
6139
6497
  the_break.label = token_nxt;
6140
6498
  advance();
6141
6499
  }
6142
- advance(";");
6500
+ semicolon();
6143
6501
  return the_break;
6144
6502
  }
6145
6503
 
@@ -6158,7 +6516,7 @@ function jslint_phase3_parse(state) {
6158
6516
  check_not_top_level(the_continue);
6159
6517
  the_continue.disrupt = true;
6160
6518
  warn("unexpected_a", the_continue);
6161
- advance(";");
6519
+ semicolon();
6162
6520
  return the_continue;
6163
6521
  }
6164
6522
 
@@ -6186,7 +6544,7 @@ function jslint_phase3_parse(state) {
6186
6544
  // test_cause:
6187
6545
  // ["delete 0", "stmt_delete", "expected_a_b", "0", 8]
6188
6546
 
6189
- stop("expected_a_b", the_value, ".", artifact(the_value));
6547
+ return stop("expected_a_b", the_value, ".", artifact(the_value));
6190
6548
  }
6191
6549
  the_token.expression = the_value;
6192
6550
  semicolon();
@@ -6311,7 +6669,7 @@ function jslint_phase3_parse(state) {
6311
6669
  // test_cause:
6312
6670
  // ["export {}", "stmt_export", "expected_identifier_a", "}", 9]
6313
6671
 
6314
- stop("expected_identifier_a");
6672
+ return stop("expected_identifier_a", token_nxt);
6315
6673
  }
6316
6674
  the_id = token_nxt.id;
6317
6675
  export_list.push(token_nxt);
@@ -6335,11 +6693,10 @@ function jslint_phase3_parse(state) {
6335
6693
  }
6336
6694
  advance();
6337
6695
  the_export.expression.push(the_thing);
6338
- if (token_nxt.id === ",") {
6339
- advance(",");
6340
- } else {
6696
+ if (token_nxt.id !== ",") {
6341
6697
  break;
6342
6698
  }
6699
+ advance(",");
6343
6700
  }
6344
6701
 
6345
6702
  // PR-439 - Check exported properties are ordered.
@@ -6355,7 +6712,7 @@ function jslint_phase3_parse(state) {
6355
6712
  // test_cause:
6356
6713
  // ["export", "stmt_export", "unexpected_a", "(end)", 1]
6357
6714
 
6358
- stop("unexpected_a");
6715
+ return stop("unexpected_a");
6359
6716
  }
6360
6717
  }
6361
6718
  state.mode_module = true;
@@ -6477,83 +6834,115 @@ function jslint_phase3_parse(state) {
6477
6834
  function stmt_import() {
6478
6835
  const the_import = token_now;
6479
6836
  let name;
6480
- let names;
6481
-
6482
- // PR-347 - Disable warning "unexpected_directive_a".
6483
- //
6484
- // if (typeof state.mode_module === "object") {
6485
- //
6486
- // // test_cause:
6487
- // // ["
6488
- // // /*global aa*/
6489
- // // import aa from "aa"
6490
- // // ", "stmt_import", "unexpected_directive_a", "global", 1]
6491
- //
6492
- // warn(
6493
- // "unexpected_directive_a",
6494
- // state.mode_module,
6495
- // state.mode_module.directive
6496
- // );
6497
- // }
6498
-
6837
+ the_import.name_list = []; // 4. name_list for "import ..."
6499
6838
  state.mode_module = true;
6839
+ while (true) {
6500
6840
 
6501
6841
  // PR-436 - Add grammar for side-effect import-statement.
6502
6842
 
6503
- if (token_nxt.id === "(string)") {
6843
+ if (token_nxt.id === "(string)") {
6504
6844
 
6505
6845
  // test_cause:
6506
- // ["import \"./aa.mjs\";", "stmt_import", "import_side_effect", "", 0]
6846
+ // ["import \"aa\"", "stmt_import", "import_side_effect", "", 0]
6507
6847
 
6508
- test_cause("import_side_effect");
6509
- warn("expected_a_b", token_nxt, "{", artifact());
6510
- advance();
6511
- semicolon();
6512
- return the_import;
6513
- }
6514
- if (token_nxt.identifier) {
6515
- name = token_nxt;
6516
- advance();
6517
- if (name.id === "ignore") {
6848
+ test_cause("import_side_effect");
6849
+ warn("expected_a_b", token_nxt, "{", artifact());
6850
+ advance();
6851
+ semicolon();
6852
+ return the_import;
6853
+ }
6854
+ if (token_nxt.id === "*") {
6855
+ advance("*");
6856
+ advance("as");
6857
+ if (!token_nxt.identifier) {
6518
6858
 
6519
6859
  // test_cause:
6520
- // ["import ignore from \"aa\"", "stmt_import", "unexpected_a", "ignore", 8]
6860
+ // ["import * as", "stmt_import", "expected_identifier_a", "(end)", 1]
6521
6861
 
6522
- warn("unexpected_a", name);
6862
+ return stop("expected_identifier_a", token_nxt);
6863
+ }
6523
6864
  }
6524
- enroll(name, "variable", true);
6525
- the_import.name = name;
6526
- } else {
6527
- names = [];
6528
- advance("{");
6529
- if (token_nxt.id !== "}") {
6530
- while (true) {
6531
- if (!token_nxt.identifier) {
6865
+ if (token_nxt.identifier) {
6866
+ name = token_nxt;
6867
+ advance();
6868
+ if (name.id === "ignore") {
6869
+
6870
+ // test_cause:
6871
+ // ["import ignore from \"aa\"", "stmt_import", "unexpected_a", "ignore", 8]
6872
+
6873
+ warn("unexpected_a", name);
6874
+ }
6875
+ name_push(
6876
+ the_import.name_list, // name_list
6877
+ true, // enroll
6878
+ name, // name
6879
+ "variable", // role
6880
+ true, // readonly
6881
+ true // init
6882
+ );
6883
+ } else {
6884
+ advance("{");
6885
+ if (token_nxt.id !== "}") {
6886
+ while (true) {
6887
+ if (!token_nxt.identifier) {
6532
6888
 
6533
6889
  // test_cause:
6534
6890
  // ["import {", "stmt_import", "expected_identifier_a", "(end)", 1]
6535
6891
 
6536
- stop("expected_identifier_a");
6537
- }
6538
- name = token_nxt;
6539
- advance();
6540
- if (name.id === "ignore") {
6892
+ return stop("expected_identifier_a", token_nxt);
6893
+ }
6894
+ name = token_nxt;
6895
+ advance();
6896
+ if (token_nxt.id === "as") {
6897
+ advance("as");
6898
+ name = token_nxt;
6899
+ advance();
6900
+ }
6901
+ if (name.id === "ignore") {
6541
6902
 
6542
6903
  // test_cause:
6543
6904
  // ["import {ignore} from \"aa\"", "stmt_import", "unexpected_a", "ignore", 9]
6544
6905
 
6545
- warn("unexpected_a", name);
6546
- }
6547
- enroll(name, "variable", true);
6548
- names.push(name);
6549
- if (token_nxt.id !== ",") {
6550
- break;
6906
+ warn("unexpected_a", name);
6907
+ }
6908
+ name_push(
6909
+ the_import.name_list, // name_list
6910
+ true, // enroll
6911
+ name, // name
6912
+ "variable", // role
6913
+ true, // readonly
6914
+ true // init
6915
+ );
6916
+ if (token_nxt.id !== ",") {
6917
+ break;
6918
+ }
6919
+ advance(",");
6551
6920
  }
6552
- advance(",");
6553
6921
  }
6922
+ advance("}");
6923
+ }
6924
+
6925
+ // PR-347 - Disable warning "unexpected_directive_a".
6926
+ //
6927
+ // if (typeof state.mode_module === "object") {
6928
+ //
6929
+ // // test_cause:
6930
+ // // ["
6931
+ // // /*global aa*/
6932
+ // // import aa from "aa"
6933
+ // // ", "stmt_import", "unexpected_directive_a", "global", 1]
6934
+ //
6935
+ // warn(
6936
+ // "unexpected_directive_a",
6937
+ // state.mode_module,
6938
+ // state.mode_module.directive
6939
+ // );
6940
+ // }
6941
+
6942
+ if (token_nxt.id !== ",") {
6943
+ break;
6554
6944
  }
6555
- advance("}");
6556
- the_import.name = names;
6945
+ advance(",");
6557
6946
  }
6558
6947
  advance("from");
6559
6948
  advance("(string)");
@@ -6566,6 +6955,14 @@ function jslint_phase3_parse(state) {
6566
6955
  warn("bad_module_name_a", token_now);
6567
6956
  }
6568
6957
  import_list.push(token_now.value);
6958
+
6959
+ // Issue #495 - Add ES2025-syntax "import ... with {...}".
6960
+
6961
+ if (token_nxt.id === "with") {
6962
+ advance("with");
6963
+ advance("{");
6964
+ prefix_lbrace();
6965
+ }
6569
6966
  semicolon();
6570
6967
  return the_import;
6571
6968
  }
@@ -6596,7 +6993,7 @@ function jslint_phase3_parse(state) {
6596
6993
  if (token_nxt.id !== ";" && the_return.line === token_nxt.line) {
6597
6994
  the_return.expression = parse_expression(10);
6598
6995
  }
6599
- advance(";");
6996
+ semicolon();
6600
6997
  return the_return;
6601
6998
  }
6602
6999
 
@@ -6834,12 +7231,19 @@ function jslint_phase3_parse(state) {
6834
7231
  // test_cause:
6835
7232
  // ["try{}catch(){}", "stmt_try", "expected_identifier_a", ")", 12]
6836
7233
 
6837
- return stop("expected_identifier_a");
7234
+ return stop("expected_identifier_a", token_nxt);
6838
7235
  }
6839
7236
  if (token_nxt.id !== "ignore") {
6840
7237
  ignored = undefined;
6841
7238
  the_catch.name = token_nxt;
6842
- enroll(token_nxt, "exception", true);
7239
+ name_push(
7240
+ [], // name_list
7241
+ true, // enroll
7242
+ token_nxt, // name
7243
+ "exception", // role
7244
+ true, // readonly
7245
+ true // init
7246
+ );
6843
7247
  }
6844
7248
  advance();
6845
7249
  advance(")");
@@ -6876,19 +7280,15 @@ function jslint_phase3_parse(state) {
6876
7280
  }
6877
7281
 
6878
7282
  function stmt_var() {
6879
- let ellipsis;
6880
- let mode_const;
7283
+ const readonly = token_now.id === "const";
6881
7284
  let name;
6882
- let the_brace;
6883
- let the_bracket;
6884
7285
  let the_variable = token_now;
6885
7286
  let variable_prv;
6886
- mode_const = the_variable.id === "const";
6887
- the_variable.names = [];
7287
+ the_variable.name_list = []; // 5. name_list for "let [aa] = ..."
6888
7288
 
6889
7289
  // A program may use var or let, but not both.
6890
7290
 
6891
- if (!mode_const) {
7291
+ if (!readonly) {
6892
7292
  if (mode_var === undefined) {
6893
7293
  mode_var = the_variable.id;
6894
7294
  } else if (the_variable.id !== mode_var) {
@@ -6950,142 +7350,27 @@ function jslint_phase3_parse(state) {
6950
7350
  }
6951
7351
  }
6952
7352
  while (true) {
6953
- if (token_nxt.id === "{") {
6954
- if (the_variable.id === "var") {
6955
-
6956
- // test_cause:
6957
- // ["var{aa}=0", "stmt_var", "unexpected_a", "var", 1]
6958
-
6959
- warn("unexpected_a", the_variable);
6960
- }
6961
- the_brace = token_nxt;
6962
- advance("{");
6963
- while (true) {
6964
- name = token_nxt;
6965
- if (!name.identifier) {
6966
-
6967
- // test_cause:
6968
- // ["let {0}", "stmt_var", "expected_identifier_a", "0", 6]
6969
-
6970
- return stop("expected_identifier_a");
6971
- }
6972
- survey(name);
6973
- advance();
6974
- if (token_nxt.id === ":") {
6975
- advance(":");
6976
- if (!token_nxt.identifier) {
6977
-
6978
- // test_cause:
6979
- // ["let {aa:0}", "stmt_var", "expected_identifier_a", "0", 9]
6980
- // ["let {aa:{aa}}", "stmt_var", "expected_identifier_a", "{", 9]
6981
-
6982
- return stop("expected_identifier_a");
6983
- }
6984
-
6985
- // PR-363 - Bugfix
6986
- // Add test against false-warning <uninitialized 'bb'> in code
6987
- // '/*jslint node*/\nlet {aa:bb} = {}; bb();'.
6988
- //
6989
- // token_nxt.label = name;
6990
- // the_variable.names.push(token_nxt);
6991
- // enroll(token_nxt, "variable", mode_const);
6992
-
6993
- name = token_nxt;
6994
- the_variable.names.push(name);
6995
- survey(name);
6996
- enroll(name, "variable", mode_const);
6997
-
6998
- advance();
6999
- the_brace.open = true;
7000
- } else {
7001
- the_variable.names.push(name);
7002
- enroll(name, "variable", mode_const);
7003
- }
7004
-
7005
- // Issue #458 - Regression - Warn about variable usage before initialization.
7006
-
7007
- // name.dead = false;
7008
-
7009
- name.init = true;
7010
-
7011
- // test_cause:
7012
- // ["const {aa}=bb;\nconst bb=0;", "lookup", "out_of_scope_a", "bb", 12]
7013
-
7014
- if (token_nxt.id === "=") {
7015
-
7016
- // test_cause:
7017
- // ["let {aa=0}", "stmt_var", "assign", "", 0]
7018
-
7019
- test_cause("assign");
7020
- advance("=");
7021
- name.expression = parse_expression();
7022
- the_brace.open = true;
7023
- }
7024
- if (token_nxt.id !== ",") {
7025
- break;
7026
- }
7027
- advance(",");
7028
- }
7029
-
7030
- // test_cause:
7031
- // ["let{bb,aa}", "check_ordered", "expected_a_b_before_c_d", "aa", 8]
7032
-
7033
- check_ordered(the_variable.id, the_variable.names);
7034
- advance("}");
7035
- advance("=");
7036
- the_variable.expression = parse_expression(0);
7037
- } else if (token_nxt.id === "[") {
7353
+ if (token_nxt.id === "{" || token_nxt.id === "[") {
7038
7354
  if (the_variable.id === "var") {
7039
7355
 
7040
7356
  // test_cause:
7041
7357
  // ["var[aa]=0", "stmt_var", "unexpected_a", "var", 1]
7358
+ // ["var{aa}=0", "stmt_var", "unexpected_a", "var", 1]
7042
7359
 
7043
7360
  warn("unexpected_a", the_variable);
7044
7361
  }
7045
- the_bracket = token_nxt;
7046
- advance("[");
7047
- while (true) {
7048
- ellipsis = false;
7049
- if (token_nxt.id === "...") {
7050
- ellipsis = true;
7051
- advance("...");
7052
- }
7053
- if (!token_nxt.identifier) {
7054
-
7055
- // test_cause:
7056
- // ["let[]", "stmt_var", "expected_identifier_a", "]", 5]
7057
-
7058
- return stop("expected_identifier_a");
7059
- }
7060
- name = token_nxt;
7061
- advance();
7062
- the_variable.names.push(name);
7063
- enroll(name, "variable", mode_const);
7064
-
7065
- // Issue #458 - Regression - Warn about variable usage before initialization.
7066
-
7067
- // name.dead = false;
7068
-
7069
- name.init = true;
7362
+ advance();
7070
7363
 
7071
- // test_cause:
7072
- // ["const [aa]=bb;\nconst bb=0;", "lookup", "out_of_scope_a", "bb", 12]
7364
+ // PR-500 - Unify ES2015-destructure-logic. - let [aa] = ...;
7073
7365
 
7074
- if (ellipsis) {
7075
- name.ellipsis = true;
7076
- break;
7077
- }
7078
- if (token_nxt.id === "=") {
7079
- advance("=");
7080
- name.expression = parse_expression();
7081
- the_bracket.open = true;
7082
- }
7083
- if (token_nxt.id !== ",") {
7084
- break;
7085
- }
7086
- advance(",");
7087
- }
7088
- advance("]");
7366
+ prefix_destructure(
7367
+ true, // enroll
7368
+ "variable", // role
7369
+ readonly, // readonly
7370
+ the_variable.name_list, // name_list
7371
+ undefined, // the_function
7372
+ false // the_function_toplevel
7373
+ );
7089
7374
  advance("=");
7090
7375
  the_variable.expression = parse_expression(0);
7091
7376
  } else if (token_nxt.identifier) {
@@ -7100,29 +7385,24 @@ function jslint_phase3_parse(state) {
7100
7385
 
7101
7386
  warn("unexpected_a", name);
7102
7387
  }
7103
- enroll(name, "variable", mode_const);
7104
- if (token_nxt.id === "=" || mode_const) {
7388
+ if (token_nxt.id === "=" || readonly) {
7105
7389
  advance("=");
7106
-
7107
- // Issue #458 - Regression - Warn about variable usage before initialization.
7108
-
7109
- // name.dead = false;
7110
-
7111
- name.init = true;
7112
-
7113
- // test_cause:
7114
- // ["const aa=bb;\nconst bb=0;", "lookup", "out_of_scope_a", "bb", 10]
7115
-
7116
7390
  name.expression = parse_expression(0);
7117
7391
  }
7118
- the_variable.names.push(name);
7392
+ name_push(
7393
+ the_variable.name_list, // name_list
7394
+ true, // enroll
7395
+ name, // name
7396
+ "variable", // role
7397
+ readonly, // readonly
7398
+ Boolean(name.expression) // init
7399
+ );
7119
7400
  } else {
7120
7401
 
7121
7402
  // test_cause:
7122
7403
  // ["let 0", "stmt_var", "expected_identifier_a", "0", 5]
7123
- // ["var{aa:{aa}}", "stmt_var", "expected_identifier_a", "{", 8]
7124
7404
 
7125
- return stop("expected_identifier_a");
7405
+ return stop("expected_identifier_a", token_nxt);
7126
7406
  }
7127
7407
  if (token_nxt.id !== ",") {
7128
7408
  break;
@@ -7143,8 +7423,8 @@ function jslint_phase3_parse(state) {
7143
7423
  && !option_dict.variable
7144
7424
  && variable_prv
7145
7425
  && (
7146
- variable_prv.id + " " + variable_prv.names[0].id
7147
- > the_variable.id + " " + the_variable.names[0].id
7426
+ variable_prv.id + " " + variable_prv.name_list[0].id
7427
+ > the_variable.id + " " + the_variable.name_list[0].id
7148
7428
  )
7149
7429
  ) {
7150
7430
 
@@ -7157,9 +7437,9 @@ function jslint_phase3_parse(state) {
7157
7437
  "expected_a_b_before_c_d",
7158
7438
  the_variable,
7159
7439
  the_variable.id,
7160
- the_variable.names[0].id,
7440
+ the_variable.name_list[0].id,
7161
7441
  variable_prv.id,
7162
- variable_prv.names[0].id
7442
+ variable_prv.name_list[0].id
7163
7443
  );
7164
7444
  }
7165
7445
  semicolon();
@@ -7188,7 +7468,7 @@ function jslint_phase3_parse(state) {
7188
7468
  // test_cause:
7189
7469
  // ["with", "stmt_with", "unexpected_a", "with", 1]
7190
7470
 
7191
- stop("unexpected_a", token_now);
7471
+ return stop("unexpected_a", token_now);
7192
7472
  }
7193
7473
 
7194
7474
  function survey(name) {
@@ -7197,49 +7477,55 @@ function jslint_phase3_parse(state) {
7197
7477
  // Tally the property name. If it is a string, only tally strings that conform
7198
7478
  // to the identifier rules.
7199
7479
 
7200
- if (id === "(string)") {
7480
+ switch (id) {
7481
+ case "(string)":
7201
7482
  id = name.value;
7202
7483
  if (!jslint_rgx_identifier.test(id)) {
7203
7484
  return id;
7204
7485
  }
7205
- } else if (id === "`") {
7486
+ break;
7487
+ case "`":
7206
7488
  if (name.value.length === 1) {
7207
7489
  id = name.value[0].value;
7208
7490
  if (!jslint_rgx_identifier.test(id)) {
7209
7491
  return id;
7210
7492
  }
7211
7493
  }
7212
- } else if (!name.identifier) {
7494
+ break;
7495
+ default:
7496
+ if (!name.identifier) {
7213
7497
 
7214
7498
  // test_cause:
7215
7499
  // ["let aa={0:0}", "survey", "expected_identifier_a", "0", 9]
7216
7500
 
7217
- return stop("expected_identifier_a", name);
7501
+ return stop("expected_identifier_a", name);
7502
+ }
7218
7503
  }
7219
7504
 
7220
7505
  // If we have seen this name before, increment its count.
7221
7506
 
7222
7507
  if (typeof property_dict[id] === "number") {
7223
7508
  property_dict[id] += 1;
7509
+ return id;
7510
+ }
7224
7511
 
7225
7512
  // If this is the first time seeing this property name, and if there is a
7226
7513
  // tenure list, then it must be on the list. Otherwise, it must conform to
7227
7514
  // the rules for good property names.
7228
7515
 
7229
- } else {
7230
- if (state.mode_property) {
7231
- if (tenure[id] !== true) {
7516
+ if (state.mode_property) {
7517
+ if (tenure[id] !== true) {
7232
7518
 
7233
7519
  // test_cause:
7234
7520
  // ["/*property aa*/\naa.bb", "survey", "unregistered_property_a", "bb", 4]
7235
7521
 
7236
- warn("unregistered_property_a", name);
7237
- }
7238
- } else if (
7239
- !option_dict.nomen
7240
- && name.identifier
7241
- && jslint_rgx_weird_property.test(id)
7242
- ) {
7522
+ warn("unregistered_property_a", name);
7523
+ }
7524
+ } else if (
7525
+ !option_dict.nomen
7526
+ && name.identifier
7527
+ && jslint_rgx_weird_property.test(id)
7528
+ ) {
7243
7529
 
7244
7530
  // test_cause:
7245
7531
  // ["aa.$", "survey", "weird_property_a", "$", 4]
@@ -7248,10 +7534,9 @@ function jslint_phase3_parse(state) {
7248
7534
  // ["aa.aaSync", "survey", "weird_property_a", "aaSync", 4]
7249
7535
  // ["aa.aa_", "survey", "weird_property_a", "aa_", 4]
7250
7536
 
7251
- warn("weird_property_a", name);
7252
- }
7253
- property_dict[id] = 1;
7537
+ warn("weird_property_a", name);
7254
7538
  }
7539
+ property_dict[id] = 1;
7255
7540
  return id;
7256
7541
  }
7257
7542
 
@@ -7300,6 +7585,7 @@ function jslint_phase3_parse(state) {
7300
7585
  // Begin defining the language.
7301
7586
 
7302
7587
  assignment("%=");
7588
+ assignment("&&=");
7303
7589
  assignment("&=");
7304
7590
  assignment("*=");
7305
7591
  assignment("+=");
@@ -7309,8 +7595,10 @@ function jslint_phase3_parse(state) {
7309
7595
  assignment("=");
7310
7596
  assignment(">>=");
7311
7597
  assignment(">>>=");
7598
+ assignment("??=");
7312
7599
  assignment("^=");
7313
7600
  assignment("|=");
7601
+ assignment("||=");
7314
7602
  constant("(number)", "number");
7315
7603
  constant("(regexp)", "regexp");
7316
7604
  constant("(string)", "string");
@@ -7349,7 +7637,7 @@ function jslint_phase3_parse(state) {
7349
7637
  infix(160, "`", infix_grave);
7350
7638
  infix(170, ".", infix_dot);
7351
7639
  infix(170, "=>", infix_fart_unwrapped);
7352
- infix(170, "?.", infix_option_chain);
7640
+ infix(170, "?.", infix_dot);
7353
7641
  infix(170, "[", infix_lbracket);
7354
7642
  infix(35, "??");
7355
7643
  infix(40, "||");
@@ -7454,7 +7742,7 @@ function jslint_phase3_parse(state) {
7454
7742
 
7455
7743
  } else if (token_nxt.value === "use strict") {
7456
7744
  advance("(string)");
7457
- advance(";");
7745
+ semicolon();
7458
7746
  }
7459
7747
  state.token_tree = parse_statements();
7460
7748
  advance("(end)");
@@ -7589,16 +7877,13 @@ function jslint_phase4_walk(state) {
7589
7877
  };
7590
7878
  }
7591
7879
 
7592
- function init_variable(name) {
7593
- let the_variable = lookup(name);
7594
- if (!the_variable || the_variable.readonly) {
7595
- warn("bad_assignment_a", name);
7596
- return;
7597
- }
7598
- the_variable.init = true;
7599
- }
7880
+ function name_lookup(thing, init) {
7881
+
7882
+ // This function will:
7883
+ // 1. Lookup and return variable or function-parameter <the_variable> in current
7884
+ // context from given <thing>.id.
7885
+ // 2. Set <the_variable>.init = true, if lookup was from an assignment.
7600
7886
 
7601
- function lookup(thing) {
7602
7887
  let id = thing.id;
7603
7888
  let the_variable;
7604
7889
  if (thing.arity !== "variable") {
@@ -7615,7 +7900,7 @@ function jslint_phase4_walk(state) {
7615
7900
  if (the_variable && the_variable.role === "label") {
7616
7901
 
7617
7902
  // test_cause:
7618
- // ["aa:while(0){aa;}", "lookup", "label_a", "aa", 13]
7903
+ // ["aa:while(0){aa;}", "name_lookup", "label_a", "aa", 13]
7619
7904
 
7620
7905
  warn("label_a", thing);
7621
7906
  return the_variable;
@@ -7628,27 +7913,30 @@ function jslint_phase4_walk(state) {
7628
7913
  the_variable = context[id];
7629
7914
  }
7630
7915
  });
7631
-
7632
- // If it isn't in any of those either, perhaps it is a predefined global.
7633
- // If so, add it to the global context.
7634
-
7635
7916
  if (!the_variable && global_dict[id] === undefined) {
7636
7917
 
7637
7918
  // test_cause:
7638
- // ["aa", "lookup", "undeclared_a", "aa", 1]
7639
- // ["class aa{}", "lookup", "undeclared_a", "aa", 7]
7919
+ // ["aa", "name_lookup", "undeclared_a", "aa", 1]
7920
+ // ["class aa{}", "name_lookup", "undeclared_a", "aa", 7]
7640
7921
  // ["
7641
7922
  // let aa=0;try{aa();}catch(bb){bb();}bb();
7642
- // ", "lookup", "undeclared_a", "bb", 36]
7923
+ // ", "name_lookup", "undeclared_a", "bb", 36]
7643
7924
  // ["
7644
7925
  // let aa=0;try{aa();}catch(ignore){bb();}
7645
- // ", "lookup", "undeclared_a", "bb", 34]
7926
+ // ", "name_lookup", "undeclared_a", "bb", 34]
7646
7927
 
7647
7928
  warn("undeclared_a", thing);
7648
7929
  return;
7649
7930
  }
7931
+
7932
+ // If it isn't in any of those either, perhaps it is a predefined global.
7933
+ // If so, add it to the global context.
7934
+
7650
7935
  if (!the_variable) {
7651
7936
  the_variable = {
7937
+
7938
+ // 4a. Mark not dead, the global-variable, anywhere.
7939
+
7652
7940
  dead: false,
7653
7941
  id,
7654
7942
  init: true,
@@ -7672,10 +7960,18 @@ function jslint_phase4_walk(state) {
7672
7960
  ) {
7673
7961
 
7674
7962
  // test_cause:
7675
- // ["let aa;if(aa){let bb;}bb;", "lookup", "out_of_scope_a", "bb", 23]
7963
+ // ["(aa=aa)=>0", "name_lookup", "out_of_scope_a", "aa", 5]
7964
+ // ["let aa;if(aa){let bb;}bb;", "name_lookup", "out_of_scope_a", "bb", 23]
7965
+ // ["let aa=bb;let bb=0;", "name_lookup", "out_of_scope_a", "bb", 8]
7676
7966
 
7677
7967
  warn("out_of_scope_a", thing);
7678
7968
  }
7969
+
7970
+ // Set variable as initialized, if lookup was from an assignment.
7971
+
7972
+ if (init && the_variable && !the_variable.readonly) {
7973
+ the_variable.init = true;
7974
+ }
7679
7975
  return the_variable;
7680
7976
  }
7681
7977
 
@@ -7687,58 +7983,24 @@ function jslint_phase4_walk(state) {
7687
7983
 
7688
7984
  const lvalue = thing.expression[0];
7689
7985
  let right;
7690
- if (thing.id === "=") {
7691
- if (thing.names !== undefined) {
7692
-
7693
- // test_cause:
7694
- // ["if(0){aa=0}", "post_a", "=", "", 0]
7695
-
7696
- test_cause("=");
7697
-
7698
- // Probably deadcode.
7699
- // if (Array.isArray(thing.names)) {
7700
- // thing.names.forEach(init_variable);
7701
- // } else {
7702
- // init_variable(thing.names);
7703
- // }
7704
-
7705
- jslint_assert(
7706
- !Array.isArray(thing.names),
7707
- `Expected !Array.isArray(thing.names).`
7708
- );
7709
- init_variable(thing.names);
7710
- } else {
7711
- if (lvalue.id === "[" || lvalue.id === "{") {
7712
- lvalue.expression.forEach(function (thing) {
7713
- if (thing.variable) {
7714
- thing.variable.init = true;
7715
- }
7716
- });
7717
- } else if (
7718
- lvalue.id === "."
7719
- && thing.expression[1].id === "undefined"
7720
- ) {
7986
+ if (thing.id !== "=") {
7987
+ if (
7988
+ lvalue.arity === "variable"
7989
+ && (!lvalue.variable || lvalue.variable.readonly)
7990
+ ) {
7721
7991
 
7722
7992
  // test_cause:
7723
- // ["aa.aa=undefined", "post_a", "expected_a_b", "undefined", 1]
7993
+ // ["aa+=0", "post_a", "+=", "aa", 0]
7994
+ // ["aa+=0", "post_a", "bad_assignment_a", "aa", 1]
7995
+ // ["const aa=0;aa+=0", "post_a", "+=", "aa", 0]
7996
+ // ["const aa=0;aa+=0", "post_a", "bad_assignment_a", "aa", 12]
7724
7997
 
7725
- warn(
7726
- "expected_a_b",
7727
- lvalue.expression,
7728
- "delete",
7729
- "undefined"
7730
- );
7731
- }
7732
- }
7733
- } else {
7734
- if (lvalue.arity === "variable") {
7735
- if (!lvalue.variable || lvalue.variable.readonly) {
7736
- warn("bad_assignment_a", lvalue);
7737
- }
7998
+ test_cause("+=", lvalue.id);
7999
+ warn("bad_assignment_a", lvalue);
7738
8000
  }
7739
8001
  right = syntax_dict[thing.expression[1].id];
7740
8002
  if (
7741
- right !== undefined
8003
+ right
7742
8004
  && (
7743
8005
  right.id === "function"
7744
8006
  || right.id === "=>"
@@ -7755,6 +8017,33 @@ function jslint_phase4_walk(state) {
7755
8017
 
7756
8018
  warn("unexpected_a", thing.expression[1]);
7757
8019
  }
8020
+ return;
8021
+ }
8022
+ if (thing.name_list) {
8023
+ thing.name_list.forEach(function (name) {
8024
+ const the_variable = name_lookup(name, true);
8025
+ if (!the_variable || the_variable.readonly) {
8026
+
8027
+ // test_cause:
8028
+ // ["aa=0", "post_a", "=", "aa", 0]
8029
+ // ["aa=0", "post_a", "bad_assignment_a", "aa", 1]
8030
+ // ["const aa=0;aa=0", "post_a", "=", "aa", 0]
8031
+ // ["const aa=0;aa=0", "post_a", "bad_assignment_a", "aa", 12]
8032
+
8033
+ test_cause("=", name.id);
8034
+ warn("bad_assignment_a", name);
8035
+ return;
8036
+ }
8037
+ });
8038
+ return;
8039
+ }
8040
+ if (lvalue.id === "." && thing.expression[1].id === "undefined") {
8041
+
8042
+ // test_cause:
8043
+ // ["aa.aa=undefined", "post_a", "expected_a_b", "undefined", 1]
8044
+
8045
+ warn("expected_a_b", lvalue.expression, "delete", "undefined");
8046
+ return;
7758
8047
  }
7759
8048
  }
7760
8049
 
@@ -7827,10 +8116,15 @@ function jslint_phase4_walk(state) {
7827
8116
  } else if (thing.id === "." || thing.id === "?.") {
7828
8117
  if (thing.expression.id === "RegExp") {
7829
8118
 
8119
+ // PR-499 - Relax warning for ES2025-feature RegExp.escape().
8120
+
8121
+ if (!thing.name || thing.name.id !== "escape") {
8122
+
7830
8123
  // test_cause:
7831
8124
  // ["aa=RegExp.aa", "post_b", "weird_expression_a", ".", 10]
7832
8125
 
7833
- warn("weird_expression_a", thing);
8126
+ warn("weird_expression_a", thing);
8127
+ }
7834
8128
  }
7835
8129
  } else if (thing.id !== "=>" && thing.id !== "(") {
7836
8130
  right = thing.expression[1];
@@ -8055,7 +8349,7 @@ function jslint_phase4_walk(state) {
8055
8349
  }
8056
8350
  }
8057
8351
 
8058
- function post_s_export(the_thing) {
8352
+ function post_s_export_toplevel(the_thing) {
8059
8353
 
8060
8354
  // Some features must be at the most outermost level.
8061
8355
 
@@ -8064,7 +8358,7 @@ function jslint_phase4_walk(state) {
8064
8358
  // test_cause:
8065
8359
  // ["
8066
8360
  // if(0){import aa from "aa";}
8067
- // ", "post_s_export", "misplaced_a", "import", 7]
8361
+ // ", "post_s_export_toplevel", "misplaced_a", "import", 7]
8068
8362
 
8069
8363
  warn("misplaced_a", the_thing);
8070
8364
  }
@@ -8092,74 +8386,88 @@ function jslint_phase4_walk(state) {
8092
8386
 
8093
8387
  warn("unexpected_parens", thing);
8094
8388
  }
8095
- return post_s_lbrace();
8389
+ return post_s_lbrace_pop_block();
8096
8390
  }
8097
8391
 
8098
8392
  function post_s_import(the_thing) {
8099
- const name = the_thing.name;
8100
- if (name) {
8101
- if (Array.isArray(name)) {
8102
- name.forEach(function (name) {
8103
- name.dead = false;
8104
- name.init = true;
8105
- blockage.live.push(name);
8106
- });
8107
- } else {
8108
- name.dead = false;
8109
- name.init = true;
8110
- blockage.live.push(name);
8111
- }
8112
- return post_s_export(the_thing);
8113
- }
8393
+ the_thing.name_list.forEach(function (name) {
8394
+
8395
+ // 5a. Mark not dead, the import-name, after import-statement.
8396
+
8397
+ name.dead = false;
8398
+
8399
+ // 5z. Mark as dead, the import-name, after module-scope.
8400
+
8401
+ blockage.live_list.push(name);
8402
+ });
8403
+ return post_s_export_toplevel(the_thing);
8114
8404
  }
8115
8405
 
8116
- function post_s_lbrace() {
8117
- blockage.live.forEach(function (name) {
8406
+ function post_s_lbrace_pop_block() {
8407
+ blockage.live_list.forEach(function (name) {
8408
+
8409
+ // 1z. Mark as dead, the variable, after block-scope.
8410
+
8118
8411
  name.dead = true;
8119
8412
  });
8120
- delete blockage.live;
8413
+ delete blockage.live_list;
8121
8414
  blockage = block_stack.pop();
8122
8415
  }
8123
8416
 
8124
8417
  function post_s_try(thing) {
8125
- if (thing.catch) {
8126
- if (thing.catch.name) {
8127
- Object.assign(catchage.context[thing.catch.name.id], {
8128
- dead: false,
8129
- init: true
8130
- });
8131
- }
8418
+ if (!thing.catch) {
8419
+ return;
8420
+ }
8421
+ if (thing.catch.name) {
8422
+
8423
+ // 6a. Mark not dead, the exception-variable, before catch-block.
8424
+
8425
+ catchage.context[thing.catch.name.id].dead = false;
8426
+ }
8132
8427
 
8133
8428
  // Recurse walk_statement().
8134
8429
 
8135
- walk_statement(thing.catch.block);
8430
+ walk_statement(thing.catch.block);
8136
8431
 
8137
8432
  // Restore previous catch-scope after catch-block.
8138
8433
 
8139
- catchage = catch_stack.pop();
8140
- }
8434
+ catchage = catch_stack.pop();
8141
8435
  }
8142
8436
 
8143
8437
  function post_s_var(thing) {
8144
- thing.names.forEach(function (name) {
8438
+ thing.name_list.forEach(function (name) {
8439
+
8440
+ // t0d0 - Move to after walk_expression().
8441
+
8442
+ // PR-xxx - Fix long-running regression where 'let x = x;'
8443
+ // doesn't warn about uninitialized variables.
8444
+
8445
+ // 1a. Mark not dead, the variable, after variable-initialization.
8446
+
8145
8447
  name.dead = false;
8146
- if (name.expression !== undefined) {
8448
+ if (name.expression) {
8449
+
8450
+ // test_cause:
8451
+ // ["let aa=0", "post_s_var", "let aa=0", "", 0]
8452
+
8453
+ test_cause("let aa=0");
8147
8454
  walk_expression(name.expression);
8455
+ } else {
8148
8456
 
8149
- // Probably deadcode.
8150
- // if (name.id === "{" || name.id === "[") {
8151
- // name.names.forEach(subactivate);
8152
- // } else {
8153
- // name.init = true;
8154
- // }
8457
+ // test_cause:
8458
+ // ["let aa", "post_s_var", "let aa", "", 0]
8155
8459
 
8156
- jslint_assert(
8157
- !(name.id === "{" || name.id === "["),
8158
- `Expected !(name.id === "{" || name.id === "[").`
8159
- );
8160
- name.init = true;
8460
+ test_cause("let aa");
8461
+ }
8462
+ switch (thing.id) {
8463
+ case "const":
8464
+ case "let":
8465
+
8466
+ // 1z. Mark as dead, the variable, after block-scope.
8467
+
8468
+ blockage.live_list.push(name);
8469
+ break;
8161
8470
  }
8162
- blockage.live.push(name);
8163
8471
  });
8164
8472
  }
8165
8473
 
@@ -8404,33 +8712,99 @@ function jslint_phase4_walk(state) {
8404
8712
  warn("unexpected_a", thing);
8405
8713
  }
8406
8714
 
8407
- function pre_b_lparen(thing) {
8408
- const left = thing.expression[0];
8409
- let left_variable;
8410
- let parent;
8411
- if (
8412
- left.identifier
8413
- && functionage.context[left.id] === undefined
8414
- && typeof functionage.name === "object"
8415
- ) {
8416
- parent = functionage.name.parent;
8417
- if (parent) {
8418
- left_variable = parent.context[left.id];
8419
- if (
8420
- left_variable !== undefined
8421
-
8422
- // Probably deadcode.
8423
- // && left_variable.dead
8715
+ // PR-xxx - Probably deadcode.
8424
8716
 
8425
- && left_variable.parent === parent
8426
- && left_variable.calls !== undefined
8427
- && left_variable.calls[functionage.name.id] !== undefined
8428
- ) {
8429
- left_variable.dead = false;
8430
- }
8431
- }
8432
- }
8433
- }
8717
+ // function pre_b_lparen(thing) {
8718
+ //
8719
+ // // This function runs right before the parser handles a "(" symbol
8720
+ // // (like in "myFunction()"). It is a safety valve to prevent
8721
+ // // incorrect "use before definition" warnings.
8722
+ // //
8723
+ // // Example code triggering this preaction:
8724
+ // // my_function();
8725
+ //
8726
+ // // Step 1: Find out what is being called.
8727
+ // // If the code is "foo()", "left" gets the "foo" part.
8728
+ // //
8729
+ // // Code representation:
8730
+ // // left === token_foo;
8731
+ //
8732
+ // const left = thing.expression[0];
8733
+ // let left_variable;
8734
+ // let parent;
8735
+ //
8736
+ // // Step 2: Make sure we are calling a named thing (an identifier),
8737
+ // // and check that this thing is NOT defined locally inside the
8738
+ // // active function. We also make sure the active function
8739
+ // // actually has a name.
8740
+ // //
8741
+ // // Code structure matched here:
8742
+ // // function active_function() {
8743
+ // // foo(); // "foo" is not defined inside active_function
8744
+ // // }
8745
+ //
8746
+ // if (
8747
+ // left.identifier
8748
+ // && functionage.context[left.id] === undefined
8749
+ // && typeof functionage.name === "object"
8750
+ // ) {
8751
+ //
8752
+ // // Step 3: Find the outer function (the parent) that
8753
+ // // wraps our current function.
8754
+ // //
8755
+ // // Code structure matched here:
8756
+ // // function outer_parent() {
8757
+ // // function active_function() { ... }
8758
+ // // }
8759
+ //
8760
+ // parent = functionage.name.parent;
8761
+ // if (parent) {
8762
+ //
8763
+ // // Step 4: Look up the variable we are calling ("foo")
8764
+ // // inside that parent function.
8765
+ // //
8766
+ // // Code structure matched here:
8767
+ // // function outer_parent() {
8768
+ // // function foo() {} // Defined in the parent scope
8769
+ // // function active_function() { foo(); }
8770
+ // // }
8771
+ //
8772
+ // left_variable = parent.context[left.id];
8773
+ //
8774
+ // // Step 5: Check if we need to temporarily "bring it
8775
+ // // back to life".
8776
+ // // We verify it was found in the parent scope, is currently marked
8777
+ // // as "dead", belongs to this parent, and has a registered call from
8778
+ // // our active function. If so, we revive it!
8779
+ // //
8780
+ // // Code structure matched here (Mutual Recursion):
8781
+ // // function outer_parent() {
8782
+ // // function active_function() {
8783
+ // // foo(); // "foo" is forward-referenced & currently dead
8784
+ // // }
8785
+ // // function foo() {
8786
+ // // active_function();
8787
+ // // }
8788
+ // // }
8789
+ //
8790
+ // if (
8791
+ // left_variable !== undefined
8792
+ // // Probably deadcode.
8793
+ // // && left_variable.dead
8794
+ // && left_variable.parent === parent
8795
+ // && left_variable.calls !== undefined
8796
+ // && left_variable.calls[functionage.name.id] !== undefined
8797
+ // ) {
8798
+ //
8799
+ // // If all those match, revive it! Mark "dead" as
8800
+ // // false so JSLint won't raise an error for
8801
+ // // calling it before its line is executed.
8802
+ //
8803
+ // left_variable.dead = false;
8804
+ // }
8805
+ // }
8806
+ // }
8807
+ // }
8434
8808
 
8435
8809
  function pre_b_noteq(thing) {
8436
8810
 
@@ -8455,8 +8829,11 @@ function jslint_phase4_walk(state) {
8455
8829
  function pre_s_for(thing) {
8456
8830
  let the_variable;
8457
8831
  if (thing.name !== undefined) {
8832
+
8833
+ // 7a. Mark not dead, the iterator variable, during for-loop-initialization.
8834
+
8458
8835
  thing.name.dead = false;
8459
- the_variable = lookup(thing.name);
8836
+ the_variable = name_lookup(thing.name, true);
8460
8837
  if (the_variable !== undefined) {
8461
8838
  if (the_variable.init && the_variable.readonly) {
8462
8839
 
@@ -8465,7 +8842,6 @@ function jslint_phase4_walk(state) {
8465
8842
 
8466
8843
  warn("bad_assignment_a", thing.name);
8467
8844
  }
8468
- the_variable.init = true;
8469
8845
  }
8470
8846
  }
8471
8847
 
@@ -8493,13 +8869,15 @@ function jslint_phase4_walk(state) {
8493
8869
  block_stack.push(blockage);
8494
8870
  functionage = thing;
8495
8871
  blockage = thing;
8496
- thing.live = [];
8872
+ thing.live_list = [];
8497
8873
  if (typeof thing.name === "object") {
8874
+
8875
+ // 3a. Mark not dead, the function-name, in function-expression.
8876
+
8498
8877
  thing.name.dead = false;
8499
- thing.name.init = true;
8500
8878
  }
8501
8879
  if (thing.extra === "get") {
8502
- if (thing.parameters.length !== 0) {
8880
+ if (thing.parameter_count !== 0) {
8503
8881
 
8504
8882
  // test_cause:
8505
8883
  // ["
@@ -8510,7 +8888,7 @@ function jslint_phase4_walk(state) {
8510
8888
  warn("bad_get", thing);
8511
8889
  }
8512
8890
  } else if (thing.extra === "set") {
8513
- if (thing.parameters.length !== 1) {
8891
+ if (thing.parameter_count !== 1) {
8514
8892
 
8515
8893
  // test_cause:
8516
8894
  // ["
@@ -8521,21 +8899,33 @@ function jslint_phase4_walk(state) {
8521
8899
  warn("bad_set", thing);
8522
8900
  }
8523
8901
  }
8524
- thing.parameters.forEach(function (name) {
8525
- walk_expression(name.expression);
8526
- if (name.id === "{" || name.id === "[") {
8527
- name.names.forEach(subactivate);
8902
+ thing.name_list.forEach(function (name) {
8903
+ if (name.expression) {
8904
+
8905
+ // test_cause:
8906
+ // ["(aa=0)=>0", "pre_s_function", "(aa=0)=>0", "", 0]
8907
+
8908
+ test_cause("(aa=0)=>0");
8528
8909
  } else {
8529
- name.dead = false;
8530
- name.init = true;
8910
+
8911
+ // test_cause:
8912
+ // ["(aa)=>0", "pre_s_function", "(aa)=>0", "", 0]
8913
+ // ["aa=>0", "pre_s_function", "(aa)=>0", "", 0]
8914
+
8915
+ test_cause("(aa)=>0");
8531
8916
  }
8917
+ walk_expression(name.expression);
8918
+
8919
+ // 8a. Mark not dead, the function-parameter, after destructuring.
8920
+
8921
+ name.dead = false;
8532
8922
  });
8533
8923
  }
8534
8924
 
8535
8925
  function pre_s_lbrace(thing) {
8536
8926
  block_stack.push(blockage);
8537
8927
  blockage = thing;
8538
- thing.live = [];
8928
+ thing.live_list = [];
8539
8929
  }
8540
8930
 
8541
8931
  function pre_try(thing) {
@@ -8549,19 +8939,13 @@ function jslint_phase4_walk(state) {
8549
8939
  }
8550
8940
 
8551
8941
  function pre_v(thing) {
8552
- const the_variable = lookup(thing);
8942
+ const the_variable = name_lookup(thing, false);
8553
8943
  if (the_variable !== undefined) {
8554
8944
  thing.variable = the_variable;
8555
8945
  the_variable.used += 1;
8556
8946
  }
8557
8947
  }
8558
8948
 
8559
- function subactivate(name) {
8560
- name.init = true;
8561
- name.dead = false;
8562
- blockage.live.push(name);
8563
- }
8564
-
8565
8949
  function walk_expression(thing) {
8566
8950
  if (thing) {
8567
8951
  if (Array.isArray(thing)) {
@@ -8681,21 +9065,25 @@ function jslint_phase4_walk(state) {
8681
9065
  postaction("binary", "||", post_b_or);
8682
9066
  postaction("binary", post_b);
8683
9067
  postaction("statement", "const", post_s_var);
8684
- postaction("statement", "export", post_s_export);
9068
+ postaction("statement", "export", post_s_export_toplevel);
8685
9069
  postaction("statement", "for", post_s_for);
8686
9070
  postaction("statement", "function", post_s_function);
8687
9071
  postaction("statement", "import", post_s_import);
8688
9072
  postaction("statement", "let", post_s_var);
8689
9073
  postaction("statement", "try", post_s_try);
8690
9074
  postaction("statement", "var", post_s_var);
8691
- postaction("statement", "{", post_s_lbrace);
9075
+ postaction("statement", "{", post_s_lbrace_pop_block);
8692
9076
  postaction("ternary", post_t);
8693
9077
  postaction("unary", "+", post_u_plus);
8694
9078
  postaction("unary", "function", post_s_function);
8695
9079
  postaction("unary", post_u);
8696
9080
  preaction("assignment", pre_a_bitwise);
8697
9081
  preaction("binary", "!=", pre_b_noteq);
8698
- preaction("binary", "(", pre_b_lparen);
9082
+
9083
+ // PR-xxx - Probably deadcode.
9084
+
9085
+ // preaction("binary", "(", pre_b_lparen);
9086
+
8699
9087
  preaction("binary", "==", pre_b_eqeq);
8700
9088
  preaction("binary", "=>", pre_s_function);
8701
9089
  preaction("binary", "in", pre_b_in);
@@ -8752,6 +9140,8 @@ function jslint_phase5_whitage(state) {
8752
9140
  // "switch(){}"
8753
9141
  // "while(){}"
8754
9142
 
9143
+ let indent_method_dict = empty();
9144
+ let indentage;
8755
9145
  let left = token_global;
8756
9146
  let margin = 0;
8757
9147
  let mode_indent = (
@@ -8770,9 +9160,19 @@ function jslint_phase5_whitage(state) {
8770
9160
  // This is the set of infix operators that require a space on each side.
8771
9161
 
8772
9162
  let spaceop = object_assign_from_list(empty(), [
8773
- "!=", "!==", "%", "%=", "&", "&&", "&=", "*", "*=", "+=", "-=", "/",
8774
- "/=", "<", "<<", "<<=", "<=", "=", "==", "===", "=>", ">", ">=", ">>",
8775
- ">>=", ">>>", ">>>=", "^", "^=", "|", "|=", "||"
9163
+ "!=", "!==",
9164
+ "%", "%=",
9165
+ "&", "&&", "&&=", "&=",
9166
+ "*", "*=",
9167
+ "+=",
9168
+ "-=",
9169
+ "/", "/=",
9170
+ "<", "<<", "<<=", "<=",
9171
+ "=", "==", "===", "=>",
9172
+ ">", ">=", ">>", ">>=", ">>>", ">>>=",
9173
+ "??", "??=",
9174
+ "^", "^=",
9175
+ "|", "|=", "||", "||="
8776
9176
  ], true);
8777
9177
 
8778
9178
  function at_margin(fit) {
@@ -8791,24 +9191,11 @@ function jslint_phase5_whitage(state) {
8791
9191
  // ["function aa(aa) {return aa;}", "delve", "id", "", 0]
8792
9192
 
8793
9193
  test_cause("id");
8794
- if (
8795
- name.used === 0
8796
-
8797
- // Probably deadcode.
8798
- // && (
8799
- // name.role !== "function"
8800
- // || name.parent.arity !== "unary"
8801
- // )
8802
-
8803
- && jslint_assert(
8804
- name.role !== "function",
8805
- `Expected name.role !== "function".`
8806
- )
8807
- ) {
9194
+ if (!name.used) {
8808
9195
 
8809
9196
  // test_cause:
8810
9197
  // ["/*jslint node*/\nlet aa;", "delve", "unused_a", "aa", 5]
8811
- // ["function aa(aa){return;}", "delve", "unused_a", "aa", 13]
9198
+ // ["function aa(bb){return;}", "delve", "unused_a", "bb", 13]
8812
9199
  // ["let aa=0;try{aa();}catch(bb){aa();}", "delve", "unused_a", "bb", 26]
8813
9200
 
8814
9201
  warn("unused_a", name);
@@ -8946,148 +9333,106 @@ function jslint_phase5_whitage(state) {
8946
9333
  }
8947
9334
  }
8948
9335
 
8949
- function pop() {
8950
- const previous = function_stack.pop();
8951
- closer = previous.closer;
8952
- free = previous.free;
8953
- margin = previous.margin;
8954
- open = previous.open;
8955
- opening = previous.opening;
8956
- }
8957
-
8958
- function push() {
8959
- function_stack.push({
8960
- closer,
8961
- free,
8962
- margin,
8963
- open,
8964
- opening
8965
- });
8966
- }
8967
-
8968
- // uninitialized_and_unused();
8969
- // Delve into the functions looking for variables that were not initialized
8970
- // or used. If the file imports or exports, then its global object is also
8971
- // delved.
8972
-
8973
- if (state.mode_module === true || option_dict.node) {
8974
- delve(token_global);
8975
- }
8976
- catch_list.forEach(delve);
8977
- function_list.forEach(delve);
8978
-
8979
- if (option_dict.white) {
8980
- return;
8981
- }
8982
-
8983
- // whitage();
8984
- // Go through the token list, looking at usage of whitespace.
8985
-
8986
- token_list.forEach(function whitage(the_token) {
8987
- right = the_token;
8988
- if (right.id === "(comment)" || right.id === "(end)") {
8989
- nr_comments_skipped += 1;
8990
- } else {
8991
-
8992
- // If left is an opener and right is not the closer, then push the previous
8993
- // state. If the token following the opener is on the next line, then this is
8994
- // an open form. If the tokens are on the same line, then it is a closed form.
8995
- // Open form is more readable, with each item (statement, argument, parameter,
8996
- // etc) starting on its own line. Closed form is more compact. Statement blocks
8997
- // are always in open form.
8998
-
8999
- // The open and close pairs.
9000
-
9001
- switch (left.id) {
9002
- case "${":
9003
- case "(":
9004
- case "[":
9005
- case "{":
9336
+ function whitage_case() {
9006
9337
 
9007
9338
  // test_cause:
9008
- // ["let aa=[];", "whitage", "opener", "", 0]
9009
- // ["let aa=`${0}`;", "whitage", "opener", "", 0]
9010
- // ["let aa=aa();", "whitage", "opener", "", 0]
9011
- // ["let aa={};", "whitage", "opener", "", 0]
9339
+ // ["let aa=[];", "whitage_case", "opener", "", 0]
9340
+ // ["let aa=`${0}`;", "whitage_case", "opener", "", 0]
9341
+ // ["let aa=aa();", "whitage_case", "opener", "", 0]
9342
+ // ["let aa={};", "whitage_case", "opener", "", 0]
9012
9343
 
9013
- test_cause("opener");
9344
+ test_cause("opener");
9014
9345
 
9015
9346
  // Probably deadcode.
9016
9347
  // case "${}":
9017
9348
 
9018
- jslint_assert(
9019
- !(left.id + right.id === "${}"),
9020
- "Expected !(left.id + right.id === \"${}\")."
9021
- );
9022
- switch (left.id + right.id) {
9023
- case "()":
9024
- case "[]":
9025
- case "{}":
9349
+ jslint_assert(
9350
+ !(left.id + right.id === "${}"),
9351
+ "Expected !(left.id + right.id === \"${}\")."
9352
+ );
9353
+ switch (left.id + right.id) {
9354
+ case "()":
9355
+ case "[]":
9356
+ case "{}":
9026
9357
 
9027
9358
  // If left and right are opener and closer, then the placement of right depends
9028
9359
  // on the openness. Illegal pairs (like '{]') have already been detected.
9029
9360
 
9030
9361
  // test_cause:
9031
- // ["let aa=[];", "whitage", "opener_closer", "", 0]
9032
- // ["let aa=aa();", "whitage", "opener_closer", "", 0]
9033
- // ["let aa={};", "whitage", "opener_closer", "", 0]
9362
+ // ["let aa=[];", "whitage_case", "opener_closer", "", 0]
9363
+ // ["let aa=aa();", "whitage_case", "opener_closer", "", 0]
9364
+ // ["let aa={};", "whitage_case", "opener_closer", "", 0]
9034
9365
 
9035
- test_cause("opener_closer");
9036
- if (left.line === right.line) {
9366
+ test_cause("opener_closer");
9367
+ if (left.line === right.line) {
9037
9368
 
9038
9369
  // test_cause:
9039
9370
  // ["let aa = aa( );", "no_space", "unexpected_space_a_b", ")", 14]
9040
9371
 
9041
- no_space();
9042
- } else {
9372
+ no_space();
9373
+ } else {
9043
9374
 
9044
9375
  // test_cause:
9045
9376
  // ["let aa = aa(\n );", "expected_at", "expected_a_at_b_c", "1", 2]
9046
9377
 
9047
- at_margin(0);
9048
- }
9049
- break;
9050
- default:
9378
+ at_margin(0);
9379
+ }
9380
+ break;
9381
+ default:
9051
9382
 
9052
9383
  // test_cause:
9053
- // ["let aa=(0);", "whitage", "opener_operand", "", 0]
9054
- // ["let aa=[0];", "whitage", "opener_operand", "", 0]
9055
- // ["let aa=`${0}`;", "whitage", "opener_operand", "", 0]
9056
- // ["let aa=aa(0);", "whitage", "opener_operand", "", 0]
9057
- // ["let aa={aa:0};", "whitage", "opener_operand", "", 0]
9058
-
9059
- test_cause("opener_operand");
9060
- opening = left.open || (left.line !== right.line);
9061
- push();
9062
- switch (left.id) {
9063
- case "${":
9064
- closer = "}";
9065
- break;
9066
- case "(":
9067
- closer = ")";
9068
- break;
9069
- case "[":
9070
- closer = "]";
9071
- break;
9072
- case "{":
9073
- closer = "}";
9074
- break;
9075
- }
9076
- if (opening) {
9384
+ // ["let aa=(0);", "whitage_case", "opener_operand", "", 0]
9385
+ // ["let aa=[0];", "whitage_case", "opener_operand", "", 0]
9386
+ // ["let aa=`${0}`;", "whitage_case", "opener_operand", "", 0]
9387
+ // ["let aa=aa(0);", "whitage_case", "opener_operand", "", 0]
9388
+ // ["let aa={aa:0};", "whitage_case", "opener_operand", "", 0]
9389
+
9390
+ test_cause("opener_operand");
9391
+ opening = left.open || (left.line !== right.line);
9392
+ indentage = {
9393
+ closer,
9394
+ free,
9395
+ margin,
9396
+ open,
9397
+ opening
9398
+ };
9399
+ function_stack.push(indentage);
9400
+ switch (left.id) {
9401
+ case "${":
9402
+ closer = "}";
9403
+ break;
9404
+ case "(":
9405
+ closer = ")";
9406
+ break;
9407
+ case "[":
9408
+ closer = "]";
9409
+ break;
9410
+ case "{":
9411
+ closer = "}";
9412
+ break;
9413
+ }
9414
+ if (opening) {
9077
9415
 
9078
9416
  // test_cause:
9079
- // ["function aa(){\nreturn;\n}", "whitage", "opening", "", 0]
9080
- // ["let aa=(\n0\n);", "whitage", "opening", "", 0]
9081
- // ["let aa=[\n0\n];", "whitage", "opening", "", 0]
9082
- // ["let aa=`${\n0\n}`;", "whitage", "opening", "", 0]
9083
- // ["let aa={\naa:0\n};", "whitage", "opening", "", 0]
9417
+ // ["function aa(){\nreturn;\n}", "whitage_case", "opening", "", 0]
9418
+ // ["let aa=(\n0\n);", "whitage_case", "opening", "", 0]
9419
+ // ["let aa=[\n0\n];", "whitage_case", "opening", "", 0]
9420
+ // ["let aa=`${\n0\n}`;", "whitage_case", "opening", "", 0]
9421
+ // ["let aa={\naa:0\n};", "whitage_case", "opening", "", 0]
9084
9422
 
9085
- test_cause("opening");
9086
- free = closer === ")" && left.free;
9087
- open = true;
9088
- margin += mode_indent;
9089
- if (right.role === "label") {
9090
- if (right.from !== 0) {
9423
+ test_cause("opening");
9424
+ free = closer === ")" && left.free;
9425
+ open = true;
9426
+ margin += mode_indent;
9427
+ if (indent_method_dict[left.line]) {
9428
+
9429
+ // PR-498 - Relax warning on multiline-method-chaining.
9430
+
9431
+ margin += mode_indent;
9432
+ indentage.indent_method = true;
9433
+ }
9434
+ if (right.role === "label") {
9435
+ if (right.from !== 0) {
9091
9436
 
9092
9437
  // test_cause:
9093
9438
  // ["
@@ -9101,15 +9446,16 @@ function jslint_phase5_whitage(state) {
9101
9446
  // }
9102
9447
  // ", "expected_at", "expected_a_at_b_c", "1", 2]
9103
9448
 
9104
- expected_at(0);
9105
- }
9106
- } else if (right.switch) {
9107
- at_margin(-mode_indent);
9108
- } else {
9109
- at_margin(0);
9110
- }
9111
- } else {
9112
- if (right.statement || right.role === "label") {
9449
+ expected_at(0);
9450
+ }
9451
+ } else if (right.switch) {
9452
+ at_margin(-mode_indent);
9453
+ } else {
9454
+ at_margin(0);
9455
+ }
9456
+ break;
9457
+ }
9458
+ if (right.statement || right.role === "label") {
9113
9459
 
9114
9460
  // test_cause:
9115
9461
  // ["
@@ -9118,36 +9464,36 @@ function jslint_phase5_whitage(state) {
9118
9464
  // aa();
9119
9465
  // }
9120
9466
  // }
9121
- // ", "whitage", "expected_line_break_a_b", "bb", 16]
9467
+ // ", "whitage_case", "expected_line_break_a_b", "bb", 16]
9122
9468
 
9123
- warn(
9124
- "expected_line_break_a_b",
9125
- right,
9126
- artifact(left),
9127
- artifact(right)
9128
- );
9129
- }
9469
+ warn(
9470
+ "expected_line_break_a_b",
9471
+ right,
9472
+ artifact(left),
9473
+ artifact(right)
9474
+ );
9475
+ }
9130
9476
 
9131
9477
  // test_cause:
9132
- // ["let aa=(0);", "whitage", "not_free", "", 0]
9133
- // ["let aa=[0];", "whitage", "not_free", "", 0]
9134
- // ["let aa=`${0}`;", "whitage", "not_free", "", 0]
9135
- // ["let aa={aa:0};", "whitage", "not_free", "", 0]
9478
+ // ["let aa=(0);", "whitage_case", "not_free", "", 0]
9479
+ // ["let aa=[0];", "whitage_case", "not_free", "", 0]
9480
+ // ["let aa=`${0}`;", "whitage_case", "not_free", "", 0]
9481
+ // ["let aa={aa:0};", "whitage_case", "not_free", "", 0]
9136
9482
 
9137
- test_cause("not_free");
9138
- free = false;
9139
- open = false;
9483
+ test_cause("not_free");
9484
+ free = false;
9485
+ open = false;
9140
9486
 
9141
9487
  // test_cause:
9142
9488
  // ["let aa = ( 0 );", "no_space_only", "unexpected_space_a_b", "0", 12]
9143
9489
 
9144
- no_space_only();
9145
- }
9146
- }
9147
- break;
9148
- default:
9149
- if (right.statement === true) {
9150
- if (left.id === "else") {
9490
+ no_space_only();
9491
+ }
9492
+ }
9493
+
9494
+ function whitage_default() {
9495
+ if (right.statement === true) {
9496
+ if (left.id === "else") {
9151
9497
 
9152
9498
  // test_cause:
9153
9499
  // ["
@@ -9159,26 +9505,41 @@ function jslint_phase5_whitage(state) {
9159
9505
  // }
9160
9506
  // ", "one_space_only", "expected_space_a_b", "if", 9]
9161
9507
 
9162
- one_space_only();
9163
- } else {
9508
+ one_space_only();
9509
+ } else {
9164
9510
 
9165
9511
  // test_cause:
9166
9512
  // [" let aa = 0;", "expected_at", "expected_a_at_b_c", "1", 2]
9167
9513
 
9168
- at_margin(0);
9169
- open = false;
9170
- }
9514
+ at_margin(0);
9515
+ open = false;
9516
+ }
9517
+ return;
9518
+ }
9171
9519
 
9172
9520
  // If right is a closer, then pop the previous state.
9173
9521
 
9174
- } else if (right.id === closer) {
9175
- pop();
9176
- if (opening && right.id !== ";") {
9177
- at_margin(0);
9178
- } else {
9179
- no_space_only();
9180
- }
9181
- } else {
9522
+ if (right.id === closer) {
9523
+ indentage = function_stack.pop();
9524
+ closer = indentage.closer;
9525
+ free = indentage.free;
9526
+ margin = indentage.margin;
9527
+ open = indentage.open;
9528
+ opening = indentage.opening;
9529
+ if (opening && right.id !== ";") {
9530
+ at_margin(
9531
+ indentage.indent_method
9532
+
9533
+ // PR-498 - Relax warning on multiline-method-chaining.
9534
+
9535
+ ? mode_indent
9536
+ : 0
9537
+ );
9538
+ } else {
9539
+ no_space_only();
9540
+ }
9541
+ return;
9542
+ }
9182
9543
 
9183
9544
  // Left is not an opener, and right is not a closer.
9184
9545
  // The nature of left and right will determine the space between them.
@@ -9186,10 +9547,12 @@ function jslint_phase5_whitage(state) {
9186
9547
  // If left is ',' or ';' or right is a statement then if open,
9187
9548
  // right must go at the margin, or if closed, a space between.
9188
9549
 
9189
- if (right.switch) {
9190
- at_margin(-mode_indent);
9191
- } else if (right.role === "label") {
9192
- if (right.from !== 0) {
9550
+ if (right.switch) {
9551
+ at_margin(-mode_indent);
9552
+ return;
9553
+ }
9554
+ if (right.role === "label") {
9555
+ if (right.from !== 0) {
9193
9556
 
9194
9557
  // test_cause:
9195
9558
  // ["
@@ -9203,19 +9566,21 @@ function jslint_phase5_whitage(state) {
9203
9566
  // }
9204
9567
  // ", "expected_at", "expected_a_at_b_c", "1", 10]
9205
9568
 
9206
- expected_at(0);
9207
- }
9208
- } else if (left.id === ",") {
9209
- if (!open || (
9210
- (free || closer === "]")
9211
- && left.line === right.line
9212
- )) {
9569
+ expected_at(0);
9570
+ }
9571
+ return;
9572
+ }
9573
+ if (left.id === ",") {
9574
+ if (!open || (
9575
+ (free || closer === "]")
9576
+ && left.line === right.line
9577
+ )) {
9213
9578
 
9214
9579
  // test_cause:
9215
- // ["let {aa,bb} = 0;", "one_space", "expected_space_a_b", "bb", 9]
9580
+ // ["let{aa,bb} = 0;", "one_space", "expected_space_a_b", "bb", 8]
9216
9581
 
9217
- one_space();
9218
- } else {
9582
+ one_space();
9583
+ } else {
9219
9584
 
9220
9585
  // test_cause:
9221
9586
  // ["
@@ -9226,13 +9591,15 @@ function jslint_phase5_whitage(state) {
9226
9591
  // }
9227
9592
  // ", "expected_at", "expected_a_at_b_c", "9", 11]
9228
9593
 
9229
- at_margin(0);
9230
- }
9594
+ at_margin(0);
9595
+ }
9596
+ return;
9597
+ }
9231
9598
 
9232
9599
  // If right is a ternary operator, line it up on the margin.
9233
9600
 
9234
- } else if (right.arity === "ternary") {
9235
- if (open) {
9601
+ if (right.arity === "ternary") {
9602
+ if (open) {
9236
9603
 
9237
9604
  // test_cause:
9238
9605
  // ["
@@ -9243,48 +9610,68 @@ function jslint_phase5_whitage(state) {
9243
9610
  // );
9244
9611
  // ", "expected_at", "expected_a_at_b_c", "5", 1]
9245
9612
 
9246
- at_margin(0);
9247
- } else {
9613
+ at_margin(0);
9614
+ } else {
9248
9615
 
9249
9616
  // test_cause:
9250
- // ["let aa = (aa ? 0 : 1);", "whitage", "use_open", "?", 14]
9617
+ // ["let aa = (aa ? 0 : 1);", "whitage_default", "use_open", "?", 14]
9251
9618
 
9252
- warn("use_open", right);
9253
- }
9254
- } else if (
9255
- right.arity === "binary"
9256
- && right.id === "("
9257
- && free
9258
- ) {
9619
+ warn("use_open", right);
9620
+ }
9621
+ return;
9622
+ }
9623
+ if (
9624
+ right.arity === "binary"
9625
+ && right.id === "("
9626
+ && free
9627
+ ) {
9259
9628
 
9260
9629
  // test_cause:
9261
9630
  // ["let aa = aa(\naa ()\n);", "no_space", "unexpected_space_a_b", "(", 4]
9262
9631
 
9263
- no_space();
9264
- } else if (
9265
- left.id === "."
9266
- || left.id === "?."
9267
- || left.id === "..."
9268
- || right.id === ","
9269
- || right.id === ";"
9270
- || right.id === ":"
9271
- || (
9272
- right.arity === "binary"
9273
- && (right.id === "(" || right.id === "[")
9274
- )
9275
- || (
9276
- right.arity === "function"
9277
- && left.id !== "function"
9278
- )
9279
- || (right.id === "." || right.id === "?.")
9280
- ) {
9632
+ no_space();
9633
+ return;
9634
+ }
9635
+ if (
9636
+ left.id === "."
9637
+ || left.id === "?."
9638
+ || left.id === "..."
9639
+ || right.id === ","
9640
+ || right.id === ";"
9641
+ || right.id === ":"
9642
+ || (
9643
+ right.arity === "binary"
9644
+ && (right.id === "(" || right.id === "[")
9645
+ )
9646
+ || (
9647
+ right.arity === "function"
9648
+ && left.id !== "function"
9649
+ )
9650
+ ) {
9281
9651
 
9282
9652
  // test_cause:
9283
9653
  // ["let aa = 0 ;", "no_space_only", "unexpected_space_a_b", ";", 12]
9654
+
9655
+ no_space_only();
9656
+ return;
9657
+ }
9658
+ if (right.id === "." || right.id === "?.") {
9659
+ if (left.line === right.line) {
9660
+
9661
+ // test_cause:
9284
9662
  // ["let aa = aa ?.aa;", "no_space_only", "unexpected_space_a_b", "?.", 13]
9285
9663
 
9286
- no_space_only();
9287
- } else if (left.id === ";") {
9664
+ no_space_only();
9665
+ } else {
9666
+
9667
+ // PR-498 - Relax warning on multiline-method-chaining.
9668
+
9669
+ indent_method_dict[right.line] = true;
9670
+ at_margin(mode_indent);
9671
+ }
9672
+ return;
9673
+ }
9674
+ if (left.id === ";") {
9288
9675
 
9289
9676
  // test_cause:
9290
9677
  // ["
@@ -9300,23 +9687,25 @@ function jslint_phase5_whitage(state) {
9300
9687
  // }
9301
9688
  // ", "expected_at", "expected_a_at_b_c", "9", 1]
9302
9689
 
9303
- if (open) {
9304
- at_margin(0);
9305
- }
9306
- } else if (
9307
- left.arity === "ternary"
9308
- || left.id === "case"
9309
- || left.id === "catch"
9310
- || left.id === "else"
9311
- || left.id === "finally"
9312
- || left.id === "while"
9313
- || left.id === "await"
9314
- || right.id === "catch"
9315
- || right.id === "else"
9316
- || right.id === "finally"
9317
- || (right.id === "while" && !right.statement)
9318
- || (left.id === ")" && right.id === "{")
9319
- ) {
9690
+ if (open) {
9691
+ at_margin(0);
9692
+ }
9693
+ return;
9694
+ }
9695
+ if (
9696
+ left.arity === "ternary"
9697
+ || left.id === "case"
9698
+ || left.id === "catch"
9699
+ || left.id === "else"
9700
+ || left.id === "finally"
9701
+ || left.id === "while"
9702
+ || left.id === "await"
9703
+ || right.id === "catch"
9704
+ || right.id === "else"
9705
+ || right.id === "finally"
9706
+ || (right.id === "while" && !right.statement)
9707
+ || (left.id === ")" && right.id === "{")
9708
+ ) {
9320
9709
 
9321
9710
  // test_cause:
9322
9711
  // ["
@@ -9327,58 +9716,105 @@ function jslint_phase5_whitage(state) {
9327
9716
  // }
9328
9717
  // ", "one_space_only", "expected_space_a_b", "(", 12]
9329
9718
 
9330
- one_space_only();
9331
- } else if (
9719
+ one_space_only();
9720
+ return;
9721
+ }
9722
+ if (
9332
9723
 
9333
9724
  // There is a space between left and right.
9334
9725
 
9335
- spaceop[left.id] === true
9336
- || spaceop[right.id] === true
9337
- || (
9338
- left.arity === "binary"
9339
- && (left.id === "+" || left.id === "-")
9340
- )
9341
- || (
9342
- right.arity === "binary"
9343
- && (right.id === "+" || right.id === "-")
9344
- )
9345
- || left.id === "function"
9346
- || left.id === ":"
9347
- || left.id === "async"
9348
- || (
9349
- (
9350
- left.identifier
9351
- || left.id === "(string)"
9352
- || left.id === "(number)"
9353
- )
9354
- && (
9355
- right.identifier
9356
- || right.id === "(string)"
9357
- || right.id === "(number)"
9358
- )
9359
- )
9360
- || (left.arity === "statement" && right.id !== ";")
9361
- ) {
9726
+ spaceop[left.id] === true
9727
+ || spaceop[right.id] === true
9728
+ || (
9729
+ left.arity === "binary"
9730
+ && (left.id === "+" || left.id === "-")
9731
+ )
9732
+ || (
9733
+ right.arity === "binary"
9734
+ && (right.id === "+" || right.id === "-")
9735
+ )
9736
+ || left.id === "function"
9737
+ || left.id === ":"
9738
+ || left.id === "async"
9739
+ || (
9740
+ (
9741
+ left.identifier
9742
+ || left.id === "(string)"
9743
+ || left.id === "(number)"
9744
+ )
9745
+ && (
9746
+ right.identifier
9747
+ || right.id === "(string)"
9748
+ || right.id === "(number)"
9749
+ )
9750
+ )
9751
+ || (left.arity === "statement" && right.id !== ";")
9752
+ ) {
9362
9753
 
9363
9754
  // test_cause:
9364
9755
  // ["let aa=0;", "one_space", "expected_space_a_b", "0", 8]
9365
9756
  // ["let aa={\naa:\n0\n};", "expected_at", "expected_a_at_b_c", "5", 1]
9366
9757
 
9367
- one_space();
9368
- } else if (left.arity === "unary" && left.id !== "`") {
9369
- no_space_only();
9370
- }
9371
- }
9372
- }
9373
- nr_comments_skipped = 0;
9374
- delete left.calls;
9375
- delete left.dead;
9376
- delete left.free;
9377
- delete left.init;
9378
- delete left.open;
9379
- delete left.used;
9380
- left = right;
9758
+ one_space();
9759
+ return;
9760
+ }
9761
+ if (left.arity === "unary" && left.id !== "`") {
9762
+ no_space_only();
9763
+ return;
9764
+ }
9765
+ }
9766
+
9767
+ // uninitialized_and_unused();
9768
+ // Delve into the functions looking for variables that were not initialized
9769
+ // or used. If the file imports or exports, then its global object is also
9770
+ // delved.
9771
+
9772
+ // PR-xxx - tighten warning of unused variables to be always on.
9773
+
9774
+ delve(token_global);
9775
+ catch_list.forEach(delve);
9776
+ function_list.forEach(delve);
9777
+ if (option_dict.white) {
9778
+ return;
9779
+ }
9780
+
9781
+ // whitage();
9782
+ // Go through the token list, looking at usage of whitespace.
9783
+
9784
+ token_list.forEach(function (the_token) {
9785
+ right = the_token;
9786
+ if (right.id === "(comment)" || right.id === "(end)") {
9787
+ nr_comments_skipped += 1;
9788
+ return;
9381
9789
  }
9790
+
9791
+ // If left is an opener and right is not the closer, then push the previous
9792
+ // state. If the token following the opener is on the next line, then this is
9793
+ // an open form. If the tokens are on the same line, then it is a closed form.
9794
+ // Open form is more readable, with each item (statement, argument, parameter,
9795
+ // etc) starting on its own line. Closed form is more compact. Statement blocks
9796
+ // are always in open form.
9797
+
9798
+ // The open and close pairs.
9799
+
9800
+ switch (left.id) {
9801
+ case "${":
9802
+ case "(":
9803
+ case "[":
9804
+ case "{":
9805
+ whitage_case();
9806
+ break;
9807
+ default:
9808
+ whitage_default();
9809
+ }
9810
+ nr_comments_skipped = 0;
9811
+ delete left.calls;
9812
+ delete left.dead;
9813
+ delete left.free;
9814
+ delete left.init;
9815
+ delete left.open;
9816
+ delete left.used;
9817
+ left = right;
9382
9818
  });
9383
9819
  }
9384
9820
 
@@ -9420,10 +9856,10 @@ function jslint_report({
9420
9856
  // Google Lighthouse Accessibility - <dl>'s do not contain only properly-ordered
9421
9857
  // <dt> and <dd> groups, <script>, <template> or <div> elements.
9422
9858
 
9423
- "<dl>"
9424
- + "<dt>" + htmlEscape(title) + "</dt>"
9425
- + "<dd>" + list.join(", ") + "</dd>"
9426
- + "</dl>"
9859
+ "<dl>" +
9860
+ "<dt>" + htmlEscape(title) + "</dt>" +
9861
+ "<dd>" + list.map(htmlEscape).join(", ") + "</dd>" +
9862
+ "</dl>"
9427
9863
  )
9428
9864
  : ""
9429
9865
  );
@@ -9905,14 +10341,10 @@ pyNj+JctcQLXenBOCms46aMkenIx45WpXqxxVJQLz/vgpmAVa0fmDv6Pue9xVTBPfVxCUGfj\
9905
10341
  level,
9906
10342
  line,
9907
10343
  name,
9908
-
9909
- // Bugfix - fix html-report from crashing if parameters is undefined.
9910
-
9911
- parameters = [],
10344
+ name_list = [],
9912
10345
  signature
9913
10346
  } = the_function;
9914
10347
  let list = Object.keys(context);
9915
- let params;
9916
10348
  html += (
9917
10349
  "<div class=\"level level" + htmlEscape(level) + "\">"
9918
10350
  + address(line, from + 1)
@@ -9932,26 +10364,9 @@ pyNj+JctcQLXenBOCms46aMkenIx45WpXqxxVJQLz/vgpmAVa0fmDv6Pue9xVTBPfVxCUGfj\
9932
10364
  )
9933
10365
  + "</dfn>"
9934
10366
  );
9935
- params = [];
9936
- parameters.forEach(function extract({
9937
- id,
9938
- names
9939
- }) {
9940
- switch (id) {
9941
- case "[":
9942
- case "{":
9943
-
9944
- // Recurse extract().
9945
-
9946
- names.forEach(extract);
9947
- break;
9948
- case "ignore":
9949
- break;
9950
- default:
9951
- params.push(id);
9952
- }
9953
- });
9954
- html += detail("parameter", params.sort());
10367
+ html += detail("parameter", name_list.map(function ({id}) {
10368
+ return id;
10369
+ }).sort());
9955
10370
  list.sort();
9956
10371
  html += detail("variable", list.filter(function (id) {
9957
10372
  return (
@@ -11354,13 +11769,9 @@ function sentinel() {}
11354
11769
  // Coverage-hack - Ugly-hack to get test-coverage under both win32 and linux.
11355
11770
 
11356
11771
  if (processArgv0 === "npm") {
11357
- processArgv0 = process.platform.replace(
11358
- "win32",
11359
- "npm.cmd"
11360
- ).replace(
11361
- process.platform,
11362
- "npm"
11363
- );
11772
+ processArgv0 = process.platform
11773
+ .replace("win32", "npm.cmd")
11774
+ .replace(process.platform, "npm");
11364
11775
  }
11365
11776
  moduleChildProcess.spawn(
11366
11777
  processArgv0,