sqlmath 0.0.5 → 2022.4.28

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,48 +94,47 @@
94
94
  /*jslint beta, node*/
95
95
 
96
96
  /*property
97
- mode_conditional,
98
97
  JSLINT_BETA, NODE_V8_COVERAGE, a, all, argv, arity, artifact,
99
98
  assertErrorThrownAsync, assertJsonEqual, assertOrThrow, assign, async, b,
100
99
  beta, bitwise, block, body, browser, c, calls, catch, catch_list,
101
- catch_stack, causes, char, children, clear, closer,
102
- closure, code, column, concat, consoleError, console_error, console_log,
103
- constant, context, convert, count, coverageDir, create, cwd, d, dead,
104
- debugInline, default, delta, devel, directive, directive_list,
105
- directive_quiet, directives, dirname, disrupt, dot, edition, elem_list,
106
- ellipsis, else, end, endOffset, endsWith, entries, env, error, eval, every,
107
- example_list, exec, execArgv, exit, export_dict, exports, expression, extra,
108
- file, fileList, fileURLToPath, filter, finally, flag, floor, for, forEach,
109
- formatted_message, free, freeze, from, froms,
110
- fsWriteFileWithParents, fud, functionName, function_list, function_stack,
111
- functions, get, getset, github_repo, global, global_dict, global_list,
112
- holeList, htmlEscape, id, identifier, import, import_list, inc, indent2,
113
- index, indexOf, init, initial, isArray, isBlockCoverage, isHole, isNaN,
114
- is_equal, is_weird, join, jslint, jslint_apidoc, jslint_assert,
115
- jslint_charset_ascii, jslint_cli, jslint_edition, jslint_phase1_split,
116
- jslint_phase2_lex, jslint_phase3_parse, jslint_phase4_walk,
117
- jslint_phase5_whitage, jslint_report, json, jstestDescribe, jstestIt,
118
- jstestOnExit, keys, label, lbp, led, length, level, line, lineList,
119
- line_list, line_offset, line_source, lines, linesCovered, linesTotal, live,
120
- log, long, loop, m, main, map, margin, match, max, message, meta, min,
121
- mkdir, modeCoverageIgnoreFile, modeIndex, mode_cli, mode_json, mode_module,
122
- mode_noop, mode_property, mode_shebang, mode_stop, module, moduleFsInit,
123
- moduleName, module_list, name, names, node, noop, now,
124
- nr, nud, objectDeepCopyWithKeysSorted, ok, on, open, opening, option,
125
- option_dict, order, package_name, padEnd, padStart, parameters, parent,
126
- parentIi, parse, pathname, platform, pop, processArgv, process_argv,
127
- process_env, process_exit, process_version, promises, property,
128
- property_dict, push, quote, ranges, readFile, readdir, readonly, recursive,
129
- reduce, repeat, replace, resolve, result, reverse, rm, rmdir, role, round,
130
- scriptId, search, set, shebang, shift, signature, single, slice, some, sort,
131
- source, spawn, splice, split, stack, stack_trace, start, startOffset,
132
- startsWith, statement, statement_prv, stdio, stop, stop_at, stringify,
133
- switch, syntax_dict, tenure, test, test_cause, test_internal_error, this,
134
- thru, toString, token, token_global, token_list, token_nxt, token_tree,
135
- tokens, trace, tree, trim, trimEnd, trimRight, try, type, unlink, unordered,
136
- unshift, url, used, v8CoverageListMerge, v8CoverageReportCreate, value,
137
- variable, version, versions, warn, warn_at, warning, warning_list, warnings,
138
- white, wrapped, writeFile
100
+ catch_stack, causes, char, children, clear, closer, closure, code, column,
101
+ concat, consoleError, console_error, console_log, constant, context,
102
+ convert, count, coverageDir, create, cwd, d, dead, debugInline, default,
103
+ delta, devel, directive, directive_list, directive_quiet, directives,
104
+ dirname, disrupt, dot, edition, elem_list, ellipsis, else, end, endOffset,
105
+ endsWith, entries, env, error, eval, every, example_list, exec, execArgv,
106
+ exit, exitCode, export_dict, exports, expression, extra, file, fileList,
107
+ fileURLToPath, filter, finally, flag, floor, for, forEach,
108
+ formatted_message, free, freeze, from, froms, fsWriteFileWithParents,
109
+ fud_stmt, functionName, function_list, function_stack, functions, get,
110
+ getset, github_repo, global, global_dict, global_list, holeList, htmlEscape,
111
+ id, identifier, import, import_list, inc, indent2, index, indexOf, init,
112
+ initial, isArray, isBlockCoverage, isHole, isNaN, is_equal, is_fart,
113
+ is_weird, join, jslint, jslint_apidoc, jslint_assert, jslint_charset_ascii,
114
+ jslint_cli, jslint_edition, jslint_phase1_split, jslint_phase2_lex,
115
+ jslint_phase3_parse, jslint_phase4_walk, jslint_phase5_whitage,
116
+ jslint_report, json, jstestDescribe, jstestIt, jstestOnExit, keys, label,
117
+ lbp, led_infix, length, level, line, lineList, line_list, line_offset,
118
+ line_source, lines, linesCovered, linesTotal, live, log, long, loop, m, map,
119
+ margin, match, max, message, meta, min, mkdir, modeCoverageIgnoreFile,
120
+ modeIndex, mode_cli, mode_conditional, mode_json, mode_module, mode_noop,
121
+ mode_property, mode_shebang, mode_stop, module, moduleFsInit, moduleName,
122
+ module_list, name, names, node, noop, now, nr, nud_prefix,
123
+ objectDeepCopyWithKeysSorted, ok, on, open, opening, option, option_dict,
124
+ order, package_name, padEnd, padStart, parameters, parent, parentIi, parse,
125
+ pathname, platform, pop, processArgv, process_argv, process_env,
126
+ process_exit, promises, property, property_dict, push, quote, ranges,
127
+ readFile, readdir, readonly, recursive, reduce, repeat, replace, resolve,
128
+ result, reverse, role, round, scriptId, search, set, shebang, shift,
129
+ signature, single, slice, some, sort, source, spawn, splice, split, stack,
130
+ stack_trace, start, startOffset, startsWith, statement, statement_prv,
131
+ stdio, stop, stop_at, stringify, switch, syntax_dict, tenure, test,
132
+ test_cause, test_internal_error, this, thru, toString, token, token_global,
133
+ token_list, token_nxt, token_tree, tokens, trace, tree, trim, trimEnd,
134
+ trimRight, try, type, unlink, unordered, unshift, url, used,
135
+ v8CoverageListMerge, v8CoverageReportCreate, value, variable, version,
136
+ versions, warn, warn_at, warning, warning_list, warnings, white, wrapped,
137
+ writeFile
139
138
  */
140
139
 
141
140
  // init debugInline
@@ -165,11 +164,96 @@ let jslint_charset_ascii = (
165
164
  + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
166
165
  + "`abcdefghijklmnopqrstuvwxyz{|}~\u007f"
167
166
  );
168
- let jslint_edition = "v2021.12.1-beta";
167
+ let jslint_edition = "v2022.5.1-beta";
169
168
  let jslint_export; // The jslint object to be exported.
170
169
  let jslint_fudge = 1; // Fudge starting line and starting
171
170
  // ... column to 1.
172
171
  let jslint_import_meta_url = ""; // import.meta.url used by cli.
172
+ let jslint_rgx_cap = (
173
+ /^[A-Z]/
174
+ );
175
+ let jslint_rgx_crlf = (
176
+ /\n|\r\n?/
177
+ );
178
+ let jslint_rgx_digits_bits = (
179
+ /^[01_]*/
180
+ );
181
+ let jslint_rgx_digits_decimals = (
182
+ /^[0-9_]*/
183
+ );
184
+ let jslint_rgx_digits_hexs = (
185
+ /^[0-9A-F_]*/i
186
+ );
187
+ let jslint_rgx_digits_octals = (
188
+ /^[0-7_]*/
189
+ );
190
+ let jslint_rgx_directive = (
191
+ /^(jslint|property|global)\s+(.*)$/
192
+ );
193
+ let jslint_rgx_directive_part = (
194
+ /([a-zA-Z$_][a-zA-Z0-9$_]*)(?::\s*(true|false))?,?\s*|$/g
195
+ );
196
+ let jslint_rgx_identifier = (
197
+ /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/
198
+ );
199
+ let jslint_rgx_json_number = (
200
+
201
+ // https://datatracker.ietf.org/doc/html/rfc7159#section-6
202
+ // number = [ minus ] int [ frac ] [ exp ]
203
+
204
+ /^-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][\-+]?\d+)?$/
205
+ );
206
+ let jslint_rgx_mega = (
207
+
208
+ // Vim-hack - vim-editor has trouble parsing naked '`' in regexp
209
+
210
+ /[\u0060\\]|\$\{/
211
+ );
212
+ let jslint_rgx_module = (
213
+ /^[a-zA-Z0-9_$:.@\-\/]+$/
214
+ );
215
+ let jslint_rgx_numeric_separator_illegal = (
216
+ /__|_$|_n$/m
217
+ );
218
+ let jslint_rgx_slash_star_or_slash = (
219
+ /\/\*|\/$/
220
+ );
221
+ let jslint_rgx_tab = (
222
+ /\t/g
223
+ );
224
+ let jslint_rgx_todo = (
225
+ /\b(?:todo|TO\s?DO|HACK)\b/
226
+ );
227
+ let jslint_rgx_token = new RegExp(
228
+ "^("
229
+ + "(\\s+)"
230
+ + "|([a-zA-Z_$][a-zA-Z0-9_$]*)"
231
+ + "|[(){}\\[\\],:;'\"~\\`]"
232
+ + "|\\?[?.]?"
233
+ + "|=(?:==?|>)?"
234
+ + "|\\.+"
235
+ + "|\\*[*\\/=]?"
236
+ + "|\\/[*\\/]?"
237
+ + "|\\+[=+]?"
238
+ + "|-[=\\-]?"
239
+ + "|[\\^%]=?"
240
+ + "|&[&=]?"
241
+ + "|\\"
242
+ + "|[|=]?"
243
+ + "|>{1,3}=?"
244
+ + "|<<?=?"
245
+ + "|!(?:!|==?)?"
246
+
247
+ // PR-351 - Add BigInt support.
248
+ // PR-390 - Add numeric-separator support.
249
+
250
+ + "|((?:0_?|[1-9][0-9_]*)n?)"
251
+ + ")"
252
+ + "(.*)$"
253
+ );
254
+ let jslint_rgx_weird_property = (
255
+ /^_|\$|Sync$|_$/m
256
+ );
173
257
  let jstestCountFailed = 0;
174
258
  let jstestCountTotal = 0;
175
259
  let jstestItCount = 0;
@@ -202,11 +286,12 @@ function assertJsonEqual(aa, bb, message) {
202
286
 
203
287
  // This function will assert JSON.stringify(<aa>) === JSON.stringify(<bb>).
204
288
 
205
- aa = JSON.stringify(objectDeepCopyWithKeysSorted(aa));
206
- bb = JSON.stringify(objectDeepCopyWithKeysSorted(bb));
289
+ aa = JSON.stringify(objectDeepCopyWithKeysSorted(aa), undefined, 1);
290
+ bb = JSON.stringify(objectDeepCopyWithKeysSorted(bb), undefined, 1);
207
291
  if (aa !== bb) {
208
292
  throw new Error(
209
- JSON.stringify(aa) + " !== " + JSON.stringify(bb) + (
293
+ "\n" + aa + "\n!==\n" + bb
294
+ + (
210
295
  typeof message === "string"
211
296
  ? " - " + message
212
297
  : message
@@ -304,10 +389,7 @@ function jslint(
304
389
  let import_list = []; // The array collecting all import-from strings.
305
390
  let line_list = String( // The array containing source lines.
306
391
  "\n" + source
307
- ).split(
308
- // rx_crlf
309
- /\n|\r\n?/
310
- ).map(function (line_source) {
392
+ ).split(jslint_rgx_crlf).map(function (line_source) {
311
393
  return {
312
394
  line_source
313
395
  };
@@ -352,8 +434,6 @@ function jslint(
352
434
  }
353
435
 
354
436
  function is_equal(aa, bb) {
355
- let aa_value;
356
- let bb_value;
357
437
 
358
438
  // test_cause:
359
439
  // ["0&&0", "is_equal", "", "", 0]
@@ -374,6 +454,7 @@ function jslint(
374
454
 
375
455
  // test_cause:
376
456
  // ["`${0}`&&`${0}`", "is_equal", "recurse_isArray", "", 0]
457
+ // ["`${0}`&&`${1}`", "is_equal", "recurse_isArray", "", 0]
377
458
 
378
459
  test_cause("recurse_isArray");
379
460
  return is_equal(value, bb[index]);
@@ -387,21 +468,19 @@ function jslint(
387
468
  // }
388
469
 
389
470
  jslint_assert(!Array.isArray(bb), `Expected !Array.isArray(bb).`);
390
- if (aa.id === "(number)" && bb.id === "(number)") {
471
+ switch (aa.id === bb.id && aa.id) {
472
+ case "(number)":
473
+ case "(string)":
391
474
  return aa.value === bb.value;
392
- }
393
- if (aa.id === "(string)") {
394
- aa_value = aa.value;
395
- } else if (aa.id === "`" && aa.constant) {
396
- aa_value = aa.value[0];
397
- }
398
- if (bb.id === "(string)") {
399
- bb_value = bb.value;
400
- } else if (bb.id === "`" && bb.constant) {
401
- bb_value = bb.value[0];
402
- }
403
- if (typeof aa_value === "string") {
404
- return aa_value === bb_value;
475
+
476
+ // PR-394 - Bugfix
477
+ // Fix jslint falsely believing megastring literals `0` and `1` are similar.
478
+
479
+ case "`":
480
+ if (!is_equal(aa.value, bb.value)) {
481
+ return false;
482
+ }
483
+ break;
405
484
  }
406
485
  if (is_weird(aa) || is_weird(bb)) {
407
486
 
@@ -678,8 +757,17 @@ function jslint(
678
757
  `Expected 'Object.freeze('. All export values should be frozen.`
679
758
  );
680
759
  break;
681
- case "function_in_loop":
682
- mm = `Don't create functions within a loop.`;
760
+
761
+ // PR-378 - Relax warning "function_in_loop".
762
+ //
763
+ // case "function_in_loop":
764
+ // mm = `Don't create functions within a loop.`;
765
+ // break;
766
+
767
+ // PR-390 - Add numeric-separator check.
768
+
769
+ case "illegal_num_separator":
770
+ mm = `Illegal numeric separator '_' at column ${column}.`;
683
771
  break;
684
772
  case "infix_in":
685
773
  mm = (
@@ -833,6 +921,15 @@ function jslint(
833
921
  case "use_double":
834
922
  mm = `Use double quotes, not single quotes.`;
835
923
  break;
924
+
925
+ // PR-386 - Fix issue #382 - Make fart-related warnings more readable.
926
+
927
+ case "use_function_not_fart":
928
+ mm = (
929
+ `Use 'function (...)', not '(...) =>' when arrow functions`
930
+ + ` become too complex.`
931
+ );
932
+ break;
836
933
  case "use_open":
837
934
  mm = (
838
935
  `Wrap a ternary expression in parens,`
@@ -866,6 +963,12 @@ function jslint(
866
963
  case "wrap_condition":
867
964
  mm = `Wrap the condition in parens.`;
868
965
  break;
966
+
967
+ // PR-386 - Fix issue #382 - Make fart-related warnings more readable.
968
+
969
+ case "wrap_fart_parameter":
970
+ mm = `Wrap the parameter before '=>' in parens.`;
971
+ break;
869
972
  case "wrap_immediate":
870
973
  mm = (
871
974
  `Wrap an immediate function invocation in parentheses to assist`
@@ -873,9 +976,6 @@ function jslint(
873
976
  + ` result of a function, and not the function itself.`
874
977
  );
875
978
  break;
876
- case "wrap_parameter":
877
- mm = `Wrap the parameter in parens.`;
878
- break;
879
979
  case "wrap_regexp":
880
980
  mm = `Wrap this regexp in parens to avoid confusion.`;
881
981
  break;
@@ -1451,8 +1551,8 @@ async function jslint_cli({
1451
1551
  let command;
1452
1552
  let data;
1453
1553
  let exit_code = 0;
1454
- let mode_plugin_vim;
1455
1554
  let mode_report;
1555
+ let mode_wrapper_vim;
1456
1556
  let result;
1457
1557
 
1458
1558
  function jslint_from_file({
@@ -1525,7 +1625,7 @@ async function jslint_cli({
1525
1625
  if (result_from_file.warnings.length > 0) {
1526
1626
  exit_code = 1;
1527
1627
  console_error(
1528
- mode_plugin_vim
1628
+ mode_wrapper_vim
1529
1629
 
1530
1630
  // PR-349 - Print warnings in format readable by vim.
1531
1631
 
@@ -1658,17 +1758,17 @@ async function jslint_cli({
1658
1758
  }));
1659
1759
  return;
1660
1760
 
1661
- // COMMIT-b26d6df2 - Add command jslint_plugin_vim.
1761
+ // PR-363 - Add command jslint_report.
1662
1762
 
1663
- case "jslint_plugin_vim":
1664
- mode_plugin_vim = true;
1763
+ case "jslint_report":
1764
+ mode_report = command[1];
1665
1765
  process_argv = process_argv.slice(1);
1666
1766
  break;
1667
1767
 
1668
- // PR-363 - Add command jslint_report.
1768
+ // COMMIT-b26d6df2 - Add command jslint_wrapper_vim.
1669
1769
 
1670
- case "jslint_report":
1671
- mode_report = command[1];
1770
+ case "jslint_wrapper_vim":
1771
+ mode_wrapper_vim = true;
1672
1772
  process_argv = process_argv.slice(1);
1673
1773
  break;
1674
1774
 
@@ -1676,6 +1776,7 @@ async function jslint_cli({
1676
1776
 
1677
1777
  case "v8_coverage_report":
1678
1778
  await v8CoverageReportCreate({
1779
+ consoleError: console_error,
1679
1780
  coverageDir: command[1],
1680
1781
  processArgv: process_argv.slice(3)
1681
1782
  });
@@ -1684,9 +1785,9 @@ async function jslint_cli({
1684
1785
 
1685
1786
  // PR-349 - Detect cli-option --mode-vim-plugin.
1686
1787
 
1687
- mode_plugin_vim = (
1788
+ mode_wrapper_vim = (
1688
1789
  process_argv.slice(2).indexOf("--mode-vim-plugin") >= 0
1689
- || mode_plugin_vim
1790
+ || mode_wrapper_vim
1690
1791
  );
1691
1792
 
1692
1793
  // Normalize file relative to process.cwd().
@@ -1822,37 +1923,16 @@ function jslint_phase2_lex(state) {
1822
1923
  let line_mega; // The starting line of megastring.
1823
1924
  let line_source = ""; // The remaining line source string.
1824
1925
  let line_whole = ""; // The whole line source string.
1926
+ let mode_digits_empty_string = 1;
1927
+ let mode_digits_numeric_separator = 2;
1825
1928
  let mode_directive = true; // true if directives are still allowed.
1826
1929
  let mode_mega = false; // true if currently parsing a megastring
1827
1930
  // ... literal.
1828
1931
  let mode_regexp; // true if regular expression literal seen on
1829
1932
  // ... this line.
1830
- let rx_token = new RegExp(
1831
- "^("
1832
- + "(\\s+)"
1833
- + "|([a-zA-Z_$][a-zA-Z0-9_$]*)"
1834
- + "|[(){}\\[\\],:;'\"~\\`]"
1835
- + "|\\?[?.]?"
1836
- + "|=(?:==?|>)?"
1837
- + "|\\.+"
1838
- + "|\\*[*\\/=]?"
1839
- + "|\\/[*\\/]?"
1840
- + "|\\+[=+]?"
1841
- + "|-[=\\-]?"
1842
- + "|[\\^%]=?"
1843
- + "|&[&=]?"
1844
- + "|\\"
1845
- + "|[|=]?"
1846
- + "|>{1,3}=?"
1847
- + "|<<?=?"
1848
- + "|!(?:!|==?)?"
1849
-
1850
- // PR-351 - Add BigInt support.
1851
-
1852
- + "|(0n?|[1-9][0-9]*n?)"
1853
- + ")"
1854
- + "(.*)$"
1855
- );
1933
+ let paren_backtrack_list = []; // List of most recent "(" tokens at any
1934
+ // ... paren-depth.
1935
+ let paren_depth = 0; // Keeps track of current paren-depth.
1856
1936
  let snippet = ""; // A piece of string.
1857
1937
  let token_1; // The first token.
1858
1938
  let token_prv = token_global; // The previous token including
@@ -1934,7 +2014,7 @@ function jslint_phase2_lex(state) {
1934
2014
 
1935
2015
  warn_at("unexpected_a", line, column, char);
1936
2016
  }
1937
- if (read_digits("x") > 5) {
2017
+ if (read_digits("x", undefined) > 5) {
1938
2018
 
1939
2019
  // test_cause:
1940
2020
  // ["\"\\u{123456}\"", "char_after_escape", "too_many_digits", "", 11]
@@ -1951,7 +2031,7 @@ function jslint_phase2_lex(state) {
1951
2031
  return char_after();
1952
2032
  }
1953
2033
  char_before();
1954
- if (read_digits("x", true) < 4) {
2034
+ if (read_digits("x", mode_digits_empty_string) < 4) {
1955
2035
 
1956
2036
  // test_cause:
1957
2037
  // ["\"\\u0\"", "char_after_escape", "expected_four_digits", "", 5]
@@ -1986,6 +2066,26 @@ function jslint_phase2_lex(state) {
1986
2066
  return char;
1987
2067
  }
1988
2068
 
2069
+ function check_numeric_separator(digits, column) {
2070
+
2071
+ // This function will check for illegal numeric-separator in <digits>.
2072
+
2073
+ digits.replace((
2074
+ jslint_rgx_numeric_separator_illegal
2075
+ ), function (ignore, ii) {
2076
+
2077
+ // test_cause:
2078
+ // ["0x0_0_;", "check_numeric_separator", "illegal_num_separator", "", 6]
2079
+ // ["0x0_0__0;", "check_numeric_separator", "illegal_num_separator", "", 6]
2080
+ // ["aa=1_2_;", "check_numeric_separator", "illegal_num_separator", "", 7]
2081
+ // ["aa=1_2__3;", "check_numeric_separator", "illegal_num_separator", "", 7]
2082
+ // ["aa=1_2_n;", "check_numeric_separator", "illegal_num_separator", "", 7]
2083
+
2084
+ warn_at("illegal_num_separator", line, column + ii + 1);
2085
+ return "";
2086
+ });
2087
+ }
2088
+
1989
2089
  function lex_comment() {
1990
2090
  let body;
1991
2091
  let ii = 0;
@@ -2024,12 +2124,12 @@ function jslint_phase2_lex(state) {
2024
2124
  // Lex/loop through each line until "*/".
2025
2125
 
2026
2126
  while (true) {
2027
- // rx_star_slash
2127
+ // jslint_rgx_star_slash
2028
2128
  ii = line_source.indexOf("*/");
2029
2129
  if (ii >= 0) {
2030
2130
  break;
2031
2131
  }
2032
- // rx_slash_star
2132
+ // jslint_rgx_slash_star
2033
2133
  ii = line_source.indexOf("/*");
2034
2134
  if (ii >= 0) {
2035
2135
 
@@ -2049,8 +2149,7 @@ function jslint_phase2_lex(state) {
2049
2149
  }
2050
2150
  }
2051
2151
  jj = line_source.slice(0, ii).search(
2052
- // rx_slash_star_or_slash
2053
- /\/\*|\/$/
2152
+ jslint_rgx_slash_star_or_slash
2054
2153
  );
2055
2154
  if (jj >= 0) {
2056
2155
 
@@ -2068,13 +2167,7 @@ function jslint_phase2_lex(state) {
2068
2167
 
2069
2168
  // Uncompleted work comment.
2070
2169
 
2071
- if (
2072
- !option_dict.devel
2073
- && (
2074
- // rx_todo
2075
- /\b(?:todo|TO\s?DO|HACK)\b/
2076
- ).test(snippet)
2077
- ) {
2170
+ if (!option_dict.devel && jslint_rgx_todo.test(snippet)) {
2078
2171
 
2079
2172
  // test_cause:
2080
2173
  // ["//todo", "lex_comment", "todo_comment", "(comment)", 1] //jslint-quiet
@@ -2086,10 +2179,7 @@ function jslint_phase2_lex(state) {
2086
2179
 
2087
2180
  [
2088
2181
  the_comment.directive, body
2089
- ] = Array.from(snippet.match(
2090
- // rx_directive
2091
- /^(jslint|property|global)\s+(.*)$/
2092
- ) || []).slice(1);
2182
+ ] = Array.from(snippet.match(jslint_rgx_directive) || []).slice(1);
2093
2183
  if (the_comment.directive === undefined) {
2094
2184
  return the_comment;
2095
2185
  }
@@ -2111,10 +2201,12 @@ function jslint_phase2_lex(state) {
2111
2201
  // Lex/loop through each directive in /*...*/
2112
2202
 
2113
2203
  ii = 0;
2114
- body.replace((
2115
- // rx_directive_part
2116
- /([a-zA-Z$_][a-zA-Z0-9$_]*)(?::\s*(true|false))?,?\s*|$/g
2117
- ), function (match0, key, val, jj) {
2204
+ body.replace(jslint_rgx_directive_part, function (
2205
+ match0,
2206
+ key,
2207
+ val,
2208
+ jj
2209
+ ) {
2118
2210
  if (ii !== jj) {
2119
2211
 
2120
2212
  // test_cause:
@@ -2188,13 +2280,7 @@ function jslint_phase2_lex(state) {
2188
2280
  // string.
2189
2281
 
2190
2282
  while (true) {
2191
- match = line_source.match(
2192
-
2193
- // Vim-hack - vim-editor has trouble parsing '`' in regexp
2194
-
2195
- // rx_mega
2196
- /[\u0060\\]|\$\{/
2197
- ) || {
2283
+ match = line_source.match(jslint_rgx_mega) || {
2198
2284
  "0": "",
2199
2285
  index: 0
2200
2286
  };
@@ -2271,12 +2357,16 @@ function jslint_phase2_lex(state) {
2271
2357
 
2272
2358
  function lex_number() {
2273
2359
  let prefix = snippet;
2360
+
2361
+ // PR-390 - Add numeric-separator check.
2362
+
2363
+ check_numeric_separator(prefix, column - prefix.length);
2274
2364
  char_after();
2275
2365
  switch (prefix === "0" && char) {
2276
2366
  case "b":
2277
2367
  case "o":
2278
2368
  case "x":
2279
- read_digits(char);
2369
+ read_digits(char, mode_digits_numeric_separator);
2280
2370
 
2281
2371
  // PR-351 - Ignore BigInt suffix 'n'.
2282
2372
 
@@ -2286,14 +2376,14 @@ function jslint_phase2_lex(state) {
2286
2376
  break;
2287
2377
  default:
2288
2378
  if (char === ".") {
2289
- read_digits("d");
2379
+ read_digits("d", mode_digits_numeric_separator);
2290
2380
  }
2291
2381
  if (char === "E" || char === "e") {
2292
2382
  char_after(char);
2293
2383
  if (char !== "+" && char !== "-") {
2294
2384
  char_before();
2295
2385
  }
2296
- read_digits("d");
2386
+ read_digits("d", mode_digits_numeric_separator);
2297
2387
  }
2298
2388
  }
2299
2389
 
@@ -2563,7 +2653,7 @@ function jslint_phase2_lex(state) {
2563
2653
  }
2564
2654
  break;
2565
2655
  case "{":
2566
- if (read_digits("d", true) === 0) {
2656
+ if (read_digits("d", mode_digits_empty_string) === 0) {
2567
2657
 
2568
2658
  // test_cause:
2569
2659
  // ["aa=/aa{/", "lex_regexp_group", "expected_a_before_b", ",", 8]
@@ -2576,7 +2666,7 @@ function jslint_phase2_lex(state) {
2576
2666
  // ["aa=/.{,/", "lex_regexp_group", "comma", "", 0]
2577
2667
 
2578
2668
  test_cause("comma");
2579
- read_digits("d", true);
2669
+ read_digits("d", mode_digits_empty_string);
2580
2670
  }
2581
2671
  if (char_after("}") === "?") {
2582
2672
 
@@ -2869,7 +2959,7 @@ function jslint_phase2_lex(state) {
2869
2959
  }
2870
2960
  }
2871
2961
  from = column;
2872
- match = line_source.match(rx_token);
2962
+ match = line_source.match(jslint_rgx_token);
2873
2963
 
2874
2964
  // match[1] token
2875
2965
  // match[2] whitespace
@@ -3189,7 +3279,7 @@ node --input-type=module --eval '
3189
3279
  // /\*jslint beta, node*\/
3190
3280
  import moduleHttps from "https";
3191
3281
  (async function () {
3192
- let dict = {};
3282
+ let dict = Object.create(null);
3193
3283
  let result = "";
3194
3284
  await new Promise(function (resolve) {
3195
3285
  moduleHttps.get((
@@ -3252,41 +3342,48 @@ import moduleHttps from "https";
3252
3342
  return true;
3253
3343
  }
3254
3344
 
3255
- function read_digits(base, quiet) {
3345
+ function read_digits(base, mode) {
3256
3346
  let digits = line_source.match(
3257
3347
  base === "b"
3258
- ? (
3259
- // rx_bits
3260
- /^[01]*/
3261
- )
3348
+ ? jslint_rgx_digits_bits
3262
3349
  : base === "o"
3263
- ? (
3264
- // rx_octals
3265
- /^[0-7]*/
3266
- )
3350
+ ? jslint_rgx_digits_octals
3267
3351
  : base === "x"
3268
- ? (
3269
- // rx_hexs
3270
- /^[0-9A-F]*/i
3271
- )
3272
- : (
3273
- // rx_digits
3274
- /^[0-9]*/
3275
- )
3352
+ ? jslint_rgx_digits_hexs
3353
+ : jslint_rgx_digits_decimals
3276
3354
  )[0];
3277
- let length = digits.length;
3278
- if (!quiet && length === 0) {
3355
+ if (
3356
+ (mode !== mode_digits_empty_string && digits.length === 0)
3357
+ || digits[0] === "_"
3358
+ ) {
3279
3359
 
3280
3360
  // test_cause:
3281
3361
  // ["0x", "read_digits", "expected_digits_after_a", "0x", 2]
3362
+ // ["0x_", "read_digits", "expected_digits_after_a", "0x", 2]
3282
3363
 
3283
3364
  warn_at("expected_digits_after_a", line, column, snippet);
3284
3365
  }
3285
- column += length;
3286
- line_source = line_source.slice(length);
3366
+
3367
+ // PR-390 - Add numeric-separator check.
3368
+
3369
+ if (mode === mode_digits_numeric_separator) {
3370
+ check_numeric_separator(digits, column);
3371
+ } else if (digits.indexOf("_") >= 0) {
3372
+
3373
+ // test_cause:
3374
+ // ["\"\\u{1_2}\"", "read_digits", "illegal_num_separator", "", 6]
3375
+
3376
+ warn_at(
3377
+ "illegal_num_separator",
3378
+ line,
3379
+ column + digits.indexOf("_") + 1
3380
+ );
3381
+ }
3382
+ column += digits.length;
3383
+ line_source = line_source.slice(digits.length);
3287
3384
  snippet += digits;
3288
3385
  char_after();
3289
- return length;
3386
+ return digits.length;
3290
3387
  }
3291
3388
 
3292
3389
  function read_line() {
@@ -3357,6 +3454,7 @@ import moduleHttps from "https";
3357
3454
  test_cause("line_disable");
3358
3455
  line_source = "";
3359
3456
  }
3457
+ // jslint_rgx_tab
3360
3458
  if (line_source.indexOf("\t") >= 0) {
3361
3459
  if (!option_dict.white) {
3362
3460
 
@@ -3365,10 +3463,7 @@ import moduleHttps from "https";
3365
3463
 
3366
3464
  warn_at("use_spaces", line, line_source.indexOf("\t") + 1);
3367
3465
  }
3368
- line_source = line_source.replace((
3369
- // rx_tab
3370
- /\t/g
3371
- ), " ");
3466
+ line_source = line_source.replace(jslint_rgx_tab, " ");
3372
3467
  }
3373
3468
  if (!option_dict.white && line_source.endsWith(" ")) {
3374
3469
 
@@ -3388,9 +3483,11 @@ import moduleHttps from "https";
3388
3483
  from,
3389
3484
  id,
3390
3485
  identifier: Boolean(identifier),
3486
+ is_fart: false,
3391
3487
  line,
3392
3488
  nr: token_list.length,
3393
- thru: column
3489
+ thru: column,
3490
+ value
3394
3491
  };
3395
3492
  token_list.push(the_token);
3396
3493
 
@@ -3400,12 +3497,6 @@ import moduleHttps from "https";
3400
3497
  mode_directive = false;
3401
3498
  }
3402
3499
 
3403
- // If the token is to have a value, give it one.
3404
-
3405
- if (value !== undefined) {
3406
- the_token.value = value;
3407
- }
3408
-
3409
3500
  // If this token is an identifier that touches a preceding number, or
3410
3501
  // a "/", comment, or regular expression literal that touches a preceding
3411
3502
  // comment or regular expression literal, then give a missing space warning.
@@ -3439,6 +3530,29 @@ import moduleHttps from "https";
3439
3530
  the_token.dot = true;
3440
3531
  }
3441
3532
 
3533
+ // PR-385 - Bugfix - Fixes issue #382 - failure to detect destructured fart.
3534
+ // Farts are now detected by keeping a list of most recent "(" tokens at any
3535
+ // given depth. When a "=>" token is encountered, the most recent "(" token at
3536
+ // current depth is marked as a fart.
3537
+
3538
+ switch (id) {
3539
+ case "(":
3540
+ paren_backtrack_list[paren_depth] = the_token;
3541
+ paren_depth += 1;
3542
+ break;
3543
+ case ")":
3544
+ paren_depth -= 1;
3545
+ break;
3546
+ case "=>":
3547
+ if (
3548
+ token_prv_expr.id === ")"
3549
+ && paren_backtrack_list[paren_depth]
3550
+ ) {
3551
+ paren_backtrack_list[paren_depth].is_fart = true;
3552
+ }
3553
+ break;
3554
+ }
3555
+
3442
3556
  // The previous token is used to detect adjacency problems.
3443
3557
 
3444
3558
  token_prv = the_token;
@@ -3523,9 +3637,6 @@ function jslint_phase3_parse(state) {
3523
3637
  let catchage = catch_stack[0]; // The current catch-block.
3524
3638
  let functionage = token_global; // The current function.
3525
3639
  let mode_var; // "var" if using var; "let" if using let.
3526
- let rx_identifier = (
3527
- /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/
3528
- );
3529
3640
  let token_ii = 0; // The number of the next token.
3530
3641
  let token_now = token_global; // The current token being examined in
3531
3642
  // ... the parse.
@@ -3542,7 +3653,7 @@ function jslint_phase3_parse(state) {
3542
3653
  anon = token_now.id;
3543
3654
  } else if (
3544
3655
  token_now.id === "(string)"
3545
- && rx_identifier.test(token_now.value)
3656
+ && jslint_rgx_identifier.test(token_now.value)
3546
3657
  ) {
3547
3658
  anon = token_now.value;
3548
3659
  }
@@ -3554,7 +3665,7 @@ function jslint_phase3_parse(state) {
3554
3665
  match === undefined
3555
3666
 
3556
3667
  // test_cause:
3557
- // ["()", "advance", "expected_a_b", "(end)", 1]
3668
+ // ["{0:0}", "advance", "expected_a_b", "0", 2]
3558
3669
 
3559
3670
  ? stop("expected_a_b", token_nxt, id, artifact())
3560
3671
 
@@ -3603,7 +3714,7 @@ function jslint_phase3_parse(state) {
3603
3714
  // other assignment operators can modify, but they cannot initialize.
3604
3715
 
3605
3716
  const the_symbol = symbol(id, 20);
3606
- the_symbol.led = function (left) {
3717
+ the_symbol.led_infix = function (left) {
3607
3718
  const the_token = token_now;
3608
3719
  let right;
3609
3720
  the_token.arity = "assignment";
@@ -3915,7 +4026,7 @@ function jslint_phase3_parse(state) {
3915
4026
 
3916
4027
  const the_symbol = symbol(id);
3917
4028
  the_symbol.constant = true;
3918
- the_symbol.nud = (
4029
+ the_symbol.nud_prefix = (
3919
4030
  typeof value === "function"
3920
4031
  ? value
3921
4032
  : function () {
@@ -4109,7 +4220,7 @@ function jslint_phase3_parse(state) {
4109
4220
  // Create an infix operator.
4110
4221
 
4111
4222
  const the_symbol = symbol(id, bp);
4112
- the_symbol.led = function (left) {
4223
+ the_symbol.led_infix = function (left) {
4113
4224
  const the_token = token_now;
4114
4225
  the_token.arity = "binary";
4115
4226
  if (f !== undefined) {
@@ -4167,12 +4278,12 @@ function jslint_phase3_parse(state) {
4167
4278
  return the_token;
4168
4279
  }
4169
4280
 
4170
- function infix_fart_unwrapped(left) {
4281
+ function infix_fart_unwrapped() {
4171
4282
 
4172
4283
  // test_cause:
4173
- // ["aa=>0", "infix_fart_unwrapped", "wrap_parameter", "aa", 1]
4284
+ // ["aa=>0", "infix_fart_unwrapped", "wrap_fart_parameter", "=>", 3]
4174
4285
 
4175
- return stop("wrap_parameter", left);
4286
+ return stop("wrap_fart_parameter", token_now);
4176
4287
  }
4177
4288
 
4178
4289
  function infix_grave(left) {
@@ -4192,7 +4303,7 @@ function jslint_phase3_parse(state) {
4192
4303
  let the_subscript = parse_expression(0);
4193
4304
  if (the_subscript.id === "(string)" || the_subscript.id === "`") {
4194
4305
  name = survey(the_subscript);
4195
- if (rx_identifier.test(name)) {
4306
+ if (jslint_rgx_identifier.test(name)) {
4196
4307
 
4197
4308
  // test_cause:
4198
4309
  // ["aa[`aa`]", "infix_lbracket", "subscript_a", "aa", 4]
@@ -4335,13 +4446,13 @@ function jslint_phase3_parse(state) {
4335
4446
  // Create a right associative infix operator.
4336
4447
 
4337
4448
  const the_symbol = symbol(id, bp);
4338
- the_symbol.led = function parse_infixr_led(left) {
4449
+ the_symbol.led_infix = function parse_infixr_led(left) {
4339
4450
  const the_token = token_now;
4340
4451
 
4341
4452
  // test_cause:
4342
- // ["0**0", "parse_infixr_led", "led", "", 0]
4453
+ // ["0**0", "parse_infixr_led", "led_infix", "", 0]
4343
4454
 
4344
- test_cause("led");
4455
+ test_cause("led_infix");
4345
4456
  the_token.arity = "binary";
4346
4457
  the_token.expression = [left, parse_expression(bp - 1)];
4347
4458
  return the_token;
@@ -4349,39 +4460,70 @@ function jslint_phase3_parse(state) {
4349
4460
  return the_symbol;
4350
4461
  }
4351
4462
 
4352
- function lookahead() {
4353
-
4354
- // Look ahead one token without advancing, skipping comments.
4355
-
4356
- let cadet;
4357
- let ii = token_ii;
4358
- while (true) {
4359
- cadet = token_list[ii];
4360
- if (cadet.id !== "(comment)") {
4361
- return cadet;
4362
- }
4363
- ii += 1;
4364
- }
4365
- }
4366
-
4367
4463
  function parse_expression(rbp, initial) {
4368
4464
 
4369
4465
  // This is the heart of JSLINT, the Pratt parser. In addition to parsing, it
4370
- // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
4371
- // like .nud except that it is only used on the first token of a statement.
4372
- // Having .fud makes it much easier to define statement-oriented languages like
4373
- // JavaScript. I retained Pratt's nomenclature.
4466
+ // is looking for ad hoc lint patterns. We add .fud_stmt to Pratt's model, which
4467
+ // is like .nud_prefix except that it is only used on the first token of a
4468
+ // statement. Having .fud_stmt makes it much easier to define statement-oriented
4469
+ // languages like JavaScript. I retained Pratt's nomenclature.
4374
4470
  // They are elements of the parsing method called Top Down Operator Precedence.
4375
4471
 
4376
- // .nud Null denotation
4377
- // .fud First null denotation
4378
- // .led Left denotation
4379
- // lbp Left binding power
4380
- // rbp Right binding power
4381
-
4382
- // It processes a nud (variable, constant, prefix operator). It will then
4383
- // process leds (infix operators) until the bind powers cause it to stop. It
4384
- // returns the expression's parse tree.
4472
+ // .nud_prefix Null denotation. The prefix handler.
4473
+ // .fud_stmt First null denotation. The statement handler.
4474
+ // .led_infix Left denotation. The infix/postfix handler.
4475
+ // lbp Left binding power of infix operator. It tells us how strongly
4476
+ // the operator binds to the argument at its left.
4477
+ // rbp Right binding power.
4478
+
4479
+ // It processes a nud_prefix (variable, constant, prefix operator). It will then
4480
+ // process leds (infix operators) until the bind powers cause it to stop (it
4481
+ // consumes tokens until it meets a token whose lbp <= rbp). Specifically, it
4482
+ // means that it collects all tokens that bind together before returning to the
4483
+ // operator that called it. It returns the expression's parse tree.
4484
+
4485
+ // For example, "3 + 1 * 2 * 4 + 5"
4486
+ // parses into
4487
+ // {
4488
+ // "id": "+",
4489
+ // "expression": [
4490
+ // {
4491
+ // "id": "+",
4492
+ // "expression": [
4493
+ // {
4494
+ // "id": "(number)",
4495
+ // "value": "3"
4496
+ // },
4497
+ // {
4498
+ // "id": "*",
4499
+ // "expression": [
4500
+ // {
4501
+ // "id": "*",
4502
+ // "expression": [
4503
+ // {
4504
+ // "id": "(number)",
4505
+ // "value": "1"
4506
+ // },
4507
+ // {
4508
+ // "id": "(number)",
4509
+ // "value": "2"
4510
+ // }
4511
+ // ]
4512
+ // },
4513
+ // {
4514
+ // "id": "(number)",
4515
+ // "value": "4"
4516
+ // }
4517
+ // ]
4518
+ // }
4519
+ // ]
4520
+ // },
4521
+ // {
4522
+ // "id": "(number)",
4523
+ // "value": "5"
4524
+ // }
4525
+ // ]
4526
+ // }
4385
4527
 
4386
4528
  let left;
4387
4529
  let the_symbol;
@@ -4393,13 +4535,13 @@ function jslint_phase3_parse(state) {
4393
4535
  advance();
4394
4536
  }
4395
4537
  the_symbol = syntax_dict[token_now.id];
4396
- if (the_symbol !== undefined && the_symbol.nud !== undefined) {
4538
+ if (the_symbol !== undefined && the_symbol.nud_prefix !== undefined) {
4397
4539
 
4398
4540
  // test_cause:
4399
4541
  // ["0", "parse_expression", "symbol", "", 0]
4400
4542
 
4401
4543
  test_cause("symbol");
4402
- left = the_symbol.nud();
4544
+ left = the_symbol.nud_prefix();
4403
4545
  } else if (token_now.identifier) {
4404
4546
 
4405
4547
  // test_cause:
@@ -4424,32 +4566,38 @@ function jslint_phase3_parse(state) {
4424
4566
  the_symbol = syntax_dict[token_nxt.id];
4425
4567
  if (
4426
4568
  the_symbol === undefined
4427
- || the_symbol.led === undefined
4569
+ || the_symbol.led_infix === undefined
4428
4570
  || the_symbol.lbp <= rbp
4429
4571
  ) {
4430
4572
  break;
4431
4573
  }
4432
4574
  advance();
4433
- left = the_symbol.led(left);
4575
+ left = the_symbol.led_infix(left);
4434
4576
  }
4435
4577
  return left;
4436
4578
  }
4437
4579
 
4438
- function parse_fart(pl) {
4580
+ function parse_fart() {
4581
+ let parameters;
4582
+ let signature;
4439
4583
  let the_fart;
4584
+ [parameters, signature] = prefix_function_arg();
4440
4585
  advance("=>");
4441
4586
  the_fart = token_now;
4442
4587
  the_fart.arity = "binary";
4443
4588
  the_fart.name = "=>";
4444
4589
  the_fart.level = functionage.level + 1;
4445
4590
  function_list.push(the_fart);
4446
- if (functionage.loop > 0) {
4447
4591
 
4448
- // test_cause:
4449
- // ["while(0){aa.map(()=>0);}", "parse_fart", "function_in_loop", "=>", 19]
4592
+ // PR-384 - Relax warning "function_in_loop".
4593
+ //
4594
+ // if (functionage.loop > 0) {
4450
4595
 
4451
- warn("function_in_loop", the_fart);
4452
- }
4596
+ // // test_cause:
4597
+ // // ["while(0){aa.map(()=>0);}", "parse_fart", "function_in_loop", "=>", 19]
4598
+ //
4599
+ // warn("function_in_loop", the_fart);
4600
+ // }
4453
4601
 
4454
4602
  // Give the function properties storing its names and for observing the depth
4455
4603
  // of loops and switches.
@@ -4457,6 +4605,8 @@ function jslint_phase3_parse(state) {
4457
4605
  the_fart.context = empty();
4458
4606
  the_fart.finally = 0;
4459
4607
  the_fart.loop = 0;
4608
+ the_fart.parameters = parameters;
4609
+ the_fart.signature = signature;
4460
4610
  the_fart.switch = 0;
4461
4611
  the_fart.try = 0;
4462
4612
 
@@ -4464,23 +4614,42 @@ function jslint_phase3_parse(state) {
4464
4614
 
4465
4615
  function_stack.push(functionage);
4466
4616
  functionage = the_fart;
4467
- the_fart.parameters = pl[0];
4468
- the_fart.signature = pl[1];
4469
- the_fart.parameters.forEach(function (name) {
4617
+ the_fart.parameters.forEach(function enroll_parameter(name) {
4618
+ if (name.identifier) {
4619
+ enroll(name, "parameter", true);
4620
+ } else {
4621
+
4622
+ // PR-385 - Bugfix - Fixes issue #382 - fix warnings against destructured fart.
4470
4623
 
4471
4624
  // test_cause:
4472
- // ["(aa)=>{}", "parse_fart", "parameter", "", 0]
4625
+ // ["([aa])=>0", "enroll_parameter", "use_function_not_fart", "=>", 7]
4626
+ // ["({aa})=>0", "enroll_parameter", "use_function_not_fart", "=>", 7]
4627
+
4628
+ warn("use_function_not_fart", the_fart);
4629
+
4630
+ // Recurse enroll_parameter().
4473
4631
 
4474
- test_cause("parameter");
4475
- enroll(name, "parameter", true);
4632
+ name.names.forEach(enroll_parameter);
4633
+ }
4476
4634
  });
4477
4635
  if (token_nxt.id === "{") {
4478
4636
 
4479
4637
  // test_cause:
4480
- // ["()=>{}", "parse_fart", "expected_a_b", "=>", 3]
4638
+ // ["()=>{}", "parse_fart", "use_function_not_fart", "=>", 3]
4481
4639
 
4482
- warn("expected_a_b", the_fart, "function", "=>");
4640
+ warn("use_function_not_fart", the_fart);
4483
4641
  the_fart.block = block("body");
4642
+ } else if (
4643
+ syntax_dict[token_nxt.id] !== undefined
4644
+ && syntax_dict[token_nxt.id].fud_stmt !== undefined
4645
+ ) {
4646
+
4647
+ // PR-384 - Bugfix - Fixes issue #379 - warn against naked-statement in fart.
4648
+
4649
+ // test_cause:
4650
+ // ["()=>delete aa", "parse_fart", "unexpected_a_after_b", "=>", 5]
4651
+
4652
+ stop("unexpected_a_after_b", token_nxt, token_nxt.id, "=>");
4484
4653
  } else {
4485
4654
  the_fart.expression = parse_expression(0);
4486
4655
  }
@@ -4495,13 +4664,7 @@ function jslint_phase3_parse(state) {
4495
4664
  let negative;
4496
4665
  switch (token_nxt.id) {
4497
4666
  case "(number)":
4498
- if (!(
4499
-
4500
- // https://datatracker.ietf.org/doc/html/rfc7159#section-6
4501
- // number = [ minus ] int [ frac ] [ exp ]
4502
-
4503
- /^-?(?:0|[1-9]\d*?)(?:\.\d*?)?(?:[eE][+\-]?\d+?)?$/
4504
- ).test(token_nxt.value)) {
4667
+ if (!jslint_rgx_json_number.test(token_nxt.value)) {
4505
4668
 
4506
4669
  // test_cause:
4507
4670
  // ["[-.0]", "parse_json", "unexpected_a", ".", 3]
@@ -4703,7 +4866,7 @@ function jslint_phase3_parse(state) {
4703
4866
  the_symbol = syntax_dict[first.id];
4704
4867
  if (
4705
4868
  the_symbol !== undefined
4706
- && the_symbol.fud !== undefined
4869
+ && the_symbol.fud_stmt !== undefined
4707
4870
 
4708
4871
  // PR-318 - Bugfix - Fixes issues #316, #317 - dynamic-import().
4709
4872
 
@@ -4712,7 +4875,7 @@ function jslint_phase3_parse(state) {
4712
4875
  the_symbol.disrupt = false;
4713
4876
  the_symbol.statement = true;
4714
4877
  token_now.arity = "statement";
4715
- the_statement = the_symbol.fud();
4878
+ the_statement = the_symbol.fud_stmt();
4716
4879
  functionage.statement_prv = the_statement;
4717
4880
  } else {
4718
4881
 
@@ -4782,7 +4945,7 @@ function jslint_phase3_parse(state) {
4782
4945
  // Create one of the postassign operators.
4783
4946
 
4784
4947
  const the_symbol = symbol(id, 150);
4785
- the_symbol.led = function (left) {
4948
+ the_symbol.led_infix = function (left) {
4786
4949
  token_now.expression = left;
4787
4950
  token_now.arity = "postassign";
4788
4951
  check_mutation(token_now.expression);
@@ -4796,7 +4959,7 @@ function jslint_phase3_parse(state) {
4796
4959
  // Create one of the preassign operators.
4797
4960
 
4798
4961
  const the_symbol = symbol(id);
4799
- the_symbol.nud = function () {
4962
+ the_symbol.nud_prefix = function () {
4800
4963
  const the_token = token_now;
4801
4964
  the_token.arity = "preassign";
4802
4965
  the_token.expression = parse_expression(150);
@@ -4811,7 +4974,7 @@ function jslint_phase3_parse(state) {
4811
4974
  // Create a prefix operator.
4812
4975
 
4813
4976
  const the_symbol = symbol(id);
4814
- the_symbol.nud = function () {
4977
+ the_symbol.nud_prefix = function () {
4815
4978
  const the_token = token_now;
4816
4979
  the_token.arity = "unary";
4817
4980
  if (typeof f === "function") {
@@ -4932,18 +5095,20 @@ function jslint_phase3_parse(state) {
4932
5095
  // }
4933
5096
  // jslint_assert(!mode_mega, `Expected !mode_mega.`);
4934
5097
 
4935
- // Don't create functions in loops. It is inefficient, and it can lead to
4936
- // scoping errors.
4937
-
4938
- if (functionage.loop > 0) {
4939
-
4940
- // test_cause:
4941
- // ["
4942
- // while(0){aa.map(function(){});}
4943
- // ", "prefix_function", "function_in_loop", "function", 17]
4944
-
4945
- warn("function_in_loop", the_function);
4946
- }
5098
+ // PR-378 - Relax warning "function_in_loop".
5099
+ //
5100
+ // // Don't create functions in loops. It is inefficient, and it can lead to
5101
+ // // scoping errors.
5102
+ //
5103
+ // if (functionage.loop > 0) {
5104
+ //
5105
+ // // test_cause:
5106
+ // // ["
5107
+ // // while(0){aa.map(function(){});}
5108
+ // // ", "prefix_function", "function_in_loop", "function", 17]
5109
+ //
5110
+ // warn("function_in_loop", the_function);
5111
+ // }
4947
5112
 
4948
5113
  // Give the function properties for storing its names and for observing the
4949
5114
  // depth of loops and switches.
@@ -4991,6 +5156,9 @@ function jslint_phase3_parse(state) {
4991
5156
  if (name.identifier) {
4992
5157
  enroll(name, "parameter", false);
4993
5158
  } else {
5159
+
5160
+ // Recurse enroll_parameter().
5161
+
4994
5162
  name.names.forEach(enroll_parameter);
4995
5163
  }
4996
5164
  });
@@ -5451,25 +5619,14 @@ function jslint_phase3_parse(state) {
5451
5619
  }
5452
5620
 
5453
5621
  function prefix_lparen() {
5454
- const cadet = lookahead().id;
5455
- const the_paren = token_now;
5622
+ let the_paren = token_now;
5456
5623
  let the_value;
5457
5624
 
5458
- // We can distinguish between a parameter list for => and a wrapped expression
5459
- // with one token of lookahead.
5625
+ // PR-385 - Bugfix - Fixes issue #382 - failure to detect destructured fart.
5460
5626
 
5461
- if (
5462
- token_nxt.id === ")"
5463
- || token_nxt.id === "..."
5464
- || (token_nxt.identifier && (cadet === "," || cadet === "="))
5465
- ) {
5466
-
5467
- // test_cause:
5468
- // ["()=>0", "prefix_lparen", "fart", "", 0]
5469
-
5470
- test_cause("fart");
5627
+ if (token_now.is_fart) {
5471
5628
  the_paren.free = false;
5472
- return parse_fart(prefix_function_arg());
5629
+ return parse_fart();
5473
5630
  }
5474
5631
 
5475
5632
  // test_cause:
@@ -5487,31 +5644,6 @@ function jslint_phase3_parse(state) {
5487
5644
  }
5488
5645
  the_value.wrapped = true;
5489
5646
  advance(")", the_paren);
5490
- if (token_nxt.id === "=>") {
5491
- if (the_value.arity !== "variable") {
5492
- if (the_value.id === "{" || the_value.id === "[") {
5493
-
5494
- // test_cause:
5495
- // ["([])=>0", "prefix_lparen", "expected_a_before_b", "(", 1]
5496
- // ["({})=>0", "prefix_lparen", "expected_a_before_b", "(", 1]
5497
-
5498
- warn("expected_a_before_b", the_paren, "function", "(");
5499
-
5500
- // test_cause:
5501
- // ["([])=>0", "prefix_lparen", "expected_a_b", "=>", 5]
5502
- // ["({})=>0", "prefix_lparen", "expected_a_b", "=>", 5]
5503
-
5504
- return stop("expected_a_b", token_nxt, "{", "=>");
5505
- }
5506
-
5507
- // test_cause:
5508
- // ["(0)=>0", "prefix_lparen", "expected_identifier_a", "0", 2]
5509
-
5510
- return stop("expected_identifier_a", the_value);
5511
- }
5512
- the_paren.expression = [the_value];
5513
- return parse_fart([the_paren.expression, "(" + the_value.id + ")"]);
5514
- }
5515
5647
  return the_value;
5516
5648
  }
5517
5649
 
@@ -5592,12 +5724,12 @@ function jslint_phase3_parse(state) {
5592
5724
  anon = "anonymous";
5593
5725
  }
5594
5726
 
5595
- function stmt(id, fud) {
5727
+ function stmt(id, fud_stmt) {
5596
5728
 
5597
5729
  // Create a statement.
5598
5730
 
5599
5731
  const the_symbol = symbol(id);
5600
- the_symbol.fud = fud;
5732
+ the_symbol.fud_stmt = fud_stmt;
5601
5733
  return the_symbol;
5602
5734
  }
5603
5735
 
@@ -6032,10 +6164,7 @@ function jslint_phase3_parse(state) {
6032
6164
  advance("from");
6033
6165
  advance("(string)");
6034
6166
  the_import.import = token_now;
6035
- if (!(
6036
- // rx_module
6037
- /^[a-zA-Z0-9_$:.@\-\/]+$/
6038
- ).test(token_now.value)) {
6167
+ if (!jslint_rgx_module.test(token_now.value)) {
6039
6168
 
6040
6169
  // test_cause:
6041
6170
  // ["import aa from \"!aa\"", "stmt_import", "bad_module_name_a", "!aa", 16]
@@ -6646,13 +6775,13 @@ function jslint_phase3_parse(state) {
6646
6775
 
6647
6776
  if (id === "(string)") {
6648
6777
  id = name.value;
6649
- if (!rx_identifier.test(id)) {
6778
+ if (!jslint_rgx_identifier.test(id)) {
6650
6779
  return id;
6651
6780
  }
6652
6781
  } else if (id === "`") {
6653
6782
  if (name.value.length === 1) {
6654
6783
  id = name.value[0].value;
6655
- if (!rx_identifier.test(id)) {
6784
+ if (!jslint_rgx_identifier.test(id)) {
6656
6785
  return id;
6657
6786
  }
6658
6787
  }
@@ -6685,10 +6814,7 @@ function jslint_phase3_parse(state) {
6685
6814
  } else if (
6686
6815
  !option_dict.name
6687
6816
  && name.identifier
6688
- && (
6689
- // rx_weird_property
6690
- /^_|\$|Sync$|_$/m
6691
- ).test(id)
6817
+ && jslint_rgx_weird_property.test(id)
6692
6818
  ) {
6693
6819
 
6694
6820
  // test_cause:
@@ -6726,7 +6852,7 @@ function jslint_phase3_parse(state) {
6726
6852
  // Create a ternary operator.
6727
6853
 
6728
6854
  const the_symbol = symbol(id1, 30);
6729
- the_symbol.led = function parse_ternary_led(left) {
6855
+ the_symbol.led_infix = function parse_ternary_led(left) {
6730
6856
  const the_token = token_now;
6731
6857
  let second;
6732
6858
  second = parse_expression(20);
@@ -7442,10 +7568,7 @@ function jslint_phase4_walk(state) {
7442
7568
  test_cause("cack");
7443
7569
  cack = !cack;
7444
7570
  }
7445
- if ((
7446
- // rx_cap
7447
- /^[A-Z]/
7448
- ).test(left.name.id) !== cack) {
7571
+ if (jslint_rgx_cap.test(left.name.id) !== cack) {
7449
7572
  if (the_new !== undefined) {
7450
7573
 
7451
7574
  // test_cause:
@@ -7622,6 +7745,11 @@ function jslint_phase4_walk(state) {
7622
7745
  || thing.expression[0].constant === true
7623
7746
  || is_equal(thing.expression[1], thing.expression[2])
7624
7747
  ) {
7748
+
7749
+ // test_cause:
7750
+ // ["let aa=(aa?`${0}`:`${0}`);", "post_t", "unexpected_a", "?", 11]
7751
+ // ["let aa=(aa?`0`:`0`);", "post_t", "unexpected_a", "?", 11]
7752
+
7625
7753
  warn("unexpected_a", thing);
7626
7754
  } else if (is_equal(thing.expression[0], thing.expression[1])) {
7627
7755
 
@@ -9314,6 +9442,9 @@ body {
9314
9442
  : "global"
9315
9443
  );
9316
9444
  if (global.length + froms.length + exports.length > 0) {
9445
+ if (functions.length === 0) {
9446
+ html += "<br>\n";
9447
+ }
9317
9448
  html += "<div class=\"level level0\">\n";
9318
9449
  html += detail(module, global);
9319
9450
  html += detail("import from", froms);
@@ -9478,14 +9609,14 @@ function jstestIt(description, testFunction, mode) {
9478
9609
  }));
9479
9610
  }
9480
9611
 
9481
- function jstestOnExit(exitCode, processExit, countFailed) {
9612
+ function jstestOnExit(exitCode, mode) {
9482
9613
 
9483
9614
  // This function will on process-exit, print test-report
9484
9615
  // and exit with non-zero exit-code if any test failed.
9485
9616
 
9486
9617
  let message = (
9487
9618
  (
9488
- (jstestCountFailed || countFailed)
9619
+ (jstestCountFailed || mode === "testsFailed")
9489
9620
  ? "\n\u001b[31m"
9490
9621
  : "\n\u001b[32m"
9491
9622
  )
@@ -9493,11 +9624,10 @@ function jstestOnExit(exitCode, processExit, countFailed) {
9493
9624
  + " tests failed - " + jstestCountFailed + "\n"
9494
9625
  + "\u001b[39m"
9495
9626
  );
9496
- if (!processExit) {
9627
+ if (mode !== "testsFailed") {
9497
9628
  console.error(message);
9498
- processExit = process.exit;
9499
9629
  }
9500
- processExit(exitCode || jstestCountFailed);
9630
+ process.exitCode = exitCode || jstestCountFailed;
9501
9631
  return message;
9502
9632
  }
9503
9633
 
@@ -9563,7 +9693,7 @@ function objectDeepCopyWithKeysSorted(obj) {
9563
9693
 
9564
9694
  // Recursively deep-copy obj with keys sorted.
9565
9695
 
9566
- sorted = {};
9696
+ sorted = Object.create(null);
9567
9697
  Object.keys(obj).sort().forEach(function (key) {
9568
9698
  sorted[key] = objectDeepCopyWithKeysSorted(obj[key]);
9569
9699
  });
@@ -10837,7 +10967,7 @@ function sentinel() {}
10837
10967
 
10838
10968
  // 3. Create html-coverage-reports in <coverageDir>.
10839
10969
 
10840
- fileDict = {};
10970
+ fileDict = Object.create(null);
10841
10971
  await Promise.all(v8CoverageObj.result.map(async function ({
10842
10972
  functions,
10843
10973
  url: pathname