sqlmath 2022.3.5 → 2022.6.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/jslint.mjs CHANGED
@@ -1,14 +1,15 @@
1
1
  // #!/usr/bin/env node
2
2
  // JSLint
3
- // Original Author: Douglas Crockford (https://www.jslint.com).
4
3
 
4
+ // The Unlicense
5
+ //
5
6
  // This is free and unencumbered software released into the public domain.
6
-
7
+ //
7
8
  // Anyone is free to copy, modify, publish, use, compile, sell, or
8
9
  // distribute this software, either in source code form or as a compiled
9
10
  // binary, for any purpose, commercial or non-commercial, and by any
10
11
  // means.
11
-
12
+ //
12
13
  // In jurisdictions that recognize copyright laws, the author or authors
13
14
  // of this software dedicate any and all copyright interest in the
14
15
  // software to the public domain. We make this dedication for the benefit
@@ -16,7 +17,7 @@
16
17
  // successors. We intend this dedication to be an overt act of
17
18
  // relinquishment in perpetuity of all present and future rights to this
18
19
  // software under copyright law.
19
-
20
+ //
20
21
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
22
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
23
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -24,7 +25,7 @@
24
25
  // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25
26
  // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26
27
  // OTHER DEALINGS IN THE SOFTWARE.
27
-
28
+ //
28
29
  // For more information, please refer to <https://unlicense.org/>
29
30
 
30
31
 
@@ -92,49 +93,46 @@
92
93
  // WARNING: JSLint will hurt your feelings.
93
94
 
94
95
  /*jslint beta, node*/
95
-
96
96
  /*property
97
- fud_stmt,
98
- is_fart,
99
- mode_conditional,
100
97
  JSLINT_BETA, NODE_V8_COVERAGE, a, all, argv, arity, artifact,
101
98
  assertErrorThrownAsync, assertJsonEqual, assertOrThrow, assign, async, b,
102
99
  beta, bitwise, block, body, browser, c, calls, catch, catch_list,
103
- catch_stack, causes, char, children, clear, closer,
104
- closure, code, column, concat, consoleError, console_error, console_log,
105
- constant, context, convert, count, coverageDir, create, cwd, d, dead,
106
- debugInline, default, delta, devel, directive, directive_list,
107
- directive_quiet, directives, dirname, disrupt, dot, edition, elem_list,
108
- ellipsis, else, end, endOffset, endsWith, entries, env, error, eval, every,
109
- example_list, exec, execArgv, exit, export_dict, exports, expression, extra,
110
- file, fileList, fileURLToPath, filter, finally, flag, floor, for, forEach,
111
- formatted_message, free, freeze, from, froms,
112
- fsWriteFileWithParents, functionName, function_list, function_stack,
113
- functions, get, getset, github_repo, global, global_dict, global_list,
114
- holeList, htmlEscape, id, identifier, import, import_list, inc, indent2,
115
- index, indexOf, init, initial, isArray, isBlockCoverage, isHole, isNaN,
116
- is_equal, is_weird, join, jslint, jslint_apidoc, jslint_assert,
117
- jslint_charset_ascii, jslint_cli, jslint_edition, jslint_phase1_split,
118
- jslint_phase2_lex, jslint_phase3_parse, jslint_phase4_walk,
119
- jslint_phase5_whitage, jslint_report, json, jstestDescribe, jstestIt,
120
- jstestOnExit, keys, label, lbp, led_infix, length, level, line, lineList,
121
- line_list, line_offset, line_source, lines, linesCovered, linesTotal, live,
122
- log, long, loop, m, main, map, margin, match, max, message, meta, min,
123
- mkdir, modeCoverageIgnoreFile, modeIndex, mode_cli, mode_json, mode_module,
124
- mode_noop, mode_property, mode_shebang, mode_stop, module, moduleFsInit,
125
- moduleName, module_list, name, names, node, noop, now,
126
- nr, nud_prefix, objectDeepCopyWithKeysSorted, ok, on, open, opening, option,
127
- option_dict, order, package_name, padEnd, padStart, parameters, parent,
128
- parentIi, parse, pathname, platform, pop, processArgv, process_argv,
129
- process_env, process_exit, process_version, promises, property,
130
- property_dict, push, quote, ranges, readFile, readdir, readonly, recursive,
131
- reduce, repeat, replace, resolve, result, reverse, rm, rmdir, role, round,
132
- scriptId, search, set, shebang, shift, signature, single, slice, some, sort,
133
- source, spawn, splice, split, stack, stack_trace, start, startOffset,
134
- startsWith, statement, statement_prv, stdio, stop, stop_at, stringify,
135
- switch, syntax_dict, tenure, test, test_cause, test_internal_error, this,
136
- thru, toString, token, token_global, token_list, token_nxt, token_tree,
137
- tokens, trace, tree, trim, trimEnd, trimRight, try, type, unlink, unordered,
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_ignore_line, directive_list, directives,
104
+ dirname, disrupt, dot, edition, elem_list, ellipsis, else, end, endOffset,
105
+ endsWith, entries, env, error, eval, every, example_list, excludeList, exec,
106
+ execArgv, exit, exitCode, export_dict, exports, expression, extra, file,
107
+ fileList, 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, globExclude, global, global_dict, global_list,
111
+ holeList, htmlEscape, id, identifier, import, import_list, import_meta_url,
112
+ inc, includeList, indent2, index, indexOf, init, initial, isArray,
113
+ isBlockCoverage, isHole, isNaN, is_equal, is_fart, is_weird, join, jslint,
114
+ jslint_apidoc, jslint_assert, jslint_charset_ascii, jslint_cli,
115
+ jslint_edition, jslint_phase1_split, jslint_phase2_lex, jslint_phase3_parse,
116
+ jslint_phase4_walk, jslint_phase5_whitage, jslint_report, json,
117
+ jstestDescribe, jstestIt, jstestOnExit, keys, label, lbp, led_infix, length,
118
+ level, line, lineList, line_list, line_offset, line_source, lines,
119
+ linesCovered, linesTotal, live, log, long, loop, m, map, margin, match, max,
120
+ message, meta, min, mkdir, modeCoverageIgnoreFile, modeIndex, mode_cli,
121
+ mode_conditional, mode_json, mode_module, mode_noop, mode_property,
122
+ mode_shebang, mode_stop, module, moduleFsInit, moduleName, module_list,
123
+ name, names, node, nomen, noop, now, nr, nud_prefix,
124
+ objectDeepCopyWithKeysSorted, ok, on, open, opening, option, option_dict,
125
+ order, package_name, padEnd, padStart, parameters, parent, parentIi, parse,
126
+ pathname, pathnameList, platform, pop, processArgv, process_argv,
127
+ process_env, process_exit, promises, property, property_dict, push, quote,
128
+ ranges, readFile, readdir, readonly, recursive, reduce, repeat, replace,
129
+ resolve, result, reverse, role, round, scriptId, search, set, shebang,
130
+ shift, signature, single, slice, some, sort, source, spawn, splice, split,
131
+ stack, stack_trace, start, startOffset, startsWith, statement,
132
+ statement_prv, stdio, stop, stop_at, stringify, subscript, switch,
133
+ syntax_dict, tenure, test, test_cause, test_internal_error, this, thru,
134
+ toString, token, token_global, token_list, token_nxt, token_tree, tokens,
135
+ trace, tree, trim, trimEnd, trimRight, try, type, unlink, unordered,
138
136
  unshift, url, used, v8CoverageListMerge, v8CoverageReportCreate, value,
139
137
  variable, version, versions, warn, warn_at, warning, warning_list, warnings,
140
138
  white, wrapped, writeFile
@@ -142,20 +140,20 @@
142
140
 
143
141
  // init debugInline
144
142
  let debugInline = (function () {
145
- let consoleError = function () {
143
+ let __consoleError = function () {
146
144
  return;
147
145
  };
148
146
  function debug(...argv) {
149
147
 
150
148
  // This function will print <argv> to stderr and then return <argv>[0].
151
149
 
152
- consoleError("\n\ndebugInline");
153
- consoleError(...argv);
154
- consoleError("\n");
150
+ __consoleError("\n\ndebugInline");
151
+ __consoleError(...argv);
152
+ __consoleError("\n");
155
153
  return argv[0];
156
154
  }
157
155
  debug(); // Coverage-hack.
158
- consoleError = console.error;
156
+ __consoleError = console.error;
159
157
  return debug;
160
158
  }());
161
159
  let jslint_charset_ascii = (
@@ -167,11 +165,99 @@ let jslint_charset_ascii = (
167
165
  + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
168
166
  + "`abcdefghijklmnopqrstuvwxyz{|}~\u007f"
169
167
  );
170
- let jslint_edition = "v2022.2.20";
168
+ let jslint_edition = "v2022.7.1-beta";
171
169
  let jslint_export; // The jslint object to be exported.
172
170
  let jslint_fudge = 1; // Fudge starting line and starting
173
171
  // ... column to 1.
174
172
  let jslint_import_meta_url = ""; // import.meta.url used by cli.
173
+ let jslint_rgx_cap = (
174
+ /^[A-Z]/
175
+ );
176
+ let jslint_rgx_crlf = (
177
+ /\n|\r\n?/
178
+ );
179
+ let jslint_rgx_digits_bits = (
180
+ /^[01_]*/
181
+ );
182
+ let jslint_rgx_digits_decimals = (
183
+ /^[0-9_]*/
184
+ );
185
+ let jslint_rgx_digits_hexs = (
186
+ /^[0-9A-F_]*/i
187
+ );
188
+ let jslint_rgx_digits_octals = (
189
+ /^[0-7_]*/
190
+ );
191
+ let jslint_rgx_directive = (
192
+ /^(jslint|property|global)\s+(.*)$/
193
+ );
194
+ let jslint_rgx_directive_part = (
195
+ /([a-zA-Z$_][a-zA-Z0-9$_]*)(?::\s*(true|false))?,?\s*|$/g
196
+ );
197
+ let jslint_rgx_identifier = (
198
+ /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/
199
+ );
200
+ let jslint_rgx_json_number = (
201
+
202
+ // https://datatracker.ietf.org/doc/html/rfc7159#section-6
203
+ // number = [ minus ] int [ frac ] [ exp ]
204
+
205
+ /^-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][\-+]?\d+)?$/
206
+ );
207
+ let jslint_rgx_mega = (
208
+
209
+ // Vim-hack - vim-editor has trouble parsing naked '`' in regexp
210
+
211
+ /[\u0060\\]|\$\{/
212
+ );
213
+ let jslint_rgx_module = (
214
+ /^[a-zA-Z0-9_$:.@\-\/]+$/
215
+ );
216
+ let jslint_rgx_numeric_separator_illegal = (
217
+ /__|_$|_n$/m
218
+ );
219
+ let jslint_rgx_slash_star_or_slash = (
220
+ /\/\*|\/$/
221
+ );
222
+ let jslint_rgx_tab = (
223
+ /\t/g
224
+ );
225
+ let jslint_rgx_todo = (
226
+ /\b(?:todo|TO\s?DO|HACK)\b/
227
+ );
228
+ let jslint_rgx_token = new RegExp(
229
+ "^("
230
+ + "(\\s+)"
231
+ + "|([a-zA-Z_$][a-zA-Z0-9_$]*)"
232
+ + "|[(){}\\[\\],:;'\"~\\`]"
233
+ + "|\\?[?.]?"
234
+ + "|=(?:==?|>)?"
235
+ + "|\\.+"
236
+ + "|\\*[*\\/=]?"
237
+ + "|\\/[*\\/]?"
238
+ + "|\\+[=+]?"
239
+ + "|-[=\\-]?"
240
+ + "|[\\^%]=?"
241
+ + "|&[&=]?"
242
+ + "|\\"
243
+ + "|[|=]?"
244
+ + "|>{1,3}=?"
245
+ + "|<<?=?"
246
+ + "|!(?:!|==?)?"
247
+
248
+ // PR-351 - Add BigInt support.
249
+ // PR-390 - Add numeric-separator support.
250
+
251
+ + "|((?:0_?|[1-9][0-9_]*)n?)"
252
+ + ")"
253
+ + "(.*)$"
254
+ );
255
+ let jslint_rgx_url_search_window_jslint = (
256
+ /[&?]window_jslint=1(?:$|&)/m
257
+ );
258
+ let jslint_rgx_weird_property = (
259
+ /^_|\$|Sync$|_$/m
260
+ );
175
261
  let jstestCountFailed = 0;
176
262
  let jstestCountTotal = 0;
177
263
  let jstestItCount = 0;
@@ -267,6 +353,226 @@ async function fsWriteFileWithParents(pathname, data) {
267
353
  console.error("wrote file " + pathname);
268
354
  }
269
355
 
356
+ function globExclude({
357
+ excludeList = [],
358
+ includeList = [],
359
+ pathnameList = []
360
+ }) {
361
+
362
+ // This function will
363
+ // 1. Exclude pathnames in <pathnameList> that don't match glob-patterns in
364
+ // <includeList>.
365
+ // 2. Exclude pathnames in <pathnameList> that match glob-patterns in
366
+ // <excludeList>.
367
+
368
+ function globAssertNotWeird(list, name) {
369
+
370
+ // This function will check if <list> of strings contain weird characters.
371
+
372
+ [
373
+ [
374
+ "\n", (
375
+ /^.*?([\u0000-\u0007\r]).*/gm
376
+ )
377
+ ],
378
+ [
379
+ "\r", (
380
+ /^.*?([\n]).*/gm
381
+ )
382
+ ]
383
+ ].forEach(function ([
384
+ separator, rgx
385
+ ]) {
386
+ list.join(separator).replace(rgx, function (match0, char) {
387
+ throw new Error(
388
+ "Weird character "
389
+ + JSON.stringify(char)
390
+ + " found in " + name + " "
391
+ + JSON.stringify(match0)
392
+ );
393
+ });
394
+ });
395
+ }
396
+
397
+ function globToRegexp(pattern) {
398
+
399
+ // This function will translate glob <pattern> to javascript-regexp,
400
+ // which javascript can then use to "glob" pathnames.
401
+
402
+ let ii = 0;
403
+ let isClass = false;
404
+ let strClass = "";
405
+ let strRegex = "";
406
+ pattern = pattern.replace((
407
+ /\/\/+/g
408
+ ), "/");
409
+ pattern = pattern.replace((
410
+ /\*\*\*+/g
411
+ ), "**");
412
+ pattern.replace((
413
+ /\\\\|\\\[|\\\]|\[|\]|./g
414
+ ), function (match0) {
415
+ switch (match0) {
416
+ case "[":
417
+ if (isClass) {
418
+ strClass += "[";
419
+ return;
420
+ }
421
+ strClass += "\u0000";
422
+ strRegex += "\u0000";
423
+ isClass = true;
424
+ return;
425
+ case "]":
426
+ if (isClass) {
427
+ isClass = false;
428
+ return;
429
+ }
430
+ strRegex += "]";
431
+ return;
432
+ default:
433
+ if (isClass) {
434
+ strClass += match0;
435
+ return;
436
+ }
437
+ strRegex += match0;
438
+ }
439
+ return "";
440
+ });
441
+ strClass += "\u0000";
442
+
443
+ // An expression "[!...]" matches a single character, namely any character that
444
+ // is not matched by the expression obtained by removing the first '!' from it.
445
+ // (Thus, "[!a-]" matches any single character except 'a', and '-'.)
446
+
447
+ strClass = strClass.replace((
448
+ /\u0000!/g
449
+ ), "\u0000^");
450
+
451
+ // One may include '-' in its literal meaning by making it the first or last
452
+ // character between the brackets.
453
+
454
+ strClass = strClass.replace((
455
+ /\u0000-/g
456
+ ), "\u0000\\-");
457
+ strClass = strClass.replace((
458
+ /-\u0000/g
459
+ ), "\\-\u0000");
460
+
461
+ // Escape brackets '[', ']' in character class.
462
+
463
+ strClass = strClass.replace((
464
+ /[\[\]]/g
465
+ ), "\\$&");
466
+
467
+ // https://stackoverflow.com/questions/3561493
468
+ // /is-there-a-regexp-escape-function-in-javascript
469
+ // $()*+-./?[\]^{|}
470
+
471
+ strRegex = strRegex.replace((
472
+
473
+ // Ignore [-/].
474
+
475
+ /[$()*+.?\[\\\]\^{|}]/g
476
+ ), "\\$&");
477
+
478
+ // Expand wildcard '**/*'.
479
+
480
+ strRegex = strRegex.replace((
481
+ /\\\*\\\*\/(?:\\\*)+/g
482
+ ), ".*?");
483
+
484
+ // Expand wildcard '**'.
485
+
486
+ strRegex = strRegex.replace((
487
+ /(^|\/)\\\*\\\*(\/|$)/gm
488
+ ), "$1.*?$2");
489
+
490
+ // Expand wildcard '*'.
491
+
492
+ strRegex = strRegex.replace((
493
+ /(?:\\\*)+/g
494
+ ), "[^\\/]*?");
495
+
496
+ // Expand wildcard '?'.
497
+
498
+ strRegex = strRegex.replace((
499
+ /\\\?/g
500
+ ), "[^\\/]");
501
+
502
+ // Expand directory-with-trailing-slash '.../'.
503
+
504
+ strRegex = strRegex.replace((
505
+ /\/$/gm
506
+ ), "\\/.*?");
507
+
508
+ // Merge strClass into strRegex.
509
+
510
+ ii = 0;
511
+ strClass = strClass.split("\u0000");
512
+ strRegex = strRegex.replace((
513
+ /\u0000/g
514
+ ), function () {
515
+ ii += 1;
516
+ if (strClass[ii] === "") {
517
+ return "";
518
+ }
519
+ return "[" + strClass[ii] + "]";
520
+ });
521
+
522
+ // Change strRegex from string to regexp.
523
+
524
+ strRegex = new RegExp("^" + strRegex + "$", "gm");
525
+ return strRegex;
526
+ }
527
+
528
+ // Validate excludeList, includeList, pathnameList.
529
+
530
+ globAssertNotWeird(excludeList, "pattern");
531
+ globAssertNotWeird(includeList, "pattern");
532
+ globAssertNotWeird(pathnameList, "pathname");
533
+
534
+ // Optimization
535
+ // Concat pathnames into a single, newline-separated string,
536
+ // whose pathnames can all be filtered with a single, regexp-pass.
537
+
538
+ pathnameList = pathnameList.join("\n");
539
+
540
+ // 1. Exclude pathnames in <pathnameList> that don't match glob-patterns in
541
+ // <includeList>.
542
+
543
+ if (includeList.length > 0) {
544
+ includeList = includeList.map(globToRegexp);
545
+ includeList.forEach(function (pattern) {
546
+ pathnameList = pathnameList.replace(pattern, "\u0000$&");
547
+ });
548
+ pathnameList = pathnameList.replace((
549
+ /^[^\u0000].*/gm
550
+ ), "");
551
+ pathnameList = pathnameList.replace((
552
+ /^\u0000+/gm
553
+ ), "");
554
+ }
555
+
556
+ // 2. Exclude pathnames in <pathnameList> that match glob-patterns in
557
+ // <excludeList>.
558
+
559
+ excludeList = excludeList.map(globToRegexp);
560
+ excludeList.forEach(function (pattern) {
561
+ pathnameList = pathnameList.replace(pattern, "");
562
+ });
563
+
564
+ // Split newline-separated pathnames back to list.
565
+
566
+ pathnameList = pathnameList.split("\n").filter(function (elem) {
567
+ return elem;
568
+ });
569
+ return {
570
+ excludeList,
571
+ includeList,
572
+ pathnameList
573
+ };
574
+ }
575
+
270
576
  function htmlEscape(str) {
271
577
 
272
578
  // This function will make <str> html-safe by escaping & < >.
@@ -307,10 +613,7 @@ function jslint(
307
613
  let import_list = []; // The array collecting all import-from strings.
308
614
  let line_list = String( // The array containing source lines.
309
615
  "\n" + source
310
- ).split(
311
- // rx_crlf
312
- /\n|\r\n?/
313
- ).map(function (line_source) {
616
+ ).split(jslint_rgx_crlf).map(function (line_source) {
314
617
  return {
315
618
  line_source
316
619
  };
@@ -355,8 +658,6 @@ function jslint(
355
658
  }
356
659
 
357
660
  function is_equal(aa, bb) {
358
- let aa_value;
359
- let bb_value;
360
661
 
361
662
  // test_cause:
362
663
  // ["0&&0", "is_equal", "", "", 0]
@@ -377,6 +678,7 @@ function jslint(
377
678
 
378
679
  // test_cause:
379
680
  // ["`${0}`&&`${0}`", "is_equal", "recurse_isArray", "", 0]
681
+ // ["`${0}`&&`${1}`", "is_equal", "recurse_isArray", "", 0]
380
682
 
381
683
  test_cause("recurse_isArray");
382
684
  return is_equal(value, bb[index]);
@@ -390,21 +692,19 @@ function jslint(
390
692
  // }
391
693
 
392
694
  jslint_assert(!Array.isArray(bb), `Expected !Array.isArray(bb).`);
393
- if (aa.id === "(number)" && bb.id === "(number)") {
695
+ switch (aa.id === bb.id && aa.id) {
696
+ case "(number)":
697
+ case "(string)":
394
698
  return aa.value === bb.value;
395
- }
396
- if (aa.id === "(string)") {
397
- aa_value = aa.value;
398
- } else if (aa.id === "`" && aa.constant) {
399
- aa_value = aa.value[0];
400
- }
401
- if (bb.id === "(string)") {
402
- bb_value = bb.value;
403
- } else if (bb.id === "`" && bb.constant) {
404
- bb_value = bb.value[0];
405
- }
406
- if (typeof aa_value === "string") {
407
- return aa_value === bb_value;
699
+
700
+ // PR-394 - Bugfix
701
+ // Fix jslint falsely believing megastring literals `0` and `1` are similar.
702
+
703
+ case "`":
704
+ if (!is_equal(aa.value, bb.value)) {
705
+ return false;
706
+ }
707
+ break;
408
708
  }
409
709
  if (is_weird(aa) || is_weird(bb)) {
410
710
 
@@ -415,10 +715,11 @@ function jslint(
415
715
  return false;
416
716
  }
417
717
  if (aa.arity === bb.arity && aa.id === bb.id) {
418
- if (aa.id === ".") {
718
+ if (aa.id === "." || aa.id === "?.") {
419
719
 
420
720
  // test_cause:
421
721
  // ["aa.bb&&aa.bb", "is_equal", "recurse_arity_id", "", 0]
722
+ // ["aa?.bb&&aa?.bb", "is_equal", "recurse_arity_id", "", 0]
422
723
 
423
724
  test_cause("recurse_arity_id");
424
725
  return (
@@ -687,6 +988,12 @@ function jslint(
687
988
  // case "function_in_loop":
688
989
  // mm = `Don't create functions within a loop.`;
689
990
  // break;
991
+
992
+ // PR-390 - Add numeric-separator check.
993
+
994
+ case "illegal_num_separator":
995
+ mm = `Illegal numeric separator '_' at column ${column}.`;
996
+ break;
690
997
  case "infix_in":
691
998
  mm = (
692
999
  `Unexpected 'in'. Compare with undefined,`
@@ -912,12 +1219,12 @@ function jslint(
912
1219
  if (option_dict.trace) {
913
1220
  warning.stack_trace = new Error().stack;
914
1221
  }
915
- if (warning.directive_quiet) {
1222
+ if (warning.directive_ignore_line) {
916
1223
 
917
1224
  // test_cause:
918
- // ["0 //jslint-quiet", "semicolon", "directive_quiet", "", 0]
1225
+ // ["0 //jslint-ignore-line", "semicolon", "directive_ignore_line", "", 0]
919
1226
 
920
- test_cause("directive_quiet");
1227
+ test_cause("directive_ignore_line");
921
1228
  return warning;
922
1229
  }
923
1230
  warning_list.push(warning);
@@ -951,7 +1258,7 @@ function jslint(
951
1258
  mode_json: false, // true if parsing JSON.
952
1259
  mode_module: false, // true if import or export was used.
953
1260
  mode_property: false, // true if directive /*property*/ is
954
- // used.
1261
+ // ... used.
955
1262
  mode_shebang: false, // true if #! is seen on the first line.
956
1263
  option_dict,
957
1264
  property_dict,
@@ -1455,6 +1762,7 @@ async function jslint_cli({
1455
1762
  console_error,
1456
1763
  console_log,
1457
1764
  file,
1765
+ import_meta_url,
1458
1766
  mode_cli,
1459
1767
  mode_noop,
1460
1768
  option,
@@ -1623,11 +1931,26 @@ async function jslint_cli({
1623
1931
  return count;
1624
1932
  }
1625
1933
 
1934
+ // PR-396 - window.jslint
1935
+ // Check import.meta.url for directive to export jslint to window-object.
1936
+ // Useful for ES5-era browser-scripts that rely on window.jslint,
1937
+ // like CodeMirror.
1938
+ //
1939
+ // Example usage:
1940
+ // <script type="module" src="./jslint.mjs?window_jslint=1"></script>
1941
+
1942
+ import_meta_url = import_meta_url || jslint_import_meta_url;
1943
+ if (
1944
+ jslint_rgx_url_search_window_jslint.test(import_meta_url)
1945
+ && (typeof globalThis === "object" && globalThis)
1946
+ ) {
1947
+ globalThis.jslint = jslint;
1948
+ }
1949
+
1626
1950
  // Feature-detect nodejs.
1627
1951
 
1628
1952
  if (!(
1629
- typeof process === "object"
1630
- && process
1953
+ (typeof process === "object" && process)
1631
1954
  && process.versions
1632
1955
  && typeof process.versions.node === "string"
1633
1956
  && !mode_noop
@@ -1653,7 +1976,7 @@ async function jslint_cli({
1653
1976
  ).test(process_argv[1])
1654
1977
  || mode_cli
1655
1978
  )
1656
- && moduleUrl.fileURLToPath(jslint_import_meta_url)
1979
+ && moduleUrl.fileURLToPath(import_meta_url)
1657
1980
  === modulePath.resolve(process_argv[1])
1658
1981
  )
1659
1982
  && !mode_cli
@@ -1799,7 +2122,9 @@ async function jslint_cli({
1799
2122
  option
1800
2123
  });
1801
2124
  if (mode_report) {
1802
- await fsWriteFileWithParents(mode_report, jslint_report(result));
2125
+ result = jslint.jslint_report(result);
2126
+ result = `<body class="JSLINT_ JSLINT_REPORT_">\n${result}</body>\n`;
2127
+ await fsWriteFileWithParents(mode_report, result);
1803
2128
  }
1804
2129
  process_exit(exit_code);
1805
2130
  return exit_code;
@@ -1841,6 +2166,8 @@ function jslint_phase2_lex(state) {
1841
2166
  let line_mega; // The starting line of megastring.
1842
2167
  let line_source = ""; // The remaining line source string.
1843
2168
  let line_whole = ""; // The whole line source string.
2169
+ let mode_digits_empty_string = 1;
2170
+ let mode_digits_numeric_separator = 2;
1844
2171
  let mode_directive = true; // true if directives are still allowed.
1845
2172
  let mode_mega = false; // true if currently parsing a megastring
1846
2173
  // ... literal.
@@ -1848,33 +2175,7 @@ function jslint_phase2_lex(state) {
1848
2175
  // ... this line.
1849
2176
  let paren_backtrack_list = []; // List of most recent "(" tokens at any
1850
2177
  // ... paren-depth.
1851
- let paren_depth = 0; // Keeps track of current paren-depth.
1852
- let rx_token = new RegExp(
1853
- "^("
1854
- + "(\\s+)"
1855
- + "|([a-zA-Z_$][a-zA-Z0-9_$]*)"
1856
- + "|[(){}\\[\\],:;'\"~\\`]"
1857
- + "|\\?[?.]?"
1858
- + "|=(?:==?|>)?"
1859
- + "|\\.+"
1860
- + "|\\*[*\\/=]?"
1861
- + "|\\/[*\\/]?"
1862
- + "|\\+[=+]?"
1863
- + "|-[=\\-]?"
1864
- + "|[\\^%]=?"
1865
- + "|&[&=]?"
1866
- + "|\\"
1867
- + "|[|=]?"
1868
- + "|>{1,3}=?"
1869
- + "|<<?=?"
1870
- + "|!(?:!|==?)?"
1871
-
1872
- // PR-351 - Add BigInt support.
1873
-
1874
- + "|(0n?|[1-9][0-9]*n?)"
1875
- + ")"
1876
- + "(.*)$"
1877
- );
2178
+ let paren_depth = 0; // Keeps track of current paren-depth.
1878
2179
  let snippet = ""; // A piece of string.
1879
2180
  let token_1; // The first token.
1880
2181
  let token_prv = token_global; // The previous token including
@@ -1956,7 +2257,7 @@ function jslint_phase2_lex(state) {
1956
2257
 
1957
2258
  warn_at("unexpected_a", line, column, char);
1958
2259
  }
1959
- if (read_digits("x") > 5) {
2260
+ if (read_digits("x", undefined) > 5) {
1960
2261
 
1961
2262
  // test_cause:
1962
2263
  // ["\"\\u{123456}\"", "char_after_escape", "too_many_digits", "", 11]
@@ -1973,7 +2274,7 @@ function jslint_phase2_lex(state) {
1973
2274
  return char_after();
1974
2275
  }
1975
2276
  char_before();
1976
- if (read_digits("x", true) < 4) {
2277
+ if (read_digits("x", mode_digits_empty_string) < 4) {
1977
2278
 
1978
2279
  // test_cause:
1979
2280
  // ["\"\\u0\"", "char_after_escape", "expected_four_digits", "", 5]
@@ -2008,6 +2309,26 @@ function jslint_phase2_lex(state) {
2008
2309
  return char;
2009
2310
  }
2010
2311
 
2312
+ function check_numeric_separator(digits, column) {
2313
+
2314
+ // This function will check for illegal numeric-separator in <digits>.
2315
+
2316
+ digits.replace((
2317
+ jslint_rgx_numeric_separator_illegal
2318
+ ), function (ignore, ii) {
2319
+
2320
+ // test_cause:
2321
+ // ["0x0_0_;", "check_numeric_separator", "illegal_num_separator", "", 6]
2322
+ // ["0x0_0__0;", "check_numeric_separator", "illegal_num_separator", "", 6]
2323
+ // ["aa=1_2_;", "check_numeric_separator", "illegal_num_separator", "", 7]
2324
+ // ["aa=1_2__3;", "check_numeric_separator", "illegal_num_separator", "", 7]
2325
+ // ["aa=1_2_n;", "check_numeric_separator", "illegal_num_separator", "", 7]
2326
+
2327
+ warn_at("illegal_num_separator", line, column + ii + 1);
2328
+ return "";
2329
+ });
2330
+ }
2331
+
2011
2332
  function lex_comment() {
2012
2333
  let body;
2013
2334
  let ii = 0;
@@ -2046,12 +2367,12 @@ function jslint_phase2_lex(state) {
2046
2367
  // Lex/loop through each line until "*/".
2047
2368
 
2048
2369
  while (true) {
2049
- // rx_star_slash
2370
+ // jslint_rgx_star_slash
2050
2371
  ii = line_source.indexOf("*/");
2051
2372
  if (ii >= 0) {
2052
2373
  break;
2053
2374
  }
2054
- // rx_slash_star
2375
+ // jslint_rgx_slash_star
2055
2376
  ii = line_source.indexOf("/*");
2056
2377
  if (ii >= 0) {
2057
2378
 
@@ -2071,8 +2392,7 @@ function jslint_phase2_lex(state) {
2071
2392
  }
2072
2393
  }
2073
2394
  jj = line_source.slice(0, ii).search(
2074
- // rx_slash_star_or_slash
2075
- /\/\*|\/$/
2395
+ jslint_rgx_slash_star_or_slash
2076
2396
  );
2077
2397
  if (jj >= 0) {
2078
2398
 
@@ -2090,16 +2410,10 @@ function jslint_phase2_lex(state) {
2090
2410
 
2091
2411
  // Uncompleted work comment.
2092
2412
 
2093
- if (
2094
- !option_dict.devel
2095
- && (
2096
- // rx_todo
2097
- /\b(?:todo|TO\s?DO|HACK)\b/
2098
- ).test(snippet)
2099
- ) {
2413
+ if (!option_dict.devel && jslint_rgx_todo.test(snippet)) {
2100
2414
 
2101
2415
  // test_cause:
2102
- // ["//todo", "lex_comment", "todo_comment", "(comment)", 1] //jslint-quiet
2416
+ // ["//todo", "lex_comment", "todo_comment", "(comment)", 1] //jslint-ignore-line
2103
2417
 
2104
2418
  warn("todo_comment", the_comment);
2105
2419
  }
@@ -2108,10 +2422,7 @@ function jslint_phase2_lex(state) {
2108
2422
 
2109
2423
  [
2110
2424
  the_comment.directive, body
2111
- ] = Array.from(snippet.match(
2112
- // rx_directive
2113
- /^(jslint|property|global)\s+(.*)$/
2114
- ) || []).slice(1);
2425
+ ] = Array.from(snippet.match(jslint_rgx_directive) || []).slice(1);
2115
2426
  if (the_comment.directive === undefined) {
2116
2427
  return the_comment;
2117
2428
  }
@@ -2133,10 +2444,12 @@ function jslint_phase2_lex(state) {
2133
2444
  // Lex/loop through each directive in /*...*/
2134
2445
 
2135
2446
  ii = 0;
2136
- body.replace((
2137
- // rx_directive_part
2138
- /([a-zA-Z$_][a-zA-Z0-9$_]*)(?::\s*(true|false))?,?\s*|$/g
2139
- ), function (match0, key, val, jj) {
2447
+ body.replace(jslint_rgx_directive_part, function (
2448
+ match0,
2449
+ key,
2450
+ val,
2451
+ jj
2452
+ ) {
2140
2453
  if (ii !== jj) {
2141
2454
 
2142
2455
  // test_cause:
@@ -2160,6 +2473,7 @@ function jslint_phase2_lex(state) {
2160
2473
  global_dict[key] = "user-defined";
2161
2474
 
2162
2475
  // PR-347 - Disable warning "unexpected_directive_a".
2476
+ //
2163
2477
  // state.mode_module = the_comment;
2164
2478
 
2165
2479
  break;
@@ -2210,13 +2524,7 @@ function jslint_phase2_lex(state) {
2210
2524
  // string.
2211
2525
 
2212
2526
  while (true) {
2213
- match = line_source.match(
2214
-
2215
- // Vim-hack - vim-editor has trouble parsing '`' in regexp
2216
-
2217
- // rx_mega
2218
- /[\u0060\\]|\$\{/
2219
- ) || {
2527
+ match = line_source.match(jslint_rgx_mega) || {
2220
2528
  "0": "",
2221
2529
  index: 0
2222
2530
  };
@@ -2293,12 +2601,16 @@ function jslint_phase2_lex(state) {
2293
2601
 
2294
2602
  function lex_number() {
2295
2603
  let prefix = snippet;
2604
+
2605
+ // PR-390 - Add numeric-separator check.
2606
+
2607
+ check_numeric_separator(prefix, column - prefix.length);
2296
2608
  char_after();
2297
2609
  switch (prefix === "0" && char) {
2298
2610
  case "b":
2299
2611
  case "o":
2300
2612
  case "x":
2301
- read_digits(char);
2613
+ read_digits(char, mode_digits_numeric_separator);
2302
2614
 
2303
2615
  // PR-351 - Ignore BigInt suffix 'n'.
2304
2616
 
@@ -2308,14 +2620,14 @@ function jslint_phase2_lex(state) {
2308
2620
  break;
2309
2621
  default:
2310
2622
  if (char === ".") {
2311
- read_digits("d");
2623
+ read_digits("d", mode_digits_numeric_separator);
2312
2624
  }
2313
2625
  if (char === "E" || char === "e") {
2314
2626
  char_after(char);
2315
2627
  if (char !== "+" && char !== "-") {
2316
2628
  char_before();
2317
2629
  }
2318
- read_digits("d");
2630
+ read_digits("d", mode_digits_numeric_separator);
2319
2631
  }
2320
2632
  }
2321
2633
 
@@ -2585,7 +2897,7 @@ function jslint_phase2_lex(state) {
2585
2897
  }
2586
2898
  break;
2587
2899
  case "{":
2588
- if (read_digits("d", true) === 0) {
2900
+ if (read_digits("d", mode_digits_empty_string) === 0) {
2589
2901
 
2590
2902
  // test_cause:
2591
2903
  // ["aa=/aa{/", "lex_regexp_group", "expected_a_before_b", ",", 8]
@@ -2598,7 +2910,7 @@ function jslint_phase2_lex(state) {
2598
2910
  // ["aa=/.{,/", "lex_regexp_group", "comma", "", 0]
2599
2911
 
2600
2912
  test_cause("comma");
2601
- read_digits("d", true);
2913
+ read_digits("d", mode_digits_empty_string);
2602
2914
  }
2603
2915
  if (char_after("}") === "?") {
2604
2916
 
@@ -2891,7 +3203,7 @@ function jslint_phase2_lex(state) {
2891
3203
  }
2892
3204
  }
2893
3205
  from = column;
2894
- match = line_source.match(rx_token);
3206
+ match = line_source.match(jslint_rgx_token);
2895
3207
 
2896
3208
  // match[1] token
2897
3209
  // match[2] whitespace
@@ -2977,9 +3289,10 @@ function jslint_phase2_lex(state) {
2977
3289
  case "getset": // Allow get() and set().
2978
3290
  case "indent2": // Use 2-space indent.
2979
3291
  case "long": // Allow long lines.
2980
- case "name": // Allow weird property names.
2981
3292
  case "node": // Assume Node.js environment.
3293
+ case "nomen": // Allow weird property names.
2982
3294
  case "single": // Allow single-quote strings.
3295
+ case "subscript": // Allow identifier in subscript-notation.
2983
3296
  case "test_cause": // Test jslint's causes.
2984
3297
  case "test_internal_error": // Test jslint's internal-error
2985
3298
  // ... handling-ability.
@@ -2992,6 +3305,16 @@ function jslint_phase2_lex(state) {
2992
3305
  case "white": // Allow messy whitespace.
2993
3306
  option_dict[key] = val;
2994
3307
  break;
3308
+
3309
+ // PR-404 - Alias "evil" to jslint-directive "eval" for backwards-compat.
3310
+
3311
+ case "evil":
3312
+ return option_set_item("eval", val);
3313
+
3314
+ // PR-404 - Alias "nomen" to jslint-directive "name" for backwards-compat.
3315
+
3316
+ case "name":
3317
+ return option_set_item("nomen", val);
2995
3318
  default:
2996
3319
  return false;
2997
3320
  }
@@ -3080,6 +3403,7 @@ console.log(JSON.stringify(Object.keys(window).sort(), undefined, 4));
3080
3403
  "location",
3081
3404
  // "name",
3082
3405
  "navigator",
3406
+ "postMessage",
3083
3407
  // "screen",
3084
3408
  "sessionStorage",
3085
3409
  // "setInterval",
@@ -3274,41 +3598,48 @@ import moduleHttps from "https";
3274
3598
  return true;
3275
3599
  }
3276
3600
 
3277
- function read_digits(base, quiet) {
3601
+ function read_digits(base, mode) {
3278
3602
  let digits = line_source.match(
3279
3603
  base === "b"
3280
- ? (
3281
- // rx_bits
3282
- /^[01]*/
3283
- )
3604
+ ? jslint_rgx_digits_bits
3284
3605
  : base === "o"
3285
- ? (
3286
- // rx_octals
3287
- /^[0-7]*/
3288
- )
3606
+ ? jslint_rgx_digits_octals
3289
3607
  : base === "x"
3290
- ? (
3291
- // rx_hexs
3292
- /^[0-9A-F]*/i
3293
- )
3294
- : (
3295
- // rx_digits
3296
- /^[0-9]*/
3297
- )
3608
+ ? jslint_rgx_digits_hexs
3609
+ : jslint_rgx_digits_decimals
3298
3610
  )[0];
3299
- let length = digits.length;
3300
- if (!quiet && length === 0) {
3611
+ if (
3612
+ (mode !== mode_digits_empty_string && digits.length === 0)
3613
+ || digits[0] === "_"
3614
+ ) {
3301
3615
 
3302
3616
  // test_cause:
3303
3617
  // ["0x", "read_digits", "expected_digits_after_a", "0x", 2]
3618
+ // ["0x_", "read_digits", "expected_digits_after_a", "0x", 2]
3304
3619
 
3305
3620
  warn_at("expected_digits_after_a", line, column, snippet);
3306
3621
  }
3307
- column += length;
3308
- line_source = line_source.slice(length);
3622
+
3623
+ // PR-390 - Add numeric-separator check.
3624
+
3625
+ if (mode === mode_digits_numeric_separator) {
3626
+ check_numeric_separator(digits, column);
3627
+ } else if (digits.indexOf("_") >= 0) {
3628
+
3629
+ // test_cause:
3630
+ // ["\"\\u{1_2}\"", "read_digits", "illegal_num_separator", "", 6]
3631
+
3632
+ warn_at(
3633
+ "illegal_num_separator",
3634
+ line,
3635
+ column + digits.indexOf("_") + 1
3636
+ );
3637
+ }
3638
+ column += digits.length;
3639
+ line_source = line_source.slice(digits.length);
3309
3640
  snippet += digits;
3310
3641
  char_after();
3311
- return length;
3642
+ return digits.length;
3312
3643
  }
3313
3644
 
3314
3645
  function read_line() {
@@ -3327,7 +3658,7 @@ import moduleHttps from "https";
3327
3658
  ) {
3328
3659
 
3329
3660
  // test_cause:
3330
- // ["/////////////////////////////////////////////////////////////////////////////////", "read_line", "too_long", "", 1] //jslint-quiet
3661
+ // ["/////////////////////////////////////////////////////////////////////////////////", "read_line", "too_long", "", 1] //jslint-ignore-line
3331
3662
 
3332
3663
  warn_at("too_long", line);
3333
3664
  }
@@ -3345,7 +3676,7 @@ import moduleHttps from "https";
3345
3676
  // Scan each line for following ignore-directives:
3346
3677
  // "/*jslint-disable*/"
3347
3678
  // "/*jslint-enable*/"
3348
- // "//jslint-quiet"
3679
+ // "//jslint-ignore-line"
3349
3680
 
3350
3681
  if (line_source === "/*jslint-disable*/") {
3351
3682
 
@@ -3363,13 +3694,16 @@ import moduleHttps from "https";
3363
3694
  stop_at("unopened_enable", line);
3364
3695
  }
3365
3696
  line_disable = undefined;
3366
- } else if (line_source.endsWith(" //jslint-quiet")) {
3697
+ } else if (
3698
+ line_source.endsWith(" //jslint-ignore-line")
3699
+ || line_source.endsWith(" //jslint-quiet")
3700
+ ) {
3367
3701
 
3368
3702
  // test_cause:
3369
- // ["0 //jslint-quiet", "read_line", "jslint_quiet", "", 0]
3703
+ // ["0 //jslint-ignore-line", "read_line", "jslint_ignore_line", "", 0]
3370
3704
 
3371
- test_cause("jslint_quiet");
3372
- line_list[line].directive_quiet = true;
3705
+ test_cause("jslint_ignore_line");
3706
+ line_list[line].directive_ignore_line = true;
3373
3707
  }
3374
3708
  if (line_disable !== undefined) {
3375
3709
 
@@ -3379,6 +3713,7 @@ import moduleHttps from "https";
3379
3713
  test_cause("line_disable");
3380
3714
  line_source = "";
3381
3715
  }
3716
+ // jslint_rgx_tab
3382
3717
  if (line_source.indexOf("\t") >= 0) {
3383
3718
  if (!option_dict.white) {
3384
3719
 
@@ -3387,10 +3722,7 @@ import moduleHttps from "https";
3387
3722
 
3388
3723
  warn_at("use_spaces", line, line_source.indexOf("\t") + 1);
3389
3724
  }
3390
- line_source = line_source.replace((
3391
- // rx_tab
3392
- /\t/g
3393
- ), " ");
3725
+ line_source = line_source.replace(jslint_rgx_tab, " ");
3394
3726
  }
3395
3727
  if (!option_dict.white && line_source.endsWith(" ")) {
3396
3728
 
@@ -3564,9 +3896,6 @@ function jslint_phase3_parse(state) {
3564
3896
  let catchage = catch_stack[0]; // The current catch-block.
3565
3897
  let functionage = token_global; // The current function.
3566
3898
  let mode_var; // "var" if using var; "let" if using let.
3567
- let rx_identifier = (
3568
- /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/
3569
- );
3570
3899
  let token_ii = 0; // The number of the next token.
3571
3900
  let token_now = token_global; // The current token being examined in
3572
3901
  // ... the parse.
@@ -3583,7 +3912,7 @@ function jslint_phase3_parse(state) {
3583
3912
  anon = token_now.id;
3584
3913
  } else if (
3585
3914
  token_now.id === "(string)"
3586
- && rx_identifier.test(token_now.value)
3915
+ && jslint_rgx_identifier.test(token_now.value)
3587
3916
  ) {
3588
3917
  anon = token_now.value;
3589
3918
  }
@@ -4174,6 +4503,8 @@ function jslint_phase3_parse(state) {
4174
4503
  left.id !== "["
4175
4504
  || (
4176
4505
  name.id !== "concat"
4506
+ && name.id !== "flat"
4507
+ && name.id !== "flatMap"
4177
4508
  && name.id !== "forEach"
4178
4509
  && name.id !== "join"
4179
4510
  && name.id !== "map"
@@ -4233,7 +4564,10 @@ function jslint_phase3_parse(state) {
4233
4564
  let the_subscript = parse_expression(0);
4234
4565
  if (the_subscript.id === "(string)" || the_subscript.id === "`") {
4235
4566
  name = survey(the_subscript);
4236
- if (rx_identifier.test(name)) {
4567
+
4568
+ // PR-404 - Add new directive "subscript" to play nice with Google Closure.
4569
+
4570
+ if (!option_dict.subscript && jslint_rgx_identifier.test(name)) {
4237
4571
 
4238
4572
  // test_cause:
4239
4573
  // ["aa[`aa`]", "infix_lbracket", "subscript_a", "aa", 4]
@@ -4594,13 +4928,7 @@ function jslint_phase3_parse(state) {
4594
4928
  let negative;
4595
4929
  switch (token_nxt.id) {
4596
4930
  case "(number)":
4597
- if (!(
4598
-
4599
- // https://datatracker.ietf.org/doc/html/rfc7159#section-6
4600
- // number = [ minus ] int [ frac ] [ exp ]
4601
-
4602
- /^-?(?:0|[1-9]\d*?)(?:\.\d*?)?(?:[eE][+\-]?\d+?)?$/
4603
- ).test(token_nxt.value)) {
4931
+ if (!jslint_rgx_json_number.test(token_nxt.value)) {
4604
4932
 
4605
4933
  // test_cause:
4606
4934
  // ["[-.0]", "parse_json", "unexpected_a", ".", 3]
@@ -4968,10 +5296,13 @@ function jslint_phase3_parse(state) {
4968
5296
  functionage.async += 1;
4969
5297
  }
4970
5298
  if (the_await.arity === "statement") {
4971
- the_await.block = parse_expression();
5299
+
5300
+ // PR-405 - Bugfix - fix expression after "await" mis-identified as statement.
5301
+
5302
+ the_await.expression = parse_expression(150);
4972
5303
  semicolon();
4973
5304
  } else {
4974
- the_await.expression = parse_expression();
5305
+ the_await.expression = parse_expression(150);
4975
5306
  }
4976
5307
  return the_await;
4977
5308
  }
@@ -6037,6 +6368,7 @@ function jslint_phase3_parse(state) {
6037
6368
  let names;
6038
6369
 
6039
6370
  // PR-347 - Disable warning "unexpected_directive_a".
6371
+ //
6040
6372
  // if (typeof state.mode_module === "object") {
6041
6373
  //
6042
6374
  // // test_cause:
@@ -6100,10 +6432,7 @@ function jslint_phase3_parse(state) {
6100
6432
  advance("from");
6101
6433
  advance("(string)");
6102
6434
  the_import.import = token_now;
6103
- if (!(
6104
- // rx_module
6105
- /^[a-zA-Z0-9_$:.@\-\/]+$/
6106
- ).test(token_now.value)) {
6435
+ if (!jslint_rgx_module.test(token_now.value)) {
6107
6436
 
6108
6437
  // test_cause:
6109
6438
  // ["import aa from \"!aa\"", "stmt_import", "bad_module_name_a", "!aa", 16]
@@ -6397,12 +6726,16 @@ function jslint_phase3_parse(state) {
6397
6726
  // Restore previous catch-scope after catch-block.
6398
6727
 
6399
6728
  catchage = catch_stack.pop();
6400
- } else {
6401
6729
 
6402
- // test_cause:
6403
- // ["try{}finally{break;}", "stmt_try", "expected_a_before_b", "finally", 6]
6730
+ // PR-404 - Relax warning about missing `catch` in `try...finally` statement.
6731
+ //
6732
+ // } else {
6733
+ //
6734
+ // // test_cause:
6735
+ // // ["try{}finally{break;}", "stmt_try", "expected_a_before_b", "finally", 6]
6736
+ //
6737
+ // warn("expected_a_before_b", token_nxt, "catch", artifact());
6404
6738
 
6405
- warn("expected_a_before_b", token_nxt, "catch", artifact());
6406
6739
  }
6407
6740
  if (token_nxt.id === "finally") {
6408
6741
  functionage.finally += 1;
@@ -6523,12 +6856,14 @@ function jslint_phase3_parse(state) {
6523
6856
  return stop("expected_identifier_a");
6524
6857
  }
6525
6858
 
6526
- // PR-363 - Bugfix - fix false-warning
6527
- // <uninitialized 'bb'> in code '/*jslint node*/\nlet {aa:bb} = {}; bb();'
6859
+ // PR-363 - Bugfix
6860
+ // Add test against false-warning <uninitialized 'bb'> in code
6861
+ // '/*jslint node*/\nlet {aa:bb} = {}; bb();'.
6862
+ //
6863
+ // token_nxt.label = name;
6864
+ // the_variable.names.push(token_nxt);
6865
+ // enroll(token_nxt, "variable", mode_const);
6528
6866
 
6529
- // token_nxt.label = name;
6530
- // the_variable.names.push(token_nxt);
6531
- // enroll(token_nxt, "variable", mode_const);
6532
6867
  name = token_nxt;
6533
6868
  the_variable.names.push(name);
6534
6869
  survey(name);
@@ -6714,13 +7049,13 @@ function jslint_phase3_parse(state) {
6714
7049
 
6715
7050
  if (id === "(string)") {
6716
7051
  id = name.value;
6717
- if (!rx_identifier.test(id)) {
7052
+ if (!jslint_rgx_identifier.test(id)) {
6718
7053
  return id;
6719
7054
  }
6720
7055
  } else if (id === "`") {
6721
7056
  if (name.value.length === 1) {
6722
7057
  id = name.value[0].value;
6723
- if (!rx_identifier.test(id)) {
7058
+ if (!jslint_rgx_identifier.test(id)) {
6724
7059
  return id;
6725
7060
  }
6726
7061
  }
@@ -6751,12 +7086,9 @@ function jslint_phase3_parse(state) {
6751
7086
  warn("unregistered_property_a", name);
6752
7087
  }
6753
7088
  } else if (
6754
- !option_dict.name
7089
+ !option_dict.nomen
6755
7090
  && name.identifier
6756
- && (
6757
- // rx_weird_property
6758
- /^_|\$|Sync$|_$/m
6759
- ).test(id)
7091
+ && jslint_rgx_weird_property.test(id)
6760
7092
  ) {
6761
7093
 
6762
7094
  // test_cause:
@@ -7510,10 +7842,7 @@ function jslint_phase4_walk(state) {
7510
7842
  test_cause("cack");
7511
7843
  cack = !cack;
7512
7844
  }
7513
- if ((
7514
- // rx_cap
7515
- /^[A-Z]/
7516
- ).test(left.name.id) !== cack) {
7845
+ if (jslint_rgx_cap.test(left.name.id) !== cack) {
7517
7846
  if (the_new !== undefined) {
7518
7847
 
7519
7848
  // test_cause:
@@ -7690,6 +8019,11 @@ function jslint_phase4_walk(state) {
7690
8019
  || thing.expression[0].constant === true
7691
8020
  || is_equal(thing.expression[1], thing.expression[2])
7692
8021
  ) {
8022
+
8023
+ // test_cause:
8024
+ // ["let aa=(aa?`${0}`:`${0}`);", "post_t", "unexpected_a", "?", 11]
8025
+ // ["let aa=(aa?`0`:`0`);", "post_t", "unexpected_a", "?", 11]
8026
+
7693
8027
  warn("unexpected_a", thing);
7694
8028
  } else if (is_equal(thing.expression[0], thing.expression[1])) {
7695
8029
 
@@ -8165,9 +8499,6 @@ function jslint_phase4_walk(state) {
8165
8499
  // ["+[]", "walk_statement", "unexpected_expression_a", "+", 1]
8166
8500
  // ["+new aa()", "walk_statement", "unexpected_expression_a", "+", 1]
8167
8501
  // ["0", "walk_statement", "unexpected_expression_a", "0", 1]
8168
- // ["
8169
- // async function aa(){await 0;}
8170
- // ", "walk_statement", "unexpected_expression_a", "0", 27]
8171
8502
  // ["typeof 0", "walk_statement", "unexpected_expression_a", "typeof", 1]
8172
8503
 
8173
8504
  warn("unexpected_expression_a", thing);
@@ -8909,6 +9240,7 @@ function jslint_report({
8909
9240
 
8910
9241
  // This function will create human-readable, html-report
8911
9242
  // for warnings, properties, and functions from jslint-result-object.
9243
+ //
8912
9244
  // Example usage:
8913
9245
  // let result = jslint("console.log('hello world')");
8914
9246
  // let html = jslint_report(result);
@@ -8941,7 +9273,6 @@ function jslint_report({
8941
9273
  );
8942
9274
  }
8943
9275
 
8944
- html += "<div class=\"JSLINT_\" id=\"JSLINT_REPORT_HTML\">\n";
8945
9276
  html += String(`
8946
9277
  <style class="JSLINT_REPORT_STYLE">
8947
9278
  /* jslint utility2:true */
@@ -9090,19 +9421,38 @@ pyNj+JctcQLXenBOCms46aMkenIx45WpXqxxVJQLz/vgpmAVa0fmDv6Pue9xVTBPfVxCUGfj\
9090
9421
  /7xoEqvL+2E8VOyCTuT/7j269Zy4jUtN+g4="
9091
9422
  ) format("woff2");
9092
9423
  }
9093
- *,
9094
- *:after,
9095
- *:before {
9424
+ .JSLINT_,
9425
+ .JSLINT_ address,
9426
+ .JSLINT_ button,
9427
+ .JSLINT_ cite,
9428
+ .JSLINT_ dd,
9429
+ .JSLINT_ dfn,
9430
+ .JSLINT_ dl,
9431
+ .JSLINT_ dt,
9432
+ .JSLINT_ fieldset,
9433
+ .JSLINT_ fieldset > div,
9434
+ .JSLINT_ input,
9435
+ .JSLINT_ label,
9436
+ .JSLINT_ legend,
9437
+ .JSLINT_ ol,
9438
+ .JSLINT_ samp,
9439
+ .JSLINT_ style,
9440
+ .JSLINT_ textarea,
9441
+ .JSLINT_ ul {
9096
9442
  border: 0;
9097
9443
  box-sizing: border-box;
9098
9444
  margin: 0;
9099
9445
  padding: 0;
9100
9446
  }
9447
+ /* disable text inflation algorithm used on some smartphones and tablets */
9101
9448
  .JSLINT_ {
9102
9449
  -ms-text-size-adjust: none;
9103
9450
  -webkit-text-size-adjust: none;
9104
9451
  text-size-adjust: none;
9105
9452
  }
9453
+ .JSLINT_REPORT_ div {
9454
+ box-sizing: border-box;
9455
+ }
9106
9456
  /*csslint ignore:end*/
9107
9457
 
9108
9458
  /* css - jslint_report - font */
@@ -9136,7 +9486,7 @@ pyNj+JctcQLXenBOCms46aMkenIx45WpXqxxVJQLz/vgpmAVa0fmDv6Pue9xVTBPfVxCUGfj\
9136
9486
  }
9137
9487
 
9138
9488
  /* css - jslint_report - general */
9139
- body {
9489
+ .JSLINT_ {
9140
9490
  background: antiquewhite;
9141
9491
  }
9142
9492
  .JSLINT_ fieldset {
@@ -9382,6 +9732,9 @@ body {
9382
9732
  : "global"
9383
9733
  );
9384
9734
  if (global.length + froms.length + exports.length > 0) {
9735
+ if (functions.length === 0) {
9736
+ html += "<br>\n";
9737
+ }
9385
9738
  html += "<div class=\"level level0\">\n";
9386
9739
  html += detail(module, global);
9387
9740
  html += detail("import from", froms);
@@ -9470,7 +9823,6 @@ body {
9470
9823
  });
9471
9824
  html += "</div>\n";
9472
9825
  html += "</fieldset>\n";
9473
- html += "</div>\n";
9474
9826
  return html;
9475
9827
  }
9476
9828
 
@@ -9481,6 +9833,7 @@ async function jstestDescribe(description, testFunction) {
9481
9833
 
9482
9834
  let message;
9483
9835
  let result;
9836
+ let timerTimeout;
9484
9837
 
9485
9838
  // Init jstestTimeStart.
9486
9839
 
@@ -9496,7 +9849,9 @@ async function jstestDescribe(description, testFunction) {
9496
9849
 
9497
9850
  // Wait for jstestItList to resolve.
9498
9851
 
9852
+ timerTimeout = setTimeout(noop, 0x7fffffff);
9499
9853
  result = await Promise.all(jstestItList);
9854
+ clearTimeout(timerTimeout);
9500
9855
 
9501
9856
  // Print test results.
9502
9857
 
@@ -9546,14 +9901,14 @@ function jstestIt(description, testFunction, mode) {
9546
9901
  }));
9547
9902
  }
9548
9903
 
9549
- function jstestOnExit(exitCode, processExit, countFailed) {
9904
+ function jstestOnExit(exitCode, mode) {
9550
9905
 
9551
9906
  // This function will on process-exit, print test-report
9552
9907
  // and exit with non-zero exit-code if any test failed.
9553
9908
 
9554
9909
  let message = (
9555
9910
  (
9556
- (jstestCountFailed || countFailed)
9911
+ (jstestCountFailed || mode === "testsFailed")
9557
9912
  ? "\n\u001b[31m"
9558
9913
  : "\n\u001b[32m"
9559
9914
  )
@@ -9561,11 +9916,10 @@ function jstestOnExit(exitCode, processExit, countFailed) {
9561
9916
  + " tests failed - " + jstestCountFailed + "\n"
9562
9917
  + "\u001b[39m"
9563
9918
  );
9564
- if (!processExit) {
9919
+ if (mode !== "testsFailed") {
9565
9920
  console.error(message);
9566
- processExit = process.exit;
9567
9921
  }
9568
- processExit(exitCode || jstestCountFailed);
9922
+ process.exitCode = exitCode || jstestCountFailed;
9569
9923
  return message;
9570
9924
  }
9571
9925
 
@@ -9863,7 +10217,7 @@ function v8CoverageListMerge(processCovs) {
9863
10217
  let resultTree;
9864
10218
  let rightChildren;
9865
10219
 
9866
- // TODO(perf): Binary search (check overhead) //jslint-quiet
10220
+ // TODO(perf): Binary search (check overhead) //jslint-ignore-line
9867
10221
 
9868
10222
  while (ii < tree.children.length) {
9869
10223
  child = tree.children[ii];
@@ -9941,7 +10295,7 @@ function v8CoverageListMerge(processCovs) {
9941
10295
 
9942
10296
  // This function will normalize-and-sort <funcCov>.ranges.
9943
10297
  // Sorts the ranges (pre-order sort).
9944
- // TODO: Tree-based normalization of the ranges. //jslint-quiet
10298
+ // TODO: Tree-based normalization of the ranges. //jslint-ignore-line
9945
10299
  // @param funcCov Function coverage to normalize.
9946
10300
 
9947
10301
  funcCov.ranges = treeToRanges(treeFromSortedRanges(
@@ -10287,11 +10641,11 @@ async function v8CoverageReportCreate({
10287
10641
  // 3. Create html-coverage-reports in <coverageDir>.
10288
10642
 
10289
10643
  let cwd;
10644
+ let excludeList = [];
10290
10645
  let exitCode = 0;
10291
10646
  let fileDict;
10292
- let fileExcludeList = [];
10293
- let fileIncludeList = [];
10294
- let fileIncludeNodeModules;
10647
+ let includeList = [];
10648
+ let modeIncludeNodeModules;
10295
10649
  let processArgElem;
10296
10650
  let promiseList = [];
10297
10651
  let v8CoverageObj;
@@ -10316,9 +10670,19 @@ async function v8CoverageReportCreate({
10316
10670
  <style>
10317
10671
  /* jslint utility2:true */
10318
10672
  /*csslint ignore:start*/
10319
- * {
10320
- box-sizing: border-box;
10321
- font-family: consolas, menlo, monospace;
10673
+ .coverage,
10674
+ .coverage a,
10675
+ .coverage div,
10676
+ .coverage pre,
10677
+ .coverage span,
10678
+ .coverage table,
10679
+ .coverage tbody,
10680
+ .coverage td,
10681
+ .coverage th,
10682
+ .coverage thead,
10683
+ .coverage tr {
10684
+ box-sizing: border-box;
10685
+ font-family: monospace;
10322
10686
  }
10323
10687
  /*csslint ignore:end*/
10324
10688
 
@@ -10464,6 +10828,7 @@ body {
10464
10828
  }
10465
10829
  txtBorder = (
10466
10830
  "+" + "-".repeat(padPathname + 2) + "+"
10831
+ + "-".repeat(padLines + 2) + "+"
10467
10832
  + "-".repeat(padLines + 2) + "+\n"
10468
10833
  );
10469
10834
  txt = "";
@@ -10471,7 +10836,8 @@ body {
10471
10836
  txt += txtBorder;
10472
10837
  txt += (
10473
10838
  "| " + String("Files covered").padEnd(padPathname, " ") + " | "
10474
- + String("Lines").padStart(padLines, " ") + " |\n"
10839
+ + String("Lines").padStart(padLines, " ") + " | "
10840
+ + String("Remaining").padStart(padLines, " ") + " |\n"
10475
10841
  );
10476
10842
  txt += txtBorder;
10477
10843
  fileList.forEach(function ({
@@ -10551,7 +10917,8 @@ body {
10551
10917
  + String("./" + pathname).padEnd(padPathname, " ") + " | "
10552
10918
  + String(
10553
10919
  modeCoverageIgnoreFile + " " + coveragePct + " %"
10554
- ).padStart(padLines, " ") + " |\n"
10920
+ ).padStart(padLines, " ") + " | "
10921
+ + " ".repeat(padLines) + " |\n"
10555
10922
  );
10556
10923
  txt += (
10557
10924
  "| " + "*".repeat(
@@ -10559,6 +10926,9 @@ body {
10559
10926
  ).padEnd(padPathname, "_") + " | "
10560
10927
  + String(
10561
10928
  linesCovered + " / " + linesTotal
10929
+ ).padStart(padLines, " ") + " | "
10930
+ + String(
10931
+ (linesTotal - linesCovered) + " / " + linesTotal
10562
10932
  ).padStart(padLines, " ") + " |\n"
10563
10933
  );
10564
10934
  txt += txtBorder;
@@ -10722,21 +11092,6 @@ ${String(count || "-0").padStart(7, " ")}
10722
11092
  ), txt));
10723
11093
  }
10724
11094
 
10725
- function pathnameRelativeCwd(pathname) {
10726
-
10727
- // This function will if <pathname> is inside <cwd>,
10728
- // return it relative to <cwd>, else empty-string.
10729
-
10730
- pathname = modulePath.resolve(pathname).replace((
10731
- /\\/g
10732
- ), "/");
10733
- if (!pathname.startsWith(cwd)) {
10734
- return;
10735
- }
10736
- pathname = pathname.slice(cwd.length);
10737
- return pathname;
10738
- }
10739
-
10740
11095
  /*
10741
11096
  function sentinel() {}
10742
11097
  */
@@ -10768,28 +11123,26 @@ function sentinel() {}
10768
11123
  processArgElem[1] = processArgElem.slice(1).join("=");
10769
11124
  switch (processArgElem[0]) {
10770
11125
 
10771
- // PR-371 - add cli-option `--exclude=aa,bb`
11126
+ // PR-371 - Add cli-option `--exclude=...`.
10772
11127
 
10773
11128
  case "--exclude":
10774
- fileExcludeList = fileExcludeList.concat(
10775
- processArgElem[1].split(",")
10776
- );
11129
+ excludeList.push(processArgElem[1]);
10777
11130
  break;
10778
11131
 
10779
- // PR-371 - add cli-option `--exclude-node-modules=false`
11132
+ // PR-371 - Add cli-option `--include=...`
10780
11133
 
10781
- case "--exclude-node-modules":
10782
- fileIncludeNodeModules = (
10783
- /0|false|null|undefined/
10784
- ).test(processArgElem[1]);
11134
+ case "--include":
11135
+ includeList.push(processArgElem[1]);
10785
11136
  break;
10786
11137
 
10787
- // PR-371 - add cli-option `--include=aa,bb`
11138
+ // PR-400
11139
+ // Disable default-coverage of directory `node_modules`,
11140
+ // but allow override with cli-option `--include-node-modules=1`.
10788
11141
 
10789
- case "--include":
10790
- fileIncludeList = fileIncludeList.concat(
10791
- processArgElem[1].split(",")
10792
- );
11142
+ case "--include-node-modules":
11143
+ modeIncludeNodeModules = !(
11144
+ /0|false|null|undefined/
11145
+ ).test(processArgElem[1]);
10793
11146
  break;
10794
11147
  }
10795
11148
  }
@@ -10843,9 +11196,11 @@ function sentinel() {}
10843
11196
  ).test(file);
10844
11197
  });
10845
11198
  v8CoverageObj = await Promise.all(v8CoverageObj.map(async function (file) {
10846
- let data = await moduleFs.promises.readFile(coverageDir + file, "utf8");
11199
+ let data;
11200
+ let pathnameDict = Object.create(null);
11201
+ data = await moduleFs.promises.readFile(coverageDir + file, "utf8");
10847
11202
  data = JSON.parse(data);
10848
- data.result = data.result.filter(function (scriptCov) {
11203
+ data.result.forEach(function (scriptCov) {
10849
11204
  let pathname = scriptCov.url;
10850
11205
 
10851
11206
  // Filter out internal coverages.
@@ -10856,38 +11211,38 @@ function sentinel() {}
10856
11211
 
10857
11212
  // Normalize pathname.
10858
11213
 
10859
- pathname = pathnameRelativeCwd(moduleUrl.fileURLToPath(pathname));
10860
- if (
11214
+ pathname = moduleUrl.fileURLToPath(pathname);
11215
+ pathname = modulePath.resolve(pathname).replace((
11216
+ /\\/g
11217
+ ), "/");
10861
11218
 
10862
11219
  // Filter files outside of cwd.
10863
11220
 
10864
- !pathname
10865
- || pathname.startsWith("[")
11221
+ if (pathname.indexOf("[") >= 0 || !pathname.startsWith(cwd)) {
11222
+ return;
11223
+ }
10866
11224
 
10867
- // PR-371 - Filter directory node_modules.
11225
+ // Normalize pathname relative to cwd.
10868
11226
 
10869
- || (
10870
- !fileIncludeNodeModules
10871
- && (
10872
- /(?:^|\/)node_modules\//m
10873
- ).test(pathname)
10874
- )
11227
+ pathname = pathname.slice(cwd.length);
11228
+ scriptCov.url = pathname;
11229
+ pathnameDict[pathname] = scriptCov;
11230
+ });
10875
11231
 
10876
- // PR-371 - Filter fileExcludeList.
11232
+ // PR-400 - Filter directory `node_modules`.
10877
11233
 
10878
- || fileExcludeList.indexOf(pathname) >= 0
11234
+ if (!modeIncludeNodeModules) {
11235
+ excludeList.push("node_modules/");
11236
+ }
10879
11237
 
10880
- // PR-371 - Filter fileIncludeList.
11238
+ // PR-400 - Filter files by glob-patterns in excludeList, includeList.
10881
11239
 
10882
- || (
10883
- fileIncludeList.length > 0
10884
- && fileIncludeList.indexOf(pathname) === -1
10885
- )
10886
- ) {
10887
- return;
10888
- }
10889
- scriptCov.url = pathname;
10890
- return true;
11240
+ data.result = globExclude({
11241
+ excludeList,
11242
+ includeList,
11243
+ pathnameList: Object.keys(pathnameDict)
11244
+ }).pathnameList.map(function (pathname) {
11245
+ return pathnameDict[pathname];
10891
11246
  });
10892
11247
  return data;
10893
11248
  }));
@@ -10896,7 +11251,7 @@ function sentinel() {}
10896
11251
 
10897
11252
  v8CoverageObj = v8CoverageListMerge(v8CoverageObj);
10898
11253
 
10899
- // debug v8CoverageObj.
11254
+ // Debug v8CoverageObj.
10900
11255
 
10901
11256
  await fsWriteFileWithParents(
10902
11257
  coverageDir + "v8_coverage_merged.json",
@@ -11036,6 +11391,7 @@ jslint_export = Object.freeze(Object.assign(jslint, {
11036
11391
  assertOrThrow,
11037
11392
  debugInline,
11038
11393
  fsWriteFileWithParents,
11394
+ globExclude,
11039
11395
  htmlEscape,
11040
11396
  jslint,
11041
11397
  jslint_apidoc,