@jslint-org/jslint 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.
Files changed (4) hide show
  1. package/CHANGELOG.md +35 -4
  2. package/README.md +297 -177
  3. package/jslint.mjs +1546 -1154
  4. package/package.json +1 -1
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,
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
+ names,
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.6.30";
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(
@@ -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":
@@ -1479,13 +1742,10 @@ ${name}
1479
1742
  /(\([\S\s]*?\)) \{/
1480
1743
  ), function (match0, match1) {
1481
1744
  signature = htmlEscape(
1482
- match1.replace((
1483
- / *?\/\*[\S\s]*?\*\/ */g
1484
- ), "").replace((
1485
- / *?\/\/.*/g
1486
- ), "").replace((
1487
- /\n{2,}/g
1488
- ), "\n")
1745
+ match1
1746
+ .replace((/ *?\/\*[\S\s]*?\*\/ */g), "")
1747
+ .replace((/ *?\/\/.*/g), "")
1748
+ .replace((/\n{2,}/g), "\n")
1489
1749
  );
1490
1750
  return match0;
1491
1751
  });
@@ -2183,9 +2443,8 @@ function jslint_phase2_lex(state) {
2183
2443
  // ... literal.
2184
2444
  let mode_regexp; // true if regular expression literal seen on
2185
2445
  // ... 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.
2446
+ let opener_popped = empty(); // Last token popped from opener_stack.
2447
+ let opener_stack = []; // Stack of opener tokens: (, [.
2189
2448
  let snippet = ""; // A piece of string.
2190
2449
  let token_1; // The first token.
2191
2450
  let token_prv = token_global; // The previous token including
@@ -2279,7 +2538,13 @@ function jslint_phase2_lex(state) {
2279
2538
  // test_cause:
2280
2539
  // ["\"\\u{12345\"", "char_after_escape", "expected_a_before_b", "\"", 10]
2281
2540
 
2282
- stop_at("expected_a_before_b", line, column, "}", char);
2541
+ return stop_at(
2542
+ "expected_a_before_b",
2543
+ line,
2544
+ column,
2545
+ "}",
2546
+ char
2547
+ );
2283
2548
  }
2284
2549
  return char_after();
2285
2550
  }
@@ -2430,9 +2695,14 @@ function jslint_phase2_lex(state) {
2430
2695
 
2431
2696
  // Lex directives in comment.
2432
2697
 
2433
- [
2434
- the_comment.directive, body
2435
- ] = Array.from(snippet.match(jslint_rgx_directive) || []).slice(1);
2698
+ snippet.replace(jslint_rgx_directive, function (
2699
+ ignore,
2700
+ match1,
2701
+ match2
2702
+ ) {
2703
+ the_comment.directive = match1;
2704
+ body = match2;
2705
+ });
2436
2706
  if (the_comment.directive === undefined) {
2437
2707
  return the_comment;
2438
2708
  }
@@ -2825,14 +3095,55 @@ function jslint_phase2_lex(state) {
2825
3095
  case "?":
2826
3096
  char_after("?");
2827
3097
  switch (char) {
3098
+
3099
+ // ES1999-feature Negative lookahead assertion.
3100
+
2828
3101
  case "!":
2829
3102
 
2830
3103
  // PR-437 - Add grammar for regexp-named-capture-group.
2831
3104
 
2832
3105
  case "<":
3106
+
3107
+ // ES1999-feature Positive lookahead assertion.
3108
+
2833
3109
  case "=":
2834
3110
  char_after();
2835
3111
  break;
3112
+
3113
+ // PR-499 - Add ES2025-feature RegExp Modifiers.
3114
+
3115
+ case "-":
3116
+ case "i":
3117
+ case "m":
3118
+ case "s":
3119
+ char_after();
3120
+ while (true) {
3121
+ if (char === ":" && snippet.slice(-1) !== "-") {
3122
+ char_after();
3123
+ break;
3124
+ }
3125
+ switch (char) {
3126
+ case "-":
3127
+ case "i":
3128
+ case "m":
3129
+ case "s":
3130
+ char_after();
3131
+ break;
3132
+ default:
3133
+
3134
+ // test_cause:
3135
+ // ["aa=/(?-.", "lex_regexp_group", "unexpected_a_after_b", "(?-", 8]
3136
+
3137
+ return stop_at(
3138
+ "unexpected_a_after_b",
3139
+ line,
3140
+ column,
3141
+ snippet.slice(-1),
3142
+ snippet.slice(0, -1)
3143
+ );
3144
+ }
3145
+ }
3146
+ break;
2836
3147
  default:
2837
3148
  char_after(":");
2838
3149
  }
@@ -2993,14 +3304,29 @@ function jslint_phase2_lex(state) {
2993
3304
  // Process dangling flag letters.
2994
3305
 
2995
3306
  switch (!flag[char] && char) {
3307
+
3308
+ // PR-499 - Add ES2022-feature RegExp Match Indices.
3309
+
3310
+ case "d":
3311
+ break;
2996
3312
  case "g":
2997
3313
  break;
2998
3314
  case "i":
2999
3315
  break;
3000
3316
  case "m":
3001
3317
  break;
3318
+
3319
+ // PR-499 - Add ES2018-feature s (dotall) flag for regular expressions.
3320
+
3321
+ case "s":
3322
+ break;
3002
3323
  case "u":
3003
3324
  break;
3325
+
3326
+ // PR-499 - Add ES2024-feature RegExp v flag with set-notation + str-properties.
3327
+
3328
+ case "v":
3329
+ break;
3004
3330
  case "y":
3005
3331
 
3006
3332
  // test_cause:
@@ -3487,9 +3813,9 @@ import https from "https";
3487
3813
  });
3488
3814
  });
3489
3815
  result.replace((
3490
- /\n- \{\{JSxRef\("(?:Global_Objects\/)?([^"\/]+?)"/g
3816
+ /\n- \{\{jsxref\("(?:global_objects\/)?([^"]+?)"/ig
3491
3817
  ), function (ignore, key) {
3492
- if (globalThis.hasOwnProperty(key)) {
3818
+ if (Object.hasOwn(globalThis, key)) {
3493
3819
  dict[key] = true;
3494
3820
  }
3495
3821
  return "";
@@ -3513,6 +3839,7 @@ import https from "https";
3513
3839
  "Date",
3514
3840
  "Error",
3515
3841
  "EvalError",
3842
+ "Float16Array",
3516
3843
  "Float32Array",
3517
3844
  "Float64Array",
3518
3845
  "Function",
@@ -3534,10 +3861,12 @@ import https from "https";
3534
3861
  "Reflect",
3535
3862
  "RegExp",
3536
3863
  "Set",
3864
+ "ShadowRealm",
3537
3865
  "SharedArrayBuffer",
3538
3866
  "String",
3539
3867
  "Symbol",
3540
3868
  "SyntaxError",
3869
+ "Temporal",
3541
3870
  "TypeError",
3542
3871
  "URIError",
3543
3872
  "Uint16Array",
@@ -3545,6 +3874,7 @@ import https from "https";
3545
3874
  "Uint8Array",
3546
3875
  "Uint8ClampedArray",
3547
3876
  "WeakMap",
3877
+ "WeakRef",
3548
3878
  "WeakSet",
3549
3879
  "WebAssembly",
3550
3880
  "decodeURI",
@@ -3729,7 +4059,7 @@ import moduleHttps from "https";
3729
4059
  // test_cause:
3730
4060
  // ["/*jslint-enable*/", "read_line", "unopened_enable", "", 1]
3731
4061
 
3732
- stop_at("unopened_enable", line);
4062
+ return stop_at("unopened_enable", line);
3733
4063
  }
3734
4064
  line_disable = undefined;
3735
4065
  } else if (
@@ -3833,21 +4163,34 @@ import moduleHttps from "https";
3833
4163
 
3834
4164
  switch (id) {
3835
4165
  case "(":
3836
- paren_backtrack_list[paren_depth] = the_token;
3837
- paren_depth += 1;
4166
+ case "[":
4167
+ opener_stack.push(the_token);
3838
4168
  break;
3839
4169
  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;
4170
+ case "]":
4171
+ opener_popped = opener_stack.pop();
4172
+ if (noop(
4173
+ id === ")"
4174
+ ? opener_popped.id !== "("
4175
+ : opener_popped.id !== "["
4176
+ )) {
4177
+
4178
+ // test_cause:
4179
+ // [";(]", "token_create", "unexpected_a", "]", 3]
4180
+ // [";[)", "token_create", "unexpected_a", ")", 3]
4181
+
4182
+ return stop("unexpected_a", the_token);
3848
4183
  }
3849
4184
  break;
3850
4185
  }
4186
+ switch (token_prv_expr.id + " " + id) {
4187
+ case ") =>":
4188
+ opener_popped.fart = the_token;
4189
+ break;
4190
+ case "] =":
4191
+ opener_popped.assignment = the_token;
4192
+ break;
4193
+ }
3851
4194
 
3852
4195
  // The previous token is used to detect adjacency problems.
3853
4196
 
@@ -3938,6 +4281,7 @@ function jslint_phase3_parse(state) {
3938
4281
  // ... the parse.
3939
4282
  let token_nxt = token_global; // The next token to be examined in
3940
4283
  // ... <token_list>.
4284
+ let token_prv = token_global; // The previous token examined.
3941
4285
 
3942
4286
  function advance(id, match) {
3943
4287
 
@@ -3985,6 +4329,7 @@ function jslint_phase3_parse(state) {
3985
4329
 
3986
4330
  // Promote the tokens, skipping comments.
3987
4331
 
4332
+ token_prv = token_now;
3988
4333
  token_now = token_nxt;
3989
4334
  while (true) {
3990
4335
  token_nxt = token_list[token_ii];
@@ -4067,7 +4412,7 @@ function jslint_phase3_parse(state) {
4067
4412
  ) {
4068
4413
  token_nxt.statement = true;
4069
4414
  advance("(string)");
4070
- advance(";");
4415
+ semicolon();
4071
4416
  }
4072
4417
  stmts = parse_statements();
4073
4418
  the_block.block = stmts;
@@ -4162,13 +4507,20 @@ function jslint_phase3_parse(state) {
4162
4507
 
4163
4508
  // This function will warn if <token_list> is unordered.
4164
4509
 
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
- }, "");
4510
+ token_list
4511
+ .filter(function (token) {
4512
+
4513
+ // Issue #401 - Regression - Ignore tokens prefixed by ellipsis for sorting.
4514
+
4515
+ return token && !token.ellipsis;
4516
+ })
4517
+ .reduce(function (aa, token) {
4518
+ const bb = artifact(token);
4519
+ if (!option_dict.unordered && aa > bb) {
4520
+ warn("expected_a_b_before_c_d", token, type, bb, type, aa);
4521
+ }
4522
+ return bb;
4523
+ }, "");
4172
4524
  }
4173
4525
 
4174
4526
  function check_ordered_case(case_list) {
@@ -4527,7 +4879,7 @@ function jslint_phase3_parse(state) {
4527
4879
  the_symbol.led_infix = function (left) {
4528
4880
  const the_token = token_now;
4529
4881
  the_token.arity = "binary";
4530
- if (f !== undefined) {
4882
+ if (f) {
4531
4883
  return f(left);
4532
4884
  }
4533
4885
  the_token.expression = [left, parse_expression(bp)];
@@ -4542,17 +4894,39 @@ function jslint_phase3_parse(state) {
4542
4894
  if (
4543
4895
  (
4544
4896
  left.id !== "(string)"
4545
- || (name.id !== "indexOf" && name.id !== "repeat")
4897
+ || (
4898
+ name.id !== "at"
4899
+ && name.id !== "charCodeAt"
4900
+ && name.id !== "includes"
4901
+ && name.id !== "indexOf"
4902
+ && name.id !== "isWellFormed"
4903
+ && name.id !== "match"
4904
+ && name.id !== "repeat"
4905
+ && name.id !== "replace"
4906
+ && name.id !== "toLowerCase"
4907
+ && name.id !== "toUpperCase"
4908
+ && name.id !== "toWellFormed"
4909
+ )
4546
4910
  )
4547
4911
  && (
4548
4912
  left.id !== "["
4549
4913
  || (
4550
- name.id !== "concat"
4914
+ name.id !== "at"
4915
+ && name.id !== "concat"
4916
+ && name.id !== "every"
4917
+ && name.id !== "filter"
4918
+ && name.id !== "find"
4919
+ && name.id !== "findIndex"
4551
4920
  && name.id !== "flat"
4552
4921
  && name.id !== "flatMap"
4553
4922
  && name.id !== "forEach"
4923
+ && name.id !== "includes"
4554
4924
  && name.id !== "join"
4555
4925
  && name.id !== "map"
4926
+ && name.id !== "reduce"
4927
+ && name.id !== "some"
4928
+ && name.id !== "toReversed"
4929
+ && name.id !== "toSorted"
4556
4930
  )
4557
4931
  )
4558
4932
  && (left.id !== "+" || name.id !== "slice")
@@ -4563,16 +4937,36 @@ function jslint_phase3_parse(state) {
4563
4937
  ) {
4564
4938
 
4565
4939
  // test_cause:
4940
+ // ["(/./)?.0", "check_left", "unexpected_a", "?.", 6]
4566
4941
  // ["\"\".aa", "check_left", "unexpected_a", ".", 3]
4942
+ // ["\"aa\"?.0", "check_left", "unexpected_a", "?.", 5]
4943
+ // ["aa=[]?.aa", "check_left", "unexpected_a", "?.", 6]
4567
4944
 
4568
4945
  check_left(left, the_token);
4569
4946
  }
4947
+
4948
+ // Issue #468 - Fix optional dynamic-property/function-call not recognized.
4949
+
4950
+ if (
4951
+ the_token.id === "?."
4952
+ && (name.id === "[" || name.id === "(")
4953
+ ) {
4954
+
4955
+ // test_cause:
4956
+ // ["aa?.(bb)", "infix_dot", "dyn_prop_or_call", "", 0]
4957
+ // ["aa?.[bb]", "infix_dot", "dyn_prop_or_call", "", 0]
4958
+
4959
+ test_cause("dyn_prop_or_call");
4960
+ return left;
4961
+ }
4570
4962
  if (!name.identifier) {
4571
4963
 
4572
4964
  // test_cause:
4965
+ // ["(0+0)?.0", "infix_dot", "expected_identifier_a", "0", 8]
4573
4966
  // ["aa.0", "infix_dot", "expected_identifier_a", "0", 4]
4967
+ // ["aa?.0", "infix_dot", "expected_identifier_a", "0", 5]
4574
4968
 
4575
- stop("expected_identifier_a");
4969
+ return stop("expected_identifier_a", name);
4576
4970
  }
4577
4971
  advance();
4578
4972
  survey(name);
@@ -4585,11 +4979,7 @@ function jslint_phase3_parse(state) {
4585
4979
  }
4586
4980
 
4587
4981
  function infix_fart_unwrapped() {
4588
-
4589
- // test_cause:
4590
- // ["aa=>0", "infix_fart_unwrapped", "wrap_fart_parameter", "=>", 3]
4591
-
4592
- return stop("wrap_fart_parameter", token_now);
4982
+ return parse_fart(token_now, true);
4593
4983
  }
4594
4984
 
4595
4985
  function infix_grave(left) {
@@ -4632,7 +5022,6 @@ function jslint_phase3_parse(state) {
4632
5022
 
4633
5023
  function infix_lparen(left) {
4634
5024
  const the_paren = token_now;
4635
- let ellipsis;
4636
5025
  let the_argument;
4637
5026
  if (left.id !== "function") {
4638
5027
 
@@ -4652,12 +5041,14 @@ function jslint_phase3_parse(state) {
4652
5041
 
4653
5042
  while (true) {
4654
5043
  if (token_nxt.id === "...") {
4655
- ellipsis = true;
4656
- advance("...");
4657
- }
4658
- the_argument = parse_expression(10);
4659
- if (ellipsis) {
4660
- the_argument.ellipsis = true;
5044
+
5045
+ // test_cause:
5046
+ // ["aa(...aa)", "infix_lparen", "aa(...aa)", "", 0]
5047
+
5048
+ test_cause("aa(...aa)");
5049
+ the_argument = prefix_ellipsis();
5050
+ } else {
5051
+ the_argument = parse_expression(10);
4661
5052
  }
4662
5053
  the_paren.expression.push(the_argument);
4663
5054
  if (token_nxt.id !== ",") {
@@ -4702,71 +5093,6 @@ function jslint_phase3_parse(state) {
4702
5093
  return the_paren;
4703
5094
  }
4704
5095
 
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
- )
4722
-
4723
- // test_cause:
4724
- // ["(0+0)?.0", "infix_option_chain", "check_left", "", 0]
4725
-
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");
4733
-
4734
- // 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]
4738
-
4739
- check_left(left, the_token);
4740
- }
4741
-
4742
- // Issue #468 - Fix optional dynamic-property/function-call not recognized.
4743
-
4744
- if (name.id === "[" || name.id === "(") {
4745
- test_cause("dyn_prop_or_call");
4746
-
4747
- // test_cause:
4748
- // ["aa?.(bb)", "infix_option_chain", "dyn_prop_or_call", "", 0]
4749
- // ["aa?.[bb]", "infix_option_chain", "dyn_prop_or_call", "", 0]
4750
-
4751
- return left;
4752
- }
4753
- if (!name.identifier) {
4754
-
4755
- // test_cause:
4756
- // ["aa?.0", "infix_option_chain", "expected_identifier_a", "0", 5]
4757
-
4758
- stop("expected_identifier_a");
4759
- }
4760
- advance();
4761
- survey(name);
4762
-
4763
- // The property name is not an expression.
4764
-
4765
- the_token.name = name;
4766
- the_token.expression = left;
4767
- return the_token;
4768
- }
4769
-
4770
5096
  function infixr(bp, id) {
4771
5097
 
4772
5098
  // Create a right associative infix operator.
@@ -4800,7 +5126,10 @@ function jslint_phase3_parse(state) {
4800
5126
  // .led_infix Left denotation. The infix/postfix handler.
4801
5127
  // lbp Left binding power of infix operator. It tells us how strongly
4802
5128
  // the operator binds to the argument at its left.
4803
- // rbp Right binding power.
5129
+ // rbp Right binding power. Parser will continue consuming tokens while
5130
+ // next token's lbp > rbp.
5131
+ // initial Whether first token has already been advanced. If falsy,
5132
+ // immediately calls advance().
4804
5133
 
4805
5134
  // It processes a nud_prefix (variable, constant, prefix operator). It will then
4806
5135
  // process leds (infix operators) until the bind powers cause it to stop (it
@@ -4903,7 +5232,7 @@ function jslint_phase3_parse(state) {
4903
5232
  return left;
4904
5233
  }
4905
5234
 
4906
- function parse_fart(the_fart) {
5235
+ function parse_fart(the_fart, mode_infix) {
4907
5236
 
4908
5237
  // Give the function properties storing its names and for observing the depth
4909
5238
  // of loops and switches.
@@ -4934,11 +5263,34 @@ function jslint_phase3_parse(state) {
4934
5263
  function_list.push(the_fart);
4935
5264
  function_stack.push(functionage);
4936
5265
  functionage = the_fart;
5266
+ if (mode_infix) {
5267
+ if (!token_prv.identifier) {
5268
+
5269
+ // test_cause:
5270
+ // ["0=>0", "parse_fart", "expected_identifier_a", "0", 1]
5271
+
5272
+ return stop("expected_identifier_a", token_prv);
5273
+ }
5274
+
5275
+ // PR-499 - Update ES2015-feature arrow, to continue parsing unwrapped-form
5276
+ // with warning, instead of stopping.
5277
+
5278
+ // test_cause:
5279
+ // ["aa=>0", "parse_fart", "wrap_fart_parameter", "=>", 3]
5280
+
5281
+ warn("wrap_fart_parameter", token_now);
5282
+ the_fart.name = "anonymous";
5283
+ the_fart.names = [token_prv];
5284
+ the_fart.parameter_count = 1;
5285
+ the_fart.signature = token_prv.id;
5286
+ enroll(token_prv, "parameter", false);
5287
+ } else {
4937
5288
 
4938
5289
  // Parse the parameter list.
4939
5290
 
4940
- prefix_function_parameter(the_fart);
4941
- advance("=>");
5291
+ prefix_function_parameter(the_fart);
5292
+ advance("=>");
5293
+ }
4942
5294
 
4943
5295
  // The function's body is a block.
4944
5296
 
@@ -4951,21 +5303,28 @@ function jslint_phase3_parse(state) {
4951
5303
  warn("use_function_not_fart", the_fart);
4952
5304
  }
4953
5305
  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
- ) {
5306
+
5307
+ // The function's body is an expression.
5308
+
5309
+ } else {
4958
5310
 
4959
5311
  // PR-384 - Bugfix - Fixes issue #379 - warn against naked-statement in fart.
4960
5312
 
5313
+ if (
5314
+ syntax_dict[token_nxt.id] !== undefined
5315
+ && syntax_dict[token_nxt.id].fud_stmt !== undefined
5316
+ ) {
5317
+
4961
5318
  // test_cause:
4962
5319
  // ["()=>delete aa", "parse_fart", "unexpected_a_after_b", "=>", 5]
4963
5320
 
4964
- stop("unexpected_a_after_b", token_nxt, token_nxt.id, "=>");
4965
-
4966
- // The function's body is an expression.
4967
-
4968
- } else {
5321
+ return stop(
5322
+ "unexpected_a_after_b",
5323
+ token_nxt,
5324
+ token_nxt.id,
5325
+ "=>"
5326
+ );
5327
+ }
4969
5328
  the_fart.expression = parse_expression(0);
4970
5329
  }
4971
5330
 
@@ -4987,8 +5346,10 @@ function jslint_phase3_parse(state) {
4987
5346
  // test_cause:
4988
5347
  // ["[-.0]", "parse_json", "unexpected_a", ".", 3]
4989
5348
  // ["[-0x0]", "parse_json", "unexpected_a", "0x0", 3]
5349
+ // ["[...]", "parse_json", "unexpected_a", "...", 2]
4990
5350
  // ["[.0]", "parse_json", "unexpected_a", ".", 2]
4991
5351
  // ["[0x0]", "parse_json", "unexpected_a", "0x0", 2]
5352
+ // ["{...}", "parse_json", "unexpected_a", "...", 2]
4992
5353
 
4993
5354
  warn("unexpected_a");
4994
5355
  }
@@ -5029,11 +5390,6 @@ function jslint_phase3_parse(state) {
5029
5390
 
5030
5391
  container.expression.push(parse_json());
5031
5392
  if (token_nxt.id !== ",") {
5032
-
5033
- // test_cause:
5034
- // ["[0,0]", "parse_json", "comma", "", 0]
5035
-
5036
- test_cause("comma");
5037
5393
  break;
5038
5394
  }
5039
5395
  advance(",");
@@ -5122,7 +5478,7 @@ function jslint_phase3_parse(state) {
5122
5478
  // test_cause:
5123
5479
  // ["[undefined]", "parse_json", "unexpected_a", "undefined", 2]
5124
5480
 
5125
- stop("unexpected_a");
5481
+ return stop("unexpected_a");
5126
5482
  }
5127
5483
  }
5128
5484
 
@@ -5303,7 +5659,7 @@ function jslint_phase3_parse(state) {
5303
5659
  the_symbol.nud_prefix = function () {
5304
5660
  const the_token = token_now;
5305
5661
  the_token.arity = "unary";
5306
- if (typeof f === "function") {
5662
+ if (f) {
5307
5663
  return f();
5308
5664
  }
5309
5665
  the_token.expression = parse_expression(150);
@@ -5317,7 +5673,7 @@ function jslint_phase3_parse(state) {
5317
5673
  // test_cause:
5318
5674
  // ["/=", "prefix_assign_divide", "expected_a_b", "/=", 1]
5319
5675
 
5320
- stop("expected_a_b", token_now, "/\\=", "/=");
5676
+ return stop("expected_a_b", token_now, "/\\=", "/=");
5321
5677
  }
5322
5678
 
5323
5679
  function prefix_async() {
@@ -5389,44 +5745,273 @@ function jslint_phase3_parse(state) {
5389
5745
  return the_await;
5390
5746
  }
5391
5747
 
5392
- function prefix_fart() {
5748
+ function prefix_destructure(
5749
+ enroll,
5750
+ role,
5751
+ readonly,
5752
+ name_list,
5753
+ the_function,
5754
+ the_function_toplevel
5755
+ ) {
5756
+ const is_brace = token_now.id === "{";
5757
+ const sub_list = [];
5758
+ const the_destructure = token_now;
5759
+ let optional;
5760
+ function advance_and_signature_push(id) {
5761
+ advance(id);
5762
+ if (the_function?.signature) {
5763
+ the_function.signature.push(id);
5764
+ switch (id) {
5765
+ case ",":
5766
+ case ":":
5767
+ the_function.signature.push(" ");
5768
+ break;
5769
+ }
5770
+ }
5771
+ }
5772
+ function name_list_push(name) {
5773
+ sub_list.push(name);
5774
+
5775
+ // PR-500 - Fix false-warning "uninitialized_a" in statement ";[aa]=0;".
5776
+
5777
+ name.arity = role;
5778
+ if (enroll) {
5779
+ enroll(name, role, readonly);
5780
+ name.init = true;
5781
+ }
5782
+ }
5783
+ function name_parse() {
5784
+ let name = token_nxt;
5785
+ switch (name.id) {
5786
+ case "...":
5787
+ advance_and_signature_push("...");
5788
+ name = token_nxt;
5789
+ name.ellipsis = true;
5790
+ if (name.id === "...") {
5393
5791
 
5394
5792
  // test_cause:
5395
- // ["=>0", "prefix_fart", "expected_a_before_b", "=>", 1]
5793
+ // ["let[... ...]=0", "name_parse", "unexpected_a_after_b", "...", 9]
5396
5794
 
5397
- return stop("expected_a_before_b", token_now, "()", "=>");
5398
- }
5795
+ return stop("unexpected_a_after_b", name, name.id, "...");
5796
+ }
5797
+ if (optional) {
5399
5798
 
5400
- function prefix_function(the_function) {
5401
- let name = the_function && the_function.name;
5402
- if (the_function === undefined) {
5403
- the_function = token_now;
5799
+ // test_cause:
5800
+ // ["function aa(aa=0,...){}", "name_parse", "required_a_optional_b", "aa", 21]
5404
5801
 
5405
- // A function statement must have a name that will be in the parent's scope.
5802
+ warn("required_a_optional_b", name, name.id, optional.id);
5803
+ }
5406
5804
 
5407
- if (the_function.arity === "statement") {
5408
- if (!token_nxt.identifier) {
5805
+ // test_cause:
5806
+ // ["let[...aa]=0", "name_parse", "recurse_ellipsis", "", 0]
5807
+ // ["let{...aa}=0", "name_parse", "recurse_ellipsis", "", 0]
5808
+
5809
+ test_cause("recurse_ellipsis");
5810
+ name_parse();
5811
+ return true;
5812
+ case "[":
5813
+ case "{":
5814
+ if (the_function?.id === "=>" && !option_dict.fart) {
5409
5815
 
5410
5816
  // test_cause:
5411
- // ["function(){}", "prefix_function", "expected_identifier_a", "(", 9]
5412
- // ["function*aa(){}", "prefix_function", "expected_identifier_a", "*", 9]
5817
+ // ["([aa])=>0", "name_parse", "use_function_not_fart", "=>", 7]
5818
+ // ["({aa})=>0", "name_parse", "use_function_not_fart", "=>", 7]
5413
5819
 
5414
- return stop("expected_identifier_a");
5820
+ warn("use_function_not_fart", the_function);
5415
5821
  }
5416
- name = token_nxt;
5417
- enroll(name, "variable", true);
5418
- the_function.name = Object.assign(name, {
5419
- calls: empty(),
5822
+ if (optional) {
5420
5823
 
5421
- // PR-331 - Bugfix - Fixes issue #272 - function hoisting not allowed.
5824
+ // test_cause:
5825
+ // ["function aa(aa=0,[]){}", "name_parse", "required_a_optional_b", "aa", 18]
5826
+ // ["function aa(aa=0,{}){}", "name_parse", "required_a_optional_b", "aa", 18]
5422
5827
 
5423
- dead: false,
5424
- init: true
5425
- });
5426
- advance();
5427
- } else if (name === undefined) {
5828
+ warn("required_a_optional_b", name, name.id, optional.id);
5829
+ }
5428
5830
 
5429
- // A function expression may have an optional name.
5831
+ // test_cause:
5832
+ // ["let[[aa]]=0", "name_parse", "recurse_element", "", 0]
5833
+ // ["let[{aa}]=0", "name_parse", "recurse_element", "", 0]
5834
+
5835
+ test_cause("recurse_element");
5836
+ advance_and_signature_push(token_nxt.id);
5837
+ prefix_destructure(
5838
+ enroll, // enroll
5839
+ role, // role
5840
+ readonly, // readonly
5841
+ name_list, // name_list
5842
+ the_function, // the_function
5843
+ false // the_function_toplevel
5844
+ );
5845
+ return;
5846
+ }
5847
+ if (!name.identifier) {
5848
+
5849
+ // test_cause:
5850
+ // ["function aa(...0){}", "name_parse", "expected_identifier_a", "0", 16]
5851
+ // ["function aa(0){}", "name_parse", "expected_identifier_a", "0", 13]
5852
+ // ["function aa([0]){}", "name_parse", "expected_identifier_a", "0", 14]
5853
+ // ["function aa({0}){}", "name_parse", "expected_identifier_a", "0", 14]
5854
+ // ["function aa({aa:0}){}", "name_parse", "expected_identifier_a", "0", 17]
5855
+ // ["let[...0]=0", "name_parse", "expected_identifier_a", "0", 8]
5856
+ // ["let[0]=0", "name_parse", "expected_identifier_a", "0", 5]
5857
+ // ["let{0}=0", "name_parse", "expected_identifier_a", "0", 5]
5858
+
5859
+ return stop("expected_identifier_a", name);
5860
+ }
5861
+ if (is_brace) {
5862
+ survey(name);
5863
+ }
5864
+ advance_and_signature_push(token_nxt.id);
5865
+ if (is_brace && token_nxt.id === ":") {
5866
+ advance_and_signature_push(":");
5867
+ if (!the_function_toplevel) {
5868
+ the_destructure.open = true;
5869
+ }
5870
+ if (token_nxt.id === "...") {
5871
+
5872
+ // test_cause:
5873
+ // ["let{aa:...aa}=0", "name_parse", "unexpected_a", "...", 8]
5874
+
5875
+ return stop("unexpected_a", token_nxt);
5876
+ }
5877
+ if (!token_nxt.identifier) {
5878
+
5879
+ // test_cause:
5880
+ // ["let{aa:[aa]}=0", "name_parse", "recurse_property", "", 0]
5881
+ // ["let{aa:{aa}}=0", "name_parse", "recurse_property", "", 0]
5882
+
5883
+ test_cause("recurse_property");
5884
+ name_parse();
5885
+ return;
5886
+ }
5887
+ token_nxt.label = name;
5888
+ name = token_nxt;
5889
+ name_list_push(name);
5890
+ advance_and_signature_push(token_nxt.id);
5891
+ return;
5892
+ }
5893
+ name_list_push(name);
5894
+
5895
+ // test_cause:
5896
+ // ["const[aa]=bb;\nconst bb=0;", "lookup", "out_of_scope_a", "bb", 11]
5897
+ // ["const{aa}=bb;\nconst bb=0;", "lookup", "out_of_scope_a", "bb", 11]
5898
+
5899
+ if (token_nxt.id === "=") {
5900
+ optional = the_function_toplevel && token_now;
5901
+ advance_and_signature_push("=");
5902
+ if (!the_function_toplevel) {
5903
+ the_destructure.open = true;
5904
+ }
5905
+ name.expression = parse_expression(0);
5906
+
5907
+ // test_cause:
5908
+ // ["function aa([aa=aa]){}", "name_parse", "optional", "", 0]
5909
+ // ["function aa({aa=aa}){}", "name_parse", "optional", "", 0]
5910
+ // ["let[aa=0]=0", "name_parse", "optional", "", 0]
5911
+ // ["let{aa=0}=0", "name_parse", "optional", "", 0]
5912
+
5913
+ test_cause("optional");
5914
+ return;
5915
+ }
5916
+ if (optional) {
5917
+
5918
+ // test_cause:
5919
+ // ["function aa(aa=0,bb){}", "name_parse", "required_a_optional_b", "aa", 18]
5920
+
5921
+ warn("required_a_optional_b", name, name.id, optional.id);
5922
+ }
5923
+ }
5924
+ while (true) {
5925
+ if (!is_brace && !the_function_toplevel && token_nxt.id === ",") {
5926
+
5927
+ // test_cause:
5928
+ // ["(,aa)=>0", "name_parse", "expected_identifier_a", ",", 2]
5929
+ // ["([,aa])=>0", "prefix_destructure", "ignore", "", 0]
5930
+ // [";[,aa]=0", "prefix_destructure", "ignore", "", 0]
5931
+ // ["let[,aa]=0", "prefix_destructure", "ignore", "", 0]
5932
+
5933
+ test_cause("ignore");
5934
+ advance_and_signature_push(",");
5935
+ }
5936
+ if (the_function_toplevel) {
5937
+ the_function.parameter_count += 1;
5938
+ }
5939
+ if (name_parse()) {
5940
+
5941
+ // Break early from ellipsis.
5942
+
5943
+ break;
5944
+ }
5945
+ if (token_nxt.id !== ",") {
5946
+ break;
5947
+ }
5948
+ advance_and_signature_push(",");
5949
+ }
5950
+ name_list.push(...sub_list);
5951
+ if (the_function_toplevel) {
5952
+ advance_and_signature_push(")");
5953
+ } else if (is_brace) {
5954
+
5955
+ // test_cause:
5956
+ // ["
5957
+ // function aa({bb,aa}){}
5958
+ // ", "check_ordered", "expected_a_b_before_c_d", "aa", 17]
5959
+ // ["let{bb,aa}=0", "check_ordered", "expected_a_b_before_c_d", "aa", 8]
5960
+
5961
+ check_ordered(role, sub_list);
5962
+ advance_and_signature_push("}");
5963
+ } else {
5964
+ advance_and_signature_push("]");
5965
+ }
5966
+ return the_destructure;
5967
+ }
5968
+
5969
+ function prefix_ellipsis() {
5970
+ let after_ellipsis;
5971
+ advance("...");
5972
+ after_ellipsis = parse_expression(0);
5973
+ after_ellipsis.ellipsis = true;
5974
+ return after_ellipsis;
5975
+ }
5976
+
5977
+ function prefix_fart() {
5978
+
5979
+ // test_cause:
5980
+ // ["=>0", "prefix_fart", "expected_a_before_b", "=>", 1]
5981
+
5982
+ return stop("expected_a_before_b", token_now, "()", "=>");
5983
+ }
5984
+
5985
+ function prefix_function(the_function) {
5986
+ let name = the_function && the_function.name;
5987
+ if (the_function === undefined) {
5988
+ the_function = token_now;
5989
+
5990
+ // A function statement must have a name that will be in the parent's scope.
5991
+
5992
+ if (the_function.arity === "statement") {
5993
+ if (!token_nxt.identifier) {
5994
+
5995
+ // test_cause:
5996
+ // ["function(){}", "prefix_function", "expected_identifier_a", "(", 9]
5997
+ // ["function*aa(){}", "prefix_function", "expected_identifier_a", "*", 9]
5998
+
5999
+ return stop("expected_identifier_a", token_nxt);
6000
+ }
6001
+ name = token_nxt;
6002
+ enroll(name, "variable", true);
6003
+ the_function.name = Object.assign(name, {
6004
+ calls: empty(),
6005
+
6006
+ // PR-331 - Bugfix - Fixes issue #272 - function hoisting not allowed.
6007
+
6008
+ dead: false,
6009
+ init: true
6010
+ });
6011
+ advance();
6012
+ } else if (name === undefined) {
6013
+
6014
+ // A function expression may have an optional name.
5430
6015
 
5431
6016
  the_function.name = anon;
5432
6017
  if (token_nxt.identifier) {
@@ -5551,375 +6136,174 @@ function jslint_phase3_parse(state) {
5551
6136
 
5552
6137
  // This function will parse input <parameters> at beginning of <the_function>
5553
6138
 
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 {
5562
-
5563
- // 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
- }
6139
+ the_function.names = [];
6140
+ the_function.parameter_count = 0;
6141
+ the_function.signature = ["("];
6142
+ token_now.free = false;
6143
+ if (token_nxt.id !== ")" && token_nxt.id !== "(end)") {
5570
6144
 
5571
- // Recurse param_enroll().
6145
+ // PR-500 - Unify ES2015-destructure-logic. - function([aa]) {...}
5572
6146
 
5573
- name.names.forEach(param_enroll);
5574
- }
6147
+ prefix_destructure(
6148
+ enroll, // enroll
6149
+ "parameter", // role
6150
+ false, // readonly
6151
+ the_function.names, // name_list
6152
+ the_function, // the_function
6153
+ true // the_function_toplevel
6154
+ );
6155
+ } else {
6156
+ advance(")");
6157
+ the_function.signature.push(")");
5575
6158
  }
5576
- function param_parse() {
5577
- let ellipsis = false;
5578
- let param;
5579
- if (token_nxt.id === "{") {
5580
- if (optional !== undefined) {
6159
+ the_function.signature = the_function.signature.join("");
6160
+ }
6161
+
6162
+ function prefix_lbrace() {
6163
+ const seen = empty();
6164
+ const the_brace = token_now;
6165
+ function property_parse() {
6166
+ let extra;
6167
+ let full;
6168
+ let id;
6169
+ let name = token_nxt;
6170
+ let the_colon;
6171
+ let value;
6172
+ if (!name.identifier && name.id === "`") {
5581
6173
 
5582
6174
  // test_cause:
5583
- // ["function aa(aa=0,{}){}", "param_parse", "required_a_optional_b", "aa", 18]
6175
+ // ["aa={`aa`:0}", "property_parse", "unexpected_a", "`", 5]
5584
6176
 
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) {
6177
+ return stop("unexpected_a", name);
6178
+ }
5599
6179
 
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]
6180
+ // Issue #401 - Add ES2018-syntax for object-literal-spread-operator.
5603
6181
 
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) {
6182
+ if (!name.identifier && token_nxt.id === "...") {
5615
6183
 
5616
6184
  // test_cause:
5617
- // ["function aa({aa:0}){}", "param_parse", "expected_identifier_a", "}", 18]
6185
+ // ["aa={...aa}", "property_parse", "ellipsis", "", 0]
5618
6186
 
5619
- return stop(
5620
- "expected_identifier_a",
5621
- token_nxt
5622
- );
5623
- }
5624
- }
6187
+ test_cause("ellipsis");
6188
+ value = prefix_ellipsis();
6189
+ return value;
6190
+ }
6191
+ advance();
6192
+ if (
6193
+ (name.id === "get" || name.id === "set")
6194
+ && token_nxt.identifier
6195
+ ) {
6196
+ if (!option_dict.getset) {
5625
6197
 
5626
6198
  // test_cause:
5627
- // ["function aa({aa=aa},aa){}", "param_parse", "equal", "", 0]
6199
+ // ["aa={get aa(){}}", "property_parse", "unexpected_a", "get", 5]
5628
6200
 
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
- }
6201
+ warn("unexpected_a", name);
5642
6202
  }
5643
- parameters.push(param);
6203
+ extra = name.id;
6204
+ full = extra + " " + token_nxt.id;
6205
+ name = token_nxt;
6206
+ advance();
6207
+ id = survey(name);
6208
+ if (seen[full] === true || seen[id] === true) {
5644
6209
 
5645
6210
  // test_cause:
5646
- // ["
5647
- // function aa({bb,aa}){}
5648
- // ", "check_ordered", "expected_a_b_before_c_d", "aa", 17]
6211
+ // ["aa={get aa(){},get aa(){}}", "property_parse", "duplicate_a", "aa", 20]
5649
6212
 
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;
6213
+ warn("duplicate_a", name);
5658
6214
  }
5659
- } else if (token_nxt.id === "[") {
5660
- if (optional !== undefined) {
6215
+ seen[id] = false;
6216
+ seen[full] = true;
6217
+ } else {
6218
+ id = survey(name);
6219
+ if (typeof seen[id] === "boolean") {
5661
6220
 
5662
6221
  // test_cause:
5663
- // ["function aa(aa=0,[]){}", "param_parse", "required_a_optional_b", "aa", 18]
6222
+ // ["aa={aa,aa}", "property_parse", "duplicate_a", "aa", 8]
5664
6223
 
5665
- warn(
5666
- "required_a_optional_b",
5667
- token_nxt,
5668
- token_nxt.id,
5669
- optional.id
5670
- );
6224
+ warn("duplicate_a", name);
5671
6225
  }
5672
- param = token_nxt;
5673
- param.names = [];
5674
- advance("[");
5675
- signature.push("[]");
5676
- while (true) {
5677
- subparam = token_nxt;
5678
- if (!subparam.identifier) {
6226
+ seen[id] = true;
6227
+ }
6228
+ if (!name.identifier) {
5679
6229
 
5680
6230
  // test_cause:
5681
- // ["function aa(aa=0,[]){}", "param_parse", "expected_identifier_a", "]", 19]
6231
+ // ["aa={\"aa\":0}", "property_parse", "colon", "", 0]
5682
6232
 
5683
- return stop("expected_identifier_a");
5684
- }
5685
- advance();
5686
- param.names.push(subparam);
6233
+ test_cause("colon");
6234
+ advance(":");
6235
+ value = parse_expression(0);
6236
+ value.label = name;
6237
+ return value;
6238
+ }
6239
+ if (token_nxt.id === "}" || token_nxt.id === ",") {
6240
+ if (typeof extra === "string") {
5687
6241
 
5688
6242
  // test_cause:
5689
- // ["function aa([aa=aa],aa){}", "param_parse", "id", "", 0]
6243
+ // ["aa={get aa}", "property_parse", "closer", "", 0]
5690
6244
 
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;
6245
+ test_cause("closer");
6246
+ advance("(");
5710
6247
  }
6248
+ value = parse_expression(Infinity, true);
6249
+ } else if (token_nxt.id === "(") {
6250
+
6251
+ // test_cause:
6252
+ // ["aa={aa()}", "property_parse", "paren", "", 0]
6253
+ // ["aa={get aa(){}}", "property_parse", "paren", "", 0]
6254
+
6255
+ test_cause("paren");
6256
+ value = prefix_function({
6257
+ arity: "unary",
6258
+ from: name.from,
6259
+ id: "function",
6260
+ line: name.line,
6261
+ name: (
6262
+ typeof extra === "string"
6263
+ ? extra
6264
+ : id
6265
+ ),
6266
+ thru: name.from
6267
+ });
5711
6268
  } else {
5712
- if (token_nxt.id === "...") {
5713
- ellipsis = true;
5714
- signature.push("...");
5715
- advance("...");
5716
- if (optional !== undefined) {
6269
+ if (typeof extra === "string") {
5717
6270
 
5718
6271
  // test_cause:
5719
- // ["function aa(aa=0,...){}", "param_parse", "required_a_optional_b", "aa", 21]
6272
+ // ["aa={get aa.aa}", "property_parse", "paren", "", 0]
5720
6273
 
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) {
5730
-
5731
- // test_cause:
5732
- // ["function aa(0){}", "param_parse", "expected_identifier_a", "0", 13]
5733
-
5734
- return stop("expected_identifier_a");
6274
+ test_cause("paren");
6275
+ advance("(");
5735
6276
  }
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) {
6277
+ the_colon = token_nxt;
6278
+ advance(":");
6279
+ value = parse_expression(0);
6280
+ if (
6281
+ value.id === name.id
6282
+ && value.id !== "function"
6283
+ ) {
5749
6284
 
5750
6285
  // test_cause:
5751
- // ["function aa(aa=0,bb){}", "param_parse", "required_a_optional_b", "aa", 18]
6286
+ // ["aa={aa:aa}", "property_parse", "unexpected_a", ": aa", 7]
5752
6287
 
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
- }
6288
+ warn("unexpected_a", the_colon, ": " + name.id);
5767
6289
  }
5768
6290
  }
6291
+ value.label = name;
6292
+ if (typeof extra === "string") {
6293
+ value.extra = extra;
6294
+ }
6295
+ return value;
5769
6296
  }
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
6297
  the_brace.expression = [];
5796
6298
  if (token_nxt.id !== "}") {
5797
6299
 
5798
6300
  // Parse/loop through each property in {...}.
5799
6301
 
5800
6302
  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
- }
6303
+ the_brace.expression.push(property_parse());
5915
6304
  if (token_nxt.id !== ",") {
5916
6305
  break;
5917
6306
  }
5918
-
5919
- // test_cause:
5920
- // ["aa={\"aa\":0,\"bb\":0}", "prefix_lbrace", "comma", "", 0]
5921
-
5922
- test_cause("comma");
5923
6307
  advance(",");
5924
6308
  if (token_nxt.id === "}") {
5925
6309
 
@@ -5948,25 +6332,45 @@ function jslint_phase3_parse(state) {
5948
6332
  }
5949
6333
 
5950
6334
  function prefix_lbracket() {
5951
- const the_token = token_now;
5952
6335
  let element;
5953
- let ellipsis;
6336
+ let the_token = token_now;
5954
6337
  the_token.expression = [];
6338
+ if (the_token.assignment) {
6339
+ the_token = token_now.assignment;
6340
+ the_token.names = [];
6341
+
6342
+ // PR-500 - Unify ES2015-destructure-logic. - [aa] = ...;
6343
+
6344
+ element = prefix_destructure(
6345
+ undefined, // enroll
6346
+ "variable", // role
6347
+ false, // readonly
6348
+ the_token.names, // name_list
6349
+ undefined, // the_function
6350
+ false // the_function_toplevel
6351
+ );
6352
+ advance("=");
6353
+ symbol("=").led_infix(element);
6354
+ return the_token;
6355
+ }
5955
6356
  if (token_nxt.id !== "]") {
5956
6357
 
5957
6358
  // Parse/loop through each element in [...].
5958
6359
 
5959
6360
  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;
6361
+ if (!state.mode_json && token_nxt.id === "...") {
6362
+
6363
+ // test_cause:
6364
+ // ["aa=[...aa]", "prefix_lbracket", "ellipsis", "...", 0]
6365
+
6366
+ test_cause("ellipsis", token_nxt.id);
6367
+ the_token.expression.push(prefix_ellipsis());
6368
+
6369
+ // Issue #401 - Regression - Allow multiple-ellipsis in array-literal.
6370
+
6371
+ } else {
6372
+ the_token.expression.push(parse_expression(10));
5968
6373
  }
5969
- the_token.expression.push(element);
5970
6374
  if (token_nxt.id !== ",") {
5971
6375
  break;
5972
6376
  }
@@ -5974,7 +6378,7 @@ function jslint_phase3_parse(state) {
5974
6378
  if (token_nxt.id === "]") {
5975
6379
 
5976
6380
  // test_cause:
5977
- // ["let aa=[0,]", "prefix_lbracket", "unexpected_a", ",", 10]
6381
+ // ["aa=[0,]", "prefix_lbracket", "unexpected_a", ",", 6]
5978
6382
 
5979
6383
  warn("unexpected_a", token_now);
5980
6384
  break;
@@ -6139,7 +6543,7 @@ function jslint_phase3_parse(state) {
6139
6543
  the_break.label = token_nxt;
6140
6544
  advance();
6141
6545
  }
6142
- advance(";");
6546
+ semicolon();
6143
6547
  return the_break;
6144
6548
  }
6145
6549
 
@@ -6158,7 +6562,7 @@ function jslint_phase3_parse(state) {
6158
6562
  check_not_top_level(the_continue);
6159
6563
  the_continue.disrupt = true;
6160
6564
  warn("unexpected_a", the_continue);
6161
- advance(";");
6565
+ semicolon();
6162
6566
  return the_continue;
6163
6567
  }
6164
6568
 
@@ -6186,7 +6590,7 @@ function jslint_phase3_parse(state) {
6186
6590
  // test_cause:
6187
6591
  // ["delete 0", "stmt_delete", "expected_a_b", "0", 8]
6188
6592
 
6189
- stop("expected_a_b", the_value, ".", artifact(the_value));
6593
+ return stop("expected_a_b", the_value, ".", artifact(the_value));
6190
6594
  }
6191
6595
  the_token.expression = the_value;
6192
6596
  semicolon();
@@ -6311,7 +6715,7 @@ function jslint_phase3_parse(state) {
6311
6715
  // test_cause:
6312
6716
  // ["export {}", "stmt_export", "expected_identifier_a", "}", 9]
6313
6717
 
6314
- stop("expected_identifier_a");
6718
+ return stop("expected_identifier_a", token_nxt);
6315
6719
  }
6316
6720
  the_id = token_nxt.id;
6317
6721
  export_list.push(token_nxt);
@@ -6335,11 +6739,10 @@ function jslint_phase3_parse(state) {
6335
6739
  }
6336
6740
  advance();
6337
6741
  the_export.expression.push(the_thing);
6338
- if (token_nxt.id === ",") {
6339
- advance(",");
6340
- } else {
6742
+ if (token_nxt.id !== ",") {
6341
6743
  break;
6342
6744
  }
6745
+ advance(",");
6343
6746
  }
6344
6747
 
6345
6748
  // PR-439 - Check exported properties are ordered.
@@ -6355,7 +6758,7 @@ function jslint_phase3_parse(state) {
6355
6758
  // test_cause:
6356
6759
  // ["export", "stmt_export", "unexpected_a", "(end)", 1]
6357
6760
 
6358
- stop("unexpected_a");
6761
+ return stop("unexpected_a");
6359
6762
  }
6360
6763
  }
6361
6764
  state.mode_module = true;
@@ -6477,83 +6880,103 @@ function jslint_phase3_parse(state) {
6477
6880
  function stmt_import() {
6478
6881
  const the_import = token_now;
6479
6882
  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
-
6883
+ the_import.name = [];
6499
6884
  state.mode_module = true;
6885
+ while (true) {
6500
6886
 
6501
6887
  // PR-436 - Add grammar for side-effect import-statement.
6502
6888
 
6503
- if (token_nxt.id === "(string)") {
6889
+ if (token_nxt.id === "(string)") {
6504
6890
 
6505
6891
  // test_cause:
6506
- // ["import \"./aa.mjs\";", "stmt_import", "import_side_effect", "", 0]
6892
+ // ["import \"aa\"", "stmt_import", "import_side_effect", "", 0]
6507
6893
 
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") {
6894
+ test_cause("import_side_effect");
6895
+ warn("expected_a_b", token_nxt, "{", artifact());
6896
+ advance();
6897
+ semicolon();
6898
+ return the_import;
6899
+ }
6900
+ if (token_nxt.id === "*") {
6901
+ advance("*");
6902
+ advance("as");
6903
+ if (!token_nxt.identifier) {
6518
6904
 
6519
6905
  // test_cause:
6520
- // ["import ignore from \"aa\"", "stmt_import", "unexpected_a", "ignore", 8]
6906
+ // ["import * as", "stmt_import", "expected_identifier_a", "(end)", 1]
6521
6907
 
6522
- warn("unexpected_a", name);
6908
+ return stop("expected_identifier_a", token_nxt);
6909
+ }
6523
6910
  }
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) {
6911
+ if (token_nxt.identifier) {
6912
+ name = token_nxt;
6913
+ advance();
6914
+ if (name.id === "ignore") {
6915
+
6916
+ // test_cause:
6917
+ // ["import ignore from \"aa\"", "stmt_import", "unexpected_a", "ignore", 8]
6918
+
6919
+ warn("unexpected_a", name);
6920
+ }
6921
+ enroll(name, "variable", true);
6922
+ the_import.name.push(name);
6923
+ } else {
6924
+ advance("{");
6925
+ if (token_nxt.id !== "}") {
6926
+ while (true) {
6927
+ if (!token_nxt.identifier) {
6532
6928
 
6533
6929
  // test_cause:
6534
6930
  // ["import {", "stmt_import", "expected_identifier_a", "(end)", 1]
6535
6931
 
6536
- stop("expected_identifier_a");
6537
- }
6538
- name = token_nxt;
6539
- advance();
6540
- if (name.id === "ignore") {
6932
+ return stop("expected_identifier_a", token_nxt);
6933
+ }
6934
+ name = token_nxt;
6935
+ advance();
6936
+ if (token_nxt.id === "as") {
6937
+ advance("as");
6938
+ name = token_nxt;
6939
+ advance();
6940
+ }
6941
+ if (name.id === "ignore") {
6541
6942
 
6542
6943
  // test_cause:
6543
6944
  // ["import {ignore} from \"aa\"", "stmt_import", "unexpected_a", "ignore", 9]
6544
6945
 
6545
- warn("unexpected_a", name);
6546
- }
6547
- enroll(name, "variable", true);
6548
- names.push(name);
6549
- if (token_nxt.id !== ",") {
6550
- break;
6946
+ warn("unexpected_a", name);
6947
+ }
6948
+ enroll(name, "variable", true);
6949
+ the_import.name.push(name);
6950
+ if (token_nxt.id !== ",") {
6951
+ break;
6952
+ }
6953
+ advance(",");
6551
6954
  }
6552
- advance(",");
6553
6955
  }
6956
+ advance("}");
6957
+ }
6958
+
6959
+ // PR-347 - Disable warning "unexpected_directive_a".
6960
+ //
6961
+ // if (typeof state.mode_module === "object") {
6962
+ //
6963
+ // // test_cause:
6964
+ // // ["
6965
+ // // /*global aa*/
6966
+ // // import aa from "aa"
6967
+ // // ", "stmt_import", "unexpected_directive_a", "global", 1]
6968
+ //
6969
+ // warn(
6970
+ // "unexpected_directive_a",
6971
+ // state.mode_module,
6972
+ // state.mode_module.directive
6973
+ // );
6974
+ // }
6975
+
6976
+ if (token_nxt.id !== ",") {
6977
+ break;
6554
6978
  }
6555
- advance("}");
6556
- the_import.name = names;
6979
+ advance(",");
6557
6980
  }
6558
6981
  advance("from");
6559
6982
  advance("(string)");
@@ -6566,6 +6989,14 @@ function jslint_phase3_parse(state) {
6566
6989
  warn("bad_module_name_a", token_now);
6567
6990
  }
6568
6991
  import_list.push(token_now.value);
6992
+
6993
+ // Issue #495 - Add ES2025-syntax "import ... with {...}".
6994
+
6995
+ if (token_nxt.id === "with") {
6996
+ advance("with");
6997
+ advance("{");
6998
+ prefix_lbrace();
6999
+ }
6569
7000
  semicolon();
6570
7001
  return the_import;
6571
7002
  }
@@ -6596,7 +7027,7 @@ function jslint_phase3_parse(state) {
6596
7027
  if (token_nxt.id !== ";" && the_return.line === token_nxt.line) {
6597
7028
  the_return.expression = parse_expression(10);
6598
7029
  }
6599
- advance(";");
7030
+ semicolon();
6600
7031
  return the_return;
6601
7032
  }
6602
7033
 
@@ -6834,7 +7265,7 @@ function jslint_phase3_parse(state) {
6834
7265
  // test_cause:
6835
7266
  // ["try{}catch(){}", "stmt_try", "expected_identifier_a", ")", 12]
6836
7267
 
6837
- return stop("expected_identifier_a");
7268
+ return stop("expected_identifier_a", token_nxt);
6838
7269
  }
6839
7270
  if (token_nxt.id !== "ignore") {
6840
7271
  ignored = undefined;
@@ -6876,19 +7307,15 @@ function jslint_phase3_parse(state) {
6876
7307
  }
6877
7308
 
6878
7309
  function stmt_var() {
6879
- let ellipsis;
6880
- let mode_const;
7310
+ const readonly = token_now.id === "const";
6881
7311
  let name;
6882
- let the_brace;
6883
- let the_bracket;
6884
7312
  let the_variable = token_now;
6885
7313
  let variable_prv;
6886
- mode_const = the_variable.id === "const";
6887
7314
  the_variable.names = [];
6888
7315
 
6889
7316
  // A program may use var or let, but not both.
6890
7317
 
6891
- if (!mode_const) {
7318
+ if (!readonly) {
6892
7319
  if (mode_var === undefined) {
6893
7320
  mode_var = the_variable.id;
6894
7321
  } else if (the_variable.id !== mode_var) {
@@ -6950,142 +7377,27 @@ function jslint_phase3_parse(state) {
6950
7377
  }
6951
7378
  }
6952
7379
  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 === "[") {
7380
+ if (token_nxt.id === "{" || token_nxt.id === "[") {
7038
7381
  if (the_variable.id === "var") {
7039
7382
 
7040
7383
  // test_cause:
7041
7384
  // ["var[aa]=0", "stmt_var", "unexpected_a", "var", 1]
7385
+ // ["var{aa}=0", "stmt_var", "unexpected_a", "var", 1]
7042
7386
 
7043
7387
  warn("unexpected_a", the_variable);
7044
7388
  }
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;
7389
+ advance();
7070
7390
 
7071
- // test_cause:
7072
- // ["const [aa]=bb;\nconst bb=0;", "lookup", "out_of_scope_a", "bb", 12]
7391
+ // PR-500 - Unify ES2015-destructure-logic. - let [aa] = ...;
7073
7392
 
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("]");
7393
+ prefix_destructure(
7394
+ enroll, // enroll
7395
+ "variable", // role
7396
+ readonly, // readonly
7397
+ the_variable.names, // name_list
7398
+ undefined, // the_function
7399
+ false // the_function_toplevel
7400
+ );
7089
7401
  advance("=");
7090
7402
  the_variable.expression = parse_expression(0);
7091
7403
  } else if (token_nxt.identifier) {
@@ -7100,8 +7412,8 @@ function jslint_phase3_parse(state) {
7100
7412
 
7101
7413
  warn("unexpected_a", name);
7102
7414
  }
7103
- enroll(name, "variable", mode_const);
7104
- if (token_nxt.id === "=" || mode_const) {
7415
+ enroll(name, "variable", readonly);
7416
+ if (token_nxt.id === "=" || readonly) {
7105
7417
  advance("=");
7106
7418
 
7107
7419
  // Issue #458 - Regression - Warn about variable usage before initialization.
@@ -7120,9 +7432,8 @@ function jslint_phase3_parse(state) {
7120
7432
 
7121
7433
  // test_cause:
7122
7434
  // ["let 0", "stmt_var", "expected_identifier_a", "0", 5]
7123
- // ["var{aa:{aa}}", "stmt_var", "expected_identifier_a", "{", 8]
7124
7435
 
7125
- return stop("expected_identifier_a");
7436
+ return stop("expected_identifier_a", token_nxt);
7126
7437
  }
7127
7438
  if (token_nxt.id !== ",") {
7128
7439
  break;
@@ -7188,7 +7499,7 @@ function jslint_phase3_parse(state) {
7188
7499
  // test_cause:
7189
7500
  // ["with", "stmt_with", "unexpected_a", "with", 1]
7190
7501
 
7191
- stop("unexpected_a", token_now);
7502
+ return stop("unexpected_a", token_now);
7192
7503
  }
7193
7504
 
7194
7505
  function survey(name) {
@@ -7197,49 +7508,55 @@ function jslint_phase3_parse(state) {
7197
7508
  // Tally the property name. If it is a string, only tally strings that conform
7198
7509
  // to the identifier rules.
7199
7510
 
7200
- if (id === "(string)") {
7511
+ switch (id) {
7512
+ case "(string)":
7201
7513
  id = name.value;
7202
7514
  if (!jslint_rgx_identifier.test(id)) {
7203
7515
  return id;
7204
7516
  }
7205
- } else if (id === "`") {
7517
+ break;
7518
+ case "`":
7206
7519
  if (name.value.length === 1) {
7207
7520
  id = name.value[0].value;
7208
7521
  if (!jslint_rgx_identifier.test(id)) {
7209
7522
  return id;
7210
7523
  }
7211
7524
  }
7212
- } else if (!name.identifier) {
7525
+ break;
7526
+ default:
7527
+ if (!name.identifier) {
7213
7528
 
7214
7529
  // test_cause:
7215
7530
  // ["let aa={0:0}", "survey", "expected_identifier_a", "0", 9]
7216
7531
 
7217
- return stop("expected_identifier_a", name);
7532
+ return stop("expected_identifier_a", name);
7533
+ }
7218
7534
  }
7219
7535
 
7220
7536
  // If we have seen this name before, increment its count.
7221
7537
 
7222
7538
  if (typeof property_dict[id] === "number") {
7223
7539
  property_dict[id] += 1;
7540
+ return id;
7541
+ }
7224
7542
 
7225
7543
  // If this is the first time seeing this property name, and if there is a
7226
7544
  // tenure list, then it must be on the list. Otherwise, it must conform to
7227
7545
  // the rules for good property names.
7228
7546
 
7229
- } else {
7230
- if (state.mode_property) {
7231
- if (tenure[id] !== true) {
7547
+ if (state.mode_property) {
7548
+ if (tenure[id] !== true) {
7232
7549
 
7233
7550
  // test_cause:
7234
7551
  // ["/*property aa*/\naa.bb", "survey", "unregistered_property_a", "bb", 4]
7235
7552
 
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
- ) {
7553
+ warn("unregistered_property_a", name);
7554
+ }
7555
+ } else if (
7556
+ !option_dict.nomen
7557
+ && name.identifier
7558
+ && jslint_rgx_weird_property.test(id)
7559
+ ) {
7243
7560
 
7244
7561
  // test_cause:
7245
7562
  // ["aa.$", "survey", "weird_property_a", "$", 4]
@@ -7248,10 +7565,9 @@ function jslint_phase3_parse(state) {
7248
7565
  // ["aa.aaSync", "survey", "weird_property_a", "aaSync", 4]
7249
7566
  // ["aa.aa_", "survey", "weird_property_a", "aa_", 4]
7250
7567
 
7251
- warn("weird_property_a", name);
7252
- }
7253
- property_dict[id] = 1;
7568
+ warn("weird_property_a", name);
7254
7569
  }
7570
+ property_dict[id] = 1;
7255
7571
  return id;
7256
7572
  }
7257
7573
 
@@ -7300,6 +7616,7 @@ function jslint_phase3_parse(state) {
7300
7616
  // Begin defining the language.
7301
7617
 
7302
7618
  assignment("%=");
7619
+ assignment("&&=");
7303
7620
  assignment("&=");
7304
7621
  assignment("*=");
7305
7622
  assignment("+=");
@@ -7309,8 +7626,10 @@ function jslint_phase3_parse(state) {
7309
7626
  assignment("=");
7310
7627
  assignment(">>=");
7311
7628
  assignment(">>>=");
7629
+ assignment("??=");
7312
7630
  assignment("^=");
7313
7631
  assignment("|=");
7632
+ assignment("||=");
7314
7633
  constant("(number)", "number");
7315
7634
  constant("(regexp)", "regexp");
7316
7635
  constant("(string)", "string");
@@ -7349,7 +7668,7 @@ function jslint_phase3_parse(state) {
7349
7668
  infix(160, "`", infix_grave);
7350
7669
  infix(170, ".", infix_dot);
7351
7670
  infix(170, "=>", infix_fart_unwrapped);
7352
- infix(170, "?.", infix_option_chain);
7671
+ infix(170, "?.", infix_dot);
7353
7672
  infix(170, "[", infix_lbracket);
7354
7673
  infix(35, "??");
7355
7674
  infix(40, "||");
@@ -7454,7 +7773,7 @@ function jslint_phase3_parse(state) {
7454
7773
 
7455
7774
  } else if (token_nxt.value === "use strict") {
7456
7775
  advance("(string)");
7457
- advance(";");
7776
+ semicolon();
7458
7777
  }
7459
7778
  state.token_tree = parse_statements();
7460
7779
  advance("(end)");
@@ -7672,7 +7991,9 @@ function jslint_phase4_walk(state) {
7672
7991
  ) {
7673
7992
 
7674
7993
  // test_cause:
7994
+ // ["(aa=aa)=>0", "lookup", "out_of_scope_a", "aa", 5]
7675
7995
  // ["let aa;if(aa){let bb;}bb;", "lookup", "out_of_scope_a", "bb", 23]
7996
+ // ["let aa=bb;let bb=0;", "lookup", "out_of_scope_a", "bb", 8]
7676
7997
 
7677
7998
  warn("out_of_scope_a", thing);
7678
7999
  }
@@ -7689,24 +8010,23 @@ function jslint_phase4_walk(state) {
7689
8010
  let right;
7690
8011
  if (thing.id === "=") {
7691
8012
  if (thing.names !== undefined) {
8013
+ if (Array.isArray(thing.names)) {
8014
+
8015
+ // PR-500 - Fix false-warning "uninitialized_a" in statement ";[aa]=0;".
7692
8016
 
7693
8017
  // test_cause:
7694
- // ["if(0){aa=0}", "post_a", "=", "", 0]
8018
+ // [";[aa]=0", "post_a", ";[aa]=0", "", 0]
7695
8019
 
7696
- test_cause("=");
8020
+ test_cause(";[aa]=0");
8021
+ thing.names.forEach(init_variable);
8022
+ } else {
7697
8023
 
7698
- // Probably deadcode.
7699
- // if (Array.isArray(thing.names)) {
7700
- // thing.names.forEach(init_variable);
7701
- // } else {
7702
- // init_variable(thing.names);
7703
- // }
8024
+ // test_cause:
8025
+ // ["aa=0", "post_a", "aa=0", "", 0]
7704
8026
 
7705
- jslint_assert(
7706
- !Array.isArray(thing.names),
7707
- `Expected !Array.isArray(thing.names).`
7708
- );
7709
- init_variable(thing.names);
8027
+ test_cause("aa=0");
8028
+ init_variable(thing.names);
8029
+ }
7710
8030
  } else {
7711
8031
  if (lvalue.id === "[" || lvalue.id === "{") {
7712
8032
  lvalue.expression.forEach(function (thing) {
@@ -7827,10 +8147,15 @@ function jslint_phase4_walk(state) {
7827
8147
  } else if (thing.id === "." || thing.id === "?.") {
7828
8148
  if (thing.expression.id === "RegExp") {
7829
8149
 
8150
+ // PR-499 - Relax warning for ES2025-feature RegExp.escape().
8151
+
8152
+ if (!thing.name || thing.name.id !== "escape") {
8153
+
7830
8154
  // test_cause:
7831
8155
  // ["aa=RegExp.aa", "post_b", "weird_expression_a", ".", 10]
7832
8156
 
7833
- warn("weird_expression_a", thing);
8157
+ warn("weird_expression_a", thing);
8158
+ }
7834
8159
  }
7835
8160
  } else if (thing.id !== "=>" && thing.id !== "(") {
7836
8161
  right = thing.expression[1];
@@ -8096,21 +8421,12 @@ function jslint_phase4_walk(state) {
8096
8421
  }
8097
8422
 
8098
8423
  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
- }
8424
+ the_thing.name.forEach(function (name) {
8425
+ name.dead = false;
8426
+ name.init = true;
8427
+ blockage.live.push(name);
8428
+ });
8429
+ return post_s_export(the_thing);
8114
8430
  }
8115
8431
 
8116
8432
  function post_s_lbrace() {
@@ -8143,7 +8459,12 @@ function jslint_phase4_walk(state) {
8143
8459
  function post_s_var(thing) {
8144
8460
  thing.names.forEach(function (name) {
8145
8461
  name.dead = false;
8146
- if (name.expression !== undefined) {
8462
+ if (name.expression) {
8463
+
8464
+ // test_cause:
8465
+ // ["let aa=0", "post_s_var", "let aa=0", "", 0]
8466
+
8467
+ test_cause("let aa=0");
8147
8468
  walk_expression(name.expression);
8148
8469
 
8149
8470
  // Probably deadcode.
@@ -8153,11 +8474,20 @@ function jslint_phase4_walk(state) {
8153
8474
  // name.init = true;
8154
8475
  // }
8155
8476
 
8156
- jslint_assert(
8157
- !(name.id === "{" || name.id === "["),
8158
- `Expected !(name.id === "{" || name.id === "[").`
8159
- );
8477
+ // PR-500 - Unify property the_function.parameters into the_function.names.
8478
+
8479
+ // jslint_assert(
8480
+ // !(name.id === "{" || name.id === "["),
8481
+ // `Expected !(name.id === "{" || name.id === "[").`
8482
+ // );
8483
+
8160
8484
  name.init = true;
8485
+ } else {
8486
+
8487
+ // test_cause:
8488
+ // ["let aa", "post_s_var", "let aa", "", 0]
8489
+
8490
+ test_cause("let aa");
8161
8491
  }
8162
8492
  blockage.live.push(name);
8163
8493
  });
@@ -8499,7 +8829,7 @@ function jslint_phase4_walk(state) {
8499
8829
  thing.name.init = true;
8500
8830
  }
8501
8831
  if (thing.extra === "get") {
8502
- if (thing.parameters.length !== 0) {
8832
+ if (thing.parameter_count !== 0) {
8503
8833
 
8504
8834
  // test_cause:
8505
8835
  // ["
@@ -8507,28 +8837,51 @@ function jslint_phase4_walk(state) {
8507
8837
  // aa={get aa(aa){}}
8508
8838
  // ", "pre_s_function", "bad_get", "function", 9]
8509
8839
 
8510
- warn("bad_get", thing);
8511
- }
8512
- } else if (thing.extra === "set") {
8513
- if (thing.parameters.length !== 1) {
8840
+ warn("bad_get", thing);
8841
+ }
8842
+ } else if (thing.extra === "set") {
8843
+ if (thing.parameter_count !== 1) {
8844
+
8845
+ // test_cause:
8846
+ // ["
8847
+ // /*jslint getset*/
8848
+ // aa={set aa(){}}
8849
+ // ", "pre_s_function", "bad_set", "function", 9]
8850
+
8851
+ warn("bad_set", thing);
8852
+ }
8853
+ }
8854
+
8855
+ // PR-500 - Unify property the_function.parameters into the_function.names.
8856
+
8857
+ // thing.parameters.forEach(function (name) {
8858
+ // walk_expression(name.expression);
8859
+ // if (name.id === "{" || name.id === "[") {
8860
+ // name.names.forEach(subactivate);
8861
+ // } else {
8862
+ // name.dead = false;
8863
+ // name.init = true;
8864
+ // }
8865
+ // });
8866
+
8867
+ thing.names.forEach(function (name) {
8868
+ if (name.expression) {
8869
+
8870
+ // test_cause:
8871
+ // ["(aa=0)=>0", "pre_s_function", "(aa=0)=>0", "", 0]
8872
+
8873
+ test_cause("(aa=0)=>0");
8874
+ } else {
8514
8875
 
8515
8876
  // test_cause:
8516
- // ["
8517
- // /*jslint getset*/
8518
- // aa={set aa(){}}
8519
- // ", "pre_s_function", "bad_set", "function", 9]
8877
+ // ["(aa)=>0", "pre_s_function", "(aa)=>0", "", 0]
8878
+ // ["aa=>0", "pre_s_function", "(aa)=>0", "", 0]
8520
8879
 
8521
- warn("bad_set", thing);
8880
+ test_cause("(aa)=>0");
8522
8881
  }
8523
- }
8524
- thing.parameters.forEach(function (name) {
8525
8882
  walk_expression(name.expression);
8526
- if (name.id === "{" || name.id === "[") {
8527
- name.names.forEach(subactivate);
8528
- } else {
8529
- name.dead = false;
8530
- name.init = true;
8531
- }
8883
+ name.dead = false;
8884
+ name.init = true;
8532
8885
  });
8533
8886
  }
8534
8887
 
@@ -8556,11 +8909,13 @@ function jslint_phase4_walk(state) {
8556
8909
  }
8557
8910
  }
8558
8911
 
8559
- function subactivate(name) {
8560
- name.init = true;
8561
- name.dead = false;
8562
- blockage.live.push(name);
8563
- }
8912
+ // PR-500 - Unify property the_function.parameters into the_function.names.
8913
+
8914
+ // function subactivate(name) {
8915
+ // name.init = true;
8916
+ // name.dead = false;
8917
+ // blockage.live.push(name);
8918
+ // }
8564
8919
 
8565
8920
  function walk_expression(thing) {
8566
8921
  if (thing) {
@@ -8752,6 +9107,8 @@ function jslint_phase5_whitage(state) {
8752
9107
  // "switch(){}"
8753
9108
  // "while(){}"
8754
9109
 
9110
+ let indent_method_dict = empty();
9111
+ let indentage;
8755
9112
  let left = token_global;
8756
9113
  let margin = 0;
8757
9114
  let mode_indent = (
@@ -8770,9 +9127,19 @@ function jslint_phase5_whitage(state) {
8770
9127
  // This is the set of infix operators that require a space on each side.
8771
9128
 
8772
9129
  let spaceop = object_assign_from_list(empty(), [
8773
- "!=", "!==", "%", "%=", "&", "&&", "&=", "*", "*=", "+=", "-=", "/",
8774
- "/=", "<", "<<", "<<=", "<=", "=", "==", "===", "=>", ">", ">=", ">>",
8775
- ">>=", ">>>", ">>>=", "^", "^=", "|", "|=", "||"
9130
+ "!=", "!==",
9131
+ "%", "%=",
9132
+ "&", "&&", "&&=", "&=",
9133
+ "*", "*=",
9134
+ "+=",
9135
+ "-=",
9136
+ "/", "/=",
9137
+ "<", "<<", "<<=", "<=",
9138
+ "=", "==", "===", "=>",
9139
+ ">", ">=", ">>", ">>=", ">>>", ">>>=",
9140
+ "??", "??=",
9141
+ "^", "^=",
9142
+ "|", "|=", "||", "||="
8776
9143
  ], true);
8777
9144
 
8778
9145
  function at_margin(fit) {
@@ -8946,148 +9313,106 @@ function jslint_phase5_whitage(state) {
8946
9313
  }
8947
9314
  }
8948
9315
 
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 "{":
9316
+ function whitage_case() {
9006
9317
 
9007
9318
  // 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]
9319
+ // ["let aa=[];", "whitage_case", "opener", "", 0]
9320
+ // ["let aa=`${0}`;", "whitage_case", "opener", "", 0]
9321
+ // ["let aa=aa();", "whitage_case", "opener", "", 0]
9322
+ // ["let aa={};", "whitage_case", "opener", "", 0]
9012
9323
 
9013
- test_cause("opener");
9324
+ test_cause("opener");
9014
9325
 
9015
9326
  // Probably deadcode.
9016
9327
  // case "${}":
9017
9328
 
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 "{}":
9329
+ jslint_assert(
9330
+ !(left.id + right.id === "${}"),
9331
+ "Expected !(left.id + right.id === \"${}\")."
9332
+ );
9333
+ switch (left.id + right.id) {
9334
+ case "()":
9335
+ case "[]":
9336
+ case "{}":
9026
9337
 
9027
9338
  // If left and right are opener and closer, then the placement of right depends
9028
9339
  // on the openness. Illegal pairs (like '{]') have already been detected.
9029
9340
 
9030
9341
  // test_cause:
9031
- // ["let aa=[];", "whitage", "opener_closer", "", 0]
9032
- // ["let aa=aa();", "whitage", "opener_closer", "", 0]
9033
- // ["let aa={};", "whitage", "opener_closer", "", 0]
9342
+ // ["let aa=[];", "whitage_case", "opener_closer", "", 0]
9343
+ // ["let aa=aa();", "whitage_case", "opener_closer", "", 0]
9344
+ // ["let aa={};", "whitage_case", "opener_closer", "", 0]
9034
9345
 
9035
- test_cause("opener_closer");
9036
- if (left.line === right.line) {
9346
+ test_cause("opener_closer");
9347
+ if (left.line === right.line) {
9037
9348
 
9038
9349
  // test_cause:
9039
9350
  // ["let aa = aa( );", "no_space", "unexpected_space_a_b", ")", 14]
9040
9351
 
9041
- no_space();
9042
- } else {
9352
+ no_space();
9353
+ } else {
9043
9354
 
9044
9355
  // test_cause:
9045
9356
  // ["let aa = aa(\n );", "expected_at", "expected_a_at_b_c", "1", 2]
9046
9357
 
9047
- at_margin(0);
9048
- }
9049
- break;
9050
- default:
9358
+ at_margin(0);
9359
+ }
9360
+ break;
9361
+ default:
9051
9362
 
9052
9363
  // 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) {
9364
+ // ["let aa=(0);", "whitage_case", "opener_operand", "", 0]
9365
+ // ["let aa=[0];", "whitage_case", "opener_operand", "", 0]
9366
+ // ["let aa=`${0}`;", "whitage_case", "opener_operand", "", 0]
9367
+ // ["let aa=aa(0);", "whitage_case", "opener_operand", "", 0]
9368
+ // ["let aa={aa:0};", "whitage_case", "opener_operand", "", 0]
9369
+
9370
+ test_cause("opener_operand");
9371
+ opening = left.open || (left.line !== right.line);
9372
+ indentage = {
9373
+ closer,
9374
+ free,
9375
+ margin,
9376
+ open,
9377
+ opening
9378
+ };
9379
+ function_stack.push(indentage);
9380
+ switch (left.id) {
9381
+ case "${":
9382
+ closer = "}";
9383
+ break;
9384
+ case "(":
9385
+ closer = ")";
9386
+ break;
9387
+ case "[":
9388
+ closer = "]";
9389
+ break;
9390
+ case "{":
9391
+ closer = "}";
9392
+ break;
9393
+ }
9394
+ if (opening) {
9077
9395
 
9078
9396
  // 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]
9397
+ // ["function aa(){\nreturn;\n}", "whitage_case", "opening", "", 0]
9398
+ // ["let aa=(\n0\n);", "whitage_case", "opening", "", 0]
9399
+ // ["let aa=[\n0\n];", "whitage_case", "opening", "", 0]
9400
+ // ["let aa=`${\n0\n}`;", "whitage_case", "opening", "", 0]
9401
+ // ["let aa={\naa:0\n};", "whitage_case", "opening", "", 0]
9402
+
9403
+ test_cause("opening");
9404
+ free = closer === ")" && left.free;
9405
+ open = true;
9406
+ margin += mode_indent;
9407
+ if (indent_method_dict[left.line]) {
9084
9408
 
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) {
9409
+ // PR-498 - Relax warning on multiline-method-chaining.
9410
+
9411
+ margin += mode_indent;
9412
+ indentage.indent_method = true;
9413
+ }
9414
+ if (right.role === "label") {
9415
+ if (right.from !== 0) {
9091
9416
 
9092
9417
  // test_cause:
9093
9418
  // ["
@@ -9101,15 +9426,16 @@ function jslint_phase5_whitage(state) {
9101
9426
  // }
9102
9427
  // ", "expected_at", "expected_a_at_b_c", "1", 2]
9103
9428
 
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") {
9429
+ expected_at(0);
9430
+ }
9431
+ } else if (right.switch) {
9432
+ at_margin(-mode_indent);
9433
+ } else {
9434
+ at_margin(0);
9435
+ }
9436
+ break;
9437
+ }
9438
+ if (right.statement || right.role === "label") {
9113
9439
 
9114
9440
  // test_cause:
9115
9441
  // ["
@@ -9118,36 +9444,36 @@ function jslint_phase5_whitage(state) {
9118
9444
  // aa();
9119
9445
  // }
9120
9446
  // }
9121
- // ", "whitage", "expected_line_break_a_b", "bb", 16]
9447
+ // ", "whitage_case", "expected_line_break_a_b", "bb", 16]
9122
9448
 
9123
- warn(
9124
- "expected_line_break_a_b",
9125
- right,
9126
- artifact(left),
9127
- artifact(right)
9128
- );
9129
- }
9449
+ warn(
9450
+ "expected_line_break_a_b",
9451
+ right,
9452
+ artifact(left),
9453
+ artifact(right)
9454
+ );
9455
+ }
9130
9456
 
9131
9457
  // 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]
9458
+ // ["let aa=(0);", "whitage_case", "not_free", "", 0]
9459
+ // ["let aa=[0];", "whitage_case", "not_free", "", 0]
9460
+ // ["let aa=`${0}`;", "whitage_case", "not_free", "", 0]
9461
+ // ["let aa={aa:0};", "whitage_case", "not_free", "", 0]
9136
9462
 
9137
- test_cause("not_free");
9138
- free = false;
9139
- open = false;
9463
+ test_cause("not_free");
9464
+ free = false;
9465
+ open = false;
9140
9466
 
9141
9467
  // test_cause:
9142
9468
  // ["let aa = ( 0 );", "no_space_only", "unexpected_space_a_b", "0", 12]
9143
9469
 
9144
- no_space_only();
9145
- }
9146
- }
9147
- break;
9148
- default:
9149
- if (right.statement === true) {
9150
- if (left.id === "else") {
9470
+ no_space_only();
9471
+ }
9472
+ }
9473
+
9474
+ function whitage_default() {
9475
+ if (right.statement === true) {
9476
+ if (left.id === "else") {
9151
9477
 
9152
9478
  // test_cause:
9153
9479
  // ["
@@ -9159,26 +9485,41 @@ function jslint_phase5_whitage(state) {
9159
9485
  // }
9160
9486
  // ", "one_space_only", "expected_space_a_b", "if", 9]
9161
9487
 
9162
- one_space_only();
9163
- } else {
9488
+ one_space_only();
9489
+ } else {
9164
9490
 
9165
9491
  // test_cause:
9166
9492
  // [" let aa = 0;", "expected_at", "expected_a_at_b_c", "1", 2]
9167
9493
 
9168
- at_margin(0);
9169
- open = false;
9170
- }
9494
+ at_margin(0);
9495
+ open = false;
9496
+ }
9497
+ return;
9498
+ }
9171
9499
 
9172
9500
  // If right is a closer, then pop the previous state.
9173
9501
 
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 {
9502
+ if (right.id === closer) {
9503
+ indentage = function_stack.pop();
9504
+ closer = indentage.closer;
9505
+ free = indentage.free;
9506
+ margin = indentage.margin;
9507
+ open = indentage.open;
9508
+ opening = indentage.opening;
9509
+ if (opening && right.id !== ";") {
9510
+ at_margin(
9511
+ indentage.indent_method
9512
+
9513
+ // PR-498 - Relax warning on multiline-method-chaining.
9514
+
9515
+ ? mode_indent
9516
+ : 0
9517
+ );
9518
+ } else {
9519
+ no_space_only();
9520
+ }
9521
+ return;
9522
+ }
9182
9523
 
9183
9524
  // Left is not an opener, and right is not a closer.
9184
9525
  // The nature of left and right will determine the space between them.
@@ -9186,10 +9527,12 @@ function jslint_phase5_whitage(state) {
9186
9527
  // If left is ',' or ';' or right is a statement then if open,
9187
9528
  // right must go at the margin, or if closed, a space between.
9188
9529
 
9189
- if (right.switch) {
9190
- at_margin(-mode_indent);
9191
- } else if (right.role === "label") {
9192
- if (right.from !== 0) {
9530
+ if (right.switch) {
9531
+ at_margin(-mode_indent);
9532
+ return;
9533
+ }
9534
+ if (right.role === "label") {
9535
+ if (right.from !== 0) {
9193
9536
 
9194
9537
  // test_cause:
9195
9538
  // ["
@@ -9203,19 +9546,21 @@ function jslint_phase5_whitage(state) {
9203
9546
  // }
9204
9547
  // ", "expected_at", "expected_a_at_b_c", "1", 10]
9205
9548
 
9206
- expected_at(0);
9207
- }
9208
- } else if (left.id === ",") {
9209
- if (!open || (
9210
- (free || closer === "]")
9211
- && left.line === right.line
9212
- )) {
9549
+ expected_at(0);
9550
+ }
9551
+ return;
9552
+ }
9553
+ if (left.id === ",") {
9554
+ if (!open || (
9555
+ (free || closer === "]")
9556
+ && left.line === right.line
9557
+ )) {
9213
9558
 
9214
9559
  // test_cause:
9215
- // ["let {aa,bb} = 0;", "one_space", "expected_space_a_b", "bb", 9]
9560
+ // ["let{aa,bb} = 0;", "one_space", "expected_space_a_b", "bb", 8]
9216
9561
 
9217
- one_space();
9218
- } else {
9562
+ one_space();
9563
+ } else {
9219
9564
 
9220
9565
  // test_cause:
9221
9566
  // ["
@@ -9226,13 +9571,15 @@ function jslint_phase5_whitage(state) {
9226
9571
  // }
9227
9572
  // ", "expected_at", "expected_a_at_b_c", "9", 11]
9228
9573
 
9229
- at_margin(0);
9230
- }
9574
+ at_margin(0);
9575
+ }
9576
+ return;
9577
+ }
9231
9578
 
9232
9579
  // If right is a ternary operator, line it up on the margin.
9233
9580
 
9234
- } else if (right.arity === "ternary") {
9235
- if (open) {
9581
+ if (right.arity === "ternary") {
9582
+ if (open) {
9236
9583
 
9237
9584
  // test_cause:
9238
9585
  // ["
@@ -9243,48 +9590,68 @@ function jslint_phase5_whitage(state) {
9243
9590
  // );
9244
9591
  // ", "expected_at", "expected_a_at_b_c", "5", 1]
9245
9592
 
9246
- at_margin(0);
9247
- } else {
9593
+ at_margin(0);
9594
+ } else {
9248
9595
 
9249
9596
  // test_cause:
9250
- // ["let aa = (aa ? 0 : 1);", "whitage", "use_open", "?", 14]
9597
+ // ["let aa = (aa ? 0 : 1);", "whitage_default", "use_open", "?", 14]
9251
9598
 
9252
- warn("use_open", right);
9253
- }
9254
- } else if (
9255
- right.arity === "binary"
9256
- && right.id === "("
9257
- && free
9258
- ) {
9599
+ warn("use_open", right);
9600
+ }
9601
+ return;
9602
+ }
9603
+ if (
9604
+ right.arity === "binary"
9605
+ && right.id === "("
9606
+ && free
9607
+ ) {
9259
9608
 
9260
9609
  // test_cause:
9261
9610
  // ["let aa = aa(\naa ()\n);", "no_space", "unexpected_space_a_b", "(", 4]
9262
9611
 
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
- ) {
9612
+ no_space();
9613
+ return;
9614
+ }
9615
+ if (
9616
+ left.id === "."
9617
+ || left.id === "?."
9618
+ || left.id === "..."
9619
+ || right.id === ","
9620
+ || right.id === ";"
9621
+ || right.id === ":"
9622
+ || (
9623
+ right.arity === "binary"
9624
+ && (right.id === "(" || right.id === "[")
9625
+ )
9626
+ || (
9627
+ right.arity === "function"
9628
+ && left.id !== "function"
9629
+ )
9630
+ ) {
9281
9631
 
9282
9632
  // test_cause:
9283
9633
  // ["let aa = 0 ;", "no_space_only", "unexpected_space_a_b", ";", 12]
9634
+
9635
+ no_space_only();
9636
+ return;
9637
+ }
9638
+ if (right.id === "." || right.id === "?.") {
9639
+ if (left.line === right.line) {
9640
+
9641
+ // test_cause:
9284
9642
  // ["let aa = aa ?.aa;", "no_space_only", "unexpected_space_a_b", "?.", 13]
9285
9643
 
9286
- no_space_only();
9287
- } else if (left.id === ";") {
9644
+ no_space_only();
9645
+ } else {
9646
+
9647
+ // PR-498 - Relax warning on multiline-method-chaining.
9648
+
9649
+ indent_method_dict[right.line] = true;
9650
+ at_margin(mode_indent);
9651
+ }
9652
+ return;
9653
+ }
9654
+ if (left.id === ";") {
9288
9655
 
9289
9656
  // test_cause:
9290
9657
  // ["
@@ -9300,23 +9667,25 @@ function jslint_phase5_whitage(state) {
9300
9667
  // }
9301
9668
  // ", "expected_at", "expected_a_at_b_c", "9", 1]
9302
9669
 
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
- ) {
9670
+ if (open) {
9671
+ at_margin(0);
9672
+ }
9673
+ return;
9674
+ }
9675
+ if (
9676
+ left.arity === "ternary"
9677
+ || left.id === "case"
9678
+ || left.id === "catch"
9679
+ || left.id === "else"
9680
+ || left.id === "finally"
9681
+ || left.id === "while"
9682
+ || left.id === "await"
9683
+ || right.id === "catch"
9684
+ || right.id === "else"
9685
+ || right.id === "finally"
9686
+ || (right.id === "while" && !right.statement)
9687
+ || (left.id === ")" && right.id === "{")
9688
+ ) {
9320
9689
 
9321
9690
  // test_cause:
9322
9691
  // ["
@@ -9327,58 +9696,106 @@ function jslint_phase5_whitage(state) {
9327
9696
  // }
9328
9697
  // ", "one_space_only", "expected_space_a_b", "(", 12]
9329
9698
 
9330
- one_space_only();
9331
- } else if (
9699
+ one_space_only();
9700
+ return;
9701
+ }
9702
+ if (
9332
9703
 
9333
9704
  // There is a space between left and right.
9334
9705
 
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
- ) {
9706
+ spaceop[left.id] === true
9707
+ || spaceop[right.id] === true
9708
+ || (
9709
+ left.arity === "binary"
9710
+ && (left.id === "+" || left.id === "-")
9711
+ )
9712
+ || (
9713
+ right.arity === "binary"
9714
+ && (right.id === "+" || right.id === "-")
9715
+ )
9716
+ || left.id === "function"
9717
+ || left.id === ":"
9718
+ || left.id === "async"
9719
+ || (
9720
+ (
9721
+ left.identifier
9722
+ || left.id === "(string)"
9723
+ || left.id === "(number)"
9724
+ )
9725
+ && (
9726
+ right.identifier
9727
+ || right.id === "(string)"
9728
+ || right.id === "(number)"
9729
+ )
9730
+ )
9731
+ || (left.arity === "statement" && right.id !== ";")
9732
+ ) {
9362
9733
 
9363
9734
  // test_cause:
9364
9735
  // ["let aa=0;", "one_space", "expected_space_a_b", "0", 8]
9365
9736
  // ["let aa={\naa:\n0\n};", "expected_at", "expected_a_at_b_c", "5", 1]
9366
9737
 
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;
9738
+ one_space();
9739
+ return;
9740
+ }
9741
+ if (left.arity === "unary" && left.id !== "`") {
9742
+ no_space_only();
9743
+ return;
9744
+ }
9745
+ }
9746
+
9747
+ // uninitialized_and_unused();
9748
+ // Delve into the functions looking for variables that were not initialized
9749
+ // or used. If the file imports or exports, then its global object is also
9750
+ // delved.
9751
+
9752
+ if (state.mode_module === true || option_dict.node) {
9753
+ delve(token_global);
9754
+ }
9755
+ catch_list.forEach(delve);
9756
+ function_list.forEach(delve);
9757
+
9758
+ if (option_dict.white) {
9759
+ return;
9760
+ }
9761
+
9762
+ // whitage();
9763
+ // Go through the token list, looking at usage of whitespace.
9764
+
9765
+ token_list.forEach(function (the_token) {
9766
+ right = the_token;
9767
+ if (right.id === "(comment)" || right.id === "(end)") {
9768
+ nr_comments_skipped += 1;
9769
+ return;
9381
9770
  }
9771
+
9772
+ // If left is an opener and right is not the closer, then push the previous
9773
+ // state. If the token following the opener is on the next line, then this is
9774
+ // an open form. If the tokens are on the same line, then it is a closed form.
9775
+ // Open form is more readable, with each item (statement, argument, parameter,
9776
+ // etc) starting on its own line. Closed form is more compact. Statement blocks
9777
+ // are always in open form.
9778
+
9779
+ // The open and close pairs.
9780
+
9781
+ switch (left.id) {
9782
+ case "${":
9783
+ case "(":
9784
+ case "[":
9785
+ case "{":
9786
+ whitage_case();
9787
+ break;
9788
+ default:
9789
+ whitage_default();
9790
+ }
9791
+ nr_comments_skipped = 0;
9792
+ delete left.calls;
9793
+ delete left.dead;
9794
+ delete left.free;
9795
+ delete left.init;
9796
+ delete left.open;
9797
+ delete left.used;
9798
+ left = right;
9382
9799
  });
9383
9800
  }
9384
9801
 
@@ -9420,10 +9837,10 @@ function jslint_report({
9420
9837
  // Google Lighthouse Accessibility - <dl>'s do not contain only properly-ordered
9421
9838
  // <dt> and <dd> groups, <script>, <template> or <div> elements.
9422
9839
 
9423
- "<dl>"
9424
- + "<dt>" + htmlEscape(title) + "</dt>"
9425
- + "<dd>" + list.join(", ") + "</dd>"
9426
- + "</dl>"
9840
+ "<dl>" +
9841
+ "<dt>" + htmlEscape(title) + "</dt>" +
9842
+ "<dd>" + list.map(htmlEscape).join(", ") + "</dd>" +
9843
+ "</dl>"
9427
9844
  )
9428
9845
  : ""
9429
9846
  );
@@ -9905,14 +10322,10 @@ pyNj+JctcQLXenBOCms46aMkenIx45WpXqxxVJQLz/vgpmAVa0fmDv6Pue9xVTBPfVxCUGfj\
9905
10322
  level,
9906
10323
  line,
9907
10324
  name,
9908
-
9909
- // Bugfix - fix html-report from crashing if parameters is undefined.
9910
-
9911
- parameters = [],
10325
+ names = [],
9912
10326
  signature
9913
10327
  } = the_function;
9914
10328
  let list = Object.keys(context);
9915
- let params;
9916
10329
  html += (
9917
10330
  "<div class=\"level level" + htmlEscape(level) + "\">"
9918
10331
  + address(line, from + 1)
@@ -9932,26 +10345,9 @@ pyNj+JctcQLXenBOCms46aMkenIx45WpXqxxVJQLz/vgpmAVa0fmDv6Pue9xVTBPfVxCUGfj\
9932
10345
  )
9933
10346
  + "</dfn>"
9934
10347
  );
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());
10348
+ html += detail("parameter", names.map(function ({id}) {
10349
+ return id;
10350
+ }).sort());
9955
10351
  list.sort();
9956
10352
  html += detail("variable", list.filter(function (id) {
9957
10353
  return (
@@ -11354,13 +11750,9 @@ function sentinel() {}
11354
11750
  // Coverage-hack - Ugly-hack to get test-coverage under both win32 and linux.
11355
11751
 
11356
11752
  if (processArgv0 === "npm") {
11357
- processArgv0 = process.platform.replace(
11358
- "win32",
11359
- "npm.cmd"
11360
- ).replace(
11361
- process.platform,
11362
- "npm"
11363
- );
11753
+ processArgv0 = process.platform
11754
+ .replace("win32", "npm.cmd")
11755
+ .replace(process.platform, "npm");
11364
11756
  }
11365
11757
  moduleChildProcess.spawn(
11366
11758
  processArgv0,