@jslint-org/jslint 2021.11.20 → 2022.3.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/jslint.mjs CHANGED
@@ -94,6 +94,8 @@
94
94
  /*jslint beta, node*/
95
95
 
96
96
  /*property
97
+ fud_stmt,
98
+ is_fart,
97
99
  mode_conditional,
98
100
  JSLINT_BETA, NODE_V8_COVERAGE, a, all, argv, arity, artifact,
99
101
  assertErrorThrownAsync, assertJsonEqual, assertOrThrow, assign, async, b,
@@ -107,7 +109,7 @@
107
109
  example_list, exec, execArgv, exit, export_dict, exports, expression, extra,
108
110
  file, fileList, fileURLToPath, filter, finally, flag, floor, for, forEach,
109
111
  formatted_message, free, freeze, from, froms,
110
- fsWriteFileWithParents, fud, functionName, function_list, function_stack,
112
+ fsWriteFileWithParents, functionName, function_list, function_stack,
111
113
  functions, get, getset, github_repo, global, global_dict, global_list,
112
114
  holeList, htmlEscape, id, identifier, import, import_list, inc, indent2,
113
115
  index, indexOf, init, initial, isArray, isBlockCoverage, isHole, isNaN,
@@ -115,13 +117,13 @@
115
117
  jslint_charset_ascii, jslint_cli, jslint_edition, jslint_phase1_split,
116
118
  jslint_phase2_lex, jslint_phase3_parse, jslint_phase4_walk,
117
119
  jslint_phase5_whitage, jslint_report, json, jstestDescribe, jstestIt,
118
- jstestOnExit, keys, label, lbp, led, length, level, line, lineList,
120
+ jstestOnExit, keys, label, lbp, led_infix, length, level, line, lineList,
119
121
  line_list, line_offset, line_source, lines, linesCovered, linesTotal, live,
120
122
  log, long, loop, m, main, map, margin, match, max, message, meta, min,
121
123
  mkdir, modeCoverageIgnoreFile, modeIndex, mode_cli, mode_json, mode_module,
122
124
  mode_noop, mode_property, mode_shebang, mode_stop, module, moduleFsInit,
123
125
  moduleName, module_list, name, names, node, noop, now,
124
- nr, nud, objectDeepCopyWithKeysSorted, ok, on, open, opening, option,
126
+ nr, nud_prefix, objectDeepCopyWithKeysSorted, ok, on, open, opening, option,
125
127
  option_dict, order, package_name, padEnd, padStart, parameters, parent,
126
128
  parentIi, parse, pathname, platform, pop, processArgv, process_argv,
127
129
  process_env, process_exit, process_version, promises, property,
@@ -165,11 +167,96 @@ let jslint_charset_ascii = (
165
167
  + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
166
168
  + "`abcdefghijklmnopqrstuvwxyz{|}~\u007f"
167
169
  );
168
- let jslint_edition = "v2021.11.20";
170
+ let jslint_edition = "v2022.3.30";
169
171
  let jslint_export; // The jslint object to be exported.
170
172
  let jslint_fudge = 1; // Fudge starting line and starting
171
173
  // ... column to 1.
172
174
  let jslint_import_meta_url = ""; // import.meta.url used by cli.
175
+ let jslint_rgx_cap = (
176
+ /^[A-Z]/
177
+ );
178
+ let jslint_rgx_crlf = (
179
+ /\n|\r\n?/
180
+ );
181
+ let jslint_rgx_digits_bits = (
182
+ /^[01_]*/
183
+ );
184
+ let jslint_rgx_digits_decimals = (
185
+ /^[0-9_]*/
186
+ );
187
+ let jslint_rgx_digits_hexs = (
188
+ /^[0-9A-F_]*/i
189
+ );
190
+ let jslint_rgx_digits_octals = (
191
+ /^[0-7_]*/
192
+ );
193
+ let jslint_rgx_directive = (
194
+ /^(jslint|property|global)\s+(.*)$/
195
+ );
196
+ let jslint_rgx_directive_part = (
197
+ /([a-zA-Z$_][a-zA-Z0-9$_]*)(?::\s*(true|false))?,?\s*|$/g
198
+ );
199
+ let jslint_rgx_identifier = (
200
+ /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/
201
+ );
202
+ let jslint_rgx_json_number = (
203
+
204
+ // https://datatracker.ietf.org/doc/html/rfc7159#section-6
205
+ // number = [ minus ] int [ frac ] [ exp ]
206
+
207
+ /^-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][\-+]?\d+)?$/
208
+ );
209
+ let jslint_rgx_mega = (
210
+
211
+ // Vim-hack - vim-editor has trouble parsing naked '`' in regexp
212
+
213
+ /[\u0060\\]|\$\{/
214
+ );
215
+ let jslint_rgx_module = (
216
+ /^[a-zA-Z0-9_$:.@\-\/]+$/
217
+ );
218
+ let jslint_rgx_numeric_separator_illegal = (
219
+ /__|_$|_n$/m
220
+ );
221
+ let jslint_rgx_slash_star_or_slash = (
222
+ /\/\*|\/$/
223
+ );
224
+ let jslint_rgx_tab = (
225
+ /\t/g
226
+ );
227
+ let jslint_rgx_todo = (
228
+ /\b(?:todo|TO\s?DO|HACK)\b/
229
+ );
230
+ let jslint_rgx_token = new RegExp(
231
+ "^("
232
+ + "(\\s+)"
233
+ + "|([a-zA-Z_$][a-zA-Z0-9_$]*)"
234
+ + "|[(){}\\[\\],:;'\"~\\`]"
235
+ + "|\\?[?.]?"
236
+ + "|=(?:==?|>)?"
237
+ + "|\\.+"
238
+ + "|\\*[*\\/=]?"
239
+ + "|\\/[*\\/]?"
240
+ + "|\\+[=+]?"
241
+ + "|-[=\\-]?"
242
+ + "|[\\^%]=?"
243
+ + "|&[&=]?"
244
+ + "|\\"
245
+ + "|[|=]?"
246
+ + "|>{1,3}=?"
247
+ + "|<<?=?"
248
+ + "|!(?:!|==?)?"
249
+
250
+ // PR-351 - Add BigInt support.
251
+ // PR-390 - Add numeric-separator support.
252
+
253
+ + "|((?:0_?|[1-9][0-9_]*)n?)"
254
+ + ")"
255
+ + "(.*)$"
256
+ );
257
+ let jslint_rgx_weird_property = (
258
+ /^_|\$|Sync$|_$/m
259
+ );
173
260
  let jstestCountFailed = 0;
174
261
  let jstestCountTotal = 0;
175
262
  let jstestItCount = 0;
@@ -202,13 +289,16 @@ function assertJsonEqual(aa, bb, message) {
202
289
 
203
290
  // This function will assert JSON.stringify(<aa>) === JSON.stringify(<bb>).
204
291
 
205
- aa = JSON.stringify(objectDeepCopyWithKeysSorted(aa));
206
- bb = JSON.stringify(objectDeepCopyWithKeysSorted(bb));
292
+ aa = JSON.stringify(objectDeepCopyWithKeysSorted(aa), undefined, 1);
293
+ bb = JSON.stringify(objectDeepCopyWithKeysSorted(bb), undefined, 1);
207
294
  if (aa !== bb) {
208
295
  throw new Error(
209
- JSON.stringify(aa) + " !== " + JSON.stringify(bb) + (
210
- message
296
+ "\n" + aa + "\n!==\n" + bb
297
+ + (
298
+ typeof message === "string"
211
299
  ? " - " + message
300
+ : message
301
+ ? " - " + JSON.stringify(message)
212
302
  : ""
213
303
  )
214
304
  );
@@ -302,10 +392,7 @@ function jslint(
302
392
  let import_list = []; // The array collecting all import-from strings.
303
393
  let line_list = String( // The array containing source lines.
304
394
  "\n" + source
305
- ).split(
306
- // rx_crlf
307
- /\n|\r\n?/
308
- ).map(function (line_source) {
395
+ ).split(jslint_rgx_crlf).map(function (line_source) {
309
396
  return {
310
397
  line_source
311
398
  };
@@ -676,8 +763,17 @@ function jslint(
676
763
  `Expected 'Object.freeze('. All export values should be frozen.`
677
764
  );
678
765
  break;
679
- case "function_in_loop":
680
- mm = `Don't create functions within a loop.`;
766
+
767
+ // PR-378 - Relax warning "function_in_loop".
768
+ //
769
+ // case "function_in_loop":
770
+ // mm = `Don't create functions within a loop.`;
771
+ // break;
772
+
773
+ // PR-390 - Add numeric-separator check.
774
+
775
+ case "illegal_num_separator":
776
+ mm = `Illegal numeric separator '_' at column ${column}.`;
681
777
  break;
682
778
  case "infix_in":
683
779
  mm = (
@@ -831,6 +927,15 @@ function jslint(
831
927
  case "use_double":
832
928
  mm = `Use double quotes, not single quotes.`;
833
929
  break;
930
+
931
+ // PR-386 - Fix issue #382 - Make fart-related warnings more readable.
932
+
933
+ case "use_function_not_fart":
934
+ mm = (
935
+ `Use 'function (...)', not '(...) =>' when arrow functions`
936
+ + ` become too complex.`
937
+ );
938
+ break;
834
939
  case "use_open":
835
940
  mm = (
836
941
  `Wrap a ternary expression in parens,`
@@ -864,6 +969,12 @@ function jslint(
864
969
  case "wrap_condition":
865
970
  mm = `Wrap the condition in parens.`;
866
971
  break;
972
+
973
+ // PR-386 - Fix issue #382 - Make fart-related warnings more readable.
974
+
975
+ case "wrap_fart_parameter":
976
+ mm = `Wrap the parameter before '=>' in parens.`;
977
+ break;
867
978
  case "wrap_immediate":
868
979
  mm = (
869
980
  `Wrap an immediate function invocation in parentheses to assist`
@@ -871,9 +982,6 @@ function jslint(
871
982
  + ` result of a function, and not the function itself.`
872
983
  );
873
984
  break;
874
- case "wrap_parameter":
875
- mm = `Wrap the parameter in parens.`;
876
- break;
877
985
  case "wrap_regexp":
878
986
  mm = `Wrap this regexp in parens to avoid confusion.`;
879
987
  break;
@@ -1449,8 +1557,8 @@ async function jslint_cli({
1449
1557
  let command;
1450
1558
  let data;
1451
1559
  let exit_code = 0;
1452
- let mode_plugin_vim;
1453
1560
  let mode_report;
1561
+ let mode_wrapper_vim;
1454
1562
  let result;
1455
1563
 
1456
1564
  function jslint_from_file({
@@ -1523,7 +1631,7 @@ async function jslint_cli({
1523
1631
  if (result_from_file.warnings.length > 0) {
1524
1632
  exit_code = 1;
1525
1633
  console_error(
1526
- mode_plugin_vim
1634
+ mode_wrapper_vim
1527
1635
 
1528
1636
  // PR-349 - Print warnings in format readable by vim.
1529
1637
 
@@ -1656,17 +1764,17 @@ async function jslint_cli({
1656
1764
  }));
1657
1765
  return;
1658
1766
 
1659
- // COMMIT-b26d6df2 - Add command jslint_plugin_vim.
1767
+ // PR-363 - Add command jslint_report.
1660
1768
 
1661
- case "jslint_plugin_vim":
1662
- mode_plugin_vim = true;
1769
+ case "jslint_report":
1770
+ mode_report = command[1];
1663
1771
  process_argv = process_argv.slice(1);
1664
1772
  break;
1665
1773
 
1666
- // PR-363 - Add command jslint_report.
1774
+ // COMMIT-b26d6df2 - Add command jslint_wrapper_vim.
1667
1775
 
1668
- case "jslint_report":
1669
- mode_report = command[1];
1776
+ case "jslint_wrapper_vim":
1777
+ mode_wrapper_vim = true;
1670
1778
  process_argv = process_argv.slice(1);
1671
1779
  break;
1672
1780
 
@@ -1674,6 +1782,7 @@ async function jslint_cli({
1674
1782
 
1675
1783
  case "v8_coverage_report":
1676
1784
  await v8CoverageReportCreate({
1785
+ consoleError: console_error,
1677
1786
  coverageDir: command[1],
1678
1787
  processArgv: process_argv.slice(3)
1679
1788
  });
@@ -1682,9 +1791,9 @@ async function jslint_cli({
1682
1791
 
1683
1792
  // PR-349 - Detect cli-option --mode-vim-plugin.
1684
1793
 
1685
- mode_plugin_vim = (
1794
+ mode_wrapper_vim = (
1686
1795
  process_argv.slice(2).indexOf("--mode-vim-plugin") >= 0
1687
- || mode_plugin_vim
1796
+ || mode_wrapper_vim
1688
1797
  );
1689
1798
 
1690
1799
  // Normalize file relative to process.cwd().
@@ -1820,37 +1929,16 @@ function jslint_phase2_lex(state) {
1820
1929
  let line_mega; // The starting line of megastring.
1821
1930
  let line_source = ""; // The remaining line source string.
1822
1931
  let line_whole = ""; // The whole line source string.
1932
+ let mode_digits_empty_string = 1;
1933
+ let mode_digits_numeric_separator = 2;
1823
1934
  let mode_directive = true; // true if directives are still allowed.
1824
1935
  let mode_mega = false; // true if currently parsing a megastring
1825
1936
  // ... literal.
1826
1937
  let mode_regexp; // true if regular expression literal seen on
1827
1938
  // ... this line.
1828
- let rx_token = new RegExp(
1829
- "^("
1830
- + "(\\s+)"
1831
- + "|([a-zA-Z_$][a-zA-Z0-9_$]*)"
1832
- + "|[(){}\\[\\],:;'\"~\\`]"
1833
- + "|\\?[?.]?"
1834
- + "|=(?:==?|>)?"
1835
- + "|\\.+"
1836
- + "|\\*[*\\/=]?"
1837
- + "|\\/[*\\/]?"
1838
- + "|\\+[=+]?"
1839
- + "|-[=\\-]?"
1840
- + "|[\\^%]=?"
1841
- + "|&[&=]?"
1842
- + "|\\"
1843
- + "|[|=]?"
1844
- + "|>{1,3}=?"
1845
- + "|<<?=?"
1846
- + "|!(?:!|==?)?"
1847
-
1848
- // PR-351 - Add BigInt support.
1849
-
1850
- + "|(0n?|[1-9][0-9]*n?)"
1851
- + ")"
1852
- + "(.*)$"
1853
- );
1939
+ let paren_backtrack_list = []; // List of most recent "(" tokens at any
1940
+ // ... paren-depth.
1941
+ let paren_depth = 0; // Keeps track of current paren-depth.
1854
1942
  let snippet = ""; // A piece of string.
1855
1943
  let token_1; // The first token.
1856
1944
  let token_prv = token_global; // The previous token including
@@ -1932,7 +2020,7 @@ function jslint_phase2_lex(state) {
1932
2020
 
1933
2021
  warn_at("unexpected_a", line, column, char);
1934
2022
  }
1935
- if (read_digits("x") > 5) {
2023
+ if (read_digits("x", undefined) > 5) {
1936
2024
 
1937
2025
  // test_cause:
1938
2026
  // ["\"\\u{123456}\"", "char_after_escape", "too_many_digits", "", 11]
@@ -1949,7 +2037,7 @@ function jslint_phase2_lex(state) {
1949
2037
  return char_after();
1950
2038
  }
1951
2039
  char_before();
1952
- if (read_digits("x", true) < 4) {
2040
+ if (read_digits("x", mode_digits_empty_string) < 4) {
1953
2041
 
1954
2042
  // test_cause:
1955
2043
  // ["\"\\u0\"", "char_after_escape", "expected_four_digits", "", 5]
@@ -1984,6 +2072,26 @@ function jslint_phase2_lex(state) {
1984
2072
  return char;
1985
2073
  }
1986
2074
 
2075
+ function check_numeric_separator(digits, column) {
2076
+
2077
+ // This function will check for illegal numeric-separator in <digits>.
2078
+
2079
+ digits.replace((
2080
+ jslint_rgx_numeric_separator_illegal
2081
+ ), function (ignore, ii) {
2082
+
2083
+ // test_cause:
2084
+ // ["0x0_0_;", "check_numeric_separator", "illegal_num_separator", "", 6]
2085
+ // ["0x0_0__0;", "check_numeric_separator", "illegal_num_separator", "", 6]
2086
+ // ["aa=1_2_;", "check_numeric_separator", "illegal_num_separator", "", 7]
2087
+ // ["aa=1_2__3;", "check_numeric_separator", "illegal_num_separator", "", 7]
2088
+ // ["aa=1_2_n;", "check_numeric_separator", "illegal_num_separator", "", 7]
2089
+
2090
+ warn_at("illegal_num_separator", line, column + ii + 1);
2091
+ return "";
2092
+ });
2093
+ }
2094
+
1987
2095
  function lex_comment() {
1988
2096
  let body;
1989
2097
  let ii = 0;
@@ -2022,12 +2130,12 @@ function jslint_phase2_lex(state) {
2022
2130
  // Lex/loop through each line until "*/".
2023
2131
 
2024
2132
  while (true) {
2025
- // rx_star_slash
2133
+ // jslint_rgx_star_slash
2026
2134
  ii = line_source.indexOf("*/");
2027
2135
  if (ii >= 0) {
2028
2136
  break;
2029
2137
  }
2030
- // rx_slash_star
2138
+ // jslint_rgx_slash_star
2031
2139
  ii = line_source.indexOf("/*");
2032
2140
  if (ii >= 0) {
2033
2141
 
@@ -2047,8 +2155,7 @@ function jslint_phase2_lex(state) {
2047
2155
  }
2048
2156
  }
2049
2157
  jj = line_source.slice(0, ii).search(
2050
- // rx_slash_star_or_slash
2051
- /\/\*|\/$/
2158
+ jslint_rgx_slash_star_or_slash
2052
2159
  );
2053
2160
  if (jj >= 0) {
2054
2161
 
@@ -2066,13 +2173,7 @@ function jslint_phase2_lex(state) {
2066
2173
 
2067
2174
  // Uncompleted work comment.
2068
2175
 
2069
- if (
2070
- !option_dict.devel
2071
- && (
2072
- // rx_todo
2073
- /\b(?:todo|TO\s?DO|HACK)\b/
2074
- ).test(snippet)
2075
- ) {
2176
+ if (!option_dict.devel && jslint_rgx_todo.test(snippet)) {
2076
2177
 
2077
2178
  // test_cause:
2078
2179
  // ["//todo", "lex_comment", "todo_comment", "(comment)", 1] //jslint-quiet
@@ -2084,10 +2185,7 @@ function jslint_phase2_lex(state) {
2084
2185
 
2085
2186
  [
2086
2187
  the_comment.directive, body
2087
- ] = Array.from(snippet.match(
2088
- // rx_directive
2089
- /^(jslint|property|global)\s+(.*)$/
2090
- ) || []).slice(1);
2188
+ ] = Array.from(snippet.match(jslint_rgx_directive) || []).slice(1);
2091
2189
  if (the_comment.directive === undefined) {
2092
2190
  return the_comment;
2093
2191
  }
@@ -2109,10 +2207,12 @@ function jslint_phase2_lex(state) {
2109
2207
  // Lex/loop through each directive in /*...*/
2110
2208
 
2111
2209
  ii = 0;
2112
- body.replace((
2113
- // rx_directive_part
2114
- /([a-zA-Z$_][a-zA-Z0-9$_]*)(?::\s*(true|false))?,?\s*|$/g
2115
- ), function (match0, key, val, jj) {
2210
+ body.replace(jslint_rgx_directive_part, function (
2211
+ match0,
2212
+ key,
2213
+ val,
2214
+ jj
2215
+ ) {
2116
2216
  if (ii !== jj) {
2117
2217
 
2118
2218
  // test_cause:
@@ -2186,13 +2286,7 @@ function jslint_phase2_lex(state) {
2186
2286
  // string.
2187
2287
 
2188
2288
  while (true) {
2189
- match = line_source.match(
2190
-
2191
- // Vim-hack - vim-editor has trouble parsing '`' in regexp
2192
-
2193
- // rx_mega
2194
- /[\u0060\\]|\$\{/
2195
- ) || {
2289
+ match = line_source.match(jslint_rgx_mega) || {
2196
2290
  "0": "",
2197
2291
  index: 0
2198
2292
  };
@@ -2269,12 +2363,16 @@ function jslint_phase2_lex(state) {
2269
2363
 
2270
2364
  function lex_number() {
2271
2365
  let prefix = snippet;
2366
+
2367
+ // PR-390 - Add numeric-separator check.
2368
+
2369
+ check_numeric_separator(prefix, column - prefix.length);
2272
2370
  char_after();
2273
2371
  switch (prefix === "0" && char) {
2274
2372
  case "b":
2275
2373
  case "o":
2276
2374
  case "x":
2277
- read_digits(char);
2375
+ read_digits(char, mode_digits_numeric_separator);
2278
2376
 
2279
2377
  // PR-351 - Ignore BigInt suffix 'n'.
2280
2378
 
@@ -2284,14 +2382,14 @@ function jslint_phase2_lex(state) {
2284
2382
  break;
2285
2383
  default:
2286
2384
  if (char === ".") {
2287
- read_digits("d");
2385
+ read_digits("d", mode_digits_numeric_separator);
2288
2386
  }
2289
2387
  if (char === "E" || char === "e") {
2290
2388
  char_after(char);
2291
2389
  if (char !== "+" && char !== "-") {
2292
2390
  char_before();
2293
2391
  }
2294
- read_digits("d");
2392
+ read_digits("d", mode_digits_numeric_separator);
2295
2393
  }
2296
2394
  }
2297
2395
 
@@ -2561,7 +2659,7 @@ function jslint_phase2_lex(state) {
2561
2659
  }
2562
2660
  break;
2563
2661
  case "{":
2564
- if (read_digits("d", true) === 0) {
2662
+ if (read_digits("d", mode_digits_empty_string) === 0) {
2565
2663
 
2566
2664
  // test_cause:
2567
2665
  // ["aa=/aa{/", "lex_regexp_group", "expected_a_before_b", ",", 8]
@@ -2574,7 +2672,7 @@ function jslint_phase2_lex(state) {
2574
2672
  // ["aa=/.{,/", "lex_regexp_group", "comma", "", 0]
2575
2673
 
2576
2674
  test_cause("comma");
2577
- read_digits("d", true);
2675
+ read_digits("d", mode_digits_empty_string);
2578
2676
  }
2579
2677
  if (char_after("}") === "?") {
2580
2678
 
@@ -2867,7 +2965,7 @@ function jslint_phase2_lex(state) {
2867
2965
  }
2868
2966
  }
2869
2967
  from = column;
2870
- match = line_source.match(rx_token);
2968
+ match = line_source.match(jslint_rgx_token);
2871
2969
 
2872
2970
  // match[1] token
2873
2971
  // match[2] whitespace
@@ -3028,6 +3126,7 @@ console.log(JSON.stringify(Object.keys(window).sort(), undefined, 4));
3028
3126
 
3029
3127
  // Window.
3030
3128
 
3129
+ "Blob",
3031
3130
  // "CharacterData",
3032
3131
  // "DocumentType",
3033
3132
  // "Element",
@@ -3186,7 +3285,7 @@ node --input-type=module --eval '
3186
3285
  // /\*jslint beta, node*\/
3187
3286
  import moduleHttps from "https";
3188
3287
  (async function () {
3189
- let dict = {};
3288
+ let dict = Object.create(null);
3190
3289
  let result = "";
3191
3290
  await new Promise(function (resolve) {
3192
3291
  moduleHttps.get((
@@ -3249,41 +3348,48 @@ import moduleHttps from "https";
3249
3348
  return true;
3250
3349
  }
3251
3350
 
3252
- function read_digits(base, quiet) {
3351
+ function read_digits(base, mode) {
3253
3352
  let digits = line_source.match(
3254
3353
  base === "b"
3255
- ? (
3256
- // rx_bits
3257
- /^[01]*/
3258
- )
3354
+ ? jslint_rgx_digits_bits
3259
3355
  : base === "o"
3260
- ? (
3261
- // rx_octals
3262
- /^[0-7]*/
3263
- )
3356
+ ? jslint_rgx_digits_octals
3264
3357
  : base === "x"
3265
- ? (
3266
- // rx_hexs
3267
- /^[0-9A-F]*/i
3268
- )
3269
- : (
3270
- // rx_digits
3271
- /^[0-9]*/
3272
- )
3358
+ ? jslint_rgx_digits_hexs
3359
+ : jslint_rgx_digits_decimals
3273
3360
  )[0];
3274
- let length = digits.length;
3275
- if (!quiet && length === 0) {
3361
+ if (
3362
+ (mode !== mode_digits_empty_string && digits.length === 0)
3363
+ || digits[0] === "_"
3364
+ ) {
3276
3365
 
3277
3366
  // test_cause:
3278
3367
  // ["0x", "read_digits", "expected_digits_after_a", "0x", 2]
3368
+ // ["0x_", "read_digits", "expected_digits_after_a", "0x", 2]
3279
3369
 
3280
3370
  warn_at("expected_digits_after_a", line, column, snippet);
3281
3371
  }
3282
- column += length;
3283
- line_source = line_source.slice(length);
3372
+
3373
+ // PR-390 - Add numeric-separator check.
3374
+
3375
+ if (mode === mode_digits_numeric_separator) {
3376
+ check_numeric_separator(digits, column);
3377
+ } else if (digits.indexOf("_") >= 0) {
3378
+
3379
+ // test_cause:
3380
+ // ["\"\\u{1_2}\"", "read_digits", "illegal_num_separator", "", 6]
3381
+
3382
+ warn_at(
3383
+ "illegal_num_separator",
3384
+ line,
3385
+ column + digits.indexOf("_") + 1
3386
+ );
3387
+ }
3388
+ column += digits.length;
3389
+ line_source = line_source.slice(digits.length);
3284
3390
  snippet += digits;
3285
3391
  char_after();
3286
- return length;
3392
+ return digits.length;
3287
3393
  }
3288
3394
 
3289
3395
  function read_line() {
@@ -3354,6 +3460,7 @@ import moduleHttps from "https";
3354
3460
  test_cause("line_disable");
3355
3461
  line_source = "";
3356
3462
  }
3463
+ // jslint_rgx_tab
3357
3464
  if (line_source.indexOf("\t") >= 0) {
3358
3465
  if (!option_dict.white) {
3359
3466
 
@@ -3362,10 +3469,7 @@ import moduleHttps from "https";
3362
3469
 
3363
3470
  warn_at("use_spaces", line, line_source.indexOf("\t") + 1);
3364
3471
  }
3365
- line_source = line_source.replace((
3366
- // rx_tab
3367
- /\t/g
3368
- ), " ");
3472
+ line_source = line_source.replace(jslint_rgx_tab, " ");
3369
3473
  }
3370
3474
  if (!option_dict.white && line_source.endsWith(" ")) {
3371
3475
 
@@ -3385,9 +3489,11 @@ import moduleHttps from "https";
3385
3489
  from,
3386
3490
  id,
3387
3491
  identifier: Boolean(identifier),
3492
+ is_fart: false,
3388
3493
  line,
3389
3494
  nr: token_list.length,
3390
- thru: column
3495
+ thru: column,
3496
+ value
3391
3497
  };
3392
3498
  token_list.push(the_token);
3393
3499
 
@@ -3397,12 +3503,6 @@ import moduleHttps from "https";
3397
3503
  mode_directive = false;
3398
3504
  }
3399
3505
 
3400
- // If the token is to have a value, give it one.
3401
-
3402
- if (value !== undefined) {
3403
- the_token.value = value;
3404
- }
3405
-
3406
3506
  // If this token is an identifier that touches a preceding number, or
3407
3507
  // a "/", comment, or regular expression literal that touches a preceding
3408
3508
  // comment or regular expression literal, then give a missing space warning.
@@ -3436,6 +3536,29 @@ import moduleHttps from "https";
3436
3536
  the_token.dot = true;
3437
3537
  }
3438
3538
 
3539
+ // PR-385 - Bugfix - Fixes issue #382 - failure to detect destructured fart.
3540
+ // Farts are now detected by keeping a list of most recent "(" tokens at any
3541
+ // given depth. When a "=>" token is encountered, the most recent "(" token at
3542
+ // current depth is marked as a fart.
3543
+
3544
+ switch (id) {
3545
+ case "(":
3546
+ paren_backtrack_list[paren_depth] = the_token;
3547
+ paren_depth += 1;
3548
+ break;
3549
+ case ")":
3550
+ paren_depth -= 1;
3551
+ break;
3552
+ case "=>":
3553
+ if (
3554
+ token_prv_expr.id === ")"
3555
+ && paren_backtrack_list[paren_depth]
3556
+ ) {
3557
+ paren_backtrack_list[paren_depth].is_fart = true;
3558
+ }
3559
+ break;
3560
+ }
3561
+
3439
3562
  // The previous token is used to detect adjacency problems.
3440
3563
 
3441
3564
  token_prv = the_token;
@@ -3520,9 +3643,6 @@ function jslint_phase3_parse(state) {
3520
3643
  let catchage = catch_stack[0]; // The current catch-block.
3521
3644
  let functionage = token_global; // The current function.
3522
3645
  let mode_var; // "var" if using var; "let" if using let.
3523
- let rx_identifier = (
3524
- /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/
3525
- );
3526
3646
  let token_ii = 0; // The number of the next token.
3527
3647
  let token_now = token_global; // The current token being examined in
3528
3648
  // ... the parse.
@@ -3539,7 +3659,7 @@ function jslint_phase3_parse(state) {
3539
3659
  anon = token_now.id;
3540
3660
  } else if (
3541
3661
  token_now.id === "(string)"
3542
- && rx_identifier.test(token_now.value)
3662
+ && jslint_rgx_identifier.test(token_now.value)
3543
3663
  ) {
3544
3664
  anon = token_now.value;
3545
3665
  }
@@ -3551,7 +3671,7 @@ function jslint_phase3_parse(state) {
3551
3671
  match === undefined
3552
3672
 
3553
3673
  // test_cause:
3554
- // ["()", "advance", "expected_a_b", "(end)", 1]
3674
+ // ["{0:0}", "advance", "expected_a_b", "0", 2]
3555
3675
 
3556
3676
  ? stop("expected_a_b", token_nxt, id, artifact())
3557
3677
 
@@ -3600,7 +3720,7 @@ function jslint_phase3_parse(state) {
3600
3720
  // other assignment operators can modify, but they cannot initialize.
3601
3721
 
3602
3722
  const the_symbol = symbol(id, 20);
3603
- the_symbol.led = function (left) {
3723
+ the_symbol.led_infix = function (left) {
3604
3724
  const the_token = token_now;
3605
3725
  let right;
3606
3726
  the_token.arity = "assignment";
@@ -3912,7 +4032,7 @@ function jslint_phase3_parse(state) {
3912
4032
 
3913
4033
  const the_symbol = symbol(id);
3914
4034
  the_symbol.constant = true;
3915
- the_symbol.nud = (
4035
+ the_symbol.nud_prefix = (
3916
4036
  typeof value === "function"
3917
4037
  ? value
3918
4038
  : function () {
@@ -4106,7 +4226,7 @@ function jslint_phase3_parse(state) {
4106
4226
  // Create an infix operator.
4107
4227
 
4108
4228
  const the_symbol = symbol(id, bp);
4109
- the_symbol.led = function (left) {
4229
+ the_symbol.led_infix = function (left) {
4110
4230
  const the_token = token_now;
4111
4231
  the_token.arity = "binary";
4112
4232
  if (f !== undefined) {
@@ -4164,12 +4284,12 @@ function jslint_phase3_parse(state) {
4164
4284
  return the_token;
4165
4285
  }
4166
4286
 
4167
- function infix_fart_unwrapped(left) {
4287
+ function infix_fart_unwrapped() {
4168
4288
 
4169
4289
  // test_cause:
4170
- // ["aa=>0", "infix_fart_unwrapped", "wrap_parameter", "aa", 1]
4290
+ // ["aa=>0", "infix_fart_unwrapped", "wrap_fart_parameter", "=>", 3]
4171
4291
 
4172
- return stop("wrap_parameter", left);
4292
+ return stop("wrap_fart_parameter", token_now);
4173
4293
  }
4174
4294
 
4175
4295
  function infix_grave(left) {
@@ -4189,7 +4309,7 @@ function jslint_phase3_parse(state) {
4189
4309
  let the_subscript = parse_expression(0);
4190
4310
  if (the_subscript.id === "(string)" || the_subscript.id === "`") {
4191
4311
  name = survey(the_subscript);
4192
- if (rx_identifier.test(name)) {
4312
+ if (jslint_rgx_identifier.test(name)) {
4193
4313
 
4194
4314
  // test_cause:
4195
4315
  // ["aa[`aa`]", "infix_lbracket", "subscript_a", "aa", 4]
@@ -4332,13 +4452,13 @@ function jslint_phase3_parse(state) {
4332
4452
  // Create a right associative infix operator.
4333
4453
 
4334
4454
  const the_symbol = symbol(id, bp);
4335
- the_symbol.led = function parse_infixr_led(left) {
4455
+ the_symbol.led_infix = function parse_infixr_led(left) {
4336
4456
  const the_token = token_now;
4337
4457
 
4338
4458
  // test_cause:
4339
- // ["0**0", "parse_infixr_led", "led", "", 0]
4459
+ // ["0**0", "parse_infixr_led", "led_infix", "", 0]
4340
4460
 
4341
- test_cause("led");
4461
+ test_cause("led_infix");
4342
4462
  the_token.arity = "binary";
4343
4463
  the_token.expression = [left, parse_expression(bp - 1)];
4344
4464
  return the_token;
@@ -4346,39 +4466,70 @@ function jslint_phase3_parse(state) {
4346
4466
  return the_symbol;
4347
4467
  }
4348
4468
 
4349
- function lookahead() {
4350
-
4351
- // Look ahead one token without advancing, skipping comments.
4352
-
4353
- let cadet;
4354
- let ii = token_ii;
4355
- while (true) {
4356
- cadet = token_list[ii];
4357
- if (cadet.id !== "(comment)") {
4358
- return cadet;
4359
- }
4360
- ii += 1;
4361
- }
4362
- }
4363
-
4364
4469
  function parse_expression(rbp, initial) {
4365
4470
 
4366
4471
  // This is the heart of JSLINT, the Pratt parser. In addition to parsing, it
4367
- // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
4368
- // like .nud except that it is only used on the first token of a statement.
4369
- // Having .fud makes it much easier to define statement-oriented languages like
4370
- // JavaScript. I retained Pratt's nomenclature.
4472
+ // is looking for ad hoc lint patterns. We add .fud_stmt to Pratt's model, which
4473
+ // is like .nud_prefix except that it is only used on the first token of a
4474
+ // statement. Having .fud_stmt makes it much easier to define statement-oriented
4475
+ // languages like JavaScript. I retained Pratt's nomenclature.
4371
4476
  // They are elements of the parsing method called Top Down Operator Precedence.
4372
4477
 
4373
- // .nud Null denotation
4374
- // .fud First null denotation
4375
- // .led Left denotation
4376
- // lbp Left binding power
4377
- // rbp Right binding power
4378
-
4379
- // It processes a nud (variable, constant, prefix operator). It will then
4380
- // process leds (infix operators) until the bind powers cause it to stop. It
4381
- // returns the expression's parse tree.
4478
+ // .nud_prefix Null denotation. The prefix handler.
4479
+ // .fud_stmt First null denotation. The statement handler.
4480
+ // .led_infix Left denotation. The infix/postfix handler.
4481
+ // lbp Left binding power of infix operator. It tells us how strongly
4482
+ // the operator binds to the argument at its left.
4483
+ // rbp Right binding power.
4484
+
4485
+ // It processes a nud_prefix (variable, constant, prefix operator). It will then
4486
+ // process leds (infix operators) until the bind powers cause it to stop (it
4487
+ // consumes tokens until it meets a token whose lbp <= rbp). Specifically, it
4488
+ // means that it collects all tokens that bind together before returning to the
4489
+ // operator that called it. It returns the expression's parse tree.
4490
+
4491
+ // For example, "3 + 1 * 2 * 4 + 5"
4492
+ // parses into
4493
+ // {
4494
+ // "id": "+",
4495
+ // "expression": [
4496
+ // {
4497
+ // "id": "+",
4498
+ // "expression": [
4499
+ // {
4500
+ // "id": "(number)",
4501
+ // "value": "3"
4502
+ // },
4503
+ // {
4504
+ // "id": "*",
4505
+ // "expression": [
4506
+ // {
4507
+ // "id": "*",
4508
+ // "expression": [
4509
+ // {
4510
+ // "id": "(number)",
4511
+ // "value": "1"
4512
+ // },
4513
+ // {
4514
+ // "id": "(number)",
4515
+ // "value": "2"
4516
+ // }
4517
+ // ]
4518
+ // },
4519
+ // {
4520
+ // "id": "(number)",
4521
+ // "value": "4"
4522
+ // }
4523
+ // ]
4524
+ // }
4525
+ // ]
4526
+ // },
4527
+ // {
4528
+ // "id": "(number)",
4529
+ // "value": "5"
4530
+ // }
4531
+ // ]
4532
+ // }
4382
4533
 
4383
4534
  let left;
4384
4535
  let the_symbol;
@@ -4390,13 +4541,13 @@ function jslint_phase3_parse(state) {
4390
4541
  advance();
4391
4542
  }
4392
4543
  the_symbol = syntax_dict[token_now.id];
4393
- if (the_symbol !== undefined && the_symbol.nud !== undefined) {
4544
+ if (the_symbol !== undefined && the_symbol.nud_prefix !== undefined) {
4394
4545
 
4395
4546
  // test_cause:
4396
4547
  // ["0", "parse_expression", "symbol", "", 0]
4397
4548
 
4398
4549
  test_cause("symbol");
4399
- left = the_symbol.nud();
4550
+ left = the_symbol.nud_prefix();
4400
4551
  } else if (token_now.identifier) {
4401
4552
 
4402
4553
  // test_cause:
@@ -4421,32 +4572,38 @@ function jslint_phase3_parse(state) {
4421
4572
  the_symbol = syntax_dict[token_nxt.id];
4422
4573
  if (
4423
4574
  the_symbol === undefined
4424
- || the_symbol.led === undefined
4575
+ || the_symbol.led_infix === undefined
4425
4576
  || the_symbol.lbp <= rbp
4426
4577
  ) {
4427
4578
  break;
4428
4579
  }
4429
4580
  advance();
4430
- left = the_symbol.led(left);
4581
+ left = the_symbol.led_infix(left);
4431
4582
  }
4432
4583
  return left;
4433
4584
  }
4434
4585
 
4435
- function parse_fart(pl) {
4586
+ function parse_fart() {
4587
+ let parameters;
4588
+ let signature;
4436
4589
  let the_fart;
4590
+ [parameters, signature] = prefix_function_arg();
4437
4591
  advance("=>");
4438
4592
  the_fart = token_now;
4439
4593
  the_fart.arity = "binary";
4440
4594
  the_fart.name = "=>";
4441
4595
  the_fart.level = functionage.level + 1;
4442
4596
  function_list.push(the_fart);
4443
- if (functionage.loop > 0) {
4444
4597
 
4445
- // test_cause:
4446
- // ["while(0){aa.map(()=>0);}", "parse_fart", "function_in_loop", "=>", 19]
4598
+ // PR-384 - Relax warning "function_in_loop".
4599
+ //
4600
+ // if (functionage.loop > 0) {
4447
4601
 
4448
- warn("function_in_loop", the_fart);
4449
- }
4602
+ // // test_cause:
4603
+ // // ["while(0){aa.map(()=>0);}", "parse_fart", "function_in_loop", "=>", 19]
4604
+ //
4605
+ // warn("function_in_loop", the_fart);
4606
+ // }
4450
4607
 
4451
4608
  // Give the function properties storing its names and for observing the depth
4452
4609
  // of loops and switches.
@@ -4454,6 +4611,8 @@ function jslint_phase3_parse(state) {
4454
4611
  the_fart.context = empty();
4455
4612
  the_fart.finally = 0;
4456
4613
  the_fart.loop = 0;
4614
+ the_fart.parameters = parameters;
4615
+ the_fart.signature = signature;
4457
4616
  the_fart.switch = 0;
4458
4617
  the_fart.try = 0;
4459
4618
 
@@ -4461,23 +4620,42 @@ function jslint_phase3_parse(state) {
4461
4620
 
4462
4621
  function_stack.push(functionage);
4463
4622
  functionage = the_fart;
4464
- the_fart.parameters = pl[0];
4465
- the_fart.signature = pl[1];
4466
- the_fart.parameters.forEach(function (name) {
4623
+ the_fart.parameters.forEach(function enroll_parameter(name) {
4624
+ if (name.identifier) {
4625
+ enroll(name, "parameter", true);
4626
+ } else {
4627
+
4628
+ // PR-385 - Bugfix - Fixes issue #382 - fix warnings against destructured fart.
4467
4629
 
4468
4630
  // test_cause:
4469
- // ["(aa)=>{}", "parse_fart", "parameter", "", 0]
4631
+ // ["([aa])=>0", "enroll_parameter", "use_function_not_fart", "=>", 7]
4632
+ // ["({aa})=>0", "enroll_parameter", "use_function_not_fart", "=>", 7]
4633
+
4634
+ warn("use_function_not_fart", the_fart);
4635
+
4636
+ // Recurse enroll_parameter().
4470
4637
 
4471
- test_cause("parameter");
4472
- enroll(name, "parameter", true);
4638
+ name.names.forEach(enroll_parameter);
4639
+ }
4473
4640
  });
4474
4641
  if (token_nxt.id === "{") {
4475
4642
 
4476
4643
  // test_cause:
4477
- // ["()=>{}", "parse_fart", "expected_a_b", "=>", 3]
4644
+ // ["()=>{}", "parse_fart", "use_function_not_fart", "=>", 3]
4478
4645
 
4479
- warn("expected_a_b", the_fart, "function", "=>");
4646
+ warn("use_function_not_fart", the_fart);
4480
4647
  the_fart.block = block("body");
4648
+ } else if (
4649
+ syntax_dict[token_nxt.id] !== undefined
4650
+ && syntax_dict[token_nxt.id].fud_stmt !== undefined
4651
+ ) {
4652
+
4653
+ // PR-384 - Bugfix - Fixes issue #379 - warn against naked-statement in fart.
4654
+
4655
+ // test_cause:
4656
+ // ["()=>delete aa", "parse_fart", "unexpected_a_after_b", "=>", 5]
4657
+
4658
+ stop("unexpected_a_after_b", token_nxt, token_nxt.id, "=>");
4481
4659
  } else {
4482
4660
  the_fart.expression = parse_expression(0);
4483
4661
  }
@@ -4492,13 +4670,7 @@ function jslint_phase3_parse(state) {
4492
4670
  let negative;
4493
4671
  switch (token_nxt.id) {
4494
4672
  case "(number)":
4495
- if (!(
4496
-
4497
- // https://datatracker.ietf.org/doc/html/rfc7159#section-6
4498
- // number = [ minus ] int [ frac ] [ exp ]
4499
-
4500
- /^-?(?:0|[1-9]\d*?)(?:\.\d*?)?(?:[eE][+\-]?\d+?)?$/
4501
- ).test(token_nxt.value)) {
4673
+ if (!jslint_rgx_json_number.test(token_nxt.value)) {
4502
4674
 
4503
4675
  // test_cause:
4504
4676
  // ["[-.0]", "parse_json", "unexpected_a", ".", 3]
@@ -4700,7 +4872,7 @@ function jslint_phase3_parse(state) {
4700
4872
  the_symbol = syntax_dict[first.id];
4701
4873
  if (
4702
4874
  the_symbol !== undefined
4703
- && the_symbol.fud !== undefined
4875
+ && the_symbol.fud_stmt !== undefined
4704
4876
 
4705
4877
  // PR-318 - Bugfix - Fixes issues #316, #317 - dynamic-import().
4706
4878
 
@@ -4709,7 +4881,7 @@ function jslint_phase3_parse(state) {
4709
4881
  the_symbol.disrupt = false;
4710
4882
  the_symbol.statement = true;
4711
4883
  token_now.arity = "statement";
4712
- the_statement = the_symbol.fud();
4884
+ the_statement = the_symbol.fud_stmt();
4713
4885
  functionage.statement_prv = the_statement;
4714
4886
  } else {
4715
4887
 
@@ -4779,7 +4951,7 @@ function jslint_phase3_parse(state) {
4779
4951
  // Create one of the postassign operators.
4780
4952
 
4781
4953
  const the_symbol = symbol(id, 150);
4782
- the_symbol.led = function (left) {
4954
+ the_symbol.led_infix = function (left) {
4783
4955
  token_now.expression = left;
4784
4956
  token_now.arity = "postassign";
4785
4957
  check_mutation(token_now.expression);
@@ -4793,7 +4965,7 @@ function jslint_phase3_parse(state) {
4793
4965
  // Create one of the preassign operators.
4794
4966
 
4795
4967
  const the_symbol = symbol(id);
4796
- the_symbol.nud = function () {
4968
+ the_symbol.nud_prefix = function () {
4797
4969
  const the_token = token_now;
4798
4970
  the_token.arity = "preassign";
4799
4971
  the_token.expression = parse_expression(150);
@@ -4808,7 +4980,7 @@ function jslint_phase3_parse(state) {
4808
4980
  // Create a prefix operator.
4809
4981
 
4810
4982
  const the_symbol = symbol(id);
4811
- the_symbol.nud = function () {
4983
+ the_symbol.nud_prefix = function () {
4812
4984
  const the_token = token_now;
4813
4985
  the_token.arity = "unary";
4814
4986
  if (typeof f === "function") {
@@ -4929,18 +5101,20 @@ function jslint_phase3_parse(state) {
4929
5101
  // }
4930
5102
  // jslint_assert(!mode_mega, `Expected !mode_mega.`);
4931
5103
 
4932
- // Don't create functions in loops. It is inefficient, and it can lead to
4933
- // scoping errors.
4934
-
4935
- if (functionage.loop > 0) {
4936
-
4937
- // test_cause:
4938
- // ["
4939
- // while(0){aa.map(function(){});}
4940
- // ", "prefix_function", "function_in_loop", "function", 17]
4941
-
4942
- warn("function_in_loop", the_function);
4943
- }
5104
+ // PR-378 - Relax warning "function_in_loop".
5105
+ //
5106
+ // // Don't create functions in loops. It is inefficient, and it can lead to
5107
+ // // scoping errors.
5108
+ //
5109
+ // if (functionage.loop > 0) {
5110
+ //
5111
+ // // test_cause:
5112
+ // // ["
5113
+ // // while(0){aa.map(function(){});}
5114
+ // // ", "prefix_function", "function_in_loop", "function", 17]
5115
+ //
5116
+ // warn("function_in_loop", the_function);
5117
+ // }
4944
5118
 
4945
5119
  // Give the function properties for storing its names and for observing the
4946
5120
  // depth of loops and switches.
@@ -4988,6 +5162,9 @@ function jslint_phase3_parse(state) {
4988
5162
  if (name.identifier) {
4989
5163
  enroll(name, "parameter", false);
4990
5164
  } else {
5165
+
5166
+ // Recurse enroll_parameter().
5167
+
4991
5168
  name.names.forEach(enroll_parameter);
4992
5169
  }
4993
5170
  });
@@ -5448,25 +5625,14 @@ function jslint_phase3_parse(state) {
5448
5625
  }
5449
5626
 
5450
5627
  function prefix_lparen() {
5451
- const cadet = lookahead().id;
5452
- const the_paren = token_now;
5628
+ let the_paren = token_now;
5453
5629
  let the_value;
5454
5630
 
5455
- // We can distinguish between a parameter list for => and a wrapped expression
5456
- // with one token of lookahead.
5457
-
5458
- if (
5459
- token_nxt.id === ")"
5460
- || token_nxt.id === "..."
5461
- || (token_nxt.identifier && (cadet === "," || cadet === "="))
5462
- ) {
5463
-
5464
- // test_cause:
5465
- // ["()=>0", "prefix_lparen", "fart", "", 0]
5631
+ // PR-385 - Bugfix - Fixes issue #382 - failure to detect destructured fart.
5466
5632
 
5467
- test_cause("fart");
5633
+ if (token_now.is_fart) {
5468
5634
  the_paren.free = false;
5469
- return parse_fart(prefix_function_arg());
5635
+ return parse_fart();
5470
5636
  }
5471
5637
 
5472
5638
  // test_cause:
@@ -5484,31 +5650,6 @@ function jslint_phase3_parse(state) {
5484
5650
  }
5485
5651
  the_value.wrapped = true;
5486
5652
  advance(")", the_paren);
5487
- if (token_nxt.id === "=>") {
5488
- if (the_value.arity !== "variable") {
5489
- if (the_value.id === "{" || the_value.id === "[") {
5490
-
5491
- // test_cause:
5492
- // ["([])=>0", "prefix_lparen", "expected_a_before_b", "(", 1]
5493
- // ["({})=>0", "prefix_lparen", "expected_a_before_b", "(", 1]
5494
-
5495
- warn("expected_a_before_b", the_paren, "function", "(");
5496
-
5497
- // test_cause:
5498
- // ["([])=>0", "prefix_lparen", "expected_a_b", "=>", 5]
5499
- // ["({})=>0", "prefix_lparen", "expected_a_b", "=>", 5]
5500
-
5501
- return stop("expected_a_b", token_nxt, "{", "=>");
5502
- }
5503
-
5504
- // test_cause:
5505
- // ["(0)=>0", "prefix_lparen", "expected_identifier_a", "0", 2]
5506
-
5507
- return stop("expected_identifier_a", the_value);
5508
- }
5509
- the_paren.expression = [the_value];
5510
- return parse_fart([the_paren.expression, "(" + the_value.id + ")"]);
5511
- }
5512
5653
  return the_value;
5513
5654
  }
5514
5655
 
@@ -5589,12 +5730,12 @@ function jslint_phase3_parse(state) {
5589
5730
  anon = "anonymous";
5590
5731
  }
5591
5732
 
5592
- function stmt(id, fud) {
5733
+ function stmt(id, fud_stmt) {
5593
5734
 
5594
5735
  // Create a statement.
5595
5736
 
5596
5737
  const the_symbol = symbol(id);
5597
- the_symbol.fud = fud;
5738
+ the_symbol.fud_stmt = fud_stmt;
5598
5739
  return the_symbol;
5599
5740
  }
5600
5741
 
@@ -6029,10 +6170,7 @@ function jslint_phase3_parse(state) {
6029
6170
  advance("from");
6030
6171
  advance("(string)");
6031
6172
  the_import.import = token_now;
6032
- if (!(
6033
- // rx_module
6034
- /^[a-zA-Z0-9_$:.@\-\/]+$/
6035
- ).test(token_now.value)) {
6173
+ if (!jslint_rgx_module.test(token_now.value)) {
6036
6174
 
6037
6175
  // test_cause:
6038
6176
  // ["import aa from \"!aa\"", "stmt_import", "bad_module_name_a", "!aa", 16]
@@ -6643,13 +6781,13 @@ function jslint_phase3_parse(state) {
6643
6781
 
6644
6782
  if (id === "(string)") {
6645
6783
  id = name.value;
6646
- if (!rx_identifier.test(id)) {
6784
+ if (!jslint_rgx_identifier.test(id)) {
6647
6785
  return id;
6648
6786
  }
6649
6787
  } else if (id === "`") {
6650
6788
  if (name.value.length === 1) {
6651
6789
  id = name.value[0].value;
6652
- if (!rx_identifier.test(id)) {
6790
+ if (!jslint_rgx_identifier.test(id)) {
6653
6791
  return id;
6654
6792
  }
6655
6793
  }
@@ -6682,10 +6820,7 @@ function jslint_phase3_parse(state) {
6682
6820
  } else if (
6683
6821
  !option_dict.name
6684
6822
  && name.identifier
6685
- && (
6686
- // rx_weird_property
6687
- /^_|\$|Sync$|_$/m
6688
- ).test(id)
6823
+ && jslint_rgx_weird_property.test(id)
6689
6824
  ) {
6690
6825
 
6691
6826
  // test_cause:
@@ -6723,7 +6858,7 @@ function jslint_phase3_parse(state) {
6723
6858
  // Create a ternary operator.
6724
6859
 
6725
6860
  const the_symbol = symbol(id1, 30);
6726
- the_symbol.led = function parse_ternary_led(left) {
6861
+ the_symbol.led_infix = function parse_ternary_led(left) {
6727
6862
  const the_token = token_now;
6728
6863
  let second;
6729
6864
  second = parse_expression(20);
@@ -7439,10 +7574,7 @@ function jslint_phase4_walk(state) {
7439
7574
  test_cause("cack");
7440
7575
  cack = !cack;
7441
7576
  }
7442
- if ((
7443
- // rx_cap
7444
- /^[A-Z]/
7445
- ).test(left.name.id) !== cack) {
7577
+ if (jslint_rgx_cap.test(left.name.id) !== cack) {
7446
7578
  if (the_new !== undefined) {
7447
7579
 
7448
7580
  // test_cause:
@@ -9311,6 +9443,9 @@ body {
9311
9443
  : "global"
9312
9444
  );
9313
9445
  if (global.length + froms.length + exports.length > 0) {
9446
+ if (functions.length === 0) {
9447
+ html += "<br>\n";
9448
+ }
9314
9449
  html += "<div class=\"level level0\">\n";
9315
9450
  html += detail(module, global);
9316
9451
  html += detail("import from", froms);
@@ -9560,7 +9695,7 @@ function objectDeepCopyWithKeysSorted(obj) {
9560
9695
 
9561
9696
  // Recursively deep-copy obj with keys sorted.
9562
9697
 
9563
- sorted = {};
9698
+ sorted = Object.create(null);
9564
9699
  Object.keys(obj).sort().forEach(function (key) {
9565
9700
  sorted[key] = objectDeepCopyWithKeysSorted(obj[key]);
9566
9701
  });
@@ -10834,7 +10969,7 @@ function sentinel() {}
10834
10969
 
10835
10970
  // 3. Create html-coverage-reports in <coverageDir>.
10836
10971
 
10837
- fileDict = {};
10972
+ fileDict = Object.create(null);
10838
10973
  await Promise.all(v8CoverageObj.result.map(async function ({
10839
10974
  functions,
10840
10975
  url: pathname