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