diff --git a/.artifact/apidoc.html b/.artifact/apidoc.html
new file mode 100644
index 000000000..c6101547c
--- /dev/null
+++ b/.artifact/apidoc.html
@@ -0,0 +1,2076 @@
+
+
+
+
+
1. 1// #!/usr/bin/env node
+
2. 1// JSLint
+
3. 1
+
4. 1// The Unlicense
+
5. 1//
+
6. 1// This is free and unencumbered software released into the public domain.
+
7. 1//
+
8. 1// Anyone is free to copy, modify, publish, use, compile, sell, or
+
9. 1// distribute this software, either in source code form or as a compiled
+
10. 1// binary, for any purpose, commercial or non-commercial, and by any
+
11. 1// means.
+
12. 1//
+
13. 1// In jurisdictions that recognize copyright laws, the author or authors
+
14. 1// of this software dedicate any and all copyright interest in the
+
15. 1// software to the public domain. We make this dedication for the benefit
+
16. 1// of the public at large and to the detriment of our heirs and
+
17. 1// successors. We intend this dedication to be an overt act of
+
18. 1// relinquishment in perpetuity of all present and future rights to this
+
19. 1// software under copyright law.
+
20. 1//
+
21. 1// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+
22. 1// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+
23. 1// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+
24. 1// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+
25. 1// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+
26. 1// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+
27. 1// OTHER DEALINGS IN THE SOFTWARE.
+
28. 1
+
29. 1
+
30. 1// jslint(source, option_dict, global_list) is a function that takes 3
+
31. 1// arguments. The second two arguments are optional.
+
32. 1
+
33. 1// source A text to analyze.
+
34. 1// option_dict An object whose keys correspond to option names.
+
35. 1// global_list An array of strings containing global variables that
+
36. 1// the file is allowed readonly access.
+
37. 1
+
38. 1// jslint returns an object containing its results. The object contains a lot
+
39. 1// of valuable information. It can be used to generate reports. The object
+
40. 1// contains:
+
41. 1
+
42. 1// directives: an array of directive comment tokens.
+
43. 1// edition: the version of JSLint that did the analysis.
+
44. 1// exports: the names exported from the module.
+
45. 1// froms: an array of strings representing each of the imports.
+
46. 1// functions: an array of objects that represent all functions
+
47. 1// declared in the file.
+
48. 1// global: an object representing the global object. Its .context property
+
49. 1// is an object containing a property for each global variable.
+
50. 1// id: "(JSLint)"
+
51. 1// json: true if the file is a JSON text.
+
52. 1// lines: an array of strings, the source.
+
53. 1// module: true if an import or export statement was used.
+
54. 1// ok: true if no warnings were generated. This is what you want.
+
55. 1// option: the option argument.
+
56. 1// property: a property object.
+
57. 1// stop: true if JSLint was unable to finish. You don't want this.
+
58. 1// tokens: an array of objects representing the tokens in the file.
+
59. 1// tree: the token objects arranged in a tree.
+
60. 1// warnings: an array of warning objects. A warning object can contain:
+
61. 1// name: "JSLintError"
+
62. 1// column: A column number in the file.
+
63. 1// line: A line number in the file.
+
64. 1// code: A warning code string.
+
65. 1// message: The warning message string.
+
66. 1// a: Exhibit A.
+
67. 1// b: Exhibit B.
+
68. 1// c: Exhibit C.
+
69. 1// d: Exhibit D.
+
70. 1
+
71. 1// jslint works in several phases. In any of these phases, errors might be
+
72. 1// found. Sometimes JSLint is able to recover from an error and continue
+
73. 1// parsing. In some cases, it cannot and will stop early. If that should happen,
+
74. 1// repair your code and try again.
+
75. 1
+
76. 1// Phases:
+
77. 1
+
78. 1// PHASE 1. Split <source> by newlines into <line_list>.
+
79. 1// PHASE 2. Lex <line_list> into <token_list>.
+
80. 1// PHASE 3. Parse <token_list> into <token_tree> using the Pratt-parser.
+
81. 1// PHASE 4. Walk <token_tree>, traversing all nodes of the tree. It is a
+
82. 1// recursive traversal. Each node may be processed on the way down
+
83. 1// (preaction) and on the way up (postaction).
+
84. 1// PHASE 5. Check whitespace between tokens in <token_list>.
+
85. 1
+
86. 1// jslint can also examine JSON text. It decides that a file is JSON text if
+
87. 1// the first token is "[" or "{". Processing of JSON text is much simpler than
+
88. 1// the processing of JavaScript programs. Only the first three phases are
+
89. 1// required.
+
90. 1
+
91. 1// WARNING: JSLint will hurt your feelings.
+
92. 1
+
93. 1/*jslint beta, node*/
+
94. 1/*property
+
95. 1 JSLINT_BETA, NODE_V8_COVERAGE, a, all, argv, arity, artifact,
+
96. 1 assertErrorThrownAsync, assertJsonEqual, assertOrThrow, assign, async, b,
+
97. 1 beta, bitwise, block, body, browser, c, calls, catch, catch_list,
+
98. 1 catch_stack, causes, char, children, clear, closer, closure, code, column,
+
99. 1 concat, consoleError, console_error, console_log, constant, context,
+
100. 1 convert, count, coverageDir, create, cwd, d, dead, debugInline, default,
+
101. 1 delta, devel, directive, directive_ignore_line, directive_list, directives,
+
102. 1 dirname, disrupt, dot, edition, elem_list, ellipsis, else, end, endOffset,
+
103. 1 endsWith, entries, env, error, eval, every, example_list, excludeList, exec,
+
104. 1 execArgv, exit, exitCode, export_dict, exports, expression, extra, fart,
+
105. 1 file, fileList, fileURLToPath, filter, finally, flag, floor, for, forEach,
+
106. 1 formatted_message, free, freeze, from, froms, fsWriteFileWithParents,
+
107. 1 fud_stmt, functionName, function_list, function_stack, functions, get,
+
108. 1 getset, github_repo, globExclude, global, global_dict, global_list,
+
109. 1 holeList, htmlEscape, id, identifier, import, import_list, import_meta_url,
+
110. 1 inc, includeList, indent2, index, indexOf, init, initial, isArray,
+
111. 1 isBlockCoverage, isHole, isNaN, is_equal, is_weird, join, jslint,
+
112. 1 jslint_apidoc, jslint_assert, jslint_charset_ascii, jslint_cli,
+
113. 1 jslint_edition, jslint_phase1_split, jslint_phase2_lex, jslint_phase3_parse,
+
114. 1 jslint_phase4_walk, jslint_phase5_whitage, jslint_report, json,
+
115. 1 jstestDescribe, jstestIt, jstestOnExit, keys, label, lbp, led_infix, length,
+
116. 1 level, line, lineList, line_list, line_offset, line_source, lines,
+
117. 1 linesCovered, linesTotal, live, log, long, loop, m, map, margin, match, max,
+
118. 1 message, meta, min, mkdir, modeCoverageIgnoreFile, modeIndex, mode_cli,
+
119. 1 mode_conditional, mode_json, mode_module, mode_noop, mode_property,
+
120. 1 mode_shebang, mode_stop, module, moduleFsInit, moduleName, module_list,
+
121. 1 name, names, node, nomen, noop, now, nr, nud_prefix,
+
122. 1 objectDeepCopyWithKeysSorted, ok, on, open, opening, option, option_dict,
+
123. 1 order, package_name, padEnd, padStart, parameters, parent, parentIi, parse,
+
124. 1 pathname, pathnameList, platform, pop, processArgv, process_argv,
+
125. 1 process_env, process_exit, promises, property, property_dict, push, quote,
+
126. 1 ranges, readFile, readdir, readonly, recursive, reduce, repeat, replace,
+
127. 1 resolve, result, reverse, role, round, scriptId, search, set, shebang,
+
128. 1 shell, shift, signature, single, slice, some, sort, source, spawn, splice,
+
129. 1 split, stack, stack_trace, start, startOffset, startsWith, statement,
+
130. 1 statement_prv, stdio, stop, stop_at, stringify, subscript, switch,
+
131. 1 syntax_dict, tenure, test, test_cause, test_internal_error, this, thru,
+
132. 1 toLocaleString, toString, token, token_global, token_list, token_nxt,
+
133. 1 token_tree, tokens, trace, tree, trim, trimEnd, trimRight, try, type,
+
134. 1 unlink, unordered, unshift, url, used, v8CoverageListMerge,
+
135. 1 v8CoverageReportCreate, value, variable, version, versions, warn, warn_at,
+
136. 1 warning, warning_list, warnings, white, wrapped, writeFile
+
137. 1*/
+
138. 1
+
139. 1// init debugInline
+
140. 1let debugInline = (function () {
+
141. 3 let __consoleError = function () {
+
142. 3 return;
+
143. 3 };
+
144. 1 function debug(...argv) {
+
145. 1
+
146. 1// This function will print <argv> to stderr and then return <argv>[0].
+
147. 1
+
148. 1 __consoleError("\n\ndebugInline");
+
149. 1 __consoleError(...argv);
+
150. 1 __consoleError("\n");
+
151. 1 return argv[0];
+
152. 1 }
+
153. 1 debug(); // Coverage-hack.
+
154. 1 __consoleError = console.error; //jslint-ignore-line
+
155. 1 return debug;
+
156. 1}());
+
157. 1let jslint_charset_ascii = (
+
158. 1 "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007"
+
159. 1 + "\b\t\n\u000b\f\r\u000e\u000f"
+
160. 1 + "\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017"
+
161. 1 + "\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f"
+
162. 1 + " !\"#$%&'()*+,-./0123456789:;<=>?"
+
163. 1 + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
+
164. 1 + "`abcdefghijklmnopqrstuvwxyz{|}~\u007f"
+
165. 1);
+
166. 1let jslint_edition = "v2024.11.24";
+
167. 1let jslint_export; // The jslint object to be exported.
+
168. 1let jslint_fudge = 1; // Fudge starting line and starting
+
169. 1 // ... column to 1.
+
170. 1let jslint_import_meta_url = ""; // import.meta.url used by cli.
+
171. 1let jslint_rgx_cap = (
+
172. 1 /^[A-Z]/
+
173. 1);
+
174. 1let jslint_rgx_crlf = (
+
175. 1 /\n|\r\n?/
+
176. 1);
+
177. 1let jslint_rgx_digits_bits = (
+
178. 1 /^[01_]*/
+
179. 1);
+
180. 1let jslint_rgx_digits_decimals = (
+
181. 1 /^[0-9_]*/
+
182. 1);
+
183. 1let jslint_rgx_digits_hexs = (
+
184. 1 /^[0-9A-F_]*/i
+
185. 1);
+
186. 1let jslint_rgx_digits_octals = (
+
187. 1 /^[0-7_]*/
+
188. 1);
+
189. 1let jslint_rgx_directive = (
+
190. 1 /^(jslint|property|global)\s+(.*)$/
+
191. 1);
+
192. 1let jslint_rgx_directive_part = (
+
193. 1 /([a-zA-Z$_][a-zA-Z0-9$_]*)(?::\s*(true|false))?,?\s*|$/g
+
194. 1);
+
195. 1let jslint_rgx_identifier = (
+
196. 1 /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/
+
197. 1);
+
198. 1let jslint_rgx_json_number = (
+
199. 1
+
200. 1// https://datatracker.ietf.org/doc/html/rfc7159#section-6
+
201. 1// number = [ minus ] int [ frac ] [ exp ]
+
202. 1
+
203. 1 /^-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][\-+]?\d+)?$/
+
204. 1);
+
205. 1let jslint_rgx_mega = (
+
206. 1
+
207. 1// Vim-hack - vim-editor has trouble parsing naked '`' in regexp
+
208. 1
+
209. 1 /[\u0060\\]|\$\{/
+
210. 1);
+
211. 1let jslint_rgx_module = (
+
212. 1 /^[a-zA-Z0-9_$:.@\-\/]+$/
+
213. 1);
+
214. 1let jslint_rgx_numeric_separator_illegal = (
+
215. 1 /__|_$|_n$/m
+
216. 1);
+
217. 1let jslint_rgx_slash_star_or_slash = (
+
218. 1 /\/\*|\/$/
+
219. 1);
+
220. 1let jslint_rgx_tab = (
+
221. 1 /\t/g
+
222. 1);
+
223. 1let jslint_rgx_todo = (
+
224. 1 /\b(?:todo|TO\s?DO|HACK)\b/
+
225. 1);
+
226. 1let jslint_rgx_token = new RegExp(
+
227. 1 "^("
+
228. 1 + "(\\s+)"
+
229. 1 + "|([a-zA-Z_$][a-zA-Z0-9_$]*)"
+
230. 1 + "|[(){}\\[\\],:;'\"~\\`]"
+
231. 1 + "|\\?[?.]?"
+
232. 1 + "|=(?:==?|>)?"
+
233. 1 + "|\\.+"
+
234. 1 + "|\\*[*\\/=]?"
+
235. 1 + "|\\/[*\\/]?"
+
236. 1 + "|\\+[=+]?"
+
237. 1 + "|-[=\\-]?"
+
238. 1 + "|[\\^%]=?"
+
239. 1 + "|&[&=]?"
+
240. 1 + "|\\"
+
241. 1 + "|[|=]?"
+
242. 1 + "|>{1,3}=?"
+
243. 1 + "|<<?=?"
+
244. 1 + "|!(?:!|==?)?"
+
245. 1
+
246. 1// PR-351 - Add BigInt support.
+
247. 1// PR-390 - Add numeric-separator support.
+
248. 1
+
249. 1 + "|((?:0_?|[1-9][0-9_]*)n?)"
+
250. 1 + ")"
+
251. 1 + "(.*)$"
+
252. 1);
+
253. 1let jslint_rgx_url_search_window_jslint = (
+
254. 1 /[&?]window_jslint=1(?:$|&)/m
+
255. 1);
+
256. 1let jslint_rgx_weird_property = (
+
257. 1 /^_|\$|Sync$|_$/m
+
258. 1);
+
259. 1let jstestCountFailed = 0;
+
260. 1let jstestCountTotal = 0;
+
261. 1let jstestItCount = 0;
+
262. 1let jstestItList = [];
+
263. 1let jstestTimeStart;
+
264. 1let moduleChildProcess;
+
265. 1let moduleFs;
+
266. 1let moduleFsInitResolveList;
+
267. 1let modulePath;
+
268. 1let moduleUrl;
+
269. 1
+
270. 11async function assertErrorThrownAsync(asyncFunc, regexp) {
+
271. 11
+
272. 11// This function will assert calling <asyncFunc> throws an error.
+
273. 11
+
274. 11 let err;
+
275. 11 try {
+
276. 1 await asyncFunc();
+
277. 10 } catch (errCaught) {
+
278. 10 err = errCaught;
+
279. 10 }
+
280. 11 assertOrThrow(err, "No error thrown.");
+
281. 11 assertOrThrow(
+
282. 4 !regexp || new RegExp(regexp).test(err.message),
+
283. 11 err
+
284. 11 );
+
285. 11}
+
286. 1
+
287. 267function assertJsonEqual(aa, bb, message) {
+
288. 267
+
289. 267// This function will assert JSON.stringify(<aa>) === JSON.stringify(<bb>).
+
290. 267
+
291. 267 aa = JSON.stringify(objectDeepCopyWithKeysSorted(aa), undefined, 1);
+
292. 267 bb = JSON.stringify(objectDeepCopyWithKeysSorted(bb), undefined, 1);
+
293. 3 if (aa !== bb) {
+
294. 3 throw new Error(
+
295. 3 "\n" + aa + "\n!==\n" + bb
+
296. 3 + (
+
297. 3 typeof message === "string"
+
298. 3 ? " - " + message
+
299. 3 : message
+
300. 3 ? " - " + JSON.stringify(message)
+
301. 3 : ""
+
302. 3 )
+
303. 3 );
+
304. 3 }
+
305. 267}
+
306. 1
+
307. 1931function assertOrThrow(condition, message) {
+
308. 1931
+
309. 1931// This function will throw <message> if <condition> is falsy.
+
310. 1931
+
311. 4 if (!condition) {
+
312. 4 throw (
+
313. 4 (!message || typeof message === "string")
+
314. 4 ? new Error(String(message).slice(0, 2048))
+
315. 4 : message
+
316. 4 );
+
317. 4 }
+
318. 1931}
+
319. 1
+
320. 94133function empty() {
+
321. 94133
+
322. 94133// The empty function produces a new empty object that inherits nothing. This is
+
323. 94133// much better than '{}' because confusions around accidental method names like
+
324. 94133// 'constructor' are completely avoided.
+
325. 94133
+
326. 94133 return Object.create(null);
+
327. 94133}
+
328. 1
+
329. 59async function fsWriteFileWithParents(pathname, data) {
+
330. 59
+
331. 59// This function will write <data> to <pathname> and lazy-mkdirp if necessary.
+
332. 59
+
333. 59 await moduleFsInit();
+
334. 59
+
335. 59// Try writing to pathname.
+
336. 59
+
337. 59 try {
+
338. 41 await moduleFs.promises.writeFile(pathname, data);
+
339. 41 } catch (ignore) {
+
340. 18
+
341. 18// Lazy mkdirp.
+
342. 18
+
343. 18 await moduleFs.promises.mkdir(modulePath.dirname(pathname), {
+
344. 18 recursive: true
+
345. 18 });
+
346. 18
+
347. 18// Retry writing to pathname.
+
348. 18
+
349. 18 await moduleFs.promises.writeFile(pathname, data);
+
350. 18 }
+
351. 59 console.error("wrote file " + pathname);
+
352. 59}
+
353. 1
+
354. 184function globExclude({
+
355. 184 excludeList = [],
+
356. 184 includeList = [],
+
357. 184 pathnameList = []
+
358. 184}) {
+
359. 184
+
360. 184// This function will
+
361. 184// 1. Exclude pathnames in <pathnameList> that don't match glob-patterns in
+
362. 184// <includeList>.
+
363. 184// 2. Exclude pathnames in <pathnameList> that match glob-patterns in
+
364. 184// <excludeList>.
+
365. 184
+
366. 552 function globAssertNotWeird(list, name) {
+
367. 552
+
368. 552// This function will check if <list> of strings contain weird characters.
+
369. 552
+
370. 552 [
+
371. 552 [
+
372. 552 "\n", (
+
373. 552 /^.*?([\u0000-\u0007\r]).*/gm
+
374. 552 )
+
375. 552 ],
+
376. 552 [
+
377. 552 "\r", (
+
378. 552 /^.*?([\n]).*/gm
+
379. 552 )
+
380. 552 ]
+
381. 1102 ].forEach(function ([
+
382. 1102 separator, rgx
+
383. 1102 ]) {
+
384. 3 list.join(separator).replace(rgx, function (match0, char) {
+
385. 3 throw new Error(
+
386. 3 "Weird character "
+
387. 3 + JSON.stringify(char)
+
388. 3 + " found in " + name + " "
+
389. 3 + JSON.stringify(match0)
+
390. 3 );
+
391. 3 });
+
392. 1102 });
+
393. 552 }
+
394. 184
+
395. 1370 function globToRegexp(pattern) {
+
396. 1370
+
397. 1370// This function will translate glob <pattern> to javascript-regexp,
+
398. 1370// which javascript can then use to "glob" pathnames.
+
399. 1370
+
400. 1370 let ii = 0;
+
401. 1370 let isClass = false;
+
402. 1370 let strClass = "";
+
403. 1370 let strRegex = "";
+
404. 1370 pattern = pattern.replace((
+
405. 1370 /\/\/+/g
+
406. 1370 ), "/");
+
407. 1370 pattern = pattern.replace((
+
408. 1370 /\*\*\*+/g
+
409. 1370 ), "**");
+
410. 1370 pattern.replace((
+
411. 1370 /\\\\|\\\[|\\\]|\[|\]|./g
+
412. 18691 ), function (match0) {
+
413. 18691 switch (match0) {
+
414. 310 case "[":
+
415. 310 if (isClass) {
+
416. 310 strClass += "[";
+
417. 310 return;
+
418. 310 }
+
419. 310 strClass += "\u0000";
+
420. 310 strRegex += "\u0000";
+
421. 310 isClass = true;
+
422. 310 return;
+
423. 310 case "]":
+
424. 310 if (isClass) {
+
425. 310 isClass = false;
+
426. 310 return;
+
427. 310 }
+
428. 310 strRegex += "]";
+
429. 310 return;
+
430. 18071 default:
+
431. 18071 if (isClass) {
+
432. 18071 strClass += match0;
+
433. 18071 return;
+
434. 18071 }
+
435. 18071 strRegex += match0;
+
436. 15021 }
+
437. 15021 return "";
+
438. 15021 });
+
439. 1370 strClass += "\u0000";
+
440. 1370
+
441. 1370// An expression "[!...]" matches a single character, namely any character that
+
442. 1370// is not matched by the expression obtained by removing the first '!' from it.
+
443. 1370// (Thus, "[!a-]" matches any single character except 'a', and '-'.)
+
444. 1370
+
445. 1370 strClass = strClass.replace((
+
446. 1370 /\u0000!/g
+
447. 1370 ), "\u0000^");
+
448. 1370
+
449. 1370// One may include '-' in its literal meaning by making it the first or last
+
450. 1370// character between the brackets.
+
451. 1370
+
452. 1370 strClass = strClass.replace((
+
453. 1370 /\u0000-/g
+
454. 1370 ), "\u0000\\-");
+
455. 1370 strClass = strClass.replace((
+
456. 1370 /-\u0000/g
+
457. 1370 ), "\\-\u0000");
+
458. 1370
+
459. 1370// Escape brackets '[', ']' in character class.
+
460. 1370
+
461. 1370 strClass = strClass.replace((
+
462. 1370 /[\[\]]/g
+
463. 1370 ), "\\$&");
+
464. 1370
+
465. 1370// https://stackoverflow.com/questions/3561493
+
466. 1370// /is-there-a-regexp-escape-function-in-javascript
+
467. 1370// $()*+-./?[\]^{|}
+
468. 1370
+
469. 1370 strRegex = strRegex.replace((
+
470. 1370
+
471. 1370// Ignore [-/].
+
472. 1370
+
473. 1370 /[$()*+.?\[\\\]\^{|}]/g
+
474. 1370 ), "\\$&");
+
475. 1370
+
476. 1370// Expand wildcard '**/*'.
+
477. 1370
+
478. 1370 strRegex = strRegex.replace((
+
479. 1370 /\\\*\\\*\/(?:\\\*)+/g
+
480. 1370 ), ".*?");
+
481. 1370
+
482. 1370// Expand wildcard '**'.
+
483. 1370
+
484. 1370 strRegex = strRegex.replace((
+
485. 1370 /(^|\/)\\\*\\\*(\/|$)/gm
+
486. 1370 ), "$1.*?$2");
+
487. 1370
+
488. 1370// Expand wildcard '*'.
+
489. 1370
+
490. 1370 strRegex = strRegex.replace((
+
491. 1370 /(?:\\\*)+/g
+
492. 1370 ), "[^\\/]*?");
+
493. 1370
+
494. 1370// Expand wildcard '?'.
+
495. 1370
+
496. 1370 strRegex = strRegex.replace((
+
497. 1370 /\\\?/g
+
498. 1370 ), "[^\\/]");
+
499. 1370
+
500. 1370// Expand directory-with-trailing-slash '.../'.
+
501. 1370
+
502. 1370 strRegex = strRegex.replace((
+
503. 1370 /\/$/gm
+
504. 1370 ), "\\/.*?");
+
505. 1370
+
506. 1370// Merge strClass into strRegex.
+
507. 1370
+
508. 1370 ii = 0;
+
509. 1370 strClass = strClass.split("\u0000");
+
510. 1370 strRegex = strRegex.replace((
+
511. 1370 /\u0000/g
+
512. 306 ), function () {
+
513. 306 ii += 1;
+
514. 2 if (strClass[ii] === "") {
+
515. 2 return "";
+
516. 304 }
+
517. 304 return "[" + strClass[ii] + "]";
+
518. 304 });
+
519. 1370
+
520. 1370// Change strRegex from string to regexp.
+
521. 1370
+
522. 1370 strRegex = new RegExp("^" + strRegex + "$", "gm");
+
523. 1370 return strRegex;
+
524. 1370 }
+
525. 184
+
526. 184// Validate excludeList, includeList, pathnameList.
+
527. 184
+
528. 184 globAssertNotWeird(excludeList, "pattern");
+
529. 184 globAssertNotWeird(includeList, "pattern");
+
530. 184 globAssertNotWeird(pathnameList, "pathname");
+
531. 184
+
532. 184// Optimization
+
533. 184// Concat pathnames into a single, newline-separated string,
+
534. 184// whose pathnames can all be filtered with a single, regexp-pass.
+
535. 184
+
536. 184 pathnameList = pathnameList.join("\n");
+
537. 184
+
538. 184// 1. Exclude pathnames in <pathnameList> that don't match glob-patterns in
+
539. 184// <includeList>.
+
540. 184
+
541. 142 if (includeList.length > 0) {
+
542. 142 includeList = includeList.map(globToRegexp);
+
543. 574 includeList.forEach(function (pattern) {
+
544. 574 pathnameList = pathnameList.replace(pattern, "\u0000$&");
+
545. 574 });
+
546. 142 pathnameList = pathnameList.replace((
+
547. 142 /^[^\u0000].*/gm
+
548. 142 ), "");
+
549. 142 pathnameList = pathnameList.replace((
+
550. 142 /^\u0000+/gm
+
551. 142 ), "");
+
552. 181 }
+
553. 181
+
554. 181// 2. Exclude pathnames in <pathnameList> that match glob-patterns in
+
555. 181// <excludeList>.
+
556. 181
+
557. 181 excludeList = excludeList.map(globToRegexp);
+
558. 796 excludeList.forEach(function (pattern) {
+
559. 796 pathnameList = pathnameList.replace(pattern, "");
+
560. 796 });
+
561. 181
+
562. 181// Split newline-separated pathnames back to list.
+
563. 181
+
564. 10117 pathnameList = pathnameList.split("\n").filter(function (elem) {
+
565. 10117 return elem;
+
566. 10117 });
+
567. 181 return {
+
568. 181 excludeList,
+
569. 181 includeList,
+
570. 181 pathnameList
+
571. 181 };
+
572. 181}
+
573. 1
+
574. 14214function htmlEscape(str) {
+
575. 14214
+
576. 14214// This function will make <str> html-safe by escaping & < >.
+
577. 14214
+
578. 14214 return String(str).replace((
+
579. 14214 /&/g
+
580. 14214 ), "&").replace((
+
581. 14214 /</g
+
582. 14214 ), "<").replace((
+
583. 14214 />/g
+
584. 14214 ), ">");
+
585. 14214}
+
586. 1
+
587. 668function jslint(
+
588. 668 source = "", // A text to analyze.
+
589. 668 option_dict = empty(), // An object whose keys correspond to option
+
590. 668 // ... names.
+
591. 668 global_list = [] // An array of strings containing global
+
592. 668 // ... variables that the file is allowed
+
593. 668 // ... readonly access.
+
594. 668) {
+
595. 668
+
596. 668// The jslint function itself.
+
597. 668
+
598. 668 let catch_list = []; // The array containing all catch-blocks.
+
599. 668 let catch_stack = [ // The stack of catch-blocks.
+
600. 668 {
+
601. 668 context: empty()
+
602. 668 }
+
603. 668 ];
+
604. 668 let cause_dict = empty(); // The object of test-causes.
+
605. 668 let directive_list = []; // The directive comments.
+
606. 668 let export_dict = empty(); // The exported names and values.
+
607. 668 let function_list = []; // The array containing all functions.
+
608. 668 let function_stack = []; // The stack of functions.
+
609. 668 let global_dict = empty(); // The object containing the global
+
610. 668 // ... declarations.
+
611. 668 let import_list = []; // The array collecting all import-from strings.
+
612. 668 let line_list = String( // The array containing source lines.
+
613. 668 "\n" + source
+
614. 105217 ).split(jslint_rgx_crlf).map(function (line_source) {
+
615. 105217 return {
+
616. 105217 line_source
+
617. 105217 };
+
618. 105217 });
+
619. 668 let mode_stop = false; // true if JSLint cannot finish.
+
620. 668 let property_dict = empty(); // The object containing the tallied
+
621. 668 // ... property names.
+
622. 668 let state = empty(); // jslint state-object to be passed between
+
623. 668 // jslint functions.
+
624. 668 let syntax_dict = empty(); // The object containing the parser.
+
625. 668 let tenure = empty(); // The predefined property registry.
+
626. 668 let token_global = { // The global object; the outermost context.
+
627. 668 async: 0,
+
628. 668 body: true,
+
629. 668 context: empty(),
+
630. 668 finally: 0,
+
631. 668 from: 0,
+
632. 668 id: "(global)",
+
633. 668 level: 0,
+
634. 668 line: jslint_fudge,
+
635. 668 live: [],
+
636. 668 loop: 0,
+
637. 668 switch: 0,
+
638. 668 thru: 0,
+
639. 668 try: 0
+
640. 668 };
+
641. 668 let token_list = []; // The array of tokens.
+
642. 668 let warning_list = []; // The array collecting all generated warnings.
+
643. 668
+
644. 668// Error reportage functions:
+
645. 668
+
646. 8041 function artifact(the_token) {
+
647. 8041
+
648. 8041// Return a string representing an artifact.
+
649. 8041
+
650. 256 the_token = the_token || state.token_nxt;
+
651. 8041 return (
+
652. 5266 (the_token.id === "(string)" || the_token.id === "(number)")
+
653. 2900 ? String(the_token.value)
+
654. 5141 : the_token.id
+
655. 8041 );
+
656. 8041 }
+
657. 668
+
658. 31957 function is_equal(aa, bb) {
+
659. 31957
+
660. 31957// test_cause:
+
661. 31957// ["0&&0", "is_equal", "", "", 0]
+
662. 31957
+
663. 31957 test_cause("");
+
664. 31957
+
665. 31957// Probably deadcode.
+
666. 31957// if (aa === bb) {
+
667. 31957// return true;
+
668. 31957// }
+
669. 31957
+
670. 31957 jslint_assert(!(aa === bb), `Expected !(aa === bb).`);
+
671. 27 if (Array.isArray(aa)) {
+
672. 27 return (
+
673. 27 Array.isArray(bb)
+
674. 27 && aa.length === bb.length
+
675. 27 && aa.every(function (value, index) {
+
676. 27
+
677. 27// test_cause:
+
678. 27// ["`${0}`&&`${0}`", "is_equal", "recurse_isArray", "", 0]
+
679. 27// ["`${0}`&&`${1}`", "is_equal", "recurse_isArray", "", 0]
+
680. 27
+
681. 27 test_cause("recurse_isArray");
+
682. 27 return is_equal(value, bb[index]);
+
683. 27 })
+
684. 27 );
+
685. 31930 }
+
686. 31930
+
687. 31930// Probably deadcode.
+
688. 31930// if (Array.isArray(bb)) {
+
689. 31930// return false;
+
690. 31930// }
+
691. 31930
+
692. 31930 jslint_assert(!Array.isArray(bb), `Expected !Array.isArray(bb).`);
+
693. 31930 switch (aa.id === bb.id && aa.id) {
+
694. 65 case "(number)":
+
695. 23429 case "(string)":
+
696. 23429 return aa.value === bb.value;
+
697. 31957
+
698. 31957// PR-394 - Bugfix
+
699. 31957// Fix jslint falsely believing megastring literals `0` and `1` are similar.
+
700. 31957
+
701. 15 case "`":
+
702. 15 if (!is_equal(aa.value, bb.value)) {
+
703. 15 return false;
+
704. 15 }
+
705. 15 break;
+
706. 8498 }
+
707. 8498 if (is_weird(aa) || is_weird(bb)) {
+
708. 34
+
709. 34// test_cause:
+
710. 34// ["aa(/./)||{}", "is_equal", "false", "", 0]
+
711. 34
+
712. 34 test_cause("false");
+
713. 34 return false;
+
714. 8464 }
+
715. 8464 if (aa.arity === bb.arity && aa.id === bb.id) {
+
716. 2147 if (aa.id === "." || aa.id === "?.") {
+
717. 2147
+
718. 2147// test_cause:
+
719. 2147// ["aa.bb&&aa.bb", "is_equal", "recurse_arity_id", "", 0]
+
720. 2147// ["aa?.bb&&aa?.bb", "is_equal", "recurse_arity_id", "", 0]
+
721. 2147
+
722. 2147 test_cause("recurse_arity_id");
+
723. 2147 return (
+
724. 2147 is_equal(aa.expression, bb.expression)
+
725. 2147 && is_equal(aa.name, bb.name)
+
726. 2147 );
+
727. 2147 }
+
728. 2147 if (aa.arity === "unary") {
+
729. 2147
+
730. 2147// test_cause:
+
731. 2147// ["+0&&+0", "is_equal", "recurse_unary", "", 0]
+
732. 2147
+
733. 2147 test_cause("recurse_unary");
+
734. 2147 return is_equal(aa.expression, bb.expression);
+
735. 2147 }
+
736. 2147 if (aa.arity === "binary") {
+
737. 2147
+
738. 2147// test_cause:
+
739. 2147// ["aa[0]&&aa[0]", "is_equal", "recurse_binary", "", 0]
+
740. 2147
+
741. 2147 test_cause("recurse_binary");
+
742. 2147 return (
+
743. 2147 aa.id !== "("
+
744. 2147 && is_equal(aa.expression[0], bb.expression[0])
+
745. 2147 && is_equal(aa.expression[1], bb.expression[1])
+
746. 2147 );
+
747. 2147 }
+
748. 2147 if (aa.arity === "ternary") {
+
749. 2147
+
750. 2147// test_cause:
+
751. 2147// ["aa=(``?``:``)&&(``?``:``)", "is_equal", "recurse_ternary", "", 0]
+
752. 2147
+
753. 2147 test_cause("recurse_ternary");
+
754. 2147 return (
+
755. 2147 is_equal(aa.expression[0], bb.expression[0])
+
756. 2147 && is_equal(aa.expression[1], bb.expression[1])
+
757. 2147 && is_equal(aa.expression[2], bb.expression[2])
+
758. 2147 );
+
759. 2147 }
+
760. 2147
+
761. 2147// Probably deadcode.
+
762. 2147// if (aa.arity === "function" || aa.arity === "regexp") {
+
763. 2147// return false;
+
764. 2147// }
+
765. 2147
+
766. 2147 jslint_assert(
+
767. 2147 !(aa.arity === "function" || aa.arity === "regexp"),
+
768. 2147 `Expected !(aa.arity === "function" || aa.arity === "regexp").`
+
769. 2147 );
+
770. 2147
+
771. 2147// test_cause:
+
772. 2147// ["undefined&&undefined", "is_equal", "true", "", 0]
+
773. 2147
+
774. 2147 test_cause("true");
+
775. 2147 return true;
+
776. 6317 }
+
777. 6317
+
778. 6317// test_cause:
+
779. 6317// ["null&&undefined", "is_equal", "false", "", 0]
+
780. 6317
+
781. 6317 test_cause("false");
+
782. 6317 return false;
+
783. 6317 }
+
784. 668
+
785. 28763 function is_weird(thing) {
+
786. 28763 switch (thing.id) {
+
787. 1 case "(regexp)":
+
788. 1 return true;
+
789. 1 case "=>":
+
790. 1 return true;
+
791. 593 case "[":
+
792. 593 return thing.arity === "unary";
+
793. 12 case "function":
+
794. 12 return true;
+
795. 8 case "{":
+
796. 8 return true;
+
797. 28148 default:
+
798. 28148 return false;
+
799. 28763 }
+
800. 28763 }
+
801. 668
+
802. 106 function stop(code, the_token, a, b, c, d) {
+
803. 106
+
804. 106// Similar to warn and stop_at. If the token already had a warning, that
+
805. 106// warning will be replaced with this new one. It is likely that the stopping
+
806. 106// warning will be the more meaningful.
+
807. 106
+
808. 38 the_token = the_token || state.token_nxt;
+
809. 106 delete the_token.warning;
+
810. 106 throw warn(code, the_token, a, b, c, d);
+
811. 106 }
+
812. 668
+
813. 28 function stop_at(code, line, column, a, b, c, d) {
+
814. 28
+
815. 28// Same as warn_at, except that it stops the analysis.
+
816. 28
+
817. 28 throw warn_at(code, line, column, a, b, c, d);
+
818. 28 }
+
819. 668
+
820. 339547 function test_cause(code, aa, column) {
+
821. 339547
+
822. 339547// This function will instrument <cause> to <cause_dict> for test-purposes.
+
823. 339547
+
824. 4882 if (option_dict.test_cause) {
+
825. 4882 cause_dict[JSON.stringify([
+
826. 4882 String(new Error().stack).replace((
+
827. 4882 /^ at (?:file|stop|stop_at|test_cause|warn|warn_at)\b.*?\n/gm
+
828. 4882 ), "").match(
+
829. 4882 /\n at ((?:Object\.\w+?_)?\w+?) /
+
830. 4882 )[1].replace((
+
831. 4882 /^Object\./
+
832. 4882 ), ""),
+
833. 4882 code,
+
834. 4882 String(
+
835. 4882 (aa === undefined || aa === token_global)
+
836. 4882 ? ""
+
837. 4882 : aa
+
838. 4882 ),
+
839. 4882 column || 0
+
840. 4882 ])] = true;
+
841. 4882 }
+
842. 339547 }
+
843. 668
+
844. 1075 function warn(code, the_token, a, b, c, d) {
+
845. 1075
+
846. 1075// Same as warn_at, except the warning will be associated with a specific token.
+
847. 1075// If there is already a warning on this token, suppress the new one. It is
+
848. 1075// likely that the first warning will be the most meaningful.
+
849. 1075
+
850. 1075 let the_warning;
+
851. 20 the_token = the_token || state.token_nxt;
+
852. 1075 the_warning = warn_at(
+
853. 1075 code,
+
854. 1075 the_token.line,
+
855. 376 (the_token.from || 0) + jslint_fudge,
+
856. 835 a || artifact(the_token),
+
857. 1075 b,
+
858. 1075 c,
+
859. 1075 d
+
860. 1075 );
+
861. 1075
+
862. 1075// Issue #408
+
863. 1075// Warnings that should be ignored sometimes suppress legitimate warnings.
+
864. 1075
+
865. 26 if (the_warning.directive_ignore_line) {
+
866. 26 return the_warning;
+
867. 1049 }
+
868. 1049
+
869. 1049// If there is already a warning on this token, suppress the new one. It is
+
870. 1049// likely that the first warning will be the most meaningful.
+
871. 1049
+
872. 1049 if (the_token.warning) {
+
873. 192 warning_list.pop();
+
874. 192 return the_warning;
+
875. 857 }
+
876. 857 the_token.warning = the_warning;
+
877. 857 return the_warning;
+
878. 857 }
+
879. 668
+
880. 1394 function warn_at(code, line, column, a, b, c, d) {
+
881. 1394
+
882. 1394// Report an error at some line and column of the program. The warning object
+
883. 1394// resembles an exception.
+
884. 1394
+
885. 1394 let mm;
+
886. 1394 let warning = Object.assign(empty(), {
+
887. 1394 a,
+
888. 1394 b,
+
889. 1394 c,
+
890. 1394 code,
+
891. 1394
+
892. 1394// Fudge column numbers in warning message.
+
893. 1394
+
894. 27 column: column || jslint_fudge,
+
895. 1394 d,
+
896. 1394 line,
+
897. 1394 line_source: "",
+
898. 1394 name: "JSLintError"
+
899. 1394 }, line_list[line]);
+
900. 1394 warning.column = Math.max(
+
901. 1394 Math.min(warning.column, warning.line_source.length),
+
902. 1394 jslint_fudge
+
903. 1394 );
+
904. 926 test_cause(code, b || a, warning.column);
+
905. 1394 switch (code) {
+
906. 1394
+
907. 1394// The bundle contains the raw text messages that are generated by jslint. It
+
908. 1394// seems that they are all error messages and warnings. There are no "Atta
+
909. 1394// boy!" or "You are so awesome!" messages. There is no positive reinforcement
+
910. 1394// or encouragement. This relentless negativity can undermine self-esteem and
+
911. 1394// wound the inner child. But if you accept it as sound advice rather than as
+
912. 1394// personal criticism, it can make your programs better.
+
913. 1394
+
914. 1 case "and":
+
915. 1 mm = `The '&&' subexpression should be wrapped in parens.`;
+
916. 1 break;
+
917. 71 case "bad_assignment_a":
+
918. 71 mm = `Bad assignment to '${a}'.`;
+
919. 71 break;
+
920. 1 case "bad_directive_a":
+
921. 1 mm = `Bad directive '${a}'.`;
+
922. 1 break;
+
923. 1 case "bad_get":
+
924. 1 mm = `A get function takes no parameters.`;
+
925. 1 break;
+
926. 1 case "bad_module_name_a":
+
927. 1 mm = `Bad module name '${a}'.`;
+
928. 1 break;
+
929. 2 case "bad_option_a":
+
930. 2 mm = `Bad option '${a}'.`;
+
931. 2 break;
+
932. 1 case "bad_set":
+
933. 1 mm = `A set function takes one parameter.`;
+
934. 1 break;
+
935. 6 case "duplicate_a":
+
936. 6 mm = `Duplicate '${a}'.`;
+
937. 6 break;
+
938. 64 case "empty_block":
+
939. 64 mm = `Empty block.`;
+
940. 64 break;
+
941. 5 case "expected_a":
+
942. 5 mm = `Expected '${a}'.`;
+
943. 5 break;
+
944. 25 case "expected_a_at_b_c":
+
945. 25 mm = `Expected '${a}' at column ${b}, not column ${c}.`;
+
946. 25 break;
+
947. 286 case "expected_a_b":
+
948. 286 mm = `Expected '${a}' and instead saw '${b}'.`;
+
949. 286 break;
+
950. 17 case "expected_a_b_before_c_d":
+
951. 17 mm = `Expected ${a} '${b}' to be ordered before ${c} '${d}'.`;
+
952. 17 break;
+
953. 2 case "expected_a_b_from_c_d":
+
954. 2 mm = (
+
955. 2 `Expected '${a}' to match '${b}' from line ${c}`
+
956. 2 + ` and instead saw '${d}'.`
+
957. 2 );
+
958. 2 break;
+
959. 30 case "expected_a_before_b":
+
960. 30 mm = `Expected '${a}' before '${b}'.`;
+
961. 30 break;
+
962. 2 case "expected_digits_after_a":
+
963. 2 mm = `Expected digits after '${a}'.`;
+
964. 2 break;
+
965. 1 case "expected_four_digits":
+
966. 1 mm = `Expected four digits after '\\u'.`;
+
967. 1 break;
+
968. 31 case "expected_identifier_a":
+
969. 31 mm = `Expected an identifier and instead saw '${a}'.`;
+
970. 31 break;
+
971. 6 case "expected_line_break_a_b":
+
972. 6 mm = `Expected a line break between '${a}' and '${b}'.`;
+
973. 6 break;
+
974. 3 case "expected_regexp_factor_a":
+
975. 3 mm = `Expected a regexp factor and instead saw '${a}'.`;
+
976. 3 break;
+
977. 76 case "expected_space_a_b":
+
978. 76 mm = `Expected one space between '${a}' and '${b}'.`;
+
979. 76 break;
+
980. 2 case "expected_statements_a":
+
981. 2 mm = `Expected statements before '${a}'.`;
+
982. 2 break;
+
983. 1 case "expected_string_a":
+
984. 1 mm = `Expected a string and instead saw '${a}'.`;
+
985. 1 break;
+
986. 1 case "expected_type_string_a":
+
987. 1 mm = `Expected a type string and instead saw '${a}'.`;
+
988. 1 break;
+
989. 6 case "freeze_exports":
+
990. 6 mm = (
+
991. 6 `Expected 'Object.freeze('. All export values should be frozen.`
+
992. 6 );
+
993. 6 break;
+
994. 1394
+
995. 1394// PR-378 - Relax warning "function_in_loop".
+
996. 1394//
+
997. 1394// case "function_in_loop":
+
998. 1394// mm = `Don't create functions within a loop.`;
+
999. 1394// break;
+
1000. 1394
+
1001. 1394// PR-390 - Add numeric-separator check.
+
1002. 1394
+
1003. 7 case "illegal_num_separator":
+
1004. 7 mm = `Illegal numeric separator '_' at column ${column}.`;
+
1005. 7 break;
+
1006. 1 case "infix_in":
+
1007. 1 mm = (
+
1008. 1 `Unexpected 'in'. Compare with undefined,`
+
1009. 1 + ` or use the hasOwnProperty method instead.`
+
1010. 1 );
+
1011. 1 break;
+
1012. 1 case "label_a":
+
1013. 1 mm = `'${a}' is a statement label.`;
+
1014. 1 break;
+
1015. 1 case "misplaced_a":
+
1016. 1 mm = `Place '${a}' at the outermost level.`;
+
1017. 1 break;
+
1018. 1 case "misplaced_directive_a":
+
1019. 1 mm = `Place the '/*${a}*/' directive before the first statement.`;
+
1020. 1 break;
+
1021. 3 case "missing_await_statement":
+
1022. 3 mm = `Expected await statement in async function.`;
+
1023. 3 break;
+
1024. 1394
+
1025. 1394// PR-347 - Disable warning "missing_browser".
+
1026. 1394//
+
1027. 1394// case "missing_browser":
+
1028. 1394// mm = `/*global*/ requires the Assume a browser option.`;
+
1029. 1394// break;
+
1030. 1394
+
1031. 1 case "missing_m":
+
1032. 1 mm = `Expected 'm' flag on a multiline regular expression.`;
+
1033. 1 break;
+
1034. 5 case "naked_block":
+
1035. 5 mm = `Naked block.`;
+
1036. 5 break;
+
1037. 2 case "nested_comment":
+
1038. 2 mm = `Nested comment.`;
+
1039. 2 break;
+
1040. 1 case "not_label_a":
+
1041. 1 mm = `'${a}' is not a label.`;
+
1042. 1 break;
+
1043. 2 case "number_isNaN":
+
1044. 2 mm = `Use Number.isNaN function to compare with NaN.`;
+
1045. 2 break;
+
1046. 4 case "out_of_scope_a":
+
1047. 4 mm = `'${a}' is out of scope.`;
+
1048. 4 break;
+
1049. 11 case "redefinition_a_b":
+
1050. 11 mm = `Redefinition of '${a}' from line ${b}.`;
+
1051. 11 break;
+
1052. 1 case "redefinition_global_a_b":
+
1053. 1 mm = `Redefinition of global ${a} variable '${b}'.`;
+
1054. 1 break;
+
1055. 6 case "required_a_optional_b":
+
1056. 6 mm = `Required parameter '${a}' after optional parameter '${b}'.`;
+
1057. 6 break;
+
1058. 1 case "reserved_a":
+
1059. 1 mm = `Reserved name '${a}'.`;
+
1060. 1 break;
+
1061. 1 case "subscript_a":
+
1062. 1 mm = `['${a}'] is better written in dot notation.`;
+
1063. 1 break;
+
1064. 16 case "todo_comment":
+
1065. 16 mm = `Unexpected TODO comment.`;
+
1066. 16 break;
+
1067. 13 case "too_long":
+
1068. 13 mm = `Line is longer than 80 characters.`;
+
1069. 13 break;
+
1070. 1 case "too_many_digits":
+
1071. 1 mm = `Too many digits.`;
+
1072. 1 break;
+
1073. 3 case "unclosed_comment":
+
1074. 3 mm = `Unclosed comment.`;
+
1075. 3 break;
+
1076. 3 case "unclosed_disable":
+
1077. 3 mm = (
+
1078. 3 `Directive '/*jslint-disable*/' was not closed`
+
1079. 3 + ` with '/*jslint-enable*/'.`
+
1080. 3 );
+
1081. 3 break;
+
1082. 3 case "unclosed_mega":
+
1083. 3 mm = `Unclosed mega literal.`;
+
1084. 3 break;
+
1085. 2 case "unclosed_string":
+
1086. 2 mm = `Unclosed string.`;
+
1087. 2 break;
+
1088. 137 case "undeclared_a":
+
1089. 137 mm = `Undeclared '${a}'.`;
+
1090. 137 break;
+
1091. 237 case "unexpected_a":
+
1092. 237 mm = `Unexpected '${a}'.`;
+
1093. 237 break;
+
1094. 2 case "unexpected_a_after_b":
+
1095. 2 mm = `Unexpected '${a}' after '${b}'.`;
+
1096. 2 break;
+
1097. 2 case "unexpected_a_before_b":
+
1098. 2 mm = `Unexpected '${a}' before '${b}'.`;
+
1099. 2 break;
+
1100. 34 case "unexpected_at_top_level_a":
+
1101. 34 mm = `Expected '${a}' to be in a function.`;
+
1102. 34 break;
+
1103. 1 case "unexpected_char_a":
+
1104. 1 mm = `Unexpected character '${a}'.`;
+
1105. 1 break;
+
1106. 2 case "unexpected_comment":
+
1107. 2 mm = `Unexpected comment.`;
+
1108. 2 break;
+
1109. 1394
+
1110. 1394// PR-347 - Disable warning "unexpected_directive_a".
+
1111. 1394//
+
1112. 1394// case "unexpected_directive_a":
+
1113. 1394// mm = `When using modules, don't use directive '/\u002a${a}'.`;
+
1114. 1394// break;
+
1115. 1394
+
1116. 128 case "unexpected_expression_a":
+
1117. 128 mm = `Unexpected expression '${a}' in statement position.`;
+
1118. 128 break;
+
1119. 4 case "unexpected_label_a":
+
1120. 4 mm = `Unexpected label '${a}'.`;
+
1121. 4 break;
+
1122. 3 case "unexpected_parens":
+
1123. 3 mm = `Don't wrap function literals in parens.`;
+
1124. 3 break;
+
1125. 8 case "unexpected_space_a_b":
+
1126. 8 mm = `Unexpected space between '${a}' and '${b}'.`;
+
1127. 8 break;
+
1128. 1 case "unexpected_statement_a":
+
1129. 1 mm = `Unexpected statement '${a}' in expression position.`;
+
1130. 1 break;
+
1131. 2 case "unexpected_trailing_space":
+
1132. 2 mm = `Unexpected trailing space.`;
+
1133. 2 break;
+
1134. 1 case "unexpected_typeof_a":
+
1135. 1 mm = (
+
1136. 1 `Unexpected 'typeof'. Use '===' to compare directly with ${a}.`
+
1137. 1 );
+
1138. 1 break;
+
1139. 1 case "uninitialized_a":
+
1140. 1 mm = `Uninitialized '${a}'.`;
+
1141. 1 break;
+
1142. 1 case "unopened_enable":
+
1143. 1 mm = (
+
1144. 1 `Directive '/*jslint-enable*/' was not opened`
+
1145. 1 + ` with '/*jslint-disable*/'.`
+
1146. 1 );
+
1147. 1 break;
+
1148. 1 case "unreachable_a":
+
1149. 1 mm = `Unreachable '${a}'.`;
+
1150. 1 break;
+
1151. 1 case "unregistered_property_a":
+
1152. 1 mm = `Unregistered property name '${a}'.`;
+
1153. 1 break;
+
1154. 6 case "unused_a":
+
1155. 6 mm = `Unused '${a}'.`;
+
1156. 6 break;
+
1157. 2 case "use_double":
+
1158. 2 mm = `Use double quotes, not single quotes.`;
+
1159. 2 break;
+
1160. 1394
+
1161. 1394// PR-386 - Fix issue #382 - Make fart-related warnings more readable.
+
1162. 1394
+
1163. 4 case "use_function_not_fart":
+
1164. 4 mm = (
+
1165. 4 `Use 'function (...)', not '(...) =>' when arrow functions`
+
1166. 4 + ` become too complex.`
+
1167. 4 );
+
1168. 4 break;
+
1169. 7 case "use_open":
+
1170. 7 mm = (
+
1171. 7 `Wrap a ternary expression in parens,`
+
1172. 7 + ` with a line break after the left paren.`
+
1173. 7 );
+
1174. 7 break;
+
1175. 1 case "use_spaces":
+
1176. 1 mm = `Use spaces, not tabs.`;
+
1177. 1 break;
+
1178. 5 case "var_on_top":
+
1179. 5 mm = `Move variable declaration to top of function or script.`;
+
1180. 5 break;
+
1181. 1 case "var_switch":
+
1182. 1 mm = `Don't declare variables in a switch.`;
+
1183. 1 break;
+
1184. 23 case "weird_condition_a":
+
1185. 23 mm = `Weird condition '${a}'.`;
+
1186. 23 break;
+
1187. 5 case "weird_expression_a":
+
1188. 5 mm = `Weird expression '${a}'.`;
+
1189. 5 break;
+
1190. 3 case "weird_loop":
+
1191. 3 mm = `Weird loop.`;
+
1192. 3 break;
+
1193. 9 case "weird_property_a":
+
1194. 9 mm = `Weird property name '${a}'.`;
+
1195. 9 break;
+
1196. 8 case "weird_relation_a":
+
1197. 8 mm = `Weird relation '${a}'.`;
+
1198. 8 break;
+
1199. 1 case "wrap_condition":
+
1200. 1 mm = `Wrap the condition in parens.`;
+
1201. 1 break;
+
1202. 1394
+
1203. 1394// PR-386 - Fix issue #382 - Make fart-related warnings more readable.
+
1204. 1394
+
1205. 1 case "wrap_fart_parameter":
+
1206. 1 mm = `Wrap the parameter before '=>' in parens.`;
+
1207. 1 break;
+
1208. 1 case "wrap_immediate":
+
1209. 1 mm = (
+
1210. 1 `Wrap an immediate function invocation in parentheses to assist`
+
1211. 1 + ` the reader in understanding that the expression is the`
+
1212. 1 + ` result of a function, and not the function itself.`
+
1213. 1 );
+
1214. 1 break;
+
1215. 18 case "wrap_regexp":
+
1216. 18 mm = `Wrap this regexp in parens to avoid confusion.`;
+
1217. 18 break;
+
1218. 1 case "wrap_unary":
+
1219. 1 mm = `Wrap the unary expression in parens.`;
+
1220. 1 break;
+
1221. 1394 }
+
1222. 1394
+
1223. 1394// Validate mm.
+
1224. 1394
+
1225. 1394 jslint_assert(mm, code);
+
1226. 1394 warning.message = mm;
+
1227. 1394
+
1228. 1394// PR-242 - Include stack_trace for jslint to debug itself for errors.
+
1229. 1394
+
1230. 6 if (option_dict.trace) {
+
1231. 6 warning.stack_trace = new Error().stack;
+
1232. 6 }
+
1233. 41 if (warning.directive_ignore_line) {
+
1234. 41
+
1235. 41// test_cause:
+
1236. 41// ["0 //jslint-ignore-line", "semicolon", "directive_ignore_line", "", 0]
+
1237. 41
+
1238. 41 test_cause("directive_ignore_line");
+
1239. 41 return warning;
+
1240. 1353 }
+
1241. 1353 warning_list.push(warning);
+
1242. 1353 return warning;
+
1243. 1353 }
+
1244. 668
+
1245. 668 try {
+
1246. 668
+
1247. 668// tokenize takes a source and produces from it an array of token objects.
+
1248. 668// JavaScript is notoriously difficult to tokenize because of the horrible
+
1249. 668// interactions between automatic semicolon insertion, regular expression
+
1250. 668// literals, and now megastring literals. JSLint benefits from eliminating
+
1251. 668// automatic semicolon insertion and nested megastring literals, which allows
+
1252. 668// full tokenization to precede parsing.
+
1253. 668
+
1254. 668 option_dict = Object.assign(empty(), option_dict);
+
1255. 668 Object.assign(state, {
+
1256. 668 artifact,
+
1257. 668 catch_list,
+
1258. 668 catch_stack,
+
1259. 668 directive_list,
+
1260. 668 export_dict,
+
1261. 668 function_list,
+
1262. 668 function_stack,
+
1263. 668 global_dict,
+
1264. 668 global_list,
+
1265. 668 import_list,
+
1266. 668 is_equal,
+
1267. 668 is_weird,
+
1268. 668 line_list,
+
1269. 668 mode_json: false, // true if parsing JSON.
+
1270. 668 mode_module: false, // true if import or export was used.
+
1271. 668 mode_property: false, // true if directive /*property*/ is
+
1272. 668 // ... used.
+
1273. 668 mode_shebang: false, // true if #! is seen on the first line.
+
1274. 668 option_dict,
+
1275. 668 property_dict,
+
1276. 668 source,
+
1277. 668 stop,
+
1278. 668 stop_at,
+
1279. 668 syntax_dict,
+
1280. 668 tenure,
+
1281. 668 test_cause,
+
1282. 668 token_global,
+
1283. 668 token_list,
+
1284. 668 token_nxt: token_global,
+
1285. 668 warn,
+
1286. 668 warn_at,
+
1287. 668 warning_list
+
1288. 668 });
+
1289. 668
+
1290. 668// PHASE 1. Split <source> by newlines into <line_list>.
+
1291. 668
+
1292. 668 jslint_phase1_split(state);
+
1293. 668 jslint_assert(catch_stack.length === 1, `catch_stack.length === 1.`);
+
1294. 668 jslint_assert(
+
1295. 668 function_stack.length === 0,
+
1296. 668 `function_stack.length === 0.`
+
1297. 668 );
+
1298. 668
+
1299. 668// PHASE 2. Lex <line_list> into <token_list>.
+
1300. 668
+
1301. 668 jslint_phase2_lex(state);
+
1302. 668 jslint_assert(catch_stack.length === 1, `catch_stack.length === 1.`);
+
1303. 668 jslint_assert(
+
1304. 668 function_stack.length === 0,
+
1305. 668 `function_stack.length === 0.`
+
1306. 668 );
+
1307. 668
+
1308. 668// PHASE 3. Parse <token_list> into <token_tree> using the Pratt-parser.
+
1309. 668
+
1310. 668 jslint_phase3_parse(state);
+
1311. 668 jslint_assert(catch_stack.length === 1, `catch_stack.length === 1.`);
+
1312. 668 jslint_assert(
+
1313. 668 function_stack.length === 0,
+
1314. 668 `function_stack.length === 0.`
+
1315. 668 );
+
1316. 668
+
1317. 668// PHASE 4. Walk <token_tree>, traversing all nodes of the tree. It is a
+
1318. 668// recursive traversal. Each node may be processed on the way down
+
1319. 668// (preaction) and on the way up (postaction).
+
1320. 668
+
1321. 518 if (!state.mode_json) {
+
1322. 518 jslint_phase4_walk(state);
+
1323. 533 }
+
1324. 533 jslint_assert(catch_stack.length === 1, `catch_stack.length === 1.`);
+
1325. 533 jslint_assert(
+
1326. 533 function_stack.length === 0,
+
1327. 533 `function_stack.length === 0.`
+
1328. 533 );
+
1329. 533
+
1330. 533// PHASE 5. Check whitespace between tokens in <token_list>.
+
1331. 533
+
1332. 533 if (!state.mode_json && warning_list.length === 0) {
+
1333. 208 jslint_phase5_whitage(state);
+
1334. 533 }
+
1335. 533 jslint_assert(catch_stack.length === 1, `catch_stack.length === 1.`);
+
1336. 533 jslint_assert(
+
1337. 533 function_stack.length === 0,
+
1338. 533 `function_stack.length === 0.`
+
1339. 533 );
+
1340. 533
+
1341. 533// PR-347 - Disable warning "missing_browser".
+
1342. 533//
+
1343. 533// if (!option_dict.browser) {
+
1344. 533// directive_list.forEach(function (comment) {
+
1345. 533// if (comment.directive === "global") {
+
1346. 533//
+
1347. 533// // test_cause:
+
1348. 533// // ["/*global aa*/", "jslint", "missing_browser", "(comment)", 1]
+
1349. 533//
+
1350. 533// warn("missing_browser", comment);
+
1351. 533// }
+
1352. 533// });
+
1353. 533// }
+
1354. 533
+
1355. 533 if (option_dict.test_internal_error) {
+
1356. 2 jslint_assert(undefined, "test_internal_error");
+
1357. 2 }
+
1358. 137 } catch (err) {
+
1359. 137 mode_stop = true;
+
1360. 137 err.message = "[JSLint was unable to finish] " + err.message;
+
1361. 137 err.mode_stop = true;
+
1362. 137 if (err.name !== "JSLintError") {
+
1363. 137 Object.assign(err, {
+
1364. 137 column: jslint_fudge,
+
1365. 137 line: jslint_fudge,
+
1366. 137 line_source: "",
+
1367. 137 stack_trace: err.stack
+
1368. 137 });
+
1369. 137 }
+
1370. 137 if (warning_list.indexOf(err) === -1) {
+
1371. 137 warning_list.push(err);
+
1372. 137 }
+
1373. 137 }
+
1374. 668
+
1375. 668// Sort warning_list by mode_stop first, line, column respectively.
+
1376. 668
+
1377. 986 warning_list.sort(function (aa, bb) {
+
1378. 986 return (
+
1379. 986 Boolean(bb.mode_stop) - Boolean(aa.mode_stop)
+
1380. 896 || aa.line - bb.line
+
1381. 876 || aa.column - bb.column
+
1382. 986 );
+
1383. 986
+
1384. 986// Update each warning with formatted_message ready-for-use by jslint_cli.
+
1385. 986
+
1386. 1164 }).map(function ({
+
1387. 1164 column,
+
1388. 1164 line,
+
1389. 1164 line_source,
+
1390. 1164 message,
+
1391. 1164 stack_trace = ""
+
1392. 1164 }, ii, list) {
+
1393. 1164 list[ii].formatted_message = String(
+
1394. 1164 String(ii + 1).padStart(2, " ")
+
1395. 1164 + ". \u001b[31m" + message + "\u001b[39m"
+
1396. 1164 + " \u001b[90m\/\/ line " + line + ", column " + column
+
1397. 1164 + "\u001b[39m\n"
+
1398. 1164 + (" " + line_source.trim()).slice(0, 72) + "\n"
+
1399. 1164 + stack_trace
+
1400. 1164 ).trimRight();
+
1401. 1164 });
+
1402. 668
+
1403. 668 return {
+
1404. 668 causes: cause_dict,
+
1405. 668 directives: directive_list,
+
1406. 668 edition: jslint_edition,
+
1407. 668 exports: export_dict,
+
1408. 668 froms: import_list,
+
1409. 668 functions: function_list,
+
1410. 668 global: token_global,
+
1411. 668 id: "(JSLint)",
+
1412. 668 json: state.mode_json,
+
1413. 668 lines: line_list,
+
1414. 668 module: state.mode_module === true,
+
1415. 164 ok: warning_list.length === 0 && !mode_stop,
+
1416. 668 option: option_dict,
+
1417. 668 property: property_dict,
+
1418. 668 shebang: (
+
1419. 668 state.mode_shebang
+
1420. 1 ? line_list[jslint_fudge].line_source
+
1421. 667 : undefined
+
1422. 668 ),
+
1423. 668 stop: mode_stop,
+
1424. 668 tokens: token_list,
+
1425. 668 tree: state.token_tree,
+
1426. 668 warnings: warning_list
+
1427. 668 };
+
1428. 668}
+
1429. 1
+
1430. 1// PR-362 - Add API Doc.
+
1431. 1
+
1432. 1async function jslint_apidoc({
+
1433. 1 example_list,
+
1434. 1 github_repo,
+
1435. 1 module_list,
+
1436. 1 package_name,
+
1437. 1 pathname,
+
1438. 1 version
+
1439. 1}) {
+
1440. 1
+
1441. 1// This function will create API Doc from <module_list>.
+
1442. 1
+
1443. 1 let elem_ii = 0;
+
1444. 1 let html;
+
1445. 1
+
1446. 27 function elem_create(moduleObj, key, moduleName) {
+
1447. 27
+
1448. 27// This function will create a sub API Doc from elem <moduleObj>[<key>].
+
1449. 27
+
1450. 27 let example = "N/A";
+
1451. 27 let id = encodeURIComponent("apidoc.elem." + moduleName + "." + key);
+
1452. 27 let name;
+
1453. 27 let signature;
+
1454. 27 let source;
+
1455. 27 name = htmlEscape((typeof moduleObj[key]) + " " + key);
+
1456. 2 if (typeof moduleObj[key] !== "function") {
+
1457. 2 return {
+
1458. 2 name,
+
1459. 2 signature: (`
+
1460. 2<a class="apidocElementLiA" href="#${id}">
+
1461. 2${name}
+
1462. 2</a>
+
1463. 2 `),
+
1464. 2 source: (`
+
1465. 2<li>
+
1466. 2 <h2>
+
1467. 2 <a href="#${id}" id="${id}">
+
1468. 2 ${name}
+
1469. 2 </a>
+
1470. 2 </h2>
+
1471. 2</li>
+
1472. 2 `)
+
1473. 2 };
+
1474. 25 }
+
1475. 25 // init source
+
1476. 25 source = htmlEscape(trim_start(moduleObj[key].toString()));
+
1477. 25 // init signature
+
1478. 25 source = source.replace((
+
1479. 25 /(\([\S\s]*?\)) \{/
+
1480. 25 ), function (match0, match1) {
+
1481. 25 signature = htmlEscape(
+
1482. 25 match1.replace((
+
1483. 25 / *?\/\*[\S\s]*?\*\/ */g
+
1484. 25 ), "").replace((
+
1485. 25 / *?\/\/.*/g
+
1486. 25 ), "").replace((
+
1487. 25 /\n{2,}/g
+
1488. 25 ), "\n")
+
1489. 25 );
+
1490. 25 return match0;
+
1491. 25 });
+
1492. 25 // init comment
+
1493. 25 source = source.replace((
+
1494. 25 /\n(?:\/\/.*?\n)+\n/
+
1495. 25 ), "<span class=\"apidocCodeCommentSpan\">$&</span>");
+
1496. 25 // init example
+
1497. 56 example_list.some(function (example2) {
+
1498. 56 example2.replace(
+
1499. 56 new RegExp((
+
1500. 56 "((?:\\n.*?){8}(function )?)\\b"
+
1501. 56 + key
+
1502. 56 + "(\\((?:.*?\\n){8})"
+
1503. 56 ), "g"),
+
1504. 132 function (ignore, header, isDeclaration, footer) {
+
1505. 124 if (!isDeclaration) {
+
1506. 124 example = "..." + trim_start(
+
1507. 124 htmlEscape(header)
+
1508. 124 + "<span class=\"apidocCodeKeywordSpan\">"
+
1509. 124 + htmlEscape(key)
+
1510. 124 + "</span>"
+
1511. 124 + htmlEscape(footer)
+
1512. 124 ).trimEnd() + "\n...";
+
1513. 124 }
+
1514. 132 return "";
+
1515. 132 }
+
1516. 56 );
+
1517. 56 return example !== "N/A";
+
1518. 56 });
+
1519. 25 if (source.length > 2048) {
+
1520. 11 source = source.slice(0, 2048) + "...\n}\n";
+
1521. 25 }
+
1522. 25 return {
+
1523. 25 name,
+
1524. 25 signature: (`
+
1525. 25<a class="apidocElementLiA" href="#${id}">
+
1526. 25${name}<span class="apidocSignatureSpan">${signature}</span>
+
1527. 25</a>
+
1528. 25 `),
+
1529. 25 source: (`
+
1530. 25<li>
+
1531. 25 <h2>
+
1532. 25 <a href="#${id}" id="${id}">
+
1533. 25 ${name}<span class="apidocSignatureSpan">${signature}</span>
+
1534. 25 </a>
+
1535. 25 </h2>
+
1536. 25</li>
+
1537. 25<li>Description and source-code:<pre class="apidocCodePre">${source}</pre></li>
+
1538. 25<li>Example usage:<pre class="apidocCodePre">${example}</pre></li>
+
1539. 25 `)
+
1540. 25 };
+
1541. 25 }
+
1542. 1
+
1543. 149 function trim_start(str) {
+
1544. 149
+
1545. 149// This function will normalize whitespace before <str>.
+
1546. 149
+
1547. 149 let whitespace = "";
+
1548. 149 str.trim().replace((
+
1549. 149 /^ */gm
+
1550. 13071 ), function (match0) {
+
1551. 8412 if (whitespace === "" || match0.length < whitespace.length) {
+
1552. 6610 whitespace = match0;
+
1553. 6610 }
+
1554. 13071 return "";
+
1555. 13071 });
+
1556. 149 str = str.replace(new RegExp("^" + whitespace, "gm"), "");
+
1557. 149 return str;
+
1558. 149 }
+
1559. 1 await moduleFsInit();
+
1560. 1
+
1561. 1// Html-escape params.
+
1562. 1
+
1563. 1 github_repo = htmlEscape(github_repo);
+
1564. 1 package_name = htmlEscape(package_name);
+
1565. 1 version = htmlEscape(version);
+
1566. 1
+
1567. 1// Init example_list.
+
1568. 1
+
1569. 3 example_list = await Promise.all(example_list.map(async function (file) {
+
1570. 3
+
1571. 3// This function will read example from given file.
+
1572. 3
+
1573. 3 let result = await moduleFs.promises.readFile(file, "utf8");
+
1574. 3 result = (
+
1575. 3 "\n\n\n\n\n\n\n\n"
+
1576. 3 // bug-workaround - truncate example to manageable size
+
1577. 3 + result.slice(0, 524288)
+
1578. 3 + "\n\n\n\n\n\n\n\n"
+
1579. 3 );
+
1580. 3 result = result.replace((
+
1581. 3 /\r\n*/g
+
1582. 3 ), "\n");
+
1583. 3 return result;
+
1584. 3 }));
+
1585. 1
+
1586. 1// Init module_list.
+
1587. 1
+
1588. 1 module_list = await Promise.all(module_list.map(async function ({
+
1589. 1 pathname
+
1590. 1 }) {
+
1591. 1 let moduleName = htmlEscape(JSON.stringify(pathname));
+
1592. 1 let moduleObj = await import(pathname);
+
1593. 1 if (moduleObj.default) {
+
1594. 1 moduleObj = moduleObj.default;
+
1595. 1 }
+
1596. 1 return {
+
1597. 27 elem_list: Object.keys(moduleObj).map(function (key) {
+
1598. 27 return elem_create(moduleObj, key, moduleName);
+
1599. 78 }).sort(function (aa, bb) {
+
1600. 78 return (
+
1601. 78 aa.name < bb.name
+
1602. 22 ? -1
+
1603. 56 : 1
+
1604. 78 );
+
1605. 27 }).map(function (elem) {
+
1606. 27 elem_ii += 1;
+
1607. 27 elem.signature = elem.signature.replace(
+
1608. 27 ">",
+
1609. 27 ">" + elem_ii + ". "
+
1610. 27 );
+
1611. 27 elem.source = elem.source.replace(
+
1612. 27 "\">",
+
1613. 27 "\">" + elem_ii + ". "
+
1614. 27 );
+
1615. 27 return elem;
+
1616. 27 }),
+
1617. 1 id: encodeURIComponent("apidoc.module." + moduleName),
+
1618. 1 moduleName
+
1619. 1 };
+
1620. 1 }));
+
1621. 1 html = (`
+
1622. 1<!DOCTYPE html>
+
1623. 1<html lang="en">
+
1624. 1<head>
+
1625. 1<meta charset="utf-8">
+
1626. 1<meta name="viewport" content="width=device-width, initial-scale=1">
+
1627. 1<meta name="description" content="${package_name} API Doc">
+
1628. 1<title>${package_name} apidoc</title>
+
1629. 1<style>
+
1630. 1/* jslint utility2:true */
+
1631. 1/*csslint*/
+
1632. 1body {
+
1633. 1 margin: 0;
+
1634. 1 padding: 20px;
+
1635. 1}
+
1636. 1.apidocCodeCommentSpan,
+
1637. 1.apidocCodeKeywordSpan {
+
1638. 1 background: royalblue;
+
1639. 1 color: white;
+
1640. 1}
+
1641. 1.apidocCodeCommentSpan {
+
1642. 1 display: block;
+
1643. 1}
+
1644. 1.apidocCodePre {
+
1645. 1 background: #eef;
+
1646. 1 border: 1px solid;
+
1647. 1 font-size: 14px;
+
1648. 1 overflow-wrap: break-word;
+
1649. 1 padding: 5px;
+
1650. 1 white-space: pre-wrap;
+
1651. 1}
+
1652. 1.apidocDiv {
+
1653. 1 color: #555;
+
1654. 1 font-family: sans-serif;
+
1655. 1}
+
1656. 1.apidocDiv a[href] {
+
1657. 1 color: royalblue;
+
1658. 1 text-decoration: none;
+
1659. 1}
+
1660. 1.apidocDiv a[href]:hover {
+
1661. 1 text-decoration: underline;
+
1662. 1}
+
1663. 1.apidocDiv li a {
+
1664. 1 display: inline-block;
+
1665. 1 padding: 8px 0;
+
1666. 1}
+
1667. 1.apidocDiv ul {
+
1668. 1 list-style: none;
+
1669. 1 padding-left: 20px;
+
1670. 1}
+
1671. 1.apidocFooterDiv {
+
1672. 1 margin-top: 20px;
+
1673. 1 text-align: center;
+
1674. 1}
+
1675. 1.apidocModuleA {
+
1676. 1 font-size: 24px;
+
1677. 1 font-weight: bold;
+
1678. 1}
+
1679. 1.apidocSectionDiv {
+
1680. 1 border-top: 1px solid;
+
1681. 1 margin-top: 20px;
+
1682. 1}
+
1683. 1.apidocSignatureSpan {
+
1684. 1 color: #666;
+
1685. 1 white-space: pre-wrap;
+
1686. 1}
+
1687. 1</style>
+
1688. 1</head>
+
1689. 1<body>
+
1690. 1<div class="apidocDiv">
+
1691. 1<h1>API Doc for <a href="${github_repo}">${package_name} (${version})</a></h1>
+
1692. 1<div class="apidocSectionDiv">
+
1693. 1 <a href="#apidocTableOfContents1" id="apidocTableOfContents1">
+
1694. 1 <h1>Table of Contents</h1>
+
1695. 1 </a>
+
1696. 1 <ul>
+
1697. 1 `) + module_list.map(function ({
+
1698. 1 elem_list,
+
1699. 1 id,
+
1700. 1 moduleName
+
1701. 1 }) {
+
1702. 1 return (
+
1703. 1 (`
+
1704. 1 <li>
+
1705. 1 <a class="apidocModuleA" href="#${id}">Module ${moduleName}</a>
+
1706. 1 <ul>
+
1707. 1 `)
+
1708. 27 + elem_list.map(function ({
+
1709. 27 signature
+
1710. 27 }) {
+
1711. 27 return "<li>\n" + signature + "\n</li>\n";
+
1712. 27 }).join("")
+
1713. 1 + (`
+
1714. 1 </ul>
+
1715. 1 </li>
+
1716. 1 `)
+
1717. 1 );
+
1718. 1 }).join("") + (`
+
1719. 1 </ul>
+
1720. 1</div>
+
1721. 1 `) + module_list.map(function ({
+
1722. 1 elem_list,
+
1723. 1 id,
+
1724. 1 moduleName
+
1725. 1 }) {
+
1726. 1 return (
+
1727. 1 (`
+
1728. 1<div class="apidocSectionDiv">
+
1729. 1 <h1><a href="#${id}" id="${id}">Module ${moduleName}</a></h1>
+
1730. 1 <ul>
+
1731. 1 `)
+
1732. 27 + elem_list.map(function ({
+
1733. 27 source
+
1734. 27 }) {
+
1735. 27 return source;
+
1736. 27 }).join("")
+
1737. 1 + (`
+
1738. 1 </ul>
+
1739. 1</div>
+
1740. 1 `)
+
1741. 1 );
+
1742. 1 }).join("") + (`
+
1743. 1<div class="apidocFooterDiv">
+
1744. 1 [
+
1745. 1 This document was created with
+
1746. 1 <a href="https://github.com/jslint-org/jslint">JSLint</a>
+
1747. 1 ]
+
1748. 1</div>
+
1749. 1</div>
+
1750. 1</body>
+
1751. 1</html>
+
1752. 1 `);
+
1753. 1 html = html.trim().replace((
+
1754. 1 / +?$/gm
+
1755. 1 ), "") + "\n";
+
1756. 1 await fsWriteFileWithParents(pathname, html);
+
1757. 1}
+
1758. 1
+
1759. 102849function jslint_assert(condition, message) {
+
1760. 102849
+
1761. 102849// This function will throw <message> if <condition> is falsy.
+
1762. 102849
+
1763. 102847 if (condition) {
+
1764. 102847 return condition;
+
1765. 102847 }
+
1766. 2 throw new Error(
+
1767. 2 `This was caused by a bug in JSLint.
+
1768. 2Please open an issue with this stack-trace (and possible example-code) at
+
1769. 2https://github.com/jslint-org/jslint/issues.
+
1770. 2edition = "${jslint_edition}";
+
1771. 2${String(message).slice(0, 2000)}`
+
1772. 2 );
+
1773. 2}
+
1774. 1
+
1775. 38async function jslint_cli({
+
1776. 38 console_error,
+
1777. 38 console_log,
+
1778. 38 file,
+
1779. 38 import_meta_url,
+
1780. 38 mode_cli,
+
1781. 38 mode_noop,
+
1782. 38 option,
+
1783. 38 process_argv,
+
1784. 38 process_env,
+
1785. 38 process_exit,
+
1786. 38 source
+
1787. 38}) {
+
1788. 38
+
1789. 38// This function will run jslint from nodejs-cli.
+
1790. 38
+
1791. 38 let command;
+
1792. 38 let data;
+
1793. 38 let exit_code = 0;
+
1794. 38 let mode_report;
+
1795. 38 let mode_wrapper_vim;
+
1796. 38 let result;
+
1797. 38
+
1798. 51 function jslint_from_file({
+
1799. 51 code,
+
1800. 51 file,
+
1801. 51 line_offset = 0,
+
1802. 51 mode_conditional,
+
1803. 51 option = empty()
+
1804. 51 }) {
+
1805. 51 let result_from_file;
+
1806. 51 if (
+
1807. 51 mode_conditional
+
1808. 5 && !(
+
1809. 5 /^\/\*jslint\b/m
+
1810. 5 ).test(code.slice(0, 65536))
+
1811. 1 ) {
+
1812. 1 return;
+
1813. 50 }
+
1814. 50 option = Object.assign(empty(), option, {
+
1815. 50 file
+
1816. 50 });
+
1817. 50 switch ((
+
1818. 50 /\.\w+?$|$/m
+
1819. 50 ).exec(file)[0]) {
+
1820. 50 case ".html":
+
1821. 3
+
1822. 3// Recursively jslint embedded "<script>\n...\n</script>".
+
1823. 3
+
1824. 3 code.replace((
+
1825. 3 /^<script\b[^>]*?>\n([\S\s]*?\n)<\/script>$/gm
+
1826. 3 ), function (ignore, match1, ii) {
+
1827. 3 jslint_from_file({
+
1828. 3 code: match1,
+
1829. 3 file: file + ".<script>.js",
+
1830. 3 line_offset: string_line_count(code.slice(0, ii)) + 1,
+
1831. 3 option: Object.assign(empty(), {
+
1832. 3 browser: true
+
1833. 3 }, option)
+
1834. 3 });
+
1835. 3 return "";
+
1836. 3 });
+
1837. 3 return;
+
1838. 2 case ".md":
+
1839. 2
+
1840. 2// Recursively jslint embedded "node --eval '\n...\n'".
+
1841. 2
+
1842. 2 jslint_node_eval({
+
1843. 2 code,
+
1844. 2 file,
+
1845. 2 mode_conditional: true,
+
1846. 2 option
+
1847. 2 });
+
1848. 2 return;
+
1849. 2 case ".sh":
+
1850. 2
+
1851. 2// Recursively jslint embedded "node --eval '\n...\n'".
+
1852. 2
+
1853. 2 jslint_node_eval({
+
1854. 2 code,
+
1855. 2 file,
+
1856. 2 option
+
1857. 2 });
+
1858. 2 return;
+
1859. 43 default:
+
1860. 43 result_from_file = jslint("\n".repeat(line_offset) + code, option);
+
1861. 43 }
+
1862. 43
+
1863. 43// Print only first 10 warnings to stderr.
+
1864. 43
+
1865. 43 if (result_from_file.warnings.length > 0) {
+
1866. 5 exit_code = 1;
+
1867. 5 console_error(
+
1868. 5 mode_wrapper_vim
+
1869. 5
+
1870. 5// PR-349 - Print warnings in format readable by vim.
+
1871. 5
+
1872. 5 ? result_from_file.warnings.slice(0, 10).map(function ({
+
1873. 5 column,
+
1874. 5 line,
+
1875. 5 message
+
1876. 5 }, ii) {
+
1877. 5 return (
+
1878. 5 file
+
1879. 5 + ":" + ii
+
1880. 5 + ":" + line
+
1881. 5 + ":" + column
+
1882. 5 + ":" + message
+
1883. 5 );
+
1884. 5 }).join("\n")
+
1885. 5
+
1886. 5// Print warnings in format readable by human.
+
1887. 5
+
1888. 5 : "\u001b[1mjslint " + file + "\u001b[22m\n"
+
1889. 11 + result_from_file.warnings.slice(0, 10).map(function ({
+
1890. 11 formatted_message
+
1891. 11 }) {
+
1892. 11 return formatted_message;
+
1893. 11 }).join("\n")
+
1894. 5 );
+
1895. 43 }
+
1896. 43 return result_from_file;
+
1897. 43 }
+
1898. 38
+
1899. 4 function jslint_node_eval({
+
1900. 4 code,
+
1901. 4 file,
+
1902. 4 mode_conditional,
+
1903. 4 option = empty()
+
1904. 4 }) {
+
1905. 4 code.replace((
+
1906. 4 /\bnode\b.*? (?:--eval|-e) '\n([\S\s]*?\n)'/gm
+
1907. 26 ), function (ignore, match1, ii) {
+
1908. 26 jslint_from_file({
+
1909. 26 code: match1,
+
1910. 26 file: file + ".<node -e>.js",
+
1911. 26 line_offset: string_line_count(code.slice(0, ii)) + 1,
+
1912. 26 mode_conditional,
+
1913. 26 option: Object.assign(empty(), {
+
1914. 26 beta: Boolean(
+
1915. 26 process_env.JSLINT_BETA
+
1916. 26 && !(
+
1917. 26 /0|false|null|undefined/
+
1918. 26 ).test(process_env.JSLINT_BETA)
+
1919. 26 ),
+
1920. 26 node: true
+
1921. 26 }, option)
+
1922. 26 });
+
1923. 26 return "";
+
1924. 26 });
+
1925. 4 }
+
1926. 38
+
1927. 28 function string_line_count(code) {
+
1928. 28
+
1929. 28// This function will count number of newlines in <code>.
+
1930. 28
+
1931. 28 let count;
+
1932. 28 let ii;
+
1933. 28
+
1934. 28// https://jsperf.com/regexp-counting-2/8
+
1935. 28
+
1936. 28 count = 0;
+
1937. 28 ii = 0;
+
1938. 23104 while (true) {
+
1939. 23104 ii = code.indexOf("\n", ii) + 1;
+
1940. 23104 if (ii === 0) {
+
1941. 23104 break;
+
1942. 23104 }
+
1943. 23104 count += 1;
+
1944. 23104 }
+
1945. 28 return count;
+
1946. 28 }
+
1947. 38
+
1948. 38// PR-396 - window.jslint
+
1949. 38// Check import.meta.url for directive to export jslint to window-object.
+
1950. 38// Useful for ES5-era browser-scripts that rely on window.jslint,
+
1951. 38// like CodeMirror.
+
1952. 38//
+
1953. 38// Example usage:
+
1954. 38// <script type="module" src="./jslint.mjs?window_jslint=1"></script>
+
1955. 38
+
1956. 22 import_meta_url = import_meta_url || jslint_import_meta_url;
+
1957. 38 if (
+
1958. 38 jslint_rgx_url_search_window_jslint.test(import_meta_url)
+
1959. 4 && (typeof globalThis === "object" && globalThis)
+
1960. 4 ) {
+
1961. 4 globalThis.jslint = jslint;
+
1962. 4 }
+
1963. 38
+
1964. 38// Feature-detect nodejs.
+
1965. 38
+
1966. 38 if (!(
+
1967. 38 (typeof process === "object" && process)
+
1968. 38 && process.versions
+
1969. 38 && typeof process.versions.node === "string"
+
1970. 38 && !mode_noop
+
1971. 1 )) {
+
1972. 1 return exit_code;
+
1973. 37 }
+
1974. 37 console_error = console_error || console.error;
+
1975. 37 console_log = console_log || console.log;
+
1976. 22 process_argv = process_argv || process.argv;
+
1977. 34 process_env = process_env || process.env;
+
1978. 24 process_exit = process_exit || process.exit;
+
1979. 37 await moduleFsInit();
+
1980. 37 if (
+
1981. 37 !(
+
1982. 37
+
1983. 37// Feature-detect nodejs-cli.
+
1984. 37
+
1985. 37 process.execArgv.indexOf("--eval") === -1
+
1986. 37 && process.execArgv.indexOf("-e") === -1
+
1987. 37 && (
+
1988. 37 (
+
1989. 37 /[\/|\\]jslint(?:\.[cm]?js)?$/m
+
1990. 37 ).test(process_argv[1])
+
1991. 37 || mode_cli
+
1992. 37 )
+
1993. 20 && (
+
1994. 20 moduleUrl.fileURLToPath(import_meta_url)
+
1995. 20 ===
+
1996. 20 modulePath.resolve(process_argv[1])
+
1997. 20 )
+
1998. 38 )
+
1999. 22 && !mode_cli
+
2000. 17 ) {
+
2001. 17 return exit_code;
+
2002. 20 }
+
2003. 20
+
2004. 20// init commmand
+
2005. 20
+
2006. 20 command = String(process_argv[2]).split("=");
+
2007. 20 command[1] = command.slice(1).join("=");
+
2008. 20
+
2009. 20 switch (command[0]) {
+
2010. 20
+
2011. 20// PR-362 - Add API Doc.
+
2012. 20
+
2013. 20 case "jslint_apidoc":
+
2014. 1 await jslint_apidoc(Object.assign(JSON.parse(process_argv[3]), {
+
2015. 1 pathname: command[1]
+
2016. 1 }));
+
2017. 1 return;
+
2018. 38
+
2019. 38// PR-363 - Add command jslint_report.
+
2020. 38
+
2021. 6 case "jslint_report":
+
2022. 6 mode_report = command[1];
+
2023. 6 process_argv = process_argv.slice(1);
+
2024. 6 break;
+
2025. 38
+
2026. 38// COMMIT-b26d6df2 - Add command jslint_wrapper_vim.
+
2027. 38
+
2028. 1 case "jslint_wrapper_vim":
+
2029. 1 mode_wrapper_vim = true;
+
2030. 1 process_argv = process_argv.slice(1);
+
2031. 1 break;
+
2032. 38
+
2033. 38// PR-364 - Add command v8_coverage_report.
+
2034. 38
+
2035. 7 case "v8_coverage_report":
+
2036. 7 await v8CoverageReportCreate({
+
2037. 7 consoleError: console_error,
+
2038. 7 coverageDir: command[1],
+
2039. 7 processArgv: process_argv.slice(3)
+
2040. 7 });
+
2041. 7 return;
+
2042. 12 }
+
2043. 12
+
2044. 12// Normalize file relative to process.cwd().
+
2045. 12
+
2046. 12 process_argv.slice(2).some(function (arg) {
+
2047. 12 if (!arg.startsWith("-")) {
+
2048. 12 file = file || arg;
+
2049. 12 return true;
+
2050. 12 }
+
2051. 12 });
+
2052. 12 if (!file) {
+
2053. 1 return;
+
2054. 11 }
+
2055. 11 file = modulePath.resolve(file) + "/";
+
2056. 11 if (file.startsWith(process.cwd() + "/")) {
+
2057. 11 file = file.replace(process.cwd() + "/", "").slice(0, -1) || ".";
+
2058. 11 }
+
2059. 11 file = file.replace((
+
2060. 11 /\\/g
+
2061. 11 ), "/").replace((
+
2062. 11 /\/$/g
+
2063. 11 ), "");
+
2064. 11 if (source) {
+
2065. 7 data = source;
+
2066. 7 } else {
+
2067. 4
+
2068. 4// jslint_cli - jslint directory.
+
2069. 4
+
2070. 4 try {
+
2071. 4 data = await moduleFs.promises.readdir(file, "utf8");
+
2072. 4 } catch (ignore) {}
+
2073. 4 if (data) {
+
2074. 34 await Promise.all(data.map(async function (file2) {
+
2075. 34 let code;
+
2076. 34 let time_start = Date.now();
+
2077. 34 file2 = file + "/" + file2;
+
2078. 34 switch ((
+
2079. 34 /\.\w+?$|$/m
+
2080. 34 ).exec(file2)[0]) {
+
2081. 4 case ".cjs":
+
2082. 5 case ".html":
+
2083. 8 case ".js":
+
2084. 10 case ".json":
+
2085. 12 case ".md":
+
2086. 14 case ".mjs":
+
2087. 16 case ".sh":
+
2088. 16 break;
+
2089. 18 default:
+
2090. 18 return;
+
2091. 16 }
+
2092. 16 try {
+
2093. 16 code = await moduleFs.promises.readFile(file2, "utf8");
+
2094. 15 } catch (ignore) {
+
2095. 4 return;
+
2096. 15 }
+
2097. 15 if (
+
2098. 15 (
+
2099. 15 /(?:\b|_)(?:lock|min|raw|rollup)(?:\b|_)/
+
2100. 15 ).test(file2)
+
2101. 15 || !(code && code.length < 1048576)
+
2102. 4 ) {
+
2103. 4 return;
+
2104. 14 }
+
2105. 14 jslint_from_file({
+
2106. 14 code,
+
2107. 14 file: file2,
+
2108. 14 option
+
2109. 14 });
+
2110. 14 console_error(
+
2111. 14 "jslint - " + (Date.now() - time_start) + "ms - " + file2
+
2112. 14 );
+
2113. 14 }));
+
2114. 4 process_exit(exit_code);
+
2115. 4 return exit_code;
+
2116. 4 }
+
2117. 4
+
2118. 4// jslint_cli - jslint file.
+
2119. 4
+
2120. 4 try {
+
2121. 4 data = await moduleFs.promises.readFile(file, "utf8");
+
2122. 4 } catch (err) {
+
2123. 4 console_error(err);
+
2124. 4 exit_code = 1;
+
2125. 4 process_exit(exit_code);
+
2126. 4 return exit_code;
+
2127. 4 }
+
2128. 9 }
+
2129. 9 result = jslint_from_file({
+
2130. 9 code: data,
+
2131. 9 file,
+
2132. 9 option
+
2133. 9 });
+
2134. 9 if (mode_report) {
+
2135. 6 result = jslint.jslint_report(result);
+
2136. 6 result = `<body class="JSLINT_ JSLINT_REPORT_">\n${result}</body>\n`;
+
2137. 6 await fsWriteFileWithParents(mode_report, result);
+
2138. 9 }
+
2139. 9 process_exit(exit_code);
+
2140. 9 return exit_code;
+
2141. 9}
+
2142. 1
+
2143. 668function jslint_phase1_split() {
+
2144. 668
+
2145. 668// PHASE 1. Split <source> by newlines into <line_list>.
+
2146. 668
+
2147. 668 return;
+
2148. 668}
+
2149. 1
+
2150. 668function jslint_phase2_lex(state) {
+
2151. 668
+
2152. 668// PHASE 2. Lex <line_list> into <token_list>.
+
2153. 668
+
2154. 668 let {
+
2155. 668 artifact,
+
2156. 668 directive_list,
+
2157. 668 global_dict,
+
2158. 668 global_list,
+
2159. 668 line_list,
+
2160. 668 option_dict,
+
2161. 668 stop,
+
2162. 668 stop_at,
+
2163. 668 tenure,
+
2164. 668 test_cause,
+
2165. 668 token_global,
+
2166. 668 token_list,
+
2167. 668 warn,
+
2168. 668 warn_at
+
2169. 668 } = state;
+
2170. 668 let char; // The current character being lexed.
+
2171. 668 let column = 0; // The column number of the next character.
+
2172. 668 let from; // The starting column number of the token.
+
2173. 668 let from_mega; // The starting column of megastring.
+
2174. 668 let line = 0; // The line number of the next character.
+
2175. 668 let line_disable; // The starting line of "/*jslint-disable*/".
+
2176. 668 let line_mega; // The starting line of megastring.
+
2177. 668 let line_source = ""; // The remaining line source string.
+
2178. 668 let line_whole = ""; // The whole line source string.
+
2179. 668 let mode_digits_empty_string = 1;
+
2180. 668 let mode_digits_numeric_separator = 2;
+
2181. 668 let mode_directive = true; // true if directives are still allowed.
+
2182. 668 let mode_mega = false; // true if currently parsing a megastring
+
2183. 668 // ... literal.
+
2184. 668 let mode_regexp; // true if regular expression literal seen on
+
2185. 668 // ... this line.
+
2186. 668 let paren_backtrack_list = []; // List of most recent "(" tokens at any
+
2187. 668 // ... paren-depth.
+
2188. 668 let paren_depth = 0; // Keeps track of current paren-depth.
+
2189. 668 let snippet = ""; // A piece of string.
+
2190. 668 let token_1; // The first token.
+
2191. 668 let token_prv = token_global; // The previous token including
+
2192. 668 // ... comments.
+
2193. 668 let token_prv_expr = token_global; // The previous token excluding
+
2194. 668 // ... comments.
+
2195. 668
+
2196. 668// Most tokens, including the identifiers, operators, and punctuators, can be
+
2197. 668// found with a regular expression. Regular expressions cannot correctly match
+
2198. 668// regular expression literals, so we will match those the hard way. String
+
2199. 668// literals and number literals can be matched by regular expressions, but they
+
2200. 668// don't provide good warnings. The functions char_after, char_before,
+
2201. 668// read_digits, and char_after_escape help in the parsing of literals.
+
2202. 668
+
2203. 238213 function char_after(match) {
+
2204. 238213
+
2205. 238213// Get the next character from the source line. Remove it from the line_source,
+
2206. 238213// and append it to the snippet. Optionally check that the previous character
+
2207. 238213// matched an expected value.
+
2208. 238213
+
2209. 5986 if (match !== undefined && char !== match) {
+
2210. 10
+
2211. 10// test_cause:
+
2212. 10// ["aa=/[", "char_after", "expected_a", "]", 5]
+
2213. 10// ["aa=/aa{/", "char_after", "expected_a_b", "/", 8]
+
2214. 10
+
2215. 10 return (
+
2216. 10 char === ""
+
2217. 10 ? stop_at("expected_a", line, column - 1, match)
+
2218. 10 : stop_at("expected_a_b", line, column, match, char)
+
2219. 10 );
+
2220. 238203 }
+
2221. 238203 char = line_source.slice(0, 1);
+
2222. 238203 line_source = line_source.slice(1);
+
2223. 238203 snippet += char || " ";
+
2224. 238213 column += 1;
+
2225. 238213 return char;
+
2226. 238213 }
+
2227. 668
+
2228. 2953 function char_after_escape(extra) {
+
2229. 2953
+
2230. 2953// Validate char after escape "\\".
+
2231. 2953
+
2232. 2953 char_after("\\");
+
2233. 2953 switch (char) {
+
2234. 1 case "":
+
2235. 1
+
2236. 1// test_cause:
+
2237. 1// ["\"\\", "char_after_escape", "unclosed_string", "", 2]
+
2238. 1
+
2239. 1 return stop_at("unclosed_string", line, column);
+
2240. 219 case "/":
+
2241. 219 return char_after();
+
2242. 355 case "\\":
+
2243. 355 return char_after();
+
2244. 1 case "`":
+
2245. 1 return char_after();
+
2246. 62 case "b":
+
2247. 62 return char_after();
+
2248. 6 case "f":
+
2249. 6 return char_after();
+
2250. 1015 case "n":
+
2251. 1015 return char_after();
+
2252. 32 case "r":
+
2253. 32 return char_after();
+
2254. 24 case "t":
+
2255. 24
+
2256. 24// test_cause:
+
2257. 24// ["\"\\/\\\\\\`\\b\\f\\n\\r\\t\"", "char_after_escape", "char_after", "", 0]
+
2258. 24
+
2259. 24 test_cause("char_after");
+
2260. 24 return char_after();
+
2261. 376 case "u":
+
2262. 376 if (char_after("u") === "{") {
+
2263. 376 if (state.mode_json) {
+
2264. 376
+
2265. 376// test_cause:
+
2266. 376// ["[\"\\u{12345}\"]", "char_after_escape", "unexpected_a", "{", 5]
+
2267. 376
+
2268. 376 warn_at("unexpected_a", line, column, char);
+
2269. 376 }
+
2270. 376 if (read_digits("x", undefined) > 5) {
+
2271. 376
+
2272. 376// test_cause:
+
2273. 376// ["\"\\u{123456}\"", "char_after_escape", "too_many_digits", "", 11]
+
2274. 376
+
2275. 376 warn_at("too_many_digits", line, column);
+
2276. 376 }
+
2277. 376 if (char !== "}") {
+
2278. 376
+
2279. 376// test_cause:
+
2280. 376// ["\"\\u{12345\"", "char_after_escape", "expected_a_before_b", "\"", 10]
+
2281. 376
+
2282. 376 stop_at("expected_a_before_b", line, column, "}", char);
+
2283. 376 }
+
2284. 376 return char_after();
+
2285. 376 }
+
2286. 376 char_before();
+
2287. 376 if (read_digits("x", mode_digits_empty_string) < 4) {
+
2288. 376
+
2289. 376// test_cause:
+
2290. 376// ["\"\\u0\"", "char_after_escape", "expected_four_digits", "", 5]
+
2291. 376
+
2292. 376 warn_at("expected_four_digits", line, column);
+
2293. 376 }
+
2294. 376 return;
+
2295. 862 default:
+
2296. 862 if (extra && extra.indexOf(char) >= 0) {
+
2297. 862 return char_after();
+
2298. 862 }
+
2299. 862
+
2300. 862// test_cause:
+
2301. 862// ["\"\\0\"", "char_after_escape", "unexpected_a_before_b", "0", 3]
+
2302. 862
+
2303. 862 warn_at("unexpected_a_before_b", line, column, "\\", char);
+
2304. 2953 }
+
2305. 2953 }
+
2306. 668
+
2307. 10013 function char_before() {
+
2308. 10013
+
2309. 10013// Back up one character by moving a character from the end of the snippet to
+
2310. 10013// the front of the line_source.
+
2311. 10013
+
2312. 10013 char = snippet.slice(-1);
+
2313. 10013 line_source = char + line_source;
+
2314. 10013 column -= char.length;
+
2315. 10013
+
2316. 10013// Remove last character from snippet.
+
2317. 10013
+
2318. 10013 snippet = snippet.slice(0, -1);
+
2319. 10013 return char;
+
2320. 10013 }
+
2321. 668
+
2322. 8924 function check_numeric_separator(digits, column) {
+
2323. 8924
+
2324. 8924// This function will check for illegal numeric-separator in <digits>.
+
2325. 8924
+
2326. 8924 digits.replace((
+
2327. 8924 jslint_rgx_numeric_separator_illegal
+
2328. 6 ), function (ignore, ii) {
+
2329. 6
+
2330. 6// test_cause:
+
2331. 6// ["0x0_0_;", "check_numeric_separator", "illegal_num_separator", "", 6]
+
2332. 6// ["0x0_0__0;", "check_numeric_separator", "illegal_num_separator", "", 6]
+
2333. 6// ["aa=1_2_;", "check_numeric_separator", "illegal_num_separator", "", 7]
+
2334. 6// ["aa=1_2__3;", "check_numeric_separator", "illegal_num_separator", "", 7]
+
2335. 6// ["aa=1_2_n;", "check_numeric_separator", "illegal_num_separator", "", 7]
+
2336. 6
+
2337. 6 warn_at("illegal_num_separator", line, column + ii + 1);
+
2338. 6 return "";
+
2339. 6 });
+
2340. 8924 }
+
2341. 668
+
2342. 11221 function lex_comment() {
+
2343. 11221 let body;
+
2344. 11221 let ii = 0;
+
2345. 11221 let jj = 0;
+
2346. 11221 let the_comment;
+
2347. 11221
+
2348. 11221// Create a comment object. Comments are not allowed in JSON text. Comments can
+
2349. 11221// include directives and notices of incompletion.
+
2350. 11221
+
2351. 11221// Create token from comment //....
+
2352. 11221
+
2353. 11107 if (snippet === "//") {
+
2354. 11107 snippet = line_source;
+
2355. 11107 line_source = "";
+
2356. 11107 the_comment = token_create("(comment)", snippet);
+
2357. 11107 if (mode_mega) {
+
2358. 11107
+
2359. 11107// test_cause:
+
2360. 11107// ["`${//}`", "lex_comment", "unexpected_comment", "`", 4]
+
2361. 11107
+
2362. 11107 warn("unexpected_comment", the_comment, "`");
+
2363. 11107 }
+
2364. 11107
+
2365. 11107// Create token from comment /*...*/.
+
2366. 11107
+
2367. 11107 } else {
+
2368. 114 snippet = [];
+
2369. 114 if (line_source[0] === "/") {
+
2370. 114
+
2371. 114// test_cause:
+
2372. 114// ["/*/", "lex_comment", "unexpected_a", "/", 2]
+
2373. 114
+
2374. 114 warn_at("unexpected_a", line, column + ii, "/");
+
2375. 114 }
+
2376. 114
+
2377. 114// Lex/loop through each line until "*/".
+
2378. 114
+
2379. 696 while (true) {
+
2380. 696 // jslint_rgx_star_slash
+
2381. 696 ii = line_source.indexOf("*/");
+
2382. 696 if (ii >= 0) {
+
2383. 696 break;
+
2384. 696 }
+
2385. 696 // jslint_rgx_slash_star
+
2386. 696 ii = line_source.indexOf("/*");
+
2387. 696 if (ii >= 0) {
+
2388. 696
+
2389. 696// test_cause:
+
2390. 696// ["/*/*", "lex_comment", "nested_comment", "", 2]
+
2391. 696
+
2392. 696 warn_at("nested_comment", line, column + ii);
+
2393. 696 }
+
2394. 696 snippet.push(line_source);
+
2395. 696 line_source = read_line();
+
2396. 696 if (line_source === undefined) {
+
2397. 696
+
2398. 696// test_cause:
+
2399. 696// ["/*", "lex_comment", "unclosed_comment", "", 1]
+
2400. 696
+
2401. 696 return stop_at("unclosed_comment", line, column);
+
2402. 696 }
+
2403. 696 }
+
2404. 114 jj = line_source.slice(0, ii).search(
+
2405. 114 jslint_rgx_slash_star_or_slash
+
2406. 114 );
+
2407. 114 if (jj >= 0) {
+
2408. 114
+
2409. 114// test_cause:
+
2410. 114// ["/*/**/", "lex_comment", "nested_comment", "", 2]
+
2411. 114
+
2412. 114 warn_at("nested_comment", line, column + jj);
+
2413. 114 }
+
2414. 114 snippet.push(line_source.slice(0, ii));
+
2415. 114 snippet = snippet.join(" ");
+
2416. 114 column += ii + 2;
+
2417. 114 line_source = line_source.slice(ii + 2);
+
2418. 114 the_comment = token_create("(comment)", snippet);
+
2419. 11218 }
+
2420. 11218
+
2421. 11218// Uncompleted work comment.
+
2422. 11218
+
2423. 11218 if (!option_dict.devel && jslint_rgx_todo.test(snippet)) {
+
2424. 16
+
2425. 16// test_cause:
+
2426. 16// ["//todo", "lex_comment", "todo_comment", "(comment)", 1] //jslint-ignore-line
+
2427. 16
+
2428. 16 warn("todo_comment", the_comment);
+
2429. 11218 }
+
2430. 11218
+
2431. 11218// Lex directives in comment.
+
2432. 11218
+
2433. 11218 [
+
2434. 11218 the_comment.directive, body
+
2435. 11218 ] = Array.from(snippet.match(jslint_rgx_directive) || []).slice(1);
+
2436. 11141 if (the_comment.directive === undefined) {
+
2437. 11141 return the_comment;
+
2438. 11141 }
+
2439. 77 directive_list.push(the_comment);
+
2440. 77 if (!mode_directive) {
+
2441. 1
+
2442. 1// test_cause:
+
2443. 1// ["0\n/*global aa*/", "lex_comment", "misplaced_directive_a", "global", 1]
+
2444. 1
+
2445. 1 warn_at("misplaced_directive_a", line, from, the_comment.directive);
+
2446. 1 return the_comment;
+
2447. 76 }
+
2448. 76
+
2449. 76// lex_directive();
+
2450. 76// JSLint recognizes three directives that can be encoded in comments. This
+
2451. 76// function processes one item, and calls itself recursively to process the
+
2452. 76// next one.
+
2453. 76
+
2454. 76// Lex/loop through each directive in /*...*/
+
2455. 76
+
2456. 76 ii = 0;
+
2457. 1835 body.replace(jslint_rgx_directive_part, function (
+
2458. 1835 match0,
+
2459. 1835 key,
+
2460. 1835 val,
+
2461. 1835 jj
+
2462. 1835 ) {
+
2463. 76 if (ii !== jj) {
+
2464. 76
+
2465. 76// test_cause:
+
2466. 76// ["/*jslint !*/", "lex_comment", "bad_directive_a", "!", 1]
+
2467. 76
+
2468. 76 return stop("bad_directive_a", the_comment, body.slice(ii));
+
2469. 1834 }
+
2470. 1834 if (match0 === "") {
+
2471. 76 return "";
+
2472. 1759 }
+
2473. 1759 ii += match0.length;
+
2474. 1759 switch (the_comment.directive) {
+
2475. 1759 case "global":
+
2476. 76 if (val) {
+
2477. 76
+
2478. 76// test_cause:
+
2479. 76// ["/*global aa:false*/", "lex_comment", "bad_option_a", "aa:false", 1]
+
2480. 76
+
2481. 76 warn("bad_option_a", the_comment, key + ":" + val);
+
2482. 76 }
+
2483. 76 global_dict[key] = "user-defined";
+
2484. 76
+
2485. 76// PR-347 - Disable warning "unexpected_directive_a".
+
2486. 76//
+
2487. 76// state.mode_module = the_comment;
+
2488. 76
+
2489. 76 break;
+
2490. 99 case "jslint":
+
2491. 99 if (!option_set_item(key, val !== "false")) {
+
2492. 99
+
2493. 99// test_cause:
+
2494. 99// ["/*jslint undefined*/", "lex_comment", "bad_option_a", "undefined", 1]
+
2495. 99
+
2496. 99 warn("bad_option_a", the_comment, key);
+
2497. 99 }
+
2498. 99 break;
+
2499. 1651 case "property":
+
2500. 1651 state.mode_property = true;
+
2501. 1651 tenure[key] = true;
+
2502. 1651 break;
+
2503. 1759 }
+
2504. 1759 return "";
+
2505. 1759 });
+
2506. 76 return the_comment;
+
2507. 76 }
+
2508. 668
+
2509. 789 function lex_megastring() {
+
2510. 789 let id;
+
2511. 789 let match;
+
2512. 789
+
2513. 789// The token is a megastring. We don't allow any kind of mega nesting.
+
2514. 789
+
2515. 1 if (mode_mega) {
+
2516. 1
+
2517. 1// test_cause:
+
2518. 1// ["`${`", "lex_megastring", "expected_a_b", "`", 4]
+
2519. 1
+
2520. 1 return stop_at("expected_a_b", line, column, "}", "`");
+
2521. 788 }
+
2522. 788 from_mega = from;
+
2523. 788 line_mega = line;
+
2524. 788 mode_mega = true;
+
2525. 788 snippet = "";
+
2526. 788
+
2527. 788// Parsing a mega literal is tricky. First create a ` token.
+
2528. 788
+
2529. 788 token_create("`");
+
2530. 788 from += 1;
+
2531. 788
+
2532. 788// Then loop, building up a string, possibly from many lines, until seeing
+
2533. 788// the end of file, a closing `, or a ${ indicting an expression within the
+
2534. 788// string.
+
2535. 788
+
2536. 5963 while (true) {
+
2537. 5963 match = line_source.match(jslint_rgx_mega) || {
+
2538. 5963 "0": "",
+
2539. 5963 index: 0
+
2540. 5963 };
+
2541. 5963 snippet += line_source.slice(0, match.index);
+
2542. 5963 column += match.index;
+
2543. 5963 line_source = line_source.slice(match.index);
+
2544. 5963 match = match[0];
+
2545. 5963 switch (match) {
+
2546. 5963 case "${":
+
2547. 5963
+
2548. 5963// if either ` or ${ was found, then the preceding joins the snippet to become
+
2549. 5963// a string token.
+
2550. 5963
+
2551. 5963 token_create("(string)", snippet).quote = "`";
+
2552. 5963 snippet = "";
+
2553. 5963
+
2554. 5963// If ${, then create tokens that will become part of an expression until
+
2555. 5963// a } token is made.
+
2556. 5963
+
2557. 5963 column += 2;
+
2558. 5963 token_create("${");
+
2559. 5963 line_source = line_source.slice(2);
+
2560. 5963
+
2561. 5963// Lex/loop through each token inside megastring-expression `${...}`.
+
2562. 5963
+
2563. 5963 while (true) {
+
2564. 5963 id = lex_token().id;
+
2565. 5963 if (id === "{") {
+
2566. 5963
+
2567. 5963// test_cause:
+
2568. 5963// ["`${{", "lex_megastring", "expected_a_b", "{", 4]
+
2569. 5963
+
2570. 5963 return stop_at("expected_a_b", line, column, "}", "{");
+
2571. 5963 }
+
2572. 5963 if (id === "}") {
+
2573. 5963 break;
+
2574. 5963 }
+
2575. 5963 }
+
2576. 5963 break;
+
2577. 5963 case "\\":
+
2578. 5963 snippet += line_source.slice(0, 2);
+
2579. 5963 line_source = line_source.slice(2);
+
2580. 5963 column += 2;
+
2581. 5963 break;
+
2582. 5963 case "`":
+
2583. 5963
+
2584. 5963// if either ` or ${ was found, then the preceding joins the snippet to become
+
2585. 5963// a string token.
+
2586. 5963
+
2587. 5963 token_create("(string)", snippet).quote = "`";
+
2588. 5963 snippet = "";
+
2589. 5963
+
2590. 5963// Terminate megastring with `.
+
2591. 5963
+
2592. 5963 line_source = line_source.slice(1);
+
2593. 5963 column += 1;
+
2594. 5963 mode_mega = false;
+
2595. 5963 return token_create("`");
+
2596. 5963 default:
+
2597. 5963
+
2598. 5963// If neither ` nor ${ is seen, then the whole line joins the snippet.
+
2599. 5963
+
2600. 5963 snippet += line_source + "\n";
+
2601. 5963 if (read_line() === undefined) {
+
2602. 5963
+
2603. 5963// test_cause:
+
2604. 5963// ["`", "lex_megastring", "unclosed_mega", "", 1]
+
2605. 5963
+
2606. 5963 return stop_at("unclosed_mega", line_mega, from_mega);
+
2607. 5963 }
+
2608. 5963 }
+
2609. 5963 }
+
2610. 789 }
+
2611. 668
+
2612. 8851 function lex_number() {
+
2613. 8851 let prefix = snippet;
+
2614. 8851
+
2615. 8851// PR-390 - Add numeric-separator check.
+
2616. 8851
+
2617. 8851 check_numeric_separator(prefix, column - prefix.length);
+
2618. 8851 char_after();
+
2619. 2880 switch (prefix === "0" && char) {
+
2620. 3 case "b":
+
2621. 6 case "o":
+
2622. 33 case "x":
+
2623. 33 read_digits(char, mode_digits_numeric_separator);
+
2624. 33
+
2625. 33// PR-351 - Ignore BigInt suffix 'n'.
+
2626. 33
+
2627. 33 if (char === "n") {
+
2628. 33 char_after("n");
+
2629. 33 }
+
2630. 33 break;
+
2631. 8818 default:
+
2632. 8818 if (char === ".") {
+
2633. 8818 read_digits("d", mode_digits_numeric_separator);
+
2634. 8818 }
+
2635. 8818 if (char === "E" || char === "e") {
+
2636. 8818 char_after(char);
+
2637. 8818 if (char !== "+" && char !== "-") {
+
2638. 8818 char_before();
+
2639. 8818 }
+
2640. 8818 read_digits("d", mode_digits_numeric_separator);
+
2641. 8818 }
+
2642. 8851 }
+
2643. 8851
+
2644. 8851// If the next character after a number is a digit or letter, then something
+
2645. 8851// unexpected is going on.
+
2646. 8851
+
2647. 8851 if (
+
2648. 1567 (char >= "0" && char <= "9")
+
2649. 44 || (char >= "a" && char <= "z")
+
2650. 8850 || (char >= "A" && char <= "Z")
+
2651. 1 ) {
+
2652. 1
+
2653. 1// test_cause:
+
2654. 1// ["0a", "lex_number", "unexpected_a_after_b", "0", 2]
+
2655. 1
+
2656. 1 return stop_at(
+
2657. 1 "unexpected_a_after_b",
+
2658. 1 line,
+
2659. 1 column,
+
2660. 1 snippet.slice(-1),
+
2661. 1 snippet.slice(0, -1)
+
2662. 1 );
+
2663. 8850 }
+
2664. 8850 char_before();
+
2665. 8850 return token_create("(number)", snippet);
+
2666. 8850 }
+
2667. 668
+
2668. 583 function lex_regexp() {
+
2669. 583
+
2670. 583// Regexp
+
2671. 583// Lex a regular expression literal.
+
2672. 583
+
2673. 583 let flag;
+
2674. 583 let mode_regexp_multiline;
+
2675. 583 let result;
+
2676. 583 let value;
+
2677. 583 mode_regexp = true;
+
2678. 583
+
2679. 209 function lex_regexp_bracketed() {
+
2680. 209 let mode_regexp_range;
+
2681. 209
+
2682. 209// RegExp
+
2683. 209// Match a class.
+
2684. 209
+
2685. 209 char_after("[");
+
2686. 35 if (char === "^") {
+
2687. 35 char_after("^");
+
2688. 35 }
+
2689. 902 while (true) {
+
2690. 902
+
2691. 902// RegExp
+
2692. 902// Match a character in a character class.
+
2693. 902
+
2694. 902 switch (char) {
+
2695. 902 case "":
+
2696. 902 case "]":
+
2697. 902
+
2698. 902// test_cause:
+
2699. 902// ["aa=/[", "lex_regexp_bracketed", "closer", "", 0]
+
2700. 902// ["aa=/[]/", "lex_regexp_bracketed", "closer", "", 0]
+
2701. 902
+
2702. 902 test_cause("closer");
+
2703. 902 if (mode_regexp_range) {
+
2704. 902
+
2705. 902// test_cause:
+
2706. 902// ["aa=/[0-]/", "lex_regexp_bracketed", "unexpected_a", "-", 7]
+
2707. 902
+
2708. 902 warn_at("unexpected_a", line, column - 1, "-");
+
2709. 902 }
+
2710. 902 return char_after("]");
+
2711. 902
+
2712. 902// PR-362 - Relax regexp-warning against using <space>.
+
2713. 902//
+
2714. 902// case " ":
+
2715. 902//
+
2716. 902// // test_cause:
+
2717. 902// // ["aa=/[ ]/", "lex_regexp_bracketed", "expected_a_b", " ", 6]
+
2718. 902//
+
2719. 902// warn_at("expected_a_b", line, column, "\\u0020", " ");
+
2720. 902// break;
+
2721. 902
+
2722. 902 case "-":
+
2723. 902 case "/":
+
2724. 902 case "[":
+
2725. 902 case "^":
+
2726. 902
+
2727. 902// test_cause:
+
2728. 902// ["aa=/[-]/", "lex_regexp_bracketed", "expected_a_before_b", "-", 6]
+
2729. 902// ["aa=/[.^]/", "lex_regexp_bracketed", "expected_a_before_b", "^", 7]
+
2730. 902// ["aa=/[/", "lex_regexp_bracketed", "expected_a_before_b", "/", 6]
+
2731. 902// ["aa=/[\\\\/]/", "lex_regexp_bracketed", "expected_a_before_b", "/", 8]
+
2732. 902// ["aa=/[\\\\[]/", "lex_regexp_bracketed", "expected_a_before_b", "[", 8]
+
2733. 902
+
2734. 902 warn_at("expected_a_before_b", line, column, "\\", char);
+
2735. 902 break;
+
2736. 902 case "\\":
+
2737. 902 char_after_escape("BbDdSsWw-[]^");
+
2738. 902 char_before();
+
2739. 902 break;
+
2740. 902 case "`":
+
2741. 902 if (mode_mega) {
+
2742. 902
+
2743. 902// test_cause:
+
2744. 902// ["`${/[`]/}`", "lex_regexp_bracketed", "unexpected_a", "`", 6]
+
2745. 902
+
2746. 902 warn_at("unexpected_a", line, column, "`");
+
2747. 902 }
+
2748. 902 break;
+
2749. 902 }
+
2750. 902 char_after();
+
2751. 902 mode_regexp_range = false;
+
2752. 902 if (char === "-") {
+
2753. 902
+
2754. 902// RegExp
+
2755. 902// Match a range of subclasses.
+
2756. 902
+
2757. 902 mode_regexp_range = true;
+
2758. 902 char_after("-");
+
2759. 902 }
+
2760. 902 }
+
2761. 209 }
+
2762. 583
+
2763. 794 function lex_regexp_group() {
+
2764. 794
+
2765. 794// RegExp
+
2766. 794// Lex sequence of characters in regexp.
+
2767. 794
+
2768. 794 switch (char) {
+
2769. 1 case "":
+
2770. 1 warn_at("expected_regexp_factor_a", line, column, char);
+
2771. 1 break;
+
2772. 1 case ")":
+
2773. 1 warn_at("expected_regexp_factor_a", line, column, char);
+
2774. 1 break;
+
2775. 1 case "]":
+
2776. 1
+
2777. 1// test_cause:
+
2778. 1// ["/ /", "lex_regexp_group", "expected_regexp_factor_a", "", 3]
+
2779. 1// ["aa=/)", "lex_regexp_group", "expected_regexp_factor_a", ")", 5]
+
2780. 1// ["aa=/]", "lex_regexp_group", "expected_regexp_factor_a", "]", 5]
+
2781. 1
+
2782. 1 warn_at("expected_regexp_factor_a", line, column, char);
+
2783. 1 break;
+
2784. 794 }
+
2785. 5592 while (true) {
+
2786. 5592 switch (char) {
+
2787. 5592 case "":
+
2788. 5592 case ")":
+
2789. 5592 case "/":
+
2790. 5592 case "]":
+
2791. 5592 return;
+
2792. 5592
+
2793. 5592// PR-362 - Relax regexp-warning against using <space>.
+
2794. 5592//
+
2795. 5592// case " ":
+
2796. 5592//
+
2797. 5592// // test_cause:
+
2798. 5592// // ["aa=/ /", "lex_regexp_group", "expected_a_b", " ", 5]
+
2799. 5592//
+
2800. 5592// warn_at("expected_a_b", line, column, "\\s", " ");
+
2801. 5592// char_after();
+
2802. 5592// break;
+
2803. 5592
+
2804. 5592 case "$":
+
2805. 5592 if (line_source[0] !== "/") {
+
2806. 5592 mode_regexp_multiline = true;
+
2807. 5592 }
+
2808. 5592 char_after();
+
2809. 5592 break;
+
2810. 5592 case "(":
+
2811. 5592
+
2812. 5592// RegExp
+
2813. 5592// Match a group that starts with left paren.
+
2814. 5592
+
2815. 5592 char_after("(");
+
2816. 5592 switch (char) {
+
2817. 5592 case ":":
+
2818. 5592
+
2819. 5592// test_cause:
+
2820. 5592// ["aa=/(:)/", "lex_regexp_group", "expected_a_before_b", ":", 6]
+
2821. 5592// ["aa=/?/", "lex_regexp_group", "expected_a_before_b", "?", 5]
+
2822. 5592
+
2823. 5592 warn_at("expected_a_before_b", line, column, "?", ":");
+
2824. 5592 break;
+
2825. 5592 case "?":
+
2826. 5592 char_after("?");
+
2827. 5592 switch (char) {
+
2828. 5592 case "!":
+
2829. 5592
+
2830. 5592// PR-437 - Add grammar for regexp-named-capture-group.
+
2831. 5592
+
2832. 5592 case "<":
+
2833. 5592 case "=":
+
2834. 5592 char_after();
+
2835. 5592 break;
+
2836. 5592 default:
+
2837. 5592 char_after(":");
+
2838. 5592 }
+
2839. 5592 break;
+
2840. 5592 }
+
2841. 5592
+
2842. 5592// RegExp
+
2843. 5592// Recurse lex_regexp_group().
+
2844. 5592
+
2845. 5592 lex_regexp_group();
+
2846. 5592 char_after(")");
+
2847. 5592 break;
+
2848. 5592 case "*":
+
2849. 5592 case "+":
+
2850. 5592 case "?":
+
2851. 5592 case "{":
+
2852. 5592 case "}":
+
2853. 5592
+
2854. 5592// test_cause:
+
2855. 5592// ["aa=/+/", "lex_regexp_group", "expected_a_before_b", "+", 5]
+
2856. 5592// ["aa=/.**/", "lex_regexp_group", "expected_a_before_b", "*", 7]
+
2857. 5592// ["aa=/?/", "lex_regexp_group", "expected_a_before_b", "?", 5]
+
2858. 5592// ["aa=/{/", "lex_regexp_group", "expected_a_before_b", "{", 5]
+
2859. 5592// ["aa=/}/", "lex_regexp_group", "expected_a_before_b", "}", 5]
+
2860. 5592
+
2861. 5592 warn_at("expected_a_before_b", line, column, "\\", char);
+
2862. 5592 char_after();
+
2863. 5592 break;
+
2864. 5592 case "[":
+
2865. 5592 lex_regexp_bracketed();
+
2866. 5592 break;
+
2867. 5592 case "\\":
+
2868. 5592
+
2869. 5592// test_cause:
+
2870. 5592// ["aa=/\\/", "lex_regexp_group", "escape", "", 0]
+
2871. 5592
+
2872. 5592 test_cause("escape");
+
2873. 5592
+
2874. 5592// PR-437 - Add grammar for regexp-named-backreference.
+
2875. 5592
+
2876. 5592 char_after_escape("BbDdSsWw^${}[]():=!.|*+?k");
+
2877. 5592 break;
+
2878. 5592 case "^":
+
2879. 5592 if (snippet !== "^") {
+
2880. 5592 mode_regexp_multiline = true;
+
2881. 5592 }
+
2882. 5592 char_after();
+
2883. 5592 break;
+
2884. 5592 case "`":
+
2885. 5592 if (mode_mega) {
+
2886. 5592
+
2887. 5592// test_cause:
+
2888. 5592// ["`${/`/}`", "lex_regexp_group", "unexpected_a", "`", 5]
+
2889. 5592
+
2890. 5592 warn_at("unexpected_a", line, column, "`");
+
2891. 5592 }
+
2892. 5592 char_after();
+
2893. 5592 break;
+
2894. 5592 default:
+
2895. 5592 char_after();
+
2896. 5592 }
+
2897. 5592
+
2898. 5592// RegExp
+
2899. 5592// Match an optional quantifier.
+
2900. 5592
+
2901. 5592 switch (char) {
+
2902. 5592 case "*":
+
2903. 5592 case "+":
+
2904. 5592 if (char_after(char) === "?") {
+
2905. 5592
+
2906. 5592// test_cause:
+
2907. 5592// ["aa=/.*?/", "lex_regexp_group", "?", "", 0]
+
2908. 5592// ["aa=/.+?/", "lex_regexp_group", "?", "", 0]
+
2909. 5592
+
2910. 5592 test_cause("?");
+
2911. 5592 char_after("?");
+
2912. 5592 }
+
2913. 5592 break;
+
2914. 5592 case "?":
+
2915. 5592 if (char_after("?") === "?") {
+
2916. 5592
+
2917. 5592// test_cause:
+
2918. 5592// ["aa=/.??/", "lex_regexp_group", "unexpected_a", "?", 7]
+
2919. 5592
+
2920. 5592 warn_at("unexpected_a", line, column, char);
+
2921. 5592 char_after("?");
+
2922. 5592 }
+
2923. 5592 break;
+
2924. 5592 case "{":
+
2925. 5592 if (read_digits("d", mode_digits_empty_string) === 0) {
+
2926. 5592
+
2927. 5592// test_cause:
+
2928. 5592// ["aa=/aa{/", "lex_regexp_group", "expected_a_before_b", ",", 8]
+
2929. 5592
+
2930. 5592 warn_at("expected_a_before_b", line, column, "0", ",");
+
2931. 5592 }
+
2932. 5592 if (char === ",") {
+
2933. 5592
+
2934. 5592// test_cause:
+
2935. 5592// ["aa=/.{,/", "lex_regexp_group", "comma", "", 0]
+
2936. 5592
+
2937. 5592 test_cause("comma");
+
2938. 5592 read_digits("d", mode_digits_empty_string);
+
2939. 5592 }
+
2940. 5592 if (char_after("}") === "?") {
+
2941. 5592
+
2942. 5592// test_cause:
+
2943. 5592// ["aa=/.{0}?/", "lex_regexp_group", "unexpected_a", "?", 9]
+
2944. 5592
+
2945. 5592 warn_at("unexpected_a", line, column, char);
+
2946. 5592 char_after("?");
+
2947. 5592 }
+
2948. 5592 break;
+
2949. 5592 }
+
2950. 5592 }
+
2951. 794 }
+
2952. 583
+
2953. 583// RegExp
+
2954. 583// Scan the regexp literal. Give a warning if the first character is = because
+
2955. 583// /= looks like a division assignment operator.
+
2956. 583
+
2957. 583 snippet = "";
+
2958. 583 char_after();
+
2959. 1 if (char === "=") {
+
2960. 1
+
2961. 1// test_cause:
+
2962. 1// ["aa=/=/", "lex_regexp", "expected_a_before_b", "=", 5]
+
2963. 1
+
2964. 1 warn_at("expected_a_before_b", line, column, "\\", "=");
+
2965. 1 }
+
2966. 583 lex_regexp_group();
+
2967. 583
+
2968. 583// RegExp
+
2969. 583// Remove last character from snippet.
+
2970. 583
+
2971. 583 snippet = snippet.slice(0, -1);
+
2972. 583
+
2973. 583// RegExp
+
2974. 583// Make sure there is a closing slash.
+
2975. 583
+
2976. 583 value = snippet;
+
2977. 583 char_after("/");
+
2978. 583
+
2979. 583// RegExp
+
2980. 583// Create flag.
+
2981. 583
+
2982. 583 flag = empty();
+
2983. 583 while (
+
2984. 583
+
2985. 583// Regexp
+
2986. 583// char is a letter.
+
2987. 583
+
2988. 512 (char >= "a" && char <= "z\uffff")
+
2989. 573 || (char >= "A" && char <= "Z\uffff")
+
2990. 510 ) {
+
2991. 510
+
2992. 510// RegExp
+
2993. 510// Process dangling flag letters.
+
2994. 510
+
2995. 510 switch (!flag[char] && char) {
+
2996. 510 case "g":
+
2997. 510 break;
+
2998. 510 case "i":
+
2999. 510 break;
+
3000. 510 case "m":
+
3001. 510 break;
+
3002. 510 case "u":
+
3003. 510 break;
+
3004. 510 case "y":
+
3005. 510
+
3006. 510// test_cause:
+
3007. 510// ["aa=/./gimuy", "lex_regexp", "flag", "", 0]
+
3008. 510
+
3009. 510 test_cause("flag");
+
3010. 510 break;
+
3011. 510 default:
+
3012. 510
+
3013. 510// test_cause:
+
3014. 510// ["aa=/./gg", "lex_regexp", "unexpected_a", "g", 8]
+
3015. 510// ["aa=/./z", "lex_regexp", "unexpected_a", "z", 7]
+
3016. 510
+
3017. 510 warn_at("unexpected_a", line, column, char);
+
3018. 510 }
+
3019. 510 flag[char] = true;
+
3020. 510 char_after();
+
3021. 573 }
+
3022. 573 char_before();
+
3023. 573 if (char === "/" || char === "*") {
+
3024. 1
+
3025. 1// test_cause:
+
3026. 1// ["aa=/.//", "lex_regexp", "unexpected_a", "/", 3]
+
3027. 1
+
3028. 1 return stop_at("unexpected_a", line, from, char);
+
3029. 572 }
+
3030. 572 result = token_create("(regexp)", char);
+
3031. 572 result.flag = flag;
+
3032. 572 result.value = value;
+
3033. 572 if (mode_regexp_multiline && !flag.m) {
+
3034. 1
+
3035. 1// test_cause:
+
3036. 1// ["aa=/$^/", "lex_regexp", "missing_m", "", 7]
+
3037. 1
+
3038. 1 warn_at("missing_m", line, column);
+
3039. 572 }
+
3040. 572 return result;
+
3041. 572 }
+
3042. 668
+
3043. 598 function lex_slash_or_regexp() {
+
3044. 598
+
3045. 598// The / can be a division operator or the beginning of a regular expression
+
3046. 598// literal. It is not possible to know which without doing a complete parse.
+
3047. 598// We want to complete the tokenization before we begin to parse, so we will
+
3048. 598// estimate. This estimator can fail in some cases. For example, it cannot
+
3049. 598// know if "}" is ending a block or ending an object literal, so it can
+
3050. 598// behave incorrectly in that case; it is not meaningful to divide an
+
3051. 598// object, so it is likely that we can get away with it. We avoided the worst
+
3052. 598// cases by eliminating automatic semicolon insertion.
+
3053. 598
+
3054. 598 let the_token;
+
3055. 598 switch (
+
3056. 598 token_prv_expr.identifier
+
3057. 18 && !token_prv_expr.dot
+
3058. 15 && token_prv_expr.id
+
3059. 598 ) {
+
3060. 1 case "case":
+
3061. 2 case "delete":
+
3062. 3 case "in":
+
3063. 4 case "instanceof":
+
3064. 5 case "new":
+
3065. 6 case "typeof":
+
3066. 7 case "void":
+
3067. 8 case "yield":
+
3068. 8 the_token = lex_regexp();
+
3069. 8
+
3070. 8// test_cause:
+
3071. 8// ["case /./", "lex_slash_or_regexp", "unexpected_a", "(regexp)", 6]
+
3072. 8// ["delete /./", "lex_slash_or_regexp", "unexpected_a", "(regexp)", 8]
+
3073. 8// ["in /./", "lex_slash_or_regexp", "unexpected_a", "(regexp)", 4]
+
3074. 8// ["instanceof /./", "lex_slash_or_regexp", "unexpected_a", "(regexp)", 12]
+
3075. 8// ["new /./", "lex_slash_or_regexp", "unexpected_a", "(regexp)", 5]
+
3076. 8// ["typeof /./", "lex_slash_or_regexp", "unexpected_a", "(regexp)", 8]
+
3077. 8// ["void /./", "lex_slash_or_regexp", "unexpected_a", "(regexp)", 6]
+
3078. 8// ["yield /./", "lex_slash_or_regexp", "unexpected_a", "(regexp)", 7]
+
3079. 8
+
3080. 8 return stop("unexpected_a", the_token);
+
3081. 1 case "return":
+
3082. 1 return lex_regexp();
+
3083. 589 }
+
3084. 589 switch (!token_prv_expr.identifier && token_prv_expr.id.slice(-1)) {
+
3085. 1 case "!":
+
3086. 2 case "%":
+
3087. 4 case "&":
+
3088. 5 case "*":
+
3089. 6 case "+":
+
3090. 7 case "-":
+
3091. 9 case "/":
+
3092. 10 case ";":
+
3093. 11 case "<":
+
3094. 12 case ">":
+
3095. 13 case "^":
+
3096. 16 case "{":
+
3097. 17 case "|":
+
3098. 18 case "}":
+
3099. 19 case "~":
+
3100. 19 the_token = lex_regexp();
+
3101. 19
+
3102. 19// test_cause:
+
3103. 19// ["!/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3104. 19// ["%/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3105. 19// ["&/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3106. 19// ["+/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3107. 19// ["-/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3108. 19// ["0 * /./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 5]
+
3109. 19// ["0 / /./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 5]
+
3110. 19// [";/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3111. 19// ["</./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3112. 19// [">/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3113. 19// ["^/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3114. 19// ["{/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3115. 19// ["|/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3116. 19// ["}/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3117. 19// ["~/./", "lex_slash_or_regexp", "wrap_regexp", "(regexp)", 2]
+
3118. 19
+
3119. 19 warn("wrap_regexp", the_token);
+
3120. 19 return the_token;
+
3121. 514 case "(":
+
3122. 515 case ",":
+
3123. 516 case ":":
+
3124. 553 case "=":
+
3125. 554 case "?":
+
3126. 555 case "[":
+
3127. 555
+
3128. 555// test_cause:
+
3129. 555// ["(/./", "lex_slash_or_regexp", "recurse", "", 0]
+
3130. 555// [",/./", "lex_slash_or_regexp", "recurse", "", 0]
+
3131. 555// [":/./", "lex_slash_or_regexp", "recurse", "", 0]
+
3132. 555// ["=/./", "lex_slash_or_regexp", "recurse", "", 0]
+
3133. 555// ["?/./", "lex_slash_or_regexp", "recurse", "", 0]
+
3134. 555// ["aa[/./", "lex_slash_or_regexp", "recurse", "", 0]
+
3135. 555
+
3136. 555 test_cause("recurse");
+
3137. 555 return lex_regexp();
+
3138. 15 }
+
3139. 15 if (line_source[0] === "=") {
+
3140. 1 column += 1;
+
3141. 1 line_source = line_source.slice(1);
+
3142. 1 snippet = "/=";
+
3143. 1 warn_at("unexpected_a", line, column, "/=");
+
3144. 15 }
+
3145. 15 return token_create(snippet);
+
3146. 15 }
+
3147. 668
+
3148. 24335 function lex_string(quote) {
+
3149. 24335
+
3150. 24335// Create a string token.
+
3151. 24335
+
3152. 24335 let the_token;
+
3153. 24333 if (!option_dict.single && quote === "'") {
+
3154. 2
+
3155. 2// test_cause:
+
3156. 2// ["''", "lex_string", "use_double", "", 1]
+
3157. 2
+
3158. 2 warn_at("use_double", line, column);
+
3159. 2 }
+
3160. 24335 snippet = "";
+
3161. 24335 char_after();
+
3162. 24335
+
3163. 24335// Lex/loop through each character in "...".
+
3164. 24335
+
3165. 217055 while (true) {
+
3166. 217055 switch (char) {
+
3167. 217055 case "":
+
3168. 217055
+
3169. 217055// test_cause:
+
3170. 217055// ["\"", "lex_string", "unclosed_string", "", 1]
+
3171. 217055
+
3172. 217055 return stop_at("unclosed_string", line, column);
+
3173. 217055 case "\\":
+
3174. 217055 char_after_escape(quote);
+
3175. 217055 break;
+
3176. 217055 case "`":
+
3177. 217055 if (mode_mega) {
+
3178. 217055
+
3179. 217055// test_cause:
+
3180. 217055// ["`${\"`\"}`", "lex_string", "unexpected_a", "`", 5]
+
3181. 217055
+
3182. 217055 warn_at("unexpected_a", line, column, "`");
+
3183. 217055 }
+
3184. 217055 char_after("`");
+
3185. 217055 break;
+
3186. 217055 case quote:
+
3187. 217055
+
3188. 217055// Remove last character from snippet.
+
3189. 217055
+
3190. 217055 snippet = snippet.slice(0, -1);
+
3191. 217055 the_token = token_create("(string)", snippet);
+
3192. 217055 the_token.quote = quote;
+
3193. 217055 return the_token;
+
3194. 217055 default:
+
3195. 217055 char_after();
+
3196. 217055 }
+
3197. 217055 }
+
3198. 24335 }
+
3199. 668
+
3200. 252255 function lex_token() {
+
3201. 252255 let match;
+
3202. 252255
+
3203. 252255// Lex/loop through each whitespace.
+
3204. 252255
+
3205. 376039 while (true) {
+
3206. 376039
+
3207. 376039// Lex/loop through each blank-line.
+
3208. 376039
+
3209. 376039 while (!line_source) {
+
3210. 376039 line_source = read_line();
+
3211. 376039 from = 0;
+
3212. 376039 if (line_source === undefined) {
+
3213. 376039 return (
+
3214. 376039 mode_mega
+
3215. 376039
+
3216. 376039// test_cause:
+
3217. 376039// ["`${//}`", "lex_token", "unclosed_mega", "", 1]
+
3218. 376039
+
3219. 376039 ? stop_at("unclosed_mega", line_mega, from_mega)
+
3220. 376039 : line_disable !== undefined
+
3221. 376039
+
3222. 376039// test_cause:
+
3223. 376039// ["/*jslint-disable*/", "lex_token", "unclosed_disable", "", 1]
+
3224. 376039
+
3225. 376039 ? stop_at("unclosed_disable", line_disable)
+
3226. 376039 : token_create("(end)")
+
3227. 376039 );
+
3228. 376039 }
+
3229. 376039 }
+
3230. 376039 from = column;
+
3231. 376039 match = line_source.match(jslint_rgx_token);
+
3232. 376039
+
3233. 376039// match[1] token
+
3234. 376039// match[2] whitespace
+
3235. 376039// match[3] identifier
+
3236. 376039// match[4] number
+
3237. 376039// match[5] rest
+
3238. 376039
+
3239. 376039 if (!match) {
+
3240. 376039
+
3241. 376039// test_cause:
+
3242. 376039// ["#", "lex_token", "unexpected_char_a", "#", 1]
+
3243. 376039
+
3244. 376039 return stop_at(
+
3245. 376039 "unexpected_char_a",
+
3246. 376039 line,
+
3247. 376039 column,
+
3248. 376039 line_source[0]
+
3249. 376039 );
+
3250. 376039 }
+
3251. 376039 snippet = match[1];
+
3252. 376039 column += snippet.length;
+
3253. 376039 line_source = match[5];
+
3254. 376039 if (!match[2]) {
+
3255. 376039 break;
+
3256. 376039 }
+
3257. 376039 }
+
3258. 251612
+
3259. 251612// The token is an identifier.
+
3260. 251612
+
3261. 251612 if (match[3]) {
+
3262. 67699 return token_create(snippet, undefined, true);
+
3263. 183913 }
+
3264. 183913
+
3265. 183913// Create token from number.
+
3266. 183913
+
3267. 183913 if (match[4]) {
+
3268. 8851 return lex_number();
+
3269. 175062 }
+
3270. 175062
+
3271. 175062// Create token from string "..." or '...'.
+
3272. 175062
+
3273. 175062 if (snippet === "\"" || snippet === "'") {
+
3274. 24335 return lex_string(snippet);
+
3275. 150727 }
+
3276. 150727
+
3277. 150727// Create token from megastring `...`.
+
3278. 150727
+
3279. 150727 if (snippet === "`") {
+
3280. 789 return lex_megastring();
+
3281. 149938 }
+
3282. 149938
+
3283. 149938// Create token from comment /*...*/ or //....
+
3284. 149938
+
3285. 149938 if (snippet === "/*" || snippet === "//") {
+
3286. 11221 return lex_comment();
+
3287. 138717 }
+
3288. 138717
+
3289. 138717// Create token from slash /.
+
3290. 138717
+
3291. 138717 if (snippet === "/") {
+
3292. 598 return lex_slash_or_regexp();
+
3293. 138119 }
+
3294. 138119 return token_create(snippet);
+
3295. 138119 }
+
3296. 668
+
3297. 2667 function option_set_item(key, val) {
+
3298. 2667
+
3299. 2667// These are the options that are recognized in the option object or that may
+
3300. 2667// appear in a /*jslint*/ directive. Most options will have a boolean value,
+
3301. 2667// usually true. Some options will also predefine some number of global
+
3302. 2667// variables.
+
3303. 2667
+
3304. 2667 switch (key) {
+
3305. 659 case "beta": // Enable experimental warnings.
+
3306. 661 case "bitwise": // Allow bitwise operator.
+
3307. 668 case "browser": // Assume browser environment.
+
3308. 670 case "convert": // Allow conversion operator.
+
3309. 672 case "couch": // Assume CouchDb environment.
+
3310. 678 case "devel": // Allow console.log() and friends.
+
3311. 2014 case "ecma": // Assume ECMAScript environment.
+
3312. 2020 case "eval": // Allow eval().
+
3313. 2024 case "fart": // Allow complex fat-arrow.
+
3314. 2029 case "for": // Allow for-statement.
+
3315. 2035 case "getset": // Allow get() and set().
+
3316. 2040 case "indent2": // Use 2-space indent.
+
3317. 2042 case "long": // Allow long lines.
+
3318. 2089 case "node": // Assume Node.js environment.
+
3319. 2093 case "nomen": // Allow weird property name.
+
3320. 2095 case "single": // Allow single-quote strings.
+
3321. 2097 case "subscript": // Allow identifier in subscript-notation.
+
3322. 2602 case "test_cause": // Test jslint's causes.
+
3323. 2604 case "test_internal_error": // Test jslint's internal-error
+
3324. 2667 // ... handling-ability.
+
3325. 2606 case "this": // Allow 'this'.
+
3326. 2609 case "trace": // Include jslint stack-trace in warnings.
+
3327. 2613 case "unordered": // Allow unordered cases, params, properties,
+
3328. 2667 // ... variables, and exports.
+
3329. 2617 case "variable": // Allow unordered const and let declarations
+
3330. 2667 // ... that are not at top of function-scope.
+
3331. 2619 case "white": // Allow messy whitespace.
+
3332. 2619 option_dict[key] = val;
+
3333. 2619 break;
+
3334. 2667
+
3335. 2667// PR-404 - Alias "evil" to jslint-directive "eval" for backwards-compat.
+
3336. 2667
+
3337. 2 case "evil":
+
3338. 2 return option_set_item("eval", val);
+
3339. 2667
+
3340. 2667// PR-404 - Alias "nomen" to jslint-directive "name" for backwards-compat.
+
3341. 2667
+
3342. 2 case "name":
+
3343. 2 return option_set_item("nomen", val);
+
3344. 44 default:
+
3345. 44 return false;
+
3346. 2619 }
+
3347. 2619
+
3348. 2619// Initialize global-variables.
+
3349. 2619
+
3350. 2619 switch (val && key) {
+
3351. 2667
+
3352. 2667// Assign global browser variables to global_dict.
+
3353. 2667/*
+
3354. 2667// /\*jslint beta, browser, devel*\/
+
3355. 2667console.log(JSON.stringify(Object.keys(window).sort(), undefined, 4));
+
3356. 2667*/
+
3357. 2667
+
3358. 6 case "browser":
+
3359. 6 object_assign_from_list(global_dict, [
+
3360. 6
+
3361. 6// Shared with Node.js.
+
3362. 6
+
3363. 6 "AbortController",
+
3364. 6 // "Buffer",
+
3365. 6 // "Crypto",
+
3366. 6 // "CryptoKey",
+
3367. 6 "Event",
+
3368. 6 "EventTarget",
+
3369. 6 "MessageChannel",
+
3370. 6 "MessageEvent",
+
3371. 6 "MessagePort",
+
3372. 6 // "Request",
+
3373. 6 // "Response",
+
3374. 6 // "SubtleCrypto",
+
3375. 6 "TextDecoder",
+
3376. 6 "TextEncoder",
+
3377. 6 "URL",
+
3378. 6 "URLSearchParams",
+
3379. 6 "WebAssembly",
+
3380. 6 // "__dirname",
+
3381. 6 // "__filename",
+
3382. 6 // "atob",
+
3383. 6 // "btoa",
+
3384. 6 // "clearImmediate",
+
3385. 6 "clearInterval",
+
3386. 6 "clearTimeout",
+
3387. 6 // "console",
+
3388. 6 // "crypto",
+
3389. 6 // "exports",
+
3390. 6 // "fetch",
+
3391. 6 // "global",
+
3392. 6 // "module",
+
3393. 6 "performance",
+
3394. 6 // "process",
+
3395. 6 "queueMicrotask",
+
3396. 6 // "require",
+
3397. 6 // "setImmediate",
+
3398. 6 "setInterval",
+
3399. 6 "setTimeout",
+
3400. 6
+
3401. 6// Web worker only.
+
3402. 6// https://github.com/mdn/content/blob/main/files/en-us/web/api
+
3403. 6// /workerglobalscope/index.md
+
3404. 6
+
3405. 6 "importScripts",
+
3406. 6
+
3407. 6// Window.
+
3408. 6
+
3409. 6 "Blob",
+
3410. 6 // "CharacterData",
+
3411. 6 // "DocumentType",
+
3412. 6 // "Element",
+
3413. 6 // "Event",
+
3414. 6 "FileReader",
+
3415. 6 // "FontFace",
+
3416. 6 "FormData",
+
3417. 6 "IntersectionObserver",
+
3418. 6 "MutationObserver",
+
3419. 6 // "Storage",
+
3420. 6 // "TextDecoder",
+
3421. 6 // "TextEncoder",
+
3422. 6 // "URL",
+
3423. 6 "Worker",
+
3424. 6 "XMLHttpRequest",
+
3425. 6 // "caches",
+
3426. 6 // "clearInterval",
+
3427. 6 // "clearTimeout",
+
3428. 6 "document",
+
3429. 6 // "event",
+
3430. 6 "fetch",
+
3431. 6 // "history",
+
3432. 6 "indexedDb",
+
3433. 6 "localStorage",
+
3434. 6 "location",
+
3435. 6 // "name",
+
3436. 6 "navigator",
+
3437. 6 "postMessage",
+
3438. 6 // "screen",
+
3439. 6 "sessionStorage",
+
3440. 6 // "setInterval",
+
3441. 6 // "setTimeout",
+
3442. 6 "structuredClone",
+
3443. 6 "window"
+
3444. 6 ], "browser");
+
3445. 6 break;
+
3446. 2667
+
3447. 2667// https://docs.couchdb.org/en/stable/query-server/javascript.html#javascript
+
3448. 2667
+
3449. 2 case "couch":
+
3450. 2 object_assign_from_list(global_dict, [
+
3451. 2 "emit",
+
3452. 2 "getRow",
+
3453. 2 "isArray",
+
3454. 2 "log",
+
3455. 2 "provides",
+
3456. 2 "registerType",
+
3457. 2 "require",
+
3458. 2 "send",
+
3459. 2 "start",
+
3460. 2 "sum",
+
3461. 2 "toJSON"
+
3462. 2 ], "CouchDb");
+
3463. 2 break;
+
3464. 6 case "devel":
+
3465. 6 object_assign_from_list(global_dict, [
+
3466. 6 "alert", "confirm", "console", "prompt"
+
3467. 6 ], "development");
+
3468. 6 break;
+
3469. 2667
+
3470. 2667// These are the globals that are provided by the language standard.
+
3471. 2667// Assign global ECMAScript variables to global_dict.
+
3472. 2667/*
+
3473. 2667node --input-type=module --eval '
+
3474. 2667// /\*jslint beta, node*\/
+
3475. 2667import https from "https";
+
3476. 2667(async function () {
+
3477. 2667 let dict = {import: true};
+
3478. 2667 let result = "";
+
3479. 2667 await new Promise(function (resolve) {
+
3480. 2667 https.get((
+
3481. 2667 "https://raw.githubusercontent.com/mdn/content/main/files"
+
3482. 2667 + "/en-us/web/javascript/reference/global_objects/index.md"
+
3483. 2667 ), function (res) {
+
3484. 2667 res.on("data", function (chunk) {
+
3485. 2667 result += chunk;
+
3486. 2667 }).on("end", resolve).setEncoding("utf8");
+
3487. 2667 });
+
3488. 2667 });
+
3489. 2667 result.replace((
+
3490. 2667 /\n- \{\{JSxRef\("(?:Global_Objects\/)?([^"\/]+?)"/g
+
3491. 2667 ), function (ignore, key) {
+
3492. 2667 if (globalThis.hasOwnProperty(key)) {
+
3493. 2667 dict[key] = true;
+
3494. 2667 }
+
3495. 2667 return "";
+
3496. 2667 });
+
3497. 2667 console.log(JSON.stringify(Object.keys(dict).sort(), undefined, 4));
+
3498. 2667}());
+
3499. 2667'
+
3500. 2667*/
+
3501. 2667
+
3502. 1336 case "ecma":
+
3503. 1336 object_assign_from_list(global_dict, [
+
3504. 1336 "AggregateError",
+
3505. 1336 "Array",
+
3506. 1336 "ArrayBuffer",
+
3507. 1336 "Atomics",
+
3508. 1336 "BigInt",
+
3509. 1336 "BigInt64Array",
+
3510. 1336 "BigUint64Array",
+
3511. 1336 "Boolean",
+
3512. 1336 "DataView",
+
3513. 1336 "Date",
+
3514. 1336 "Error",
+
3515. 1336 "EvalError",
+
3516. 1336 "Float32Array",
+
3517. 1336 "Float64Array",
+
3518. 1336 "Function",
+
3519. 1336 "Infinity",
+
3520. 1336 "Int16Array",
+
3521. 1336 "Int32Array",
+
3522. 1336 "Int8Array",
+
3523. 1336 "Intl",
+
3524. 1336 "JSON",
+
3525. 1336 "Map",
+
3526. 1336 "Math",
+
3527. 1336 "NaN",
+
3528. 1336 "Number",
+
3529. 1336 "Object",
+
3530. 1336 "Promise",
+
3531. 1336 "Proxy",
+
3532. 1336 "RangeError",
+
3533. 1336 "ReferenceError",
+
3534. 1336 "Reflect",
+
3535. 1336 "RegExp",
+
3536. 1336 "Set",
+
3537. 1336 "SharedArrayBuffer",
+
3538. 1336 "String",
+
3539. 1336 "Symbol",
+
3540. 1336 "SyntaxError",
+
3541. 1336 "TypeError",
+
3542. 1336 "URIError",
+
3543. 1336 "Uint16Array",
+
3544. 1336 "Uint32Array",
+
3545. 1336 "Uint8Array",
+
3546. 1336 "Uint8ClampedArray",
+
3547. 1336 "WeakMap",
+
3548. 1336 "WeakSet",
+
3549. 1336 "WebAssembly",
+
3550. 1336 "decodeURI",
+
3551. 1336 "decodeURIComponent",
+
3552. 1336 "encodeURI",
+
3553. 1336 "encodeURIComponent",
+
3554. 1336 "eval",
+
3555. 1336 "globalThis",
+
3556. 1336 "import",
+
3557. 1336 "isFinite",
+
3558. 1336 "isNaN",
+
3559. 1336 "parseFloat",
+
3560. 1336 "parseInt",
+
3561. 1336 "undefined"
+
3562. 1336 ], "ECMAScript");
+
3563. 1336 break;
+
3564. 2667
+
3565. 2667// Assign global Node.js variables to global_dict.
+
3566. 2667/*
+
3567. 2667node --input-type=module --eval '
+
3568. 2667// /\*jslint beta, node*\/
+
3569. 2667import moduleHttps from "https";
+
3570. 2667(async function () {
+
3571. 2667 let dict = Object.create(null);
+
3572. 2667 let result = "";
+
3573. 2667 await new Promise(function (resolve) {
+
3574. 2667 moduleHttps.get((
+
3575. 2667 "https://raw.githubusercontent.com/nodejs/node/v16.x/doc/api"
+
3576. 2667 + "/globals.md"
+
3577. 2667 ), function (res) {
+
3578. 2667 res.on("data", function (chunk) {
+
3579. 2667 result += chunk;
+
3580. 2667 }).on("end", resolve).setEncoding("utf8");
+
3581. 2667 });
+
3582. 2667 });
+
3583. 2667 result.replace((
+
3584. 2667 /\n(?:\* \[`|## |## Class: )`\w+/g
+
3585. 2667 ), function (match0) {
+
3586. 2667 dict[match0.split("`")[1]] = true;
+
3587. 2667 return "";
+
3588. 2667 });
+
3589. 2667 console.log(JSON.stringify(Object.keys(dict).sort(), undefined, 4));
+
3590. 2667}());
+
3591. 2667'
+
3592. 2667*/
+
3593. 2667
+
3594. 47 case "node":
+
3595. 47 object_assign_from_list(global_dict, [
+
3596. 47 "AbortController",
+
3597. 47 "Buffer",
+
3598. 47 // "Crypto",
+
3599. 47 // "CryptoKey",
+
3600. 47 "Event",
+
3601. 47 "EventTarget",
+
3602. 47 "MessageChannel",
+
3603. 47 "MessageEvent",
+
3604. 47 "MessagePort",
+
3605. 47 // "Request",
+
3606. 47 // "Response",
+
3607. 47 // "SubtleCrypto",
+
3608. 47 "TextDecoder",
+
3609. 47 "TextEncoder",
+
3610. 47 "URL",
+
3611. 47 "URLSearchParams",
+
3612. 47 "WebAssembly",
+
3613. 47 "__dirname",
+
3614. 47 "__filename",
+
3615. 47 // "atob",
+
3616. 47 // "btoa",
+
3617. 47 "clearImmediate",
+
3618. 47 "clearInterval",
+
3619. 47 "clearTimeout",
+
3620. 47 "console",
+
3621. 47 // "crypto",
+
3622. 47 "exports",
+
3623. 47 // "fetch",
+
3624. 47 "global",
+
3625. 47 "module",
+
3626. 47 "performance",
+
3627. 47 "process",
+
3628. 47 "queueMicrotask",
+
3629. 47 "require",
+
3630. 47 "setImmediate",
+
3631. 47 "setInterval",
+
3632. 47 "setTimeout"
+
3633. 47 ], "Node.js");
+
3634. 47 break;
+
3635. 2619 }
+
3636. 2619 return true;
+
3637. 2619 }
+
3638. 668
+
3639. 469 function read_digits(base, mode) {
+
3640. 469 let digits = line_source.match(
+
3641. 469 base === "b"
+
3642. 3 ? jslint_rgx_digits_bits
+
3643. 466 : base === "o"
+
3644. 466 ? jslint_rgx_digits_octals
+
3645. 466 : base === "x"
+
3646. 466 ? jslint_rgx_digits_hexs
+
3647. 466 : jslint_rgx_digits_decimals
+
3648. 469 )[0];
+
3649. 469 if (
+
3650. 77 (mode !== mode_digits_empty_string && digits.length === 0)
+
3651. 468 || digits[0] === "_"
+
3652. 2 ) {
+
3653. 2
+
3654. 2// test_cause:
+
3655. 2// ["0x", "read_digits", "expected_digits_after_a", "0x", 2]
+
3656. 2// ["0x_", "read_digits", "expected_digits_after_a", "0x", 2]
+
3657. 2
+
3658. 2 warn_at("expected_digits_after_a", line, column, snippet);
+
3659. 2 }
+
3660. 469
+
3661. 469// PR-390 - Add numeric-separator check.
+
3662. 469
+
3663. 73 if (mode === mode_digits_numeric_separator) {
+
3664. 73 check_numeric_separator(digits, column);
+
3665. 396 } else if (digits.indexOf("_") >= 0) {
+
3666. 396
+
3667. 396// test_cause:
+
3668. 396// ["\"\\u{1_2}\"", "read_digits", "illegal_num_separator", "", 6]
+
3669. 396
+
3670. 396 warn_at(
+
3671. 396 "illegal_num_separator",
+
3672. 396 line,
+
3673. 396 column + digits.indexOf("_") + 1
+
3674. 396 );
+
3675. 396 }
+
3676. 469 column += digits.length;
+
3677. 469 line_source = line_source.slice(digits.length);
+
3678. 469 snippet += digits;
+
3679. 469 char_after();
+
3680. 469 return digits.length;
+
3681. 469 }
+
3682. 668
+
3683. 105193 function read_line() {
+
3684. 105193
+
3685. 105193// Put the next line of source in line_source. If the line contains tabs,
+
3686. 105193// replace them with spaces and give a warning. Also warn if the line contains
+
3687. 105193// unsafe characters or is too damn long.
+
3688. 105193
+
3689. 105193 if (
+
3690. 105193 !option_dict.long
+
3691. 105189 && line_whole.length > 80
+
3692. 56 && line_disable === undefined
+
3693. 56 && !state.mode_json
+
3694. 23 && token_1
+
3695. 23 && !mode_regexp
+
3696. 13 ) {
+
3697. 13
+
3698. 13// test_cause:
+
3699. 13// ["/////////////////////////////////////////////////////////////////////////////////", "read_line", "too_long", "", 1] //jslint-ignore-line
+
3700. 13
+
3701. 13 warn_at("too_long", line);
+
3702. 13 }
+
3703. 105193 column = 0;
+
3704. 105193 line += 1;
+
3705. 105193 mode_regexp = false;
+
3706. 105193 line_source = undefined;
+
3707. 105193 line_whole = "";
+
3708. 645 if (line_list[line] === undefined) {
+
3709. 645 return line_source;
+
3710. 104548 }
+
3711. 104548 line_source = line_list[line].line_source;
+
3712. 104548 line_whole = line_source;
+
3713. 104548
+
3714. 104548// Scan each line for following ignore-directives:
+
3715. 104548// "/*jslint-disable*/"
+
3716. 104548// "/*jslint-enable*/"
+
3717. 104548// "//jslint-ignore-line"
+
3718. 104548
+
3719. 104548 if (line_source === "/*jslint-disable*/") {
+
3720. 5
+
3721. 5// test_cause:
+
3722. 5// ["/*jslint-disable*/", "read_line", "jslint_disable", "", 0]
+
3723. 5
+
3724. 5 test_cause("jslint_disable");
+
3725. 5 line_disable = line;
+
3726. 104543 } else if (line_source === "/*jslint-enable*/") {
+
3727. 104543 if (line_disable === undefined) {
+
3728. 104543
+
3729. 104543// test_cause:
+
3730. 104543// ["/*jslint-enable*/", "read_line", "unopened_enable", "", 1]
+
3731. 104543
+
3732. 104543 stop_at("unopened_enable", line);
+
3733. 104543 }
+
3734. 104543 line_disable = undefined;
+
3735. 104543 } else if (
+
3736. 104543 line_source.endsWith(" //jslint-ignore-line")
+
3737. 104543 || line_source.endsWith(" //jslint-quiet")
+
3738. 104543 ) {
+
3739. 104543
+
3740. 104543// test_cause:
+
3741. 104543// ["0 //jslint-ignore-line", "read_line", "jslint_ignore_line", "", 0]
+
3742. 104543
+
3743. 104543 test_cause("jslint_ignore_line");
+
3744. 104543 line_list[line].directive_ignore_line = true;
+
3745. 104547 }
+
3746. 104547 if (line_disable !== undefined) {
+
3747. 9
+
3748. 9// test_cause:
+
3749. 9// ["/*jslint-disable*/\n0", "read_line", "line_disable", "", 0]
+
3750. 9
+
3751. 9 test_cause("line_disable");
+
3752. 9 line_source = "";
+
3753. 104547 }
+
3754. 104547 // jslint_rgx_tab
+
3755. 104547 if (line_source.indexOf("\t") >= 0) {
+
3756. 3 if (!option_dict.white) {
+
3757. 3
+
3758. 3// test_cause:
+
3759. 3// ["\t", "read_line", "use_spaces", "", 1]
+
3760. 3
+
3761. 3 warn_at("use_spaces", line, line_source.indexOf("\t") + 1);
+
3762. 3 }
+
3763. 3 line_source = line_source.replace(jslint_rgx_tab, " ");
+
3764. 104547 }
+
3765. 104547 if (!option_dict.white && line_source.endsWith(" ")) {
+
3766. 2
+
3767. 2// test_cause:
+
3768. 2// [" ", "read_line", "unexpected_trailing_space", "", 1]
+
3769. 2
+
3770. 2 warn_at("unexpected_trailing_space", line, line_source.length - 1);
+
3771. 104547 }
+
3772. 104547 return line_source;
+
3773. 104547 }
+
3774. 668
+
3775. 255241 function token_create(id, value, identifier) {
+
3776. 255241
+
3777. 255241// Create the token object and append it to token_list.
+
3778. 255241
+
3779. 255241 let the_token = {
+
3780. 255241 from,
+
3781. 255241 id,
+
3782. 255241 identifier: Boolean(identifier),
+
3783. 255241 line,
+
3784. 255241 nr: token_list.length,
+
3785. 255241 thru: column,
+
3786. 255241 value
+
3787. 255241 };
+
3788. 255241 token_list.push(the_token);
+
3789. 255241
+
3790. 255241// Directives must appear before the first statement.
+
3791. 255241
+
3792. 244023 if (id !== "(comment)" && id !== ";") {
+
3793. 228006 mode_directive = false;
+
3794. 228006 }
+
3795. 255241
+
3796. 255241// If this token is an identifier that touches a preceding number, or
+
3797. 255241// a "/", comment, or regular expression literal that touches a preceding
+
3798. 255241// comment or regular expression literal, then give a missing space warning.
+
3799. 255241// This warning is not suppressed by option_dict.white.
+
3800. 255241
+
3801. 255241 if (
+
3802. 255241 token_prv.line === line
+
3803. 185838 && token_prv.thru === from
+
3804. 119910 && (id === "(comment)" || id === "(regexp)" || id === "/")
+
3805. 125 && (token_prv.id === "(comment)" || token_prv.id === "(regexp)")
+
3806. 1 ) {
+
3807. 1
+
3808. 1// test_cause:
+
3809. 1// ["/**//**/", "token_create", "expected_space_a_b", "(comment)", 5]
+
3810. 1
+
3811. 1 warn(
+
3812. 1 "expected_space_a_b",
+
3813. 1 the_token,
+
3814. 1 artifact(token_prv),
+
3815. 1 artifact(the_token)
+
3816. 1 );
+
3817. 1 }
+
3818. 11603 if (token_prv.id === "." && id === "(number)") {
+
3819. 4
+
3820. 4// test_cause:
+
3821. 4// [".0", "token_create", "expected_a_before_b", ".", 1]
+
3822. 4
+
3823. 4 warn("expected_a_before_b", token_prv, "0", ".");
+
3824. 4 }
+
3825. 11603 if (token_prv_expr.id === "." && the_token.identifier) {
+
3826. 11598 the_token.dot = true;
+
3827. 11598 }
+
3828. 255241
+
3829. 255241// PR-385 - Bugfix - Fixes issue #382 - failure to detect destructured fart.
+
3830. 255241// Farts are now detected by keeping a list of most recent "(" tokens at any
+
3831. 255241// given depth. When a "=>" token is encountered, the most recent "(" token at
+
3832. 255241// current depth is marked as a fart.
+
3833. 255241
+
3834. 255241 switch (id) {
+
3835. 17591 case "(":
+
3836. 17591 paren_backtrack_list[paren_depth] = the_token;
+
3837. 17591 paren_depth += 1;
+
3838. 17591 break;
+
3839. 17590 case ")":
+
3840. 17590 paren_depth -= 1;
+
3841. 17590 break;
+
3842. 16 case "=>":
+
3843. 16 if (
+
3844. 16 token_prv_expr.id === ")"
+
3845. 16 && paren_backtrack_list[paren_depth]
+
3846. 16 ) {
+
3847. 16 paren_backtrack_list[paren_depth].fart = the_token;
+
3848. 16 }
+
3849. 16 break;
+
3850. 255241 }
+
3851. 255241
+
3852. 255241// The previous token is used to detect adjacency problems.
+
3853. 255241
+
3854. 255241 token_prv = the_token;
+
3855. 255241
+
3856. 255241// The token_prv_expr token is a previous token that was not a comment.
+
3857. 255241// The token_prv_expr token
+
3858. 255241// is used to disambiguate "/", which can mean division or regular expression
+
3859. 255241// literal.
+
3860. 255241
+
3861. 244023 if (token_prv.id !== "(comment)") {
+
3862. 244023 token_prv_expr = token_prv;
+
3863. 244023 }
+
3864. 255241 return the_token;
+
3865. 255241 }
+
3866. 668
+
3867. 668// Init global_dict and option_dict.
+
3868. 668
+
3869. 668 option_set_item("ecma", true);
+
3870. 1896 Object.keys(option_dict).sort().forEach(function (key) {
+
3871. 1896 option_set_item(key, option_dict[key] === true);
+
3872. 1896 });
+
3873. 668 object_assign_from_list(global_dict, global_list, "user-defined");
+
3874. 668
+
3875. 668// Scan first line for "#!" and ignore it.
+
3876. 668
+
3877. 1 if (line_list[jslint_fudge].line_source.startsWith("#!")) {
+
3878. 1 line += 1;
+
3879. 1 state.mode_shebang = true;
+
3880. 1 }
+
3881. 668 token_1 = lex_token();
+
3882. 640 state.mode_json = token_1.id === "{" || token_1.id === "[";
+
3883. 668
+
3884. 668// Lex/loop through each token until (end).
+
3885. 668
+
3886. 249474 while (true) {
+
3887. 249474 if (lex_token().id === "(end)") {
+
3888. 249474 break;
+
3889. 249474 }
+
3890. 249474 }
+
3891. 668}
+
3892. 1
+
3893. 631function jslint_phase3_parse(state) {
+
3894. 631
+
3895. 631// PHASE 3. Parse <token_list> into <token_tree> using the Pratt-parser.
+
3896. 631
+
3897. 631// Parsing:
+
3898. 631
+
3899. 631// Parsing weaves the tokens into an abstract syntax tree. During that process,
+
3900. 631// a token may be given any of these properties:
+
3901. 631
+
3902. 631// arity string
+
3903. 631// label identifier
+
3904. 631// name identifier
+
3905. 631// expression expressions
+
3906. 631// block statements
+
3907. 631// else statements (else, default, catch)
+
3908. 631
+
3909. 631// Specialized tokens may have additional properties.
+
3910. 631
+
3911. 631 let anon = "anonymous"; // The guessed name for anonymous functions.
+
3912. 631 let {
+
3913. 631 artifact,
+
3914. 631 catch_list,
+
3915. 631 catch_stack,
+
3916. 631 export_dict,
+
3917. 631 function_list,
+
3918. 631 function_stack,
+
3919. 631 global_dict,
+
3920. 631 import_list,
+
3921. 631 is_equal,
+
3922. 631 option_dict,
+
3923. 631 property_dict,
+
3924. 631 stop,
+
3925. 631 syntax_dict,
+
3926. 631 tenure,
+
3927. 631 test_cause,
+
3928. 631 token_global,
+
3929. 631 token_list,
+
3930. 631 warn,
+
3931. 631 warn_at
+
3932. 631 } = state;
+
3933. 631 let catchage = catch_stack[0]; // The current catch-block.
+
3934. 631 let functionage = token_global; // The current function.
+
3935. 631 let mode_var; // "var" if using var; "let" if using let.
+
3936. 631 let token_ii = 0; // The number of the next token.
+
3937. 631 let token_now = token_global; // The current token being examined in
+
3938. 631 // ... the parse.
+
3939. 631 let token_nxt = token_global; // The next token to be examined in
+
3940. 631 // ... <token_list>.
+
3941. 631
+
3942. 244361 function advance(id, match) {
+
3943. 244361
+
3944. 244361// Produce the next token.
+
3945. 244361
+
3946. 244361// Attempt to give helpful names to anonymous functions.
+
3947. 244361
+
3948. 244361 if (
+
3949. 244361 token_now.identifier
+
3950. 67656 && token_now.id !== "function"
+
3951. 65664 && token_now.id !== "async"
+
3952. 65483 ) {
+
3953. 65483 anon = token_now.id;
+
3954. 178878 } else if (
+
3955. 178878 token_now.id === "(string)"
+
3956. 178878 && jslint_rgx_identifier.test(token_now.value)
+
3957. 178878 ) {
+
3958. 178878 anon = token_now.value;
+
3959. 178878 }
+
3960. 244361
+
3961. 244361// Attempt to match token_nxt with an expected id.
+
3962. 244361
+
3963. 120065 if (id !== undefined && token_nxt.id !== id) {
+
3964. 26 return (
+
3965. 26 match === undefined
+
3966. 26
+
3967. 26// test_cause:
+
3968. 26// ["{0:0}", "advance", "expected_a_b", "0", 2]
+
3969. 26
+
3970. 26 ? stop("expected_a_b", token_nxt, id, artifact())
+
3971. 26
+
3972. 26// test_cause:
+
3973. 26// ["{\"aa\":0", "advance", "expected_a_b_from_c_d", "{", 1]
+
3974. 26
+
3975. 26 : stop(
+
3976. 26 "expected_a_b_from_c_d",
+
3977. 26 token_nxt,
+
3978. 26 id,
+
3979. 26 artifact(match),
+
3980. 26 match.line,
+
3981. 26 artifact()
+
3982. 26 )
+
3983. 26 );
+
3984. 244335 }
+
3985. 244335
+
3986. 244335// Promote the tokens, skipping comments.
+
3987. 244335
+
3988. 244335 token_now = token_nxt;
+
3989. 255550 while (true) {
+
3990. 255550 token_nxt = token_list[token_ii];
+
3991. 255550 state.token_nxt = token_nxt;
+
3992. 255550 token_ii += 1;
+
3993. 255550 if (token_nxt.id !== "(comment)") {
+
3994. 255550 if (token_nxt.id === "(end)") {
+
3995. 255550 token_ii -= 1;
+
3996. 255550 }
+
3997. 255550 break;
+
3998. 255550 }
+
3999. 255550 if (state.mode_json) {
+
4000. 255550
+
4001. 255550// test_cause:
+
4002. 255550// ["[//]", "advance", "unexpected_a", "(comment)", 2]
+
4003. 255550
+
4004. 255550 warn("unexpected_a");
+
4005. 255550 }
+
4006. 255550 }
+
4007. 244361 }
+
4008. 631
+
4009. 7572 function assignment(id) {
+
4010. 7572
+
4011. 7572// Create an assignment operator. The one true assignment is different because
+
4012. 7572// its left side, when it is a variable, is not treated as an expression.
+
4013. 7572// That case is special because that is when a variable gets initialized. The
+
4014. 7572// other assignment operators can modify, but they cannot initialize.
+
4015. 7572
+
4016. 7572 const the_symbol = symbol(id, 20);
+
4017. 5013 the_symbol.led_infix = function (left) {
+
4018. 5013 const the_token = token_now;
+
4019. 5013 let right;
+
4020. 5013 the_token.arity = "assignment";
+
4021. 5013 right = parse_expression(20 - 1);
+
4022. 4234 if (id === "=" && left.arity === "variable") {
+
4023. 2818 the_token.names = left;
+
4024. 2818 the_token.expression = right;
+
4025. 2818 } else {
+
4026. 2191 the_token.expression = [left, right];
+
4027. 5009 }
+
4028. 5009 if (
+
4029. 5009 right.arity === "assignment"
+
4030. 5009 || right.arity === "preassign"
+
4031. 5007 || right.arity === "postassign"
+
4032. 2 ) {
+
4033. 2 warn("unexpected_a", right);
+
4034. 5009 }
+
4035. 5009 check_mutation(left);
+
4036. 5009 return the_token;
+
4037. 5009 };
+
4038. 7572 return the_symbol;
+
4039. 7572 }
+
4040. 631
+
4041. 5713 function block(special) {
+
4042. 5713
+
4043. 5713// Parse a block, a sequence of statements wrapped in braces.
+
4044. 5713// special "body" The block is a function body.
+
4045. 5713// "ignore" No warning on an empty block.
+
4046. 5713// "naked" No advance.
+
4047. 5713// undefined An ordinary block.
+
4048. 5713
+
4049. 5713 let stmts;
+
4050. 5713 let the_block;
+
4051. 5708 if (special !== "naked") {
+
4052. 5708 advance("{");
+
4053. 5712 }
+
4054. 5712 the_block = token_now;
+
4055. 5712 if (special !== "body") {
+
4056. 3715 functionage.statement_prv = the_block;
+
4057. 5712 }
+
4058. 5712 the_block.arity = "statement";
+
4059. 5712 the_block.body = special === "body";
+
4060. 5712
+
4061. 5712// Top level function bodies may include the "use strict" pragma.
+
4062. 5712
+
4063. 5712 if (
+
4064. 5712 special === "body"
+
4065. 5712 && function_stack.length === 1
+
4066. 281 && token_nxt.value === "use strict"
+
4067. 4 ) {
+
4068. 4 token_nxt.statement = true;
+
4069. 4 advance("(string)");
+
4070. 4 advance(";");
+
4071. 5712 }
+
4072. 5712 stmts = parse_statements();
+
4073. 5712 the_block.block = stmts;
+
4074. 5712 if (stmts.length === 0) {
+
4075. 72 if (!option_dict.devel && special !== "ignore") {
+
4076. 72
+
4077. 72// test_cause:
+
4078. 72// ["function aa(){}", "block", "empty_block", "{", 14]
+
4079. 72
+
4080. 72 warn("empty_block", the_block);
+
4081. 72 }
+
4082. 72 the_block.disrupt = false;
+
4083. 5633 } else {
+
4084. 5633 the_block.disrupt = stmts[stmts.length - 1].disrupt;
+
4085. 5705 }
+
4086. 5705 advance("}");
+
4087. 5705 return the_block;
+
4088. 5705 }
+
4089. 631
+
4090. 23297 function check_left(left, right) {
+
4091. 23297
+
4092. 23297// Warn if the left is not one of these:
+
4093. 23297// ?.
+
4094. 23297// ?:
+
4095. 23297// e()
+
4096. 23297// e.b
+
4097. 23297// e[b]
+
4098. 23297// identifier
+
4099. 23297
+
4100. 23297 const id = left.id;
+
4101. 23297 if (
+
4102. 23297 !left.identifier
+
4103. 6298 && (
+
4104. 6298 left.arity !== "ternary"
+
4105. 6298 || (
+
4106. 6298 !check_left(left.expression[1])
+
4107. 6298 && !check_left(left.expression[2])
+
4108. 6298 )
+
4109. 6298 )
+
4110. 6298 && (
+
4111. 6298 left.arity !== "binary"
+
4112. 6298 || (id !== "." && id !== "?." && id !== "(" && id !== "[")
+
4113. 6298 )
+
4114. 11 ) {
+
4115. 11 warn("unexpected_a", right || token_nxt);
+
4116. 11 return false;
+
4117. 23286 }
+
4118. 23286 return true;
+
4119. 23286 }
+
4120. 631
+
4121. 5012 function check_mutation(the_thing) {
+
4122. 5012
+
4123. 5012// The only expressions that may be assigned to are
+
4124. 5012// e.b
+
4125. 5012// e[b]
+
4126. 5012// v
+
4127. 5012// [destructure]
+
4128. 5012// {destructure}
+
4129. 5012
+
4130. 5012 if (
+
4131. 5012 the_thing.arity !== "variable"
+
4132. 1543 && the_thing.id !== "."
+
4133. 192 && the_thing.id !== "["
+
4134. 7 && the_thing.id !== "{"
+
4135. 7 ) {
+
4136. 7
+
4137. 7// test_cause:
+
4138. 7// ["0=0", "check_mutation", "bad_assignment_a", "0", 1]
+
4139. 7
+
4140. 7 warn("bad_assignment_a", the_thing);
+
4141. 7 return false;
+
4142. 5005 }
+
4143. 5005 return true;
+
4144. 5005 }
+
4145. 631
+
4146. 2208 function check_not_top_level(thing) {
+
4147. 2208
+
4148. 2208// Some features should not be at the outermost level.
+
4149. 2208
+
4150. 34 if (functionage === token_global) {
+
4151. 34
+
4152. 34// test_cause:
+
4153. 34// ["
+
4154. 34// while(0){}
+
4155. 34// ", "check_not_top_level", "unexpected_at_top_level_a", "while", 1]
+
4156. 34
+
4157. 34 warn("unexpected_at_top_level_a", thing);
+
4158. 34 }
+
4159. 2208 }
+
4160. 631
+
4161. 3360 function check_ordered(type, token_list) {
+
4162. 3360
+
4163. 3360// This function will warn if <token_list> is unordered.
+
4164. 3360
+
4165. 4062 token_list.reduce(function (aa, token) {
+
4166. 4062 const bb = artifact(token);
+
4167. 4048 if (!option_dict.unordered && aa > bb) {
+
4168. 4 warn("expected_a_b_before_c_d", token, type, bb, type, aa);
+
4169. 4 }
+
4170. 4062 return bb;
+
4171. 4062 }, "");
+
4172. 3360 }
+
4173. 631
+
4174. 1301 function check_ordered_case(case_list) {
+
4175. 1301
+
4176. 1301// This function will warn if <case_list> is unordered.
+
4177. 1301
+
4178. 2691 case_list.filter(noop).map(function (token) {
+
4179. 2650 switch (token.identifier || token.id) {
+
4180. 34 case "(number)":
+
4181. 34 return {
+
4182. 34 order: 1,
+
4183. 34 token,
+
4184. 34 type: "number",
+
4185. 34 value: Number(artifact(token))
+
4186. 34 };
+
4187. 2604 case "(string)":
+
4188. 2604 return {
+
4189. 2604 order: 2,
+
4190. 2604 token,
+
4191. 2604 type: "string",
+
4192. 2604 value: artifact(token)
+
4193. 2604 };
+
4194. 41 case true:
+
4195. 41 return {
+
4196. 41 order: 3,
+
4197. 41 token,
+
4198. 41 type: "identifier",
+
4199. 41 value: artifact(token)
+
4200. 41 };
+
4201. 2691 }
+
4202. 2691 }).reduce(function (aa, bb) {
+
4203. 2691 if (
+
4204. 2691
+
4205. 2691// PR-419 - Hide warning about unordered case-statements behind beta-flag.
+
4206. 2691
+
4207. 2691 option_dict.beta
+
4208. 2691 && !option_dict.unordered
+
4209. 2683 && aa && bb
+
4210. 1384 && (
+
4211. 1384 aa.order > bb.order
+
4212. 1384 || (aa.order === bb.order && aa.value > bb.value)
+
4213. 1384 )
+
4214. 10 ) {
+
4215. 10 warn(
+
4216. 10 "expected_a_b_before_c_d",
+
4217. 10 bb.token,
+
4218. 10 `case-${bb.type}`,
+
4219. 10 bb.value,
+
4220. 10 `case-${aa.type}`,
+
4221. 10 aa.value
+
4222. 10 );
+
4223. 10 }
+
4224. 2691 return bb;
+
4225. 2691 }, undefined);
+
4226. 1301 }
+
4227. 631
+
4228. 3263 function condition() {
+
4229. 3263
+
4230. 3263// Parse the condition part of a do, if, while.
+
4231. 3263
+
4232. 3263 const the_paren = token_nxt;
+
4233. 3263 let the_value;
+
4234. 3263
+
4235. 3263// test_cause:
+
4236. 3263// ["do{}while()", "condition", "", "", 0]
+
4237. 3263// ["if(){}", "condition", "", "", 0]
+
4238. 3263// ["while(){}", "condition", "", "", 0]
+
4239. 3263
+
4240. 3263 test_cause("");
+
4241. 3263 the_paren.free = true;
+
4242. 3263 advance("(");
+
4243. 3263 the_value = parse_expression(0);
+
4244. 3263 advance(")");
+
4245. 1 if (the_value.wrapped === true) {
+
4246. 1
+
4247. 1// test_cause:
+
4248. 1// ["while((0)){}", "condition", "unexpected_a", "(", 6]
+
4249. 1
+
4250. 1 warn("unexpected_a", the_paren);
+
4251. 3259 }
+
4252. 3259
+
4253. 3259// Check for anticondition.
+
4254. 3259
+
4255. 3259 switch (the_value.id) {
+
4256. 3259 case "%":
+
4257. 1 warn("unexpected_a", the_value);
+
4258. 1 break;
+
4259. 1 case "&":
+
4260. 1 warn("unexpected_a", the_value);
+
4261. 1 break;
+
4262. 17 case "(number)":
+
4263. 17 warn("unexpected_a", the_value);
+
4264. 17 break;
+
4265. 1 case "(string)":
+
4266. 1 warn("unexpected_a", the_value);
+
4267. 1 break;
+
4268. 1 case "*":
+
4269. 1 warn("unexpected_a", the_value);
+
4270. 1 break;
+
4271. 1 case "+":
+
4272. 1 warn("unexpected_a", the_value);
+
4273. 1 break;
+
4274. 1 case "-":
+
4275. 1 warn("unexpected_a", the_value);
+
4276. 1 break;
+
4277. 1 case "/":
+
4278. 1 warn("unexpected_a", the_value);
+
4279. 1 break;
+
4280. 1 case "<<":
+
4281. 1 warn("unexpected_a", the_value);
+
4282. 1 break;
+
4283. 1 case ">>":
+
4284. 1 warn("unexpected_a", the_value);
+
4285. 1 break;
+
4286. 1 case ">>>":
+
4287. 1 warn("unexpected_a", the_value);
+
4288. 1 break;
+
4289. 1 case "?":
+
4290. 1 warn("unexpected_a", the_value);
+
4291. 1 break;
+
4292. 1 case "^":
+
4293. 1 warn("unexpected_a", the_value);
+
4294. 1 break;
+
4295. 1 case "typeof":
+
4296. 1 warn("unexpected_a", the_value);
+
4297. 1 break;
+
4298. 1 case "|":
+
4299. 1 warn("unexpected_a", the_value);
+
4300. 1 break;
+
4301. 1 case "~":
+
4302. 1
+
4303. 1// test_cause:
+
4304. 1// ["if(0%0){}", "condition", "unexpected_a", "%", 5]
+
4305. 1// ["if(0&0){}", "condition", "unexpected_a", "&", 5]
+
4306. 1// ["if(0){}", "condition", "unexpected_a", "0", 4]
+
4307. 1// ["if(0*0){}", "condition", "unexpected_a", "*", 5]
+
4308. 1// ["if(0+0){}", "condition", "unexpected_a", "+", 5]
+
4309. 1// ["if(0-0){}", "condition", "unexpected_a", "-", 5]
+
4310. 1// ["if(0/0){}", "condition", "unexpected_a", "/", 5]
+
4311. 1// ["if(0<<0){}", "condition", "unexpected_a", "<<", 5]
+
4312. 1// ["if(0>>0){}", "condition", "unexpected_a", ">>", 5]
+
4313. 1// ["if(0>>>0){}", "condition", "unexpected_a", ">>>", 5]
+
4314. 1// ["if(0?0:0){}", "condition", "unexpected_a", "?", 5]
+
4315. 1// ["if(0^0){}", "condition", "unexpected_a", "^", 5]
+
4316. 1// ["if(0|0){}", "condition", "unexpected_a", "|", 5]
+
4317. 1// ["if(\"aa\"){}", "condition", "unexpected_a", "aa", 4]
+
4318. 1// ["if(typeof 0){}", "condition", "unexpected_a", "typeof", 4]
+
4319. 1// ["if(~0){}", "condition", "unexpected_a", "~", 4]
+
4320. 1
+
4321. 1 warn("unexpected_a", the_value);
+
4322. 1 break;
+
4323. 3259 }
+
4324. 3259 return the_value;
+
4325. 3259 }
+
4326. 631
+
4327. 10096 function constant(id, type, value) {
+
4328. 10096
+
4329. 10096// Create a constant symbol.
+
4330. 10096
+
4331. 10096 const the_symbol = symbol(id);
+
4332. 10096 the_symbol.constant = true;
+
4333. 10096 the_symbol.nud_prefix = (
+
4334. 10096 typeof value === "function"
+
4335. 4417 ? value
+
4336. 18689 : function () {
+
4337. 18689 token_now.constant = true;
+
4338. 5679 if (value !== undefined) {
+
4339. 5679 token_now.value = value;
+
4340. 5679 }
+
4341. 18689 return token_now;
+
4342. 18689 }
+
4343. 10096 );
+
4344. 10096 the_symbol.type = type;
+
4345. 10096 the_symbol.value = value;
+
4346. 10096 return the_symbol;
+
4347. 10096 }
+
4348. 631
+
4349. 5 function constant_Function() {
+
4350. 2 if (!option_dict.eval) {
+
4351. 2
+
4352. 2// test_cause:
+
4353. 2// ["Function", "constant_Function", "unexpected_a", "Function", 1]
+
4354. 2
+
4355. 2 warn("unexpected_a", token_now);
+
4356. 3 } else if (token_nxt.id !== "(") {
+
4357. 3
+
4358. 3// test_cause:
+
4359. 3// ["
+
4360. 3// /*jslint eval*/
+
4361. 3// Function
+
4362. 3// ", "constant_Function", "expected_a_before_b", "(end)", 1]
+
4363. 3
+
4364. 3 warn("expected_a_before_b", token_nxt, "(", artifact());
+
4365. 3 }
+
4366. 5 return token_now;
+
4367. 5 }
+
4368. 631
+
4369. 1 function constant_arguments() {
+
4370. 1
+
4371. 1// test_cause:
+
4372. 1// ["arguments", "constant_arguments", "unexpected_a", "arguments", 1]
+
4373. 1
+
4374. 1 warn("unexpected_a", token_now);
+
4375. 1 return token_now;
+
4376. 1 }
+
4377. 631
+
4378. 4 function constant_eval() {
+
4379. 1 if (!option_dict.eval) {
+
4380. 1
+
4381. 1// test_cause:
+
4382. 1// ["eval", "constant_eval", "unexpected_a", "eval", 1]
+
4383. 1
+
4384. 1 warn("unexpected_a", token_now);
+
4385. 3 } else if (token_nxt.id !== "(") {
+
4386. 3
+
4387. 3// test_cause:
+
4388. 3// ["/*jslint eval*/\neval", "constant_eval", "expected_a_before_b", "(end)", 1]
+
4389. 3
+
4390. 3 warn("expected_a_before_b", token_nxt, "(", artifact());
+
4391. 3 }
+
4392. 4 return token_now;
+
4393. 4 }
+
4394. 631
+
4395. 1 function constant_ignore() {
+
4396. 1
+
4397. 1// test_cause:
+
4398. 1// ["ignore", "constant_ignore", "unexpected_a", "ignore", 1]
+
4399. 1
+
4400. 1 warn("unexpected_a", token_now);
+
4401. 1 return token_now;
+
4402. 1 }
+
4403. 631
+
4404. 1 function constant_isInfinite() {
+
4405. 1
+
4406. 1// test_cause:
+
4407. 1// ["isFinite", "constant_isInfinite", "expected_a_b", "isFinite", 1]
+
4408. 1
+
4409. 1 warn("expected_a_b", token_now, "Number.isFinite", "isFinite");
+
4410. 1 return token_now;
+
4411. 1 }
+
4412. 631
+
4413. 1 function constant_isNaN() {
+
4414. 1
+
4415. 1// test_cause:
+
4416. 1// ["isNaN(0)", "constant_isNaN", "number_isNaN", "isNaN", 1]
+
4417. 1
+
4418. 1 warn("number_isNaN", token_now);
+
4419. 1 return token_now;
+
4420. 1 }
+
4421. 631
+
4422. 3 function constant_this() {
+
4423. 1 if (!option_dict.this) {
+
4424. 1
+
4425. 1// test_cause:
+
4426. 1// ["this", "constant_this", "unexpected_a", "this", 1]
+
4427. 1
+
4428. 1 warn("unexpected_a", token_now);
+
4429. 1 }
+
4430. 3 return token_now;
+
4431. 3 }
+
4432. 631
+
4433. 6366 function enroll(name, role, readonly) {
+
4434. 6366
+
4435. 6366// Enroll a name into the current function context. The role can be exception,
+
4436. 6366// function, label, parameter, or variable. We look for variable redefinition
+
4437. 6366// because it causes confusion.
+
4438. 6366
+
4439. 6366 let earlier;
+
4440. 6366 let id = name.id;
+
4441. 6366
+
4442. 6366// Reserved words may not be enrolled.
+
4443. 6366
+
4444. 42 if (syntax_dict[id] !== undefined && id !== "ignore") {
+
4445. 1
+
4446. 1// test_cause:
+
4447. 1// ["let undefined", "enroll", "reserved_a", "undefined", 5]
+
4448. 1
+
4449. 1 warn("reserved_a", name);
+
4450. 1 return;
+
4451. 6365 }
+
4452. 6365
+
4453. 6365// Has the name been enrolled in this context?
+
4454. 6365
+
4455. 6365 earlier = functionage.context[id] || catchage.context[id];
+
4456. 7 if (earlier) {
+
4457. 7
+
4458. 7// test_cause:
+
4459. 7// ["let aa;let aa", "enroll", "redefinition_a_b", "1", 12]
+
4460. 7
+
4461. 7 warn("redefinition_a_b", name, id, earlier.line);
+
4462. 7 return;
+
4463. 6358 }
+
4464. 6358
+
4465. 6358// Has the name been enrolled in an outer context?
+
4466. 6358
+
4467. 10756 function_stack.forEach(function ({
+
4468. 10756 context
+
4469. 10756 }) {
+
4470. 10601 earlier = context[id] || earlier;
+
4471. 10756 });
+
4472. 6358 if (earlier && id === "ignore") {
+
4473. 4 if (earlier.role === "variable") {
+
4474. 4
+
4475. 4// test_cause:
+
4476. 4// ["let ignore;function aa(ignore){}", "enroll", "redefinition_a_b", "1", 24]
+
4477. 4
+
4478. 4 warn("redefinition_a_b", name, id, earlier.line);
+
4479. 4 }
+
4480. 6354 } else if (
+
4481. 6354 earlier
+
4482. 6354 && role !== "parameter" && role !== "function"
+
4483. 6354 && (role !== "exception" || earlier.role !== "exception")
+
4484. 6354 ) {
+
4485. 6354
+
4486. 6354// test_cause:
+
4487. 6354// ["
+
4488. 6354// function aa(){try{aa();}catch(aa){aa();}}
+
4489. 6354// ", "enroll", "redefinition_a_b", "1", 31]
+
4490. 6354// ["function aa(){var aa;}", "enroll", "redefinition_a_b", "1", 19]
+
4491. 6354
+
4492. 6354 warn("redefinition_a_b", name, id, earlier.line);
+
4493. 6354 } else if (
+
4494. 6354 option_dict.beta
+
4495. 6354 && global_dict[id]
+
4496. 6354 && role !== "parameter"
+
4497. 6354 ) {
+
4498. 6354
+
4499. 6354// test_cause:
+
4500. 6354// ["let Array", "enroll", "redefinition_global_a_b", "Array", 5]
+
4501. 6354
+
4502. 6354 warn("redefinition_global_a_b", name, global_dict[id], id);
+
4503. 6358 }
+
4504. 6358
+
4505. 6358// Enroll it.
+
4506. 6358
+
4507. 6358 Object.assign(name, {
+
4508. 6358 dead: true,
+
4509. 6358 init: false,
+
4510. 6358 parent: (
+
4511. 6358 role === "exception"
+
4512. 6358 ? catchage
+
4513. 6328 : functionage
+
4514. 6366 ),
+
4515. 6366 readonly,
+
4516. 6366 role,
+
4517. 6366 used: 0
+
4518. 6366 });
+
4519. 6366 name.parent.context[id] = name;
+
4520. 6366 }
+
4521. 631
+
4522. 18930 function infix(bp, id, f) {
+
4523. 18930
+
4524. 18930// Create an infix operator.
+
4525. 18930
+
4526. 18930 const the_symbol = symbol(id, bp);
+
4527. 31941 the_symbol.led_infix = function (left) {
+
4528. 31941 const the_token = token_now;
+
4529. 31941 the_token.arity = "binary";
+
4530. 23493 if (f !== undefined) {
+
4531. 23493 return f(left);
+
4532. 23493 }
+
4533. 8448 the_token.expression = [left, parse_expression(bp)];
+
4534. 8448 return the_token;
+
4535. 8448 };
+
4536. 18930 return the_symbol;
+
4537. 18930 }
+
4538. 631
+
4539. 11597 function infix_dot(left) {
+
4540. 11597 const the_token = token_now;
+
4541. 11597 let name = token_nxt;
+
4542. 11597 if (
+
4543. 11597 (
+
4544. 11597 left.id !== "(string)"
+
4545. 44 || (name.id !== "indexOf" && name.id !== "repeat")
+
4546. 11597 )
+
4547. 11554 && (
+
4548. 11554 left.id !== "["
+
4549. 11554 || (
+
4550. 11554 name.id !== "concat"
+
4551. 11554 && name.id !== "flat"
+
4552. 11554 && name.id !== "flatMap"
+
4553. 11554 && name.id !== "forEach"
+
4554. 11554 && name.id !== "join"
+
4555. 11554 && name.id !== "map"
+
4556. 11554 )
+
4557. 11554 )
+
4558. 11509 && (left.id !== "+" || name.id !== "slice")
+
4559. 11504 && (
+
4560. 11504 left.id !== "(regexp)"
+
4561. 11504 || (name.id !== "exec" && name.id !== "test")
+
4562. 11504 )
+
4563. 11437 ) {
+
4564. 11437
+
4565. 11437// test_cause:
+
4566. 11437// ["\"\".aa", "check_left", "unexpected_a", ".", 3]
+
4567. 11437
+
4568. 11437 check_left(left, the_token);
+
4569. 11437 }
+
4570. 1 if (!name.identifier) {
+
4571. 1
+
4572. 1// test_cause:
+
4573. 1// ["aa.0", "infix_dot", "expected_identifier_a", "0", 4]
+
4574. 1
+
4575. 1 stop("expected_identifier_a");
+
4576. 11596 }
+
4577. 11596 advance();
+
4578. 11596 survey(name);
+
4579. 11596
+
4580. 11596// The property name is not an expression.
+
4581. 11596
+
4582. 11596 the_token.name = name;
+
4583. 11596 the_token.expression = left;
+
4584. 11596 return the_token;
+
4585. 11596 }
+
4586. 631
+
4587. 1 function infix_fart_unwrapped() {
+
4588. 1
+
4589. 1// test_cause:
+
4590. 1// ["aa=>0", "infix_fart_unwrapped", "wrap_fart_parameter", "=>", 3]
+
4591. 1
+
4592. 1 return stop("wrap_fart_parameter", token_now);
+
4593. 1 }
+
4594. 631
+
4595. 1 function infix_grave(left) {
+
4596. 1 const the_tick = prefix_tick();
+
4597. 1
+
4598. 1// test_cause:
+
4599. 1// ["0``", "check_left", "unexpected_a", "`", 2]
+
4600. 1
+
4601. 1 check_left(left, the_tick);
+
4602. 1 the_tick.expression = [left].concat(the_tick.expression);
+
4603. 1 return the_tick;
+
4604. 1 }
+
4605. 631
+
4606. 1461 function infix_lbracket(left) {
+
4607. 1461 const the_token = token_now;
+
4608. 1461 let name;
+
4609. 1461 let the_subscript = parse_expression(0);
+
4610. 1438 if (the_subscript.id === "(string)" || the_subscript.id === "`") {
+
4611. 25 name = survey(the_subscript);
+
4612. 25
+
4613. 25// PR-404 - Add new directive "subscript" to play nice with Google Closure.
+
4614. 25
+
4615. 25 if (!option_dict.subscript && jslint_rgx_identifier.test(name)) {
+
4616. 25
+
4617. 25// test_cause:
+
4618. 25// ["aa[`aa`]", "infix_lbracket", "subscript_a", "aa", 4]
+
4619. 25
+
4620. 25 warn("subscript_a", the_subscript, name);
+
4621. 25 }
+
4622. 25 }
+
4623. 1461
+
4624. 1461// test_cause:
+
4625. 1461// ["0[0]", "check_left", "unexpected_a", "[", 2]
+
4626. 1461
+
4627. 1461 check_left(left, the_token);
+
4628. 1461 the_token.expression = [left, the_subscript];
+
4629. 1461 advance("]");
+
4630. 1461 return the_token;
+
4631. 1461 }
+
4632. 631
+
4633. 10421 function infix_lparen(left) {
+
4634. 10421 const the_paren = token_now;
+
4635. 10421 let ellipsis;
+
4636. 10421 let the_argument;
+
4637. 10384 if (left.id !== "function") {
+
4638. 10384
+
4639. 10384// test_cause:
+
4640. 10384// ["(0?0:0)()", "check_left", "unexpected_a", "(", 8]
+
4641. 10384// ["0()", "check_left", "unexpected_a", "(", 2]
+
4642. 10384
+
4643. 10384 check_left(left, the_paren);
+
4644. 10384 }
+
4645. 7699 if (functionage.arity === "statement" && left.identifier) {
+
4646. 5503 functionage.name.calls[left.id] = left;
+
4647. 5503 }
+
4648. 10421 the_paren.expression = [left];
+
4649. 8962 if (token_nxt.id !== ")") {
+
4650. 8962
+
4651. 8962// Parse/loop through each token in expression (...).
+
4652. 8962
+
4653. 14286 while (true) {
+
4654. 14286 if (token_nxt.id === "...") {
+
4655. 14286 ellipsis = true;
+
4656. 14286 advance("...");
+
4657. 14286 }
+
4658. 14286 the_argument = parse_expression(10);
+
4659. 14286 if (ellipsis) {
+
4660. 14286 the_argument.ellipsis = true;
+
4661. 14286 }
+
4662. 14286 the_paren.expression.push(the_argument);
+
4663. 14286 if (token_nxt.id !== ",") {
+
4664. 14286 break;
+
4665. 14286 }
+
4666. 14286 advance(",");
+
4667. 14286 }
+
4668. 8962 }
+
4669. 10421 advance(")", the_paren);
+
4670. 5260 if (the_paren.expression.length === 2) {
+
4671. 5260
+
4672. 5260// test_cause:
+
4673. 5260// ["aa(0)", "infix_lparen", "free", "", 0]
+
4674. 5260
+
4675. 5260 test_cause("free");
+
4676. 5260 the_paren.free = true;
+
4677. 5260 if (the_argument.wrapped === true) {
+
4678. 5260
+
4679. 5260// test_cause:
+
4680. 5260// ["aa((0))", "infix_lparen", "unexpected_a", "(", 3]
+
4681. 5260
+
4682. 5260 warn("unexpected_a", the_paren);
+
4683. 5260 }
+
4684. 5260 if (the_argument.id === "(") {
+
4685. 5260 the_argument.wrapped = true;
+
4686. 5260 }
+
4687. 5260 } else {
+
4688. 5161
+
4689. 5161// test_cause:
+
4690. 5161// ["aa()", "infix_lparen", "not_free", "", 0]
+
4691. 5161// ["aa(0,0)", "infix_lparen", "not_free", "", 0]
+
4692. 5161
+
4693. 5161 test_cause("not_free");
+
4694. 5161 the_paren.free = false;
+
4695. 5161 }
+
4696. 10421 return the_paren;
+
4697. 10421 }
+
4698. 631
+
4699. 12 function infix_option_chain(left) {
+
4700. 12 const the_token = token_now;
+
4701. 12 let name = token_nxt;
+
4702. 12 if (
+
4703. 12 (
+
4704. 12 left.id !== "(string)"
+
4705. 1 || (name.id !== "indexOf" && name.id !== "repeat")
+
4706. 12 )
+
4707. 12 && (
+
4708. 12 left.id !== "["
+
4709. 1 || (
+
4710. 1 name.id !== "concat"
+
4711. 1 && name.id !== "forEach"
+
4712. 1 && name.id !== "join"
+
4713. 1 && name.id !== "map"
+
4714. 1 )
+
4715. 12 )
+
4716. 12
+
4717. 12// test_cause:
+
4718. 12// ["(0+0)?.0", "infix_option_chain", "check_left", "", 0]
+
4719. 12
+
4720. 1 && (left.id !== "+" || name.id !== "slice")
+
4721. 12 && (
+
4722. 12 left.id !== "(regexp)"
+
4723. 1 || (name.id !== "exec" && name.id !== "test")
+
4724. 12 )
+
4725. 12 ) {
+
4726. 12 test_cause("check_left");
+
4727. 12
+
4728. 12// test_cause:
+
4729. 12// ["(/./)?.0", "check_left", "unexpected_a", "?.", 6]
+
4730. 12// ["\"aa\"?.0", "check_left", "unexpected_a", "?.", 5]
+
4731. 12// ["aa=[]?.aa", "check_left", "unexpected_a", "?.", 6]
+
4732. 12
+
4733. 12 check_left(left, the_token);
+
4734. 12 }
+
4735. 12
+
4736. 12// Issue #468 - Fix optional dynamic-property/function-call not recognized.
+
4737. 12
+
4738. 11 if (name.id === "[" || name.id === "(") {
+
4739. 2 test_cause("dyn_prop_or_call");
+
4740. 2
+
4741. 2// test_cause:
+
4742. 2// ["aa?.(bb)", "infix_option_chain", "dyn_prop_or_call", "", 0]
+
4743. 2// ["aa?.[bb]", "infix_option_chain", "dyn_prop_or_call", "", 0]
+
4744. 2
+
4745. 2 return left;
+
4746. 10 }
+
4747. 10 if (!name.identifier) {
+
4748. 4
+
4749. 4// test_cause:
+
4750. 4// ["aa?.0", "infix_option_chain", "expected_identifier_a", "0", 5]
+
4751. 4
+
4752. 4 stop("expected_identifier_a");
+
4753. 6 }
+
4754. 6 advance();
+
4755. 6 survey(name);
+
4756. 6
+
4757. 6// The property name is not an expression.
+
4758. 6
+
4759. 6 the_token.name = name;
+
4760. 6 the_token.expression = left;
+
4761. 6 return the_token;
+
4762. 6 }
+
4763. 631
+
4764. 631 function infixr(bp, id) {
+
4765. 631
+
4766. 631// Create a right associative infix operator.
+
4767. 631
+
4768. 631 const the_symbol = symbol(id, bp);
+
4769. 1 the_symbol.led_infix = function parse_infixr_led(left) {
+
4770. 1 const the_token = token_now;
+
4771. 1
+
4772. 1// test_cause:
+
4773. 1// ["0**0", "parse_infixr_led", "led_infix", "", 0]
+
4774. 1
+
4775. 1 test_cause("led_infix");
+
4776. 1 the_token.arity = "binary";
+
4777. 1 the_token.expression = [left, parse_expression(bp - 1)];
+
4778. 1 return the_token;
+
4779. 1 };
+
4780. 631 return the_symbol;
+
4781. 631 }
+
4782. 631
+
4783. 56002 function parse_expression(rbp, initial) {
+
4784. 56002
+
4785. 56002// This is the heart of JSLINT, the Pratt parser. In addition to parsing, it
+
4786. 56002// is looking for ad hoc lint patterns. We add .fud_stmt to Pratt's model, which
+
4787. 56002// is like .nud_prefix except that it is only used on the first token of a
+
4788. 56002// statement. Having .fud_stmt makes it much easier to define statement-oriented
+
4789. 56002// languages like JavaScript. I retained Pratt's nomenclature.
+
4790. 56002// They are elements of the parsing method called Top Down Operator Precedence.
+
4791. 56002
+
4792. 56002// .nud_prefix Null denotation. The prefix handler.
+
4793. 56002// .fud_stmt First null denotation. The statement handler.
+
4794. 56002// .led_infix Left denotation. The infix/postfix handler.
+
4795. 56002// lbp Left binding power of infix operator. It tells us how strongly
+
4796. 56002// the operator binds to the argument at its left.
+
4797. 56002// rbp Right binding power.
+
4798. 56002
+
4799. 56002// It processes a nud_prefix (variable, constant, prefix operator). It will then
+
4800. 56002// process leds (infix operators) until the bind powers cause it to stop (it
+
4801. 56002// consumes tokens until it meets a token whose lbp <= rbp). Specifically, it
+
4802. 56002// means that it collects all tokens that bind together before returning to the
+
4803. 56002// operator that called it. It returns the expression's parse tree.
+
4804. 56002
+
4805. 56002// For example, "3 + 1 * 2 * 4 + 5"
+
4806. 56002// parses into
+
4807. 56002// {
+
4808. 56002// "id": "+",
+
4809. 56002// "expression": [
+
4810. 56002// {
+
4811. 56002// "id": "+",
+
4812. 56002// "expression": [
+
4813. 56002// {
+
4814. 56002// "id": "(number)",
+
4815. 56002// "value": "3"
+
4816. 56002// },
+
4817. 56002// {
+
4818. 56002// "id": "*",
+
4819. 56002// "expression": [
+
4820. 56002// {
+
4821. 56002// "id": "*",
+
4822. 56002// "expression": [
+
4823. 56002// {
+
4824. 56002// "id": "(number)",
+
4825. 56002// "value": "1"
+
4826. 56002// },
+
4827. 56002// {
+
4828. 56002// "id": "(number)",
+
4829. 56002// "value": "2"
+
4830. 56002// }
+
4831. 56002// ]
+
4832. 56002// },
+
4833. 56002// {
+
4834. 56002// "id": "(number)",
+
4835. 56002// "value": "4"
+
4836. 56002// }
+
4837. 56002// ]
+
4838. 56002// }
+
4839. 56002// ]
+
4840. 56002// },
+
4841. 56002// {
+
4842. 56002// "id": "(number)",
+
4843. 56002// "value": "5"
+
4844. 56002// }
+
4845. 56002// ]
+
4846. 56002// }
+
4847. 56002
+
4848. 56002 let left;
+
4849. 56002 let the_symbol;
+
4850. 56002
+
4851. 56002// Statements will have already advanced, so advance now only if the token is
+
4852. 56002// not the first of a statement.
+
4853. 56002
+
4854. 44642 if (!initial) {
+
4855. 44642 advance();
+
4856. 44642 }
+
4857. 56002 the_symbol = syntax_dict[token_now.id];
+
4858. 24510 if (the_symbol !== undefined && the_symbol.nud_prefix !== undefined) {
+
4859. 24451
+
4860. 24451// test_cause:
+
4861. 24451// ["0", "parse_expression", "symbol", "", 0]
+
4862. 24451
+
4863. 24451 test_cause("symbol");
+
4864. 24451 left = the_symbol.nud_prefix();
+
4865. 31551 } else if (token_now.identifier) {
+
4866. 31551
+
4867. 31551// test_cause:
+
4868. 31551// ["aa", "parse_expression", "identifier", "", 0]
+
4869. 31551
+
4870. 31551 test_cause("identifier");
+
4871. 31551 left = token_now;
+
4872. 31551 left.arity = "variable";
+
4873. 31551 } else {
+
4874. 31551
+
4875. 31551// test_cause:
+
4876. 31551// ["!", "parse_expression", "unexpected_a", "(end)", 1]
+
4877. 31551// ["/./", "parse_expression", "unexpected_a", "/", 1]
+
4878. 31551// ["let aa=`${}`;", "parse_expression", "unexpected_a", "}", 11]
+
4879. 31551
+
4880. 31551 return stop("unexpected_a", token_now);
+
4881. 55966 }
+
4882. 55966
+
4883. 55966// Parse/loop through each symbol in expression.
+
4884. 55966
+
4885. 93124 while (true) {
+
4886. 93124 the_symbol = syntax_dict[token_nxt.id];
+
4887. 93124 if (
+
4888. 93124 the_symbol === undefined
+
4889. 93124 || the_symbol.led_infix === undefined
+
4890. 93124 || the_symbol.lbp <= rbp
+
4891. 93124 ) {
+
4892. 93124 break;
+
4893. 93124 }
+
4894. 93124 advance();
+
4895. 93124 left = the_symbol.led_infix(left);
+
4896. 93124 }
+
4897. 55955 return left;
+
4898. 55955 }
+
4899. 631
+
4900. 14 function parse_fart(the_fart) {
+
4901. 14
+
4902. 14// Give the function properties storing its names and for observing the depth
+
4903. 14// of loops and switches.
+
4904. 14
+
4905. 14 Object.assign(the_fart, {
+
4906. 14 arity: "binary",
+
4907. 14 context: empty(),
+
4908. 14 finally: 0,
+
4909. 14 level: functionage.level + 1,
+
4910. 14 loop: 0,
+
4911. 14 name: anon,
+
4912. 14 switch: 0,
+
4913. 14 try: 0
+
4914. 14 });
+
4915. 14
+
4916. 14// PR-384 - Relax warning "function_in_loop".
+
4917. 14//
+
4918. 14// if (functionage.loop > 0) {
+
4919. 14
+
4920. 14// // test_cause:
+
4921. 14// // ["while(0){aa.map(()=>0);}", "parse_fart", "function_in_loop", "=>", 19]
+
4922. 14//
+
4923. 14// warn("function_in_loop", the_fart);
+
4924. 14// }
+
4925. 14
+
4926. 14// Push the current function context and establish a new one.
+
4927. 14
+
4928. 14 function_list.push(the_fart);
+
4929. 14 function_stack.push(functionage);
+
4930. 14 functionage = the_fart;
+
4931. 14
+
4932. 14// Parse the parameter list.
+
4933. 14
+
4934. 14 prefix_function_parameter(the_fart);
+
4935. 14 advance("=>");
+
4936. 14
+
4937. 14// The function's body is a block.
+
4938. 14
+
4939. 3 if (token_nxt.id === "{") {
+
4940. 3 if (!option_dict.fart) {
+
4941. 3
+
4942. 3// test_cause:
+
4943. 3// ["()=>{}", "parse_fart", "use_function_not_fart", "=>", 3]
+
4944. 3
+
4945. 3 warn("use_function_not_fart", the_fart);
+
4946. 3 }
+
4947. 3 the_fart.block = block("body");
+
4948. 11 } else if (
+
4949. 11 syntax_dict[token_nxt.id] !== undefined
+
4950. 11 && syntax_dict[token_nxt.id].fud_stmt !== undefined
+
4951. 11 ) {
+
4952. 11
+
4953. 11// PR-384 - Bugfix - Fixes issue #379 - warn against naked-statement in fart.
+
4954. 11
+
4955. 11// test_cause:
+
4956. 11// ["()=>delete aa", "parse_fart", "unexpected_a_after_b", "=>", 5]
+
4957. 11
+
4958. 11 stop("unexpected_a_after_b", token_nxt, token_nxt.id, "=>");
+
4959. 11
+
4960. 11// The function's body is an expression.
+
4961. 11
+
4962. 11 } else {
+
4963. 11 the_fart.expression = parse_expression(0);
+
4964. 13 }
+
4965. 13
+
4966. 13// Restore the previous context.
+
4967. 13
+
4968. 13 functionage = function_stack.pop();
+
4969. 13 return the_fart;
+
4970. 13 }
+
4971. 631
+
4972. 12961 function parse_json() {
+
4973. 12961 let container;
+
4974. 12961 let is_dup;
+
4975. 12961 let name;
+
4976. 12961 let negative;
+
4977. 12961 switch (token_nxt.id) {
+
4978. 5262 case "(number)":
+
4979. 5262 if (!jslint_rgx_json_number.test(token_nxt.value)) {
+
4980. 5262
+
4981. 5262// test_cause:
+
4982. 5262// ["[-.0]", "parse_json", "unexpected_a", ".", 3]
+
4983. 5262// ["[-0x0]", "parse_json", "unexpected_a", "0x0", 3]
+
4984. 5262// ["[.0]", "parse_json", "unexpected_a", ".", 2]
+
4985. 5262// ["[0x0]", "parse_json", "unexpected_a", "0x0", 2]
+
4986. 5262
+
4987. 5262 warn("unexpected_a");
+
4988. 5262 }
+
4989. 5262 advance("(number)");
+
4990. 5262 return token_now;
+
4991. 1767 case "(string)":
+
4992. 1767 if (token_nxt.quote !== "\"") {
+
4993. 1767
+
4994. 1767// test_cause:
+
4995. 1767// ["['']", "parse_json", "unexpected_a", "'", 2]
+
4996. 1767
+
4997. 1767 warn("unexpected_a", token_nxt, token_nxt.quote);
+
4998. 1767 }
+
4999. 1767 advance("(string)");
+
5000. 1767 return token_now;
+
5001. 3 case "-":
+
5002. 3 negative = token_nxt;
+
5003. 3 negative.arity = "unary";
+
5004. 3 advance("-");
+
5005. 3
+
5006. 3// Recurse parse_json().
+
5007. 3
+
5008. 3 negative.expression = parse_json();
+
5009. 3 return negative;
+
5010. 1649 case "[":
+
5011. 1649
+
5012. 1649// test_cause:
+
5013. 1649// ["[]", "parse_json", "bracket", "", 0]
+
5014. 1649
+
5015. 1649 test_cause("bracket");
+
5016. 1649 container = token_nxt;
+
5017. 1649 container.expression = [];
+
5018. 1649 advance("[");
+
5019. 1649 if (token_nxt.id !== "]") {
+
5020. 3300 while (true) {
+
5021. 3300
+
5022. 3300// Recurse parse_json().
+
5023. 3300
+
5024. 3300 container.expression.push(parse_json());
+
5025. 3300 if (token_nxt.id !== ",") {
+
5026. 3300
+
5027. 3300// test_cause:
+
5028. 3300// ["[0,0]", "parse_json", "comma", "", 0]
+
5029. 3300
+
5030. 3300 test_cause("comma");
+
5031. 3300 break;
+
5032. 3300 }
+
5033. 3300 advance(",");
+
5034. 3300 }
+
5035. 1649 }
+
5036. 1649 advance("]", container);
+
5037. 1649 return container;
+
5038. 509 case "false":
+
5039. 511 case "null":
+
5040. 896 case "true":
+
5041. 896
+
5042. 896// test_cause:
+
5043. 896// ["[false]", "parse_json", "constant", "", 0]
+
5044. 896// ["[null]", "parse_json", "constant", "", 0]
+
5045. 896// ["[true]", "parse_json", "constant", "", 0]
+
5046. 896
+
5047. 896 test_cause("constant");
+
5048. 896 advance();
+
5049. 896 return token_now;
+
5050. 3379 case "{":
+
5051. 3379
+
5052. 3379// test_cause:
+
5053. 3379// ["{}", "parse_json", "brace", "", 0]
+
5054. 3379
+
5055. 3379 test_cause("brace");
+
5056. 3379 container = token_nxt;
+
5057. 3379
+
5058. 3379// Explicit empty-object required to detect "__proto__".
+
5059. 3379
+
5060. 3379 is_dup = empty();
+
5061. 3379 container.expression = [];
+
5062. 3379 advance("{");
+
5063. 3379 if (token_nxt.id !== "}") {
+
5064. 3379
+
5065. 3379// JSON
+
5066. 3379// Parse/loop through each property in {...}.
+
5067. 3379
+
5068. 9636 while (true) {
+
5069. 9636 if (token_nxt.quote !== "\"") {
+
5070. 9636
+
5071. 9636// test_cause:
+
5072. 9636// ["{0:0}", "parse_json", "unexpected_a", "0", 2]
+
5073. 9636
+
5074. 9636 warn(
+
5075. 9636 "unexpected_a",
+
5076. 9636 token_nxt,
+
5077. 9636 token_nxt.quote
+
5078. 9636 );
+
5079. 9636 }
+
5080. 9636 name = token_nxt;
+
5081. 9636 advance("(string)");
+
5082. 9636 if (is_dup[token_now.value] !== undefined) {
+
5083. 9636
+
5084. 9636// test_cause:
+
5085. 9636// ["{\"aa\":0,\"aa\":0}", "parse_json", "duplicate_a", "aa", 9]
+
5086. 9636
+
5087. 9636 warn("duplicate_a", token_now);
+
5088. 9636 } else if (token_now.value === "__proto__") {
+
5089. 9636
+
5090. 9636// test_cause:
+
5091. 9636// ["{\"__proto__\":0}", "parse_json", "weird_property_a", "__proto__", 2]
+
5092. 9636
+
5093. 9636 warn("weird_property_a", token_now);
+
5094. 9636 } else {
+
5095. 9636 is_dup[token_now.value] = token_now;
+
5096. 9636 }
+
5097. 9636 advance(":");
+
5098. 9636 container.expression.push(
+
5099. 9636
+
5100. 9636// Recurse parse_json().
+
5101. 9636
+
5102. 9636 Object.assign(parse_json(), {
+
5103. 9636 label: name
+
5104. 9636 })
+
5105. 9636 );
+
5106. 9636 if (token_nxt.id !== ",") {
+
5107. 9636 break;
+
5108. 9636 }
+
5109. 9636 advance(",");
+
5110. 9636 }
+
5111. 3379 }
+
5112. 3379 advance("}", container);
+
5113. 3379 return container;
+
5114. 5 default:
+
5115. 5
+
5116. 5// test_cause:
+
5117. 5// ["[undefined]", "parse_json", "unexpected_a", "undefined", 2]
+
5118. 5
+
5119. 5 stop("unexpected_a");
+
5120. 12961 }
+
5121. 12961 }
+
5122. 631
+
5123. 20929 function parse_statement() {
+
5124. 20929
+
5125. 20929// Parse a statement. Any statement may have a label, but only four statements
+
5126. 20929// have use for one. A statement can be one of the standard statements, or
+
5127. 20929// an assignment expression, or an invocation expression.
+
5128. 20929
+
5129. 20929 let first;
+
5130. 20929 let the_label;
+
5131. 20929 let the_statement;
+
5132. 20929 let the_symbol;
+
5133. 20929 advance();
+
5134. 20742 if (token_now.identifier && token_nxt.id === ":") {
+
5135. 13 the_label = token_now;
+
5136. 13 if (the_label.id === "ignore") {
+
5137. 13
+
5138. 13// test_cause:
+
5139. 13// ["ignore:", "parse_statement", "unexpected_a", "ignore", 1]
+
5140. 13
+
5141. 13 warn("unexpected_a", the_label);
+
5142. 13 }
+
5143. 13 advance(":");
+
5144. 13 switch (token_nxt.id) {
+
5145. 13 case "do":
+
5146. 13 case "for":
+
5147. 13 case "switch":
+
5148. 13 case "while":
+
5149. 13
+
5150. 13// test_cause:
+
5151. 13// ["aa:do{}", "parse_statement", "the_statement_label", "do", 0]
+
5152. 13// ["aa:for{}", "parse_statement", "the_statement_label", "for", 0]
+
5153. 13// ["aa:switch{}", "parse_statement", "the_statement_label", "switch", 0]
+
5154. 13// ["aa:while{}", "parse_statement", "the_statement_label", "while", 0]
+
5155. 13
+
5156. 13 test_cause("the_statement_label", token_nxt.id);
+
5157. 13 enroll(the_label, "label", true);
+
5158. 13 the_label.dead = false;
+
5159. 13 the_label.init = true;
+
5160. 13 the_statement = parse_statement();
+
5161. 13 functionage.statement_prv = the_statement;
+
5162. 13 the_statement.label = the_label;
+
5163. 13 the_statement.statement = true;
+
5164. 13 return the_statement;
+
5165. 13 }
+
5166. 13 advance();
+
5167. 13
+
5168. 13// test_cause:
+
5169. 13// ["aa:", "parse_statement", "unexpected_label_a", "aa", 1]
+
5170. 13
+
5171. 13 warn("unexpected_label_a", the_label);
+
5172. 20920 }
+
5173. 20920
+
5174. 20920// Parse the statement.
+
5175. 20920
+
5176. 20920 first = token_now;
+
5177. 20920 first.statement = true;
+
5178. 20920 the_symbol = syntax_dict[first.id];
+
5179. 20920 if (
+
5180. 20920 the_symbol !== undefined
+
5181. 20920 && the_symbol.fud_stmt !== undefined
+
5182. 20929
+
5183. 20929// PR-318 - Bugfix - Fixes issues #316, #317 - dynamic-import().
+
5184. 20929
+
5185. 10154 && !(the_symbol.id === "import" && token_nxt.id === "(")
+
5186. 10152 ) {
+
5187. 10152 the_symbol.disrupt = false;
+
5188. 10152 the_symbol.statement = true;
+
5189. 10152 token_now.arity = "statement";
+
5190. 10152 the_statement = the_symbol.fud_stmt();
+
5191. 10152 functionage.statement_prv = the_statement;
+
5192. 10768 } else {
+
5193. 10768
+
5194. 10768// It is an expression statement.
+
5195. 10768
+
5196. 10768 the_statement = parse_expression(0, true);
+
5197. 10768 functionage.statement_prv = the_statement;
+
5198. 10768 if (the_statement.wrapped && the_statement.id !== "(") {
+
5199. 10768
+
5200. 10768// test_cause:
+
5201. 10768// ["(0)", "parse_statement", "unexpected_a", "(", 1]
+
5202. 10768
+
5203. 10768 warn("unexpected_a", first);
+
5204. 10768 }
+
5205. 10768 semicolon();
+
5206. 20826 }
+
5207. 20826 if (the_label !== undefined) {
+
5208. 1 the_label.dead = true;
+
5209. 20826 }
+
5210. 20826 return the_statement;
+
5211. 20826 }
+
5212. 631
+
5213. 7501 function parse_statements() {
+
5214. 7501
+
5215. 7501// Parse a list of statements. Give a warning if an unreachable statement
+
5216. 7501// follows a disruptive statement.
+
5217. 7501
+
5218. 7501 const statement_list = [];
+
5219. 7501 let a_statement;
+
5220. 7501 let disrupt = false;
+
5221. 7501
+
5222. 7501// Parse/loop each statement until a statement-terminator is reached.
+
5223. 7501
+
5224. 28003 while (true) {
+
5225. 28003 switch (token_nxt.id) {
+
5226. 28003 case "(end)":
+
5227. 28003 case "case":
+
5228. 28003 case "default":
+
5229. 28003 case "else":
+
5230. 28003 case "}":
+
5231. 28003
+
5232. 28003// test_cause:
+
5233. 28003// [";", "parse_statements", "closer", "", 0]
+
5234. 28003// ["case", "parse_statements", "closer", "", 0]
+
5235. 28003// ["default", "parse_statements", "closer", "", 0]
+
5236. 28003// ["else", "parse_statements", "closer", "", 0]
+
5237. 28003// ["}", "parse_statements", "closer", "", 0]
+
5238. 28003
+
5239. 28003 test_cause("closer");
+
5240. 28003 return statement_list;
+
5241. 28003 }
+
5242. 28003 a_statement = parse_statement();
+
5243. 28003 statement_list.push(a_statement);
+
5244. 28003 if (disrupt) {
+
5245. 28003
+
5246. 28003// test_cause:
+
5247. 28003// ["while(0){break;0;}", "parse_statements", "unreachable_a", "0", 16]
+
5248. 28003
+
5249. 28003 warn("unreachable_a", a_statement);
+
5250. 28003 }
+
5251. 28003 disrupt = a_statement.disrupt;
+
5252. 28003 }
+
5253. 7501 }
+
5254. 631
+
5255. 1262 function postassign(id) {
+
5256. 1262
+
5257. 1262// Create one of the postassign operators.
+
5258. 1262
+
5259. 1262 const the_symbol = symbol(id, 150);
+
5260. 1 the_symbol.led_infix = function (left) {
+
5261. 1 token_now.expression = left;
+
5262. 1 token_now.arity = "postassign";
+
5263. 1 check_mutation(token_now.expression);
+
5264. 1 return token_now;
+
5265. 1 };
+
5266. 1262 return the_symbol;
+
5267. 1262 }
+
5268. 631
+
5269. 1262 function preassign(id) {
+
5270. 1262
+
5271. 1262// Create one of the preassign operators.
+
5272. 1262
+
5273. 1262 const the_symbol = symbol(id);
+
5274. 2 the_symbol.nud_prefix = function () {
+
5275. 2 const the_token = token_now;
+
5276. 2 the_token.arity = "preassign";
+
5277. 2 the_token.expression = parse_expression(150);
+
5278. 2 check_mutation(the_token.expression);
+
5279. 2 return the_token;
+
5280. 2 };
+
5281. 1262 return the_symbol;
+
5282. 1262 }
+
5283. 631
+
5284. 10727 function prefix(id, f) {
+
5285. 10727
+
5286. 10727// Create a prefix operator.
+
5287. 10727
+
5288. 10727 const the_symbol = symbol(id);
+
5289. 5744 the_symbol.nud_prefix = function () {
+
5290. 5744 const the_token = token_now;
+
5291. 5744 the_token.arity = "unary";
+
5292. 4932 if (typeof f === "function") {
+
5293. 4932 return f();
+
5294. 4932 }
+
5295. 812 the_token.expression = parse_expression(150);
+
5296. 812 return the_token;
+
5297. 812 };
+
5298. 10727 return the_symbol;
+
5299. 10727 }
+
5300. 631
+
5301. 1 function prefix_assign_divide() {
+
5302. 1
+
5303. 1// test_cause:
+
5304. 1// ["/=", "prefix_assign_divide", "expected_a_b", "/=", 1]
+
5305. 1
+
5306. 1 stop("expected_a_b", token_now, "/\\=", "/=");
+
5307. 1 }
+
5308. 631
+
5309. 136 function prefix_async() {
+
5310. 136 let the_async = token_now;
+
5311. 136 let the_function;
+
5312. 136 token_nxt.arity = the_async.arity;
+
5313. 136
+
5314. 136// PR-414 - Parse async fart.
+
5315. 136
+
5316. 3 if (token_nxt.fart) {
+
5317. 3 advance("(");
+
5318. 3 the_function = Object.assign(token_now.fart, {
+
5319. 3 async: 1
+
5320. 3 });
+
5321. 3 if (!option_dict.fart) {
+
5322. 3
+
5323. 3// test_cause:
+
5324. 3// ["async()=>0", "prefix_async", "use_function_not_fart", "=>", 8]
+
5325. 3
+
5326. 3 warn("use_function_not_fart", the_function);
+
5327. 3 }
+
5328. 3 prefix_lparen();
+
5329. 3
+
5330. 3// Parse async function.
+
5331. 3
+
5332. 133 } else {
+
5333. 133 advance("function");
+
5334. 133 the_function = Object.assign(token_now, {
+
5335. 133 async: 1
+
5336. 133 });
+
5337. 133 prefix_function();
+
5338. 133 }
+
5339. 3 if (the_function.async === 1) {
+
5340. 3
+
5341. 3// test_cause:
+
5342. 3// ["
+
5343. 3// async function aa(){}
+
5344. 3// ", "prefix_async", "missing_await_statement", "function", 7]
+
5345. 3
+
5346. 3 warn("missing_await_statement", the_function);
+
5347. 3 }
+
5348. 136 return the_function;
+
5349. 136 }
+
5350. 631
+
5351. 297 function prefix_await() {
+
5352. 297 const the_await = token_now;
+
5353. 297
+
5354. 297// PR-370 - Add top-level-await support.
+
5355. 297
+
5356. 4 if (functionage.async === 0 && functionage !== token_global) {
+
5357. 2
+
5358. 2// test_cause:
+
5359. 2// ["function aa(){aa=await 0;}", "prefix_await", "unexpected_a", "await", 18]
+
5360. 2// ["function aa(){await 0;}", "prefix_await", "unexpected_a", "await", 15]
+
5361. 2
+
5362. 2 warn("unexpected_a", the_await);
+
5363. 295 } else {
+
5364. 295 functionage.async += 1;
+
5365. 295 }
+
5366. 185 if (the_await.arity === "statement") {
+
5367. 185
+
5368. 185// PR-405 - Bugfix - fix expression after "await" mis-identified as statement.
+
5369. 185
+
5370. 185 the_await.expression = parse_expression(150);
+
5371. 185 semicolon();
+
5372. 185 } else {
+
5373. 112 the_await.expression = parse_expression(150);
+
5374. 112 }
+
5375. 297 return the_await;
+
5376. 297 }
+
5377. 631
+
5378. 1 function prefix_fart() {
+
5379. 1
+
5380. 1// test_cause:
+
5381. 1// ["=>0", "prefix_fart", "expected_a_before_b", "=>", 1]
+
5382. 1
+
5383. 1 return stop("expected_a_before_b", token_now, "()", "=>");
+
5384. 1 }
+
5385. 631
+
5386. 2005 function prefix_function(the_function) {
+
5387. 11 let name = the_function && the_function.name;
+
5388. 1994 if (the_function === undefined) {
+
5389. 1994 the_function = token_now;
+
5390. 1994
+
5391. 1994// A function statement must have a name that will be in the parent's scope.
+
5392. 1994
+
5393. 1994 if (the_function.arity === "statement") {
+
5394. 1994 if (!token_nxt.identifier) {
+
5395. 1994
+
5396. 1994// test_cause:
+
5397. 1994// ["function(){}", "prefix_function", "expected_identifier_a", "(", 9]
+
5398. 1994// ["function*aa(){}", "prefix_function", "expected_identifier_a", "*", 9]
+
5399. 1994
+
5400. 1994 return stop("expected_identifier_a");
+
5401. 1994 }
+
5402. 1994 name = token_nxt;
+
5403. 1994 enroll(name, "variable", true);
+
5404. 1994 the_function.name = Object.assign(name, {
+
5405. 1994 calls: empty(),
+
5406. 1994
+
5407. 1994// PR-331 - Bugfix - Fixes issue #272 - function hoisting not allowed.
+
5408. 1994
+
5409. 1994 dead: false,
+
5410. 1994 init: true
+
5411. 1994 });
+
5412. 1994 advance();
+
5413. 1994 } else if (name === undefined) {
+
5414. 1994
+
5415. 1994// A function expression may have an optional name.
+
5416. 1994
+
5417. 1994 the_function.name = anon;
+
5418. 1994 if (token_nxt.identifier) {
+
5419. 1994 name = token_nxt;
+
5420. 1994 the_function.name = name;
+
5421. 1994 advance();
+
5422. 1994 }
+
5423. 1994 }
+
5424. 2003 }
+
5425. 2003
+
5426. 2003// Probably deadcode.
+
5427. 2003// if (mode_mega) {
+
5428. 2003// warn("unexpected_a", the_function);
+
5429. 2003// }
+
5430. 2003// jslint_assert(!mode_mega, `Expected !mode_mega.`);
+
5431. 2003
+
5432. 2003// PR-378 - Relax warning "function_in_loop".
+
5433. 2003//
+
5434. 2003// // Don't create functions in loops. It is inefficient, and it can lead to
+
5435. 2003// // scoping errors.
+
5436. 2003//
+
5437. 2003// if (functionage.loop > 0) {
+
5438. 2003//
+
5439. 2003// // test_cause:
+
5440. 2003// // ["
+
5441. 2003// // while(0){aa.map(function(){});}
+
5442. 2003// // ", "prefix_function", "function_in_loop", "function", 17]
+
5443. 2003//
+
5444. 2003// warn("function_in_loop", the_function);
+
5445. 2003// }
+
5446. 2003
+
5447. 2003// Give the function properties for storing its names and for observing the
+
5448. 2003// depth of loops and switches.
+
5449. 2003
+
5450. 2003 Object.assign(the_function, {
+
5451. 2003 async: the_function.async || 0,
+
5452. 2005 context: empty(),
+
5453. 2005 finally: 0,
+
5454. 2005 level: functionage.level + 1,
+
5455. 2005 loop: 0,
+
5456. 2005 statement_prv: undefined,
+
5457. 2005 switch: 0,
+
5458. 2005 try: 0
+
5459. 2005 });
+
5460. 929 if (the_function.arity !== "statement" && typeof name === "object") {
+
5461. 38
+
5462. 38// test_cause:
+
5463. 38// ["let aa=function bb(){return;};", "prefix_function", "expression", "bb", 0]
+
5464. 38
+
5465. 38 test_cause("expression", name.id);
+
5466. 38 enroll(name, "function", true);
+
5467. 38 name.dead = false;
+
5468. 38 name.init = true;
+
5469. 38 name.used = 1;
+
5470. 2003 }
+
5471. 2003
+
5472. 2003// PR-334 - Bugfix - fix function-redefinition not warned inside function-call.
+
5473. 2003// Push the current function context and establish a new one.
+
5474. 2003
+
5475. 2003 function_list.push(the_function);
+
5476. 2003 function_stack.push(functionage);
+
5477. 2003 functionage = the_function;
+
5478. 2003
+
5479. 2003// Parse the parameter list.
+
5480. 2003
+
5481. 2003 advance("(");
+
5482. 2003 token_now.arity = "function";
+
5483. 2003 prefix_function_parameter(the_function);
+
5484. 2003
+
5485. 2003// The function's body is a block.
+
5486. 2003
+
5487. 2003 the_function.block = block("body");
+
5488. 2003 if (
+
5489. 2003 the_function.arity === "statement"
+
5490. 2003 && token_nxt.line === token_now.line
+
5491. 2 ) {
+
5492. 2
+
5493. 2// test_cause:
+
5494. 2// ["function aa(){}0", "prefix_function", "unexpected_a", "0", 16]
+
5495. 2
+
5496. 2 return stop("unexpected_a");
+
5497. 1990 }
+
5498. 1990 if (
+
5499. 1990 token_nxt.id === "."
+
5500. 1990 || token_nxt.id === "?."
+
5501. 2005
+
5502. 2005// PR-459 - Allow destructuring-assignment after function-definition.
+
5503. 2005
+
5504. 2005 // || token_nxt.id === "["
+
5505. 2 ) {
+
5506. 2
+
5507. 2// test_cause:
+
5508. 2// ["function aa(){}\n.aa", "prefix_function", "unexpected_a", ".", 1]
+
5509. 2// ["function aa(){}\n?.aa", "prefix_function", "unexpected_a", "?.", 1]
+
5510. 2
+
5511. 2 warn("unexpected_a");
+
5512. 1990 }
+
5513. 1990
+
5514. 1990// Check functions are ordered.
+
5515. 1990
+
5516. 1990 check_ordered(
+
5517. 1990 "function",
+
5518. 1990 function_list.slice(
+
5519. 1990 function_list.indexOf(the_function) + 1
+
5520. 2515 ).map(function ({
+
5521. 2515 level,
+
5522. 2515 name
+
5523. 2515 }) {
+
5524. 1990 return (level === the_function.level + 1) && name;
+
5525. 2515 }).filter(function (name) {
+
5526. 2510 return option_dict.beta && name && name.id;
+
5527. 2515 })
+
5528. 1990 );
+
5529. 1990
+
5530. 1990// Restore the previous context.
+
5531. 1990
+
5532. 1990 functionage = function_stack.pop();
+
5533. 1990 return the_function;
+
5534. 1990 }
+
5535. 631
+
5536. 2017 function prefix_function_parameter(the_function) {
+
5537. 2017
+
5538. 2017// This function will parse input <parameters> at beginning of <the_function>
+
5539. 2017
+
5540. 2017 let optional;
+
5541. 2017 let parameters = [];
+
5542. 2017 let signature = ["("];
+
5543. 2017 let subparam;
+
5544. 2781 function param_enroll(name) {
+
5545. 2514 if (name.identifier) {
+
5546. 2514 enroll(name, "parameter", false);
+
5547. 2514 } else {
+
5548. 267
+
5549. 267// test_cause:
+
5550. 267// ["([aa])=>0", "param_enroll", "use_function_not_fart", "=>", 7]
+
5551. 267// ["({aa})=>0", "param_enroll", "use_function_not_fart", "=>", 7]
+
5552. 267
+
5553. 267 if (the_function.id === "=>" && !option_dict.fart) {
+
5554. 267 warn("use_function_not_fart", the_function);
+
5555. 267 }
+
5556. 267
+
5557. 267// Recurse param_enroll().
+
5558. 267
+
5559. 267 name.names.forEach(param_enroll);
+
5560. 267 }
+
5561. 2781 }
+
5562. 2077 function param_parse() {
+
5563. 2077 let ellipsis = false;
+
5564. 2077 let param;
+
5565. 227 if (token_nxt.id === "{") {
+
5566. 227 if (optional !== undefined) {
+
5567. 227
+
5568. 227// test_cause:
+
5569. 227// ["function aa(aa=0,{}){}", "param_parse", "required_a_optional_b", "aa", 18]
+
5570. 227
+
5571. 227 warn(
+
5572. 227 "required_a_optional_b",
+
5573. 227 token_nxt,
+
5574. 227 token_nxt.id,
+
5575. 227 optional.id
+
5576. 227 );
+
5577. 227 }
+
5578. 227 param = token_nxt;
+
5579. 227 param.names = [];
+
5580. 227 advance("{");
+
5581. 227 signature.push("{");
+
5582. 625 while (true) {
+
5583. 625 subparam = token_nxt;
+
5584. 625 if (!subparam.identifier) {
+
5585. 625
+
5586. 625// test_cause:
+
5587. 625// ["function aa(aa=0,{}){}", "param_parse", "expected_identifier_a", "}", 19]
+
5588. 625// ["function aa({0}){}", "param_parse", "expected_identifier_a", "0", 14]
+
5589. 625
+
5590. 625 return stop("expected_identifier_a");
+
5591. 625 }
+
5592. 625 survey(subparam);
+
5593. 625 advance();
+
5594. 625 signature.push(subparam.id);
+
5595. 625 if (token_nxt.id === ":") {
+
5596. 625 advance(":");
+
5597. 625 advance();
+
5598. 625 token_now.label = subparam;
+
5599. 625 subparam = token_now;
+
5600. 625 if (!subparam.identifier) {
+
5601. 625
+
5602. 625// test_cause:
+
5603. 625// ["function aa({aa:0}){}", "param_parse", "expected_identifier_a", "}", 18]
+
5604. 625
+
5605. 625 return stop(
+
5606. 625 "expected_identifier_a",
+
5607. 625 token_nxt
+
5608. 625 );
+
5609. 625 }
+
5610. 625 }
+
5611. 625
+
5612. 625// test_cause:
+
5613. 625// ["function aa({aa=aa},aa){}", "param_parse", "equal", "", 0]
+
5614. 625
+
5615. 625 test_cause("equal");
+
5616. 625 if (token_nxt.id === "=") {
+
5617. 625 advance("=");
+
5618. 625 subparam.expression = parse_expression();
+
5619. 625 param.open = true;
+
5620. 625 }
+
5621. 625 param.names.push(subparam);
+
5622. 625 if (token_nxt.id === ",") {
+
5623. 625 advance(",");
+
5624. 625 signature.push(", ");
+
5625. 625 } else {
+
5626. 625 break;
+
5627. 625 }
+
5628. 625 }
+
5629. 227 parameters.push(param);
+
5630. 227
+
5631. 227// test_cause:
+
5632. 227// ["
+
5633. 227// function aa({bb,aa}){}
+
5634. 227// ", "check_ordered", "expected_a_b_before_c_d", "aa", 17]
+
5635. 227
+
5636. 227 check_ordered("parameter", param.names);
+
5637. 227 advance("}");
+
5638. 227 signature.push("}");
+
5639. 227 if (token_nxt.id === ",") {
+
5640. 227 advance(",");
+
5641. 227 signature.push(", ");
+
5642. 227 param_parse();
+
5643. 227 return;
+
5644. 227 }
+
5645. 1850 } else if (token_nxt.id === "[") {
+
5646. 1850 if (optional !== undefined) {
+
5647. 1850
+
5648. 1850// test_cause:
+
5649. 1850// ["function aa(aa=0,[]){}", "param_parse", "required_a_optional_b", "aa", 18]
+
5650. 1850
+
5651. 1850 warn(
+
5652. 1850 "required_a_optional_b",
+
5653. 1850 token_nxt,
+
5654. 1850 token_nxt.id,
+
5655. 1850 optional.id
+
5656. 1850 );
+
5657. 1850 }
+
5658. 1850 param = token_nxt;
+
5659. 1850 param.names = [];
+
5660. 1850 advance("[");
+
5661. 1850 signature.push("[]");
+
5662. 1850 while (true) {
+
5663. 1850 subparam = token_nxt;
+
5664. 1850 if (!subparam.identifier) {
+
5665. 1850
+
5666. 1850// test_cause:
+
5667. 1850// ["function aa(aa=0,[]){}", "param_parse", "expected_identifier_a", "]", 19]
+
5668. 1850
+
5669. 1850 return stop("expected_identifier_a");
+
5670. 1850 }
+
5671. 1850 advance();
+
5672. 1850 param.names.push(subparam);
+
5673. 1850
+
5674. 1850// test_cause:
+
5675. 1850// ["function aa([aa=aa],aa){}", "param_parse", "id", "", 0]
+
5676. 1850
+
5677. 1850 test_cause("id");
+
5678. 1850 if (token_nxt.id === "=") {
+
5679. 1850 advance("=");
+
5680. 1850 subparam.expression = parse_expression();
+
5681. 1850 param.open = true;
+
5682. 1850 }
+
5683. 1850 if (token_nxt.id === ",") {
+
5684. 1850 advance(",");
+
5685. 1850 } else {
+
5686. 1850 break;
+
5687. 1850 }
+
5688. 1850 }
+
5689. 1850 parameters.push(param);
+
5690. 1850 advance("]");
+
5691. 1850 if (token_nxt.id === ",") {
+
5692. 1850 advance(",");
+
5693. 1850 signature.push(", ");
+
5694. 1850 param_parse();
+
5695. 1850 return;
+
5696. 1850 }
+
5697. 1850 } else {
+
5698. 1850 if (token_nxt.id === "...") {
+
5699. 1850 ellipsis = true;
+
5700. 1850 signature.push("...");
+
5701. 1850 advance("...");
+
5702. 1850 if (optional !== undefined) {
+
5703. 1850
+
5704. 1850// test_cause:
+
5705. 1850// ["function aa(aa=0,...){}", "param_parse", "required_a_optional_b", "aa", 21]
+
5706. 1850
+
5707. 1850 warn(
+
5708. 1850 "required_a_optional_b",
+
5709. 1850 token_nxt,
+
5710. 1850 token_nxt.id,
+
5711. 1850 optional.id
+
5712. 1850 );
+
5713. 1850 }
+
5714. 1850 }
+
5715. 1850 if (!token_nxt.identifier) {
+
5716. 1850
+
5717. 1850// test_cause:
+
5718. 1850// ["function aa(0){}", "param_parse", "expected_identifier_a", "0", 13]
+
5719. 1850
+
5720. 1850 return stop("expected_identifier_a");
+
5721. 1850 }
+
5722. 1850 param = token_nxt;
+
5723. 1850 parameters.push(param);
+
5724. 1850 advance();
+
5725. 1850 signature.push(param.id);
+
5726. 1850 if (ellipsis) {
+
5727. 1850 param.ellipsis = true;
+
5728. 1850 } else {
+
5729. 1850 if (token_nxt.id === "=") {
+
5730. 1850 optional = param;
+
5731. 1850 advance("=");
+
5732. 1850 param.expression = parse_expression(0);
+
5733. 1850 } else {
+
5734. 1850 if (optional !== undefined) {
+
5735. 1850
+
5736. 1850// test_cause:
+
5737. 1850// ["function aa(aa=0,bb){}", "param_parse", "required_a_optional_b", "aa", 18]
+
5738. 1850
+
5739. 1850 warn(
+
5740. 1850 "required_a_optional_b",
+
5741. 1850 param,
+
5742. 1850 param.id,
+
5743. 1850 optional.id
+
5744. 1850 );
+
5745. 1850 }
+
5746. 1850 }
+
5747. 1850 if (token_nxt.id === ",") {
+
5748. 1850 advance(",");
+
5749. 1850 signature.push(", ");
+
5750. 1850 param_parse();
+
5751. 1850 return;
+
5752. 1850 }
+
5753. 1850 }
+
5754. 1850 }
+
5755. 2077 }
+
5756. 2017
+
5757. 2017// test_cause:
+
5758. 2017// ["function aa(){}", "prefix_function_parameter", "opener", "(", 0]
+
5759. 2017
+
5760. 2017 test_cause("opener", token_now.id);
+
5761. 2017 token_now.free = false;
+
5762. 1485 if (token_nxt.id !== ")" && token_nxt.id !== "(end)") {
+
5763. 1485 param_parse();
+
5764. 2009 }
+
5765. 2009 advance(")");
+
5766. 2009 signature.push(")");
+
5767. 2009 parameters.forEach(param_enroll);
+
5768. 2009 the_function.parameters = parameters;
+
5769. 2009 the_function.signature = signature.join("");
+
5770. 2009 }
+
5771. 631
+
5772. 588 function prefix_lbrace() {
+
5773. 588 const seen = empty();
+
5774. 588 const the_brace = token_now;
+
5775. 588 let extra;
+
5776. 588 let full;
+
5777. 588 let id;
+
5778. 588 let name;
+
5779. 588 let the_colon;
+
5780. 588 let value;
+
5781. 588 the_brace.expression = [];
+
5782. 548 if (token_nxt.id !== "}") {
+
5783. 548
+
5784. 548// Parse/loop through each property in {...}.
+
5785. 548
+
5786. 1996 while (true) {
+
5787. 1996 name = token_nxt;
+
5788. 1996 advance();
+
5789. 1996 if (
+
5790. 1996 (name.id === "get" || name.id === "set")
+
5791. 1996 && token_nxt.identifier
+
5792. 1996 ) {
+
5793. 1996 if (!option_dict.getset) {
+
5794. 1996
+
5795. 1996// test_cause:
+
5796. 1996// ["aa={get aa(){}}", "prefix_lbrace", "unexpected_a", "get", 5]
+
5797. 1996
+
5798. 1996 warn("unexpected_a", name);
+
5799. 1996 }
+
5800. 1996 extra = name.id;
+
5801. 1996 full = extra + " " + token_nxt.id;
+
5802. 1996 name = token_nxt;
+
5803. 1996 advance();
+
5804. 1996 id = survey(name);
+
5805. 1996 if (seen[full] === true || seen[id] === true) {
+
5806. 1996
+
5807. 1996// test_cause:
+
5808. 1996// ["aa={get aa(){},get aa(){}}", "prefix_lbrace", "duplicate_a", "aa", 20]
+
5809. 1996
+
5810. 1996 warn("duplicate_a", name);
+
5811. 1996 }
+
5812. 1996 seen[id] = false;
+
5813. 1996 seen[full] = true;
+
5814. 1996 } else if (name.id === "`") {
+
5815. 1996
+
5816. 1996// test_cause:
+
5817. 1996// ["aa={`aa`:0}", "prefix_lbrace", "unexpected_a", "`", 5]
+
5818. 1996
+
5819. 1996 stop("unexpected_a", name);
+
5820. 1996
+
5821. 1996 } else {
+
5822. 1996 id = survey(name);
+
5823. 1996 if (typeof seen[id] === "boolean") {
+
5824. 1996
+
5825. 1996// test_cause:
+
5826. 1996// ["aa={aa,aa}", "prefix_lbrace", "duplicate_a", "aa", 8]
+
5827. 1996
+
5828. 1996 warn("duplicate_a", name);
+
5829. 1996 }
+
5830. 1996 seen[id] = true;
+
5831. 1996 }
+
5832. 1996 if (name.identifier) {
+
5833. 1996 if (token_nxt.id === "}" || token_nxt.id === ",") {
+
5834. 1996 if (typeof extra === "string") {
+
5835. 1996
+
5836. 1996// test_cause:
+
5837. 1996// ["aa={get aa}", "prefix_lbrace", "closer", "", 0]
+
5838. 1996
+
5839. 1996 test_cause("closer");
+
5840. 1996 advance("(");
+
5841. 1996 }
+
5842. 1996 value = parse_expression(Infinity, true);
+
5843. 1996 } else if (token_nxt.id === "(") {
+
5844. 1996
+
5845. 1996// test_cause:
+
5846. 1996// ["aa={aa()}", "prefix_lbrace", "paren", "", 0]
+
5847. 1996// ["aa={get aa(){}}", "prefix_lbrace", "paren", "", 0]
+
5848. 1996
+
5849. 1996 test_cause("paren");
+
5850. 1996 value = prefix_function({
+
5851. 1996 arity: "unary",
+
5852. 1996 from: name.from,
+
5853. 1996 id: "function",
+
5854. 1996 line: name.line,
+
5855. 1996 name: (
+
5856. 1996 typeof extra === "string"
+
5857. 1996 ? extra
+
5858. 1996 : id
+
5859. 1996 ),
+
5860. 1996 thru: name.from
+
5861. 1996 });
+
5862. 1996 } else {
+
5863. 1996 if (typeof extra === "string") {
+
5864. 1996
+
5865. 1996// test_cause:
+
5866. 1996// ["aa={get aa.aa}", "prefix_lbrace", "paren", "", 0]
+
5867. 1996
+
5868. 1996 test_cause("paren");
+
5869. 1996 advance("(");
+
5870. 1996 }
+
5871. 1996 the_colon = token_nxt;
+
5872. 1996 advance(":");
+
5873. 1996 value = parse_expression(0);
+
5874. 1996 if (
+
5875. 1996 value.id === name.id
+
5876. 1996 && value.id !== "function"
+
5877. 1996 ) {
+
5878. 1996
+
5879. 1996// test_cause:
+
5880. 1996// ["aa={aa:aa}", "prefix_lbrace", "unexpected_a", ": aa", 7]
+
5881. 1996
+
5882. 1996 warn("unexpected_a", the_colon, ": " + name.id);
+
5883. 1996 }
+
5884. 1996 }
+
5885. 1996 value.label = name;
+
5886. 1996 if (typeof extra === "string") {
+
5887. 1996 value.extra = extra;
+
5888. 1996 }
+
5889. 1996 the_brace.expression.push(value);
+
5890. 1996 } else {
+
5891. 1996
+
5892. 1996// test_cause:
+
5893. 1996// ["aa={\"aa\":0}", "prefix_lbrace", "colon", "", 0]
+
5894. 1996
+
5895. 1996 test_cause("colon");
+
5896. 1996 advance(":");
+
5897. 1996 value = parse_expression(0);
+
5898. 1996 value.label = name;
+
5899. 1996 the_brace.expression.push(value);
+
5900. 1996 }
+
5901. 1996 if (token_nxt.id !== ",") {
+
5902. 1996 break;
+
5903. 1996 }
+
5904. 1996
+
5905. 1996// test_cause:
+
5906. 1996// ["aa={\"aa\":0,\"bb\":0}", "prefix_lbrace", "comma", "", 0]
+
5907. 1996
+
5908. 1996 test_cause("comma");
+
5909. 1996 advance(",");
+
5910. 1996 if (token_nxt.id === "}") {
+
5911. 1996
+
5912. 1996// test_cause:
+
5913. 1996// ["let aa={aa:0,}", "prefix_lbrace", "unexpected_a", ",", 13]
+
5914. 1996
+
5915. 1996 warn("unexpected_a", token_now);
+
5916. 1996 break;
+
5917. 1996 }
+
5918. 1996 }
+
5919. 583 }
+
5920. 583
+
5921. 583// test_cause:
+
5922. 583// ["aa={bb,aa}", "check_ordered", "expected_a_b_before_c_d", "aa", 8]
+
5923. 583
+
5924. 583 check_ordered(
+
5925. 583 "property",
+
5926. 1991 the_brace.expression.map(function ({
+
5927. 1991 label
+
5928. 1991 }) {
+
5929. 1991 return label;
+
5930. 1991 })
+
5931. 583 );
+
5932. 583 advance("}");
+
5933. 583 return the_brace;
+
5934. 583 }
+
5935. 631
+
5936. 759 function prefix_lbracket() {
+
5937. 759 const the_token = token_now;
+
5938. 759 let element;
+
5939. 759 let ellipsis;
+
5940. 759 the_token.expression = [];
+
5941. 392 if (token_nxt.id !== "]") {
+
5942. 392
+
5943. 392// Parse/loop through each element in [...].
+
5944. 392
+
5945. 1884 while (true) {
+
5946. 1884 ellipsis = false;
+
5947. 1884 if (token_nxt.id === "...") {
+
5948. 1884 ellipsis = true;
+
5949. 1884 advance("...");
+
5950. 1884 }
+
5951. 1884 element = parse_expression(10);
+
5952. 1884 if (ellipsis) {
+
5953. 1884 element.ellipsis = true;
+
5954. 1884 }
+
5955. 1884 the_token.expression.push(element);
+
5956. 1884 if (token_nxt.id !== ",") {
+
5957. 1884 break;
+
5958. 1884 }
+
5959. 1884 advance(",");
+
5960. 1884 if (token_nxt.id === "]") {
+
5961. 1884
+
5962. 1884// test_cause:
+
5963. 1884// ["let aa=[0,]", "prefix_lbracket", "unexpected_a", ",", 10]
+
5964. 1884
+
5965. 1884 warn("unexpected_a", token_now);
+
5966. 1884 break;
+
5967. 1884 }
+
5968. 1884 }
+
5969. 392 }
+
5970. 759 advance("]");
+
5971. 759 return the_token;
+
5972. 759 }
+
5973. 631
+
5974. 1616 function prefix_lparen() {
+
5975. 1616 let the_paren = token_now;
+
5976. 1616 let the_value;
+
5977. 1616
+
5978. 1616// PR-385 - Bugfix - Fixes issue #382 - failure to detect destructured fart.
+
5979. 1616
+
5980. 14 if (token_now.fart) {
+
5981. 14 return parse_fart(token_now.fart);
+
5982. 1602 }
+
5983. 1602
+
5984. 1602// test_cause:
+
5985. 1602// ["(0)", "prefix_lparen", "expr", "", 0]
+
5986. 1602
+
5987. 1602 test_cause("expr");
+
5988. 1602 the_paren.free = true;
+
5989. 1602 the_value = parse_expression(0);
+
5990. 1602 if (the_value.wrapped === true) {
+
5991. 1
+
5992. 1// test_cause:
+
5993. 1// ["((0))", "prefix_lparen", "unexpected_a", "(", 1]
+
5994. 1
+
5995. 1 warn("unexpected_a", the_paren);
+
5996. 1602 }
+
5997. 1602 the_value.wrapped = true;
+
5998. 1602 advance(")", the_paren);
+
5999. 1602 return the_value;
+
6000. 1602 }
+
6001. 631
+
6002. 155 function prefix_new() {
+
6003. 155 const the_new = token_now;
+
6004. 155 let right;
+
6005. 155 right = parse_expression(160);
+
6006. 1 if (token_nxt.id !== "(") {
+
6007. 1
+
6008. 1// test_cause:
+
6009. 1// ["new aa", "prefix_new", "expected_a_before_b", "(end)", 1]
+
6010. 1
+
6011. 1 warn("expected_a_before_b", token_nxt, "()", artifact());
+
6012. 1 }
+
6013. 155 the_new.expression = right;
+
6014. 155 return the_new;
+
6015. 155 }
+
6016. 631
+
6017. 782 function prefix_tick() {
+
6018. 782 const the_tick = token_now;
+
6019. 782 the_tick.value = [];
+
6020. 782 the_tick.expression = [];
+
6021. 782 if (token_nxt.id !== "`") {
+
6022. 782
+
6023. 782// Parse/loop through each token in `${...}`.
+
6024. 782
+
6025. 1499 while (true) {
+
6026. 1499 advance("(string)");
+
6027. 1499 the_tick.value.push(token_now);
+
6028. 1499 if (token_nxt.id !== "${") {
+
6029. 1499 break;
+
6030. 1499 }
+
6031. 1499 advance("${");
+
6032. 1499
+
6033. 1499// test_cause:
+
6034. 1499// ["let aa=`${}`;", "prefix_tick", "${", "", 0]
+
6035. 1499
+
6036. 1499 test_cause("${");
+
6037. 1499 the_tick.expression.push(parse_expression(0));
+
6038. 1499 advance("}");
+
6039. 1499 }
+
6040. 780 }
+
6041. 780 advance("`");
+
6042. 780 return the_tick;
+
6043. 780 }
+
6044. 631
+
6045. 2 function prefix_void() {
+
6046. 2 const the_void = token_now;
+
6047. 2
+
6048. 2// test_cause:
+
6049. 2// ["void 0", "prefix_void", "unexpected_a", "void", 1]
+
6050. 2// ["void", "prefix_void", "unexpected_a", "void", 1]
+
6051. 2
+
6052. 2 warn("unexpected_a", the_void);
+
6053. 2 the_void.expression = parse_expression(0);
+
6054. 2 return the_void;
+
6055. 2 }
+
6056. 631
+
6057. 13430 function semicolon() {
+
6058. 13430
+
6059. 13430// Try to match a semicolon.
+
6060. 13430
+
6061. 13205 if (token_nxt.id === ";") {
+
6062. 13205 advance(";");
+
6063. 13205 } else {
+
6064. 225
+
6065. 225// test_cause:
+
6066. 225// ["0", "semicolon", "expected_a_b", "(end)", 1]
+
6067. 225
+
6068. 225 warn_at(
+
6069. 225 "expected_a_b",
+
6070. 225 token_now.line,
+
6071. 225 token_now.thru + 1,
+
6072. 225 ";",
+
6073. 225 artifact()
+
6074. 225 );
+
6075. 225 }
+
6076. 13430 anon = "anonymous";
+
6077. 13430 }
+
6078. 631
+
6079. 14513 function stmt(id, fud_stmt) {
+
6080. 14513
+
6081. 14513// Create a statement.
+
6082. 14513
+
6083. 14513 const the_symbol = symbol(id);
+
6084. 14513 the_symbol.fud_stmt = fud_stmt;
+
6085. 14513 return the_symbol;
+
6086. 14513 }
+
6087. 631
+
6088. 1023 function stmt_break() {
+
6089. 1023 const the_break = token_now;
+
6090. 1023 let the_label;
+
6091. 1023 if (
+
6092. 719 (functionage.loop < 1 && functionage.switch < 1)
+
6093. 1017 || functionage.finally > 0
+
6094. 6 ) {
+
6095. 6
+
6096. 6// test_cause:
+
6097. 6// ["break", "stmt_break", "unexpected_a", "break", 1]
+
6098. 6
+
6099. 6 warn("unexpected_a", the_break);
+
6100. 6 }
+
6101. 1023 the_break.disrupt = true;
+
6102. 5 if (token_nxt.identifier && token_now.line === token_nxt.line) {
+
6103. 5 the_label = functionage.context[token_nxt.id];
+
6104. 5 if (
+
6105. 5 the_label === undefined
+
6106. 5 || the_label.role !== "label"
+
6107. 5 || the_label.dead
+
6108. 5 ) {
+
6109. 5 if (the_label !== undefined && the_label.dead) {
+
6110. 5
+
6111. 5// test_cause:
+
6112. 5// ["aa:{function aa(aa){break aa;}}", "stmt_break", "out_of_scope_a", "aa", 27]
+
6113. 5
+
6114. 5 warn("out_of_scope_a");
+
6115. 5 } else {
+
6116. 5
+
6117. 5// test_cause:
+
6118. 5// ["aa:{break aa;}", "stmt_break", "not_label_a", "aa", 11]
+
6119. 5
+
6120. 5 warn("not_label_a");
+
6121. 5 }
+
6122. 5 } else {
+
6123. 5 the_label.used += 1;
+
6124. 5 }
+
6125. 5 the_break.label = token_nxt;
+
6126. 5 advance();
+
6127. 5 }
+
6128. 1023 advance(";");
+
6129. 1023 return the_break;
+
6130. 1023 }
+
6131. 631
+
6132. 2 function stmt_continue() {
+
6133. 2 const the_continue = token_now;
+
6134. 1 if (functionage.loop < 1 || functionage.finally > 0) {
+
6135. 2
+
6136. 2// test_cause:
+
6137. 2// ["continue", "stmt_continue", "unexpected_a", "continue", 1]
+
6138. 2// ["
+
6139. 2// function aa(){while(0){try{}finally{continue}}}
+
6140. 2// ", "stmt_continue", "unexpected_a", "continue", 37]
+
6141. 2
+
6142. 2 warn("unexpected_a", the_continue);
+
6143. 2 }
+
6144. 2 check_not_top_level(the_continue);
+
6145. 2 the_continue.disrupt = true;
+
6146. 2 warn("unexpected_a", the_continue);
+
6147. 2 advance(";");
+
6148. 2 return the_continue;
+
6149. 2 }
+
6150. 631
+
6151. 3 function stmt_debugger() {
+
6152. 3 const the_debug = token_now;
+
6153. 1 if (!option_dict.devel) {
+
6154. 1
+
6155. 1// test_cause:
+
6156. 1// ["debugger", "stmt_debugger", "unexpected_a", "debugger", 1]
+
6157. 1
+
6158. 1 warn("unexpected_a", the_debug);
+
6159. 1 }
+
6160. 3 semicolon();
+
6161. 3 return the_debug;
+
6162. 3 }
+
6163. 631
+
6164. 72 function stmt_delete() {
+
6165. 72 const the_token = token_now;
+
6166. 72 const the_value = parse_expression(0);
+
6167. 72 if (
+
6168. 1 (the_value.id !== "." && the_value.id !== "[")
+
6169. 71 || the_value.arity !== "binary"
+
6170. 1 ) {
+
6171. 1
+
6172. 1// test_cause:
+
6173. 1// ["delete 0", "stmt_delete", "expected_a_b", "0", 8]
+
6174. 1
+
6175. 1 stop("expected_a_b", the_value, ".", artifact(the_value));
+
6176. 71 }
+
6177. 71 the_token.expression = the_value;
+
6178. 71 semicolon();
+
6179. 71 return the_token;
+
6180. 71 }
+
6181. 631
+
6182. 5 function stmt_do() {
+
6183. 5 const the_do = token_now;
+
6184. 5 check_not_top_level(the_do);
+
6185. 5 functionage.loop += 1;
+
6186. 5 the_do.block = block();
+
6187. 5 advance("while");
+
6188. 5 the_do.expression = condition();
+
6189. 5 semicolon();
+
6190. 1 if (the_do.block.disrupt === true) {
+
6191. 1
+
6192. 1// test_cause:
+
6193. 1// ["function aa(){do{break;}while(0)}", "stmt_do", "weird_loop", "do", 15]
+
6194. 1
+
6195. 1 warn("weird_loop", the_do);
+
6196. 3 }
+
6197. 3 functionage.loop -= 1;
+
6198. 3 return the_do;
+
6199. 3 }
+
6200. 631
+
6201. 24 function stmt_export() {
+
6202. 24 let export_list = [];
+
6203. 24 let the_export = token_now;
+
6204. 24 let the_id;
+
6205. 24 let the_name;
+
6206. 24 let the_thing;
+
6207. 24
+
6208. 24 the_export.expression = [];
+
6209. 11 if (token_nxt.id === "default") {
+
6210. 11 if (export_dict.default !== undefined) {
+
6211. 11
+
6212. 11// test_cause:
+
6213. 11// ["
+
6214. 11// export default 0;export default 0
+
6215. 11// ", "stmt_export", "duplicate_a", "default", 25]
+
6216. 11
+
6217. 11 warn("duplicate_a");
+
6218. 11 }
+
6219. 11 advance("default");
+
6220. 11 the_thing = parse_expression(0);
+
6221. 11 if (
+
6222. 11 the_thing.id !== "("
+
6223. 11 || the_thing.expression[0].id !== "."
+
6224. 11 || the_thing.expression[0].expression.id !== "Object"
+
6225. 11 || the_thing.expression[0].name.id !== "freeze"
+
6226. 11 ) {
+
6227. 11
+
6228. 11// test_cause:
+
6229. 11// ["export default {}", "stmt_export", "freeze_exports", "{", 16]
+
6230. 11
+
6231. 11 warn("freeze_exports", the_thing);
+
6232. 11
+
6233. 11// PR-301 - Bugfix - Fixes issues #282 - optional-semicolon.
+
6234. 11
+
6235. 11 } else {
+
6236. 11
+
6237. 11// test_cause:
+
6238. 11// ["
+
6239. 11// export default Object.freeze({})
+
6240. 11// ", "semicolon", "expected_a_b", "(end)", 32]
+
6241. 11
+
6242. 11 semicolon();
+
6243. 11 }
+
6244. 11 export_dict.default = the_thing;
+
6245. 11 the_export.expression.push(the_thing);
+
6246. 13 } else {
+
6247. 13
+
6248. 13// PR-439 - Add grammar for "export async function ...".
+
6249. 13
+
6250. 13 if (token_nxt.id === "function" || token_nxt.id === "async") {
+
6251. 13
+
6252. 13// test_cause:
+
6253. 13// ["export async function aa(){}", "stmt_export", "freeze_exports", "async", 8]
+
6254. 13// ["export function aa(){}", "stmt_export", "freeze_exports", "function", 8]
+
6255. 13
+
6256. 13 warn("freeze_exports");
+
6257. 13 the_thing = parse_statement();
+
6258. 13 the_name = the_thing.name;
+
6259. 13 the_id = the_name.id;
+
6260. 13 the_name.used += 1;
+
6261. 13 if (export_dict[the_id] !== undefined) {
+
6262. 13
+
6263. 13// test_cause:
+
6264. 13// ["
+
6265. 13// let aa;export{aa};export function aa(){}
+
6266. 13// ", "stmt_export", "duplicate_a", "aa", 35]
+
6267. 13
+
6268. 13 warn("duplicate_a", the_name);
+
6269. 13 }
+
6270. 13 export_dict[the_id] = the_thing;
+
6271. 13 the_export.expression.push(the_thing);
+
6272. 13 the_thing.statement = false;
+
6273. 13 the_thing.arity = "unary";
+
6274. 13 } else if (
+
6275. 13 token_nxt.id === "var"
+
6276. 13 || token_nxt.id === "let"
+
6277. 13 || token_nxt.id === "const"
+
6278. 13 ) {
+
6279. 13
+
6280. 13// test_cause:
+
6281. 13// ["export const", "stmt_export", "unexpected_a", "const", 8]
+
6282. 13// ["export let", "stmt_export", "unexpected_a", "let", 8]
+
6283. 13// ["export var", "stmt_export", "unexpected_a", "var", 8]
+
6284. 13
+
6285. 13 warn("unexpected_a");
+
6286. 13 parse_statement();
+
6287. 13 } else if (token_nxt.id === "{") {
+
6288. 13
+
6289. 13// test_cause:
+
6290. 13// ["export {}", "stmt_export", "advance{", "", 0]
+
6291. 13
+
6292. 13 test_cause("advance{");
+
6293. 13 advance("{");
+
6294. 13 while (true) {
+
6295. 13 if (!token_nxt.identifier) {
+
6296. 13
+
6297. 13// test_cause:
+
6298. 13// ["export {}", "stmt_export", "expected_identifier_a", "}", 9]
+
6299. 13
+
6300. 13 stop("expected_identifier_a");
+
6301. 13 }
+
6302. 13 the_id = token_nxt.id;
+
6303. 13 export_list.push(token_nxt);
+
6304. 13 the_name = token_global.context[the_id];
+
6305. 13 if (the_name === undefined) {
+
6306. 13
+
6307. 13// test_cause:
+
6308. 13// ["export {aa}", "stmt_export", "unexpected_a", "aa", 9]
+
6309. 13
+
6310. 13 warn("unexpected_a");
+
6311. 13 } else {
+
6312. 13 the_name.used += 1;
+
6313. 13 if (export_dict[the_id] !== undefined) {
+
6314. 13
+
6315. 13// test_cause:
+
6316. 13// ["let aa;export{aa,aa}", "stmt_export", "duplicate_a", "aa", 18]
+
6317. 13
+
6318. 13 warn("duplicate_a");
+
6319. 13 }
+
6320. 13 export_dict[the_id] = the_name;
+
6321. 13 }
+
6322. 13 advance();
+
6323. 13 the_export.expression.push(the_thing);
+
6324. 13 if (token_nxt.id === ",") {
+
6325. 13 advance(",");
+
6326. 13 } else {
+
6327. 13 break;
+
6328. 13 }
+
6329. 13 }
+
6330. 13
+
6331. 13// PR-439 - Check exported properties are ordered.
+
6332. 13
+
6333. 13// test_cause:
+
6334. 13// ["export {bb, aa}", "check_ordered", "expected_a_b_before_c_d", "aa", 13]
+
6335. 13
+
6336. 13 check_ordered("export", export_list);
+
6337. 13 advance("}");
+
6338. 13 semicolon();
+
6339. 13 } else {
+
6340. 13
+
6341. 13// test_cause:
+
6342. 13// ["export", "stmt_export", "unexpected_a", "(end)", 1]
+
6343. 13
+
6344. 13 stop("unexpected_a");
+
6345. 13 }
+
6346. 18 }
+
6347. 18 state.mode_module = true;
+
6348. 18 return the_export;
+
6349. 18 }
+
6350. 631
+
6351. 12 function stmt_for() {
+
6352. 12 let first;
+
6353. 12 let the_for = token_now;
+
6354. 7 if (!option_dict.for) {
+
6355. 7
+
6356. 7// test_cause:
+
6357. 7// ["for", "stmt_for", "unexpected_a", "for", 1]
+
6358. 7
+
6359. 7 warn("unexpected_a", the_for);
+
6360. 7 }
+
6361. 12 check_not_top_level(the_for);
+
6362. 12 functionage.loop += 1;
+
6363. 12 advance("(");
+
6364. 12 token_now.free = true;
+
6365. 1 if (token_nxt.id === ";") {
+
6366. 1
+
6367. 1// test_cause:
+
6368. 1// ["for(;;){}", "stmt_for", "expected_a_b", "for (;", 1]
+
6369. 1
+
6370. 1 return stop("expected_a_b", the_for, "while (", "for (;");
+
6371. 9 }
+
6372. 9 switch (token_nxt.id) {
+
6373. 9 case "const":
+
6374. 1 case "let":
+
6375. 1 case "var":
+
6376. 1
+
6377. 1// test_cause:
+
6378. 1// ["for(const aa in aa){}", "stmt_for", "unexpected_a", "const", 5]
+
6379. 1
+
6380. 1 return stop("unexpected_a");
+
6381. 8 }
+
6382. 8 first = parse_expression(0);
+
6383. 8 if (first.id === "in") {
+
6384. 2 if (first.expression[0].arity !== "variable") {
+
6385. 2
+
6386. 2// test_cause:
+
6387. 2// ["for(0 in aa){}", "stmt_for", "bad_assignment_a", "0", 5]
+
6388. 2
+
6389. 2 warn("bad_assignment_a", first.expression[0]);
+
6390. 2 }
+
6391. 2 the_for.name = first.expression[0];
+
6392. 2 the_for.expression = first.expression[1];
+
6393. 2 warn("expected_a_b", the_for, "Object.keys", "for in");
+
6394. 6 } else {
+
6395. 6 the_for.initial = first;
+
6396. 6 advance(";");
+
6397. 6 the_for.expression = parse_expression(0);
+
6398. 6 advance(";");
+
6399. 6 the_for.inc = parse_expression(0);
+
6400. 6 if (the_for.inc.id === "++") {
+
6401. 6
+
6402. 6// test_cause:
+
6403. 6// ["for(aa;aa;aa++){}", "stmt_for", "expected_a_b", "++", 13]
+
6404. 6
+
6405. 6 warn("expected_a_b", the_for.inc, "+= 1", "++");
+
6406. 6 }
+
6407. 8 }
+
6408. 8 advance(")");
+
6409. 8 the_for.block = block();
+
6410. 8 if (the_for.block.disrupt === true) {
+
6411. 1
+
6412. 1// test_cause:
+
6413. 1// ["
+
6414. 1// /*jslint for*/
+
6415. 1// function aa(bb,cc){for(0;0;0){break;}}
+
6416. 1// ", "stmt_for", "weird_loop", "for", 20]
+
6417. 1
+
6418. 1 warn("weird_loop", the_for);
+
6419. 8 }
+
6420. 8 functionage.loop -= 1;
+
6421. 8 return the_for;
+
6422. 8 }
+
6423. 631
+
6424. 3051 function stmt_if() {
+
6425. 3051 const the_if = token_now;
+
6426. 3051 let the_else;
+
6427. 3051 the_if.expression = condition();
+
6428. 3051 the_if.block = block();
+
6429. 642 if (token_nxt.id === "else") {
+
6430. 642 advance("else");
+
6431. 642 the_else = token_now;
+
6432. 642 the_if.else = (
+
6433. 642 token_nxt.id === "if"
+
6434. 642 ? parse_statement()
+
6435. 642 : block()
+
6436. 642 );
+
6437. 642
+
6438. 642// test_cause:
+
6439. 642// ["if(0){0}else if(0){0}", "stmt_if", "else", "", 0]
+
6440. 642// ["if(0){0}else{0}", "stmt_if", "else", "", 0]
+
6441. 642
+
6442. 642 test_cause("else");
+
6443. 642 if (the_if.block.disrupt === true) {
+
6444. 642 if (the_if.else.disrupt === true) {
+
6445. 642
+
6446. 642// test_cause:
+
6447. 642// ["if(0){break;}else{break;}", "stmt_if", "disrupt", "", 0]
+
6448. 642
+
6449. 642 test_cause("disrupt");
+
6450. 642 the_if.disrupt = true;
+
6451. 642 } else {
+
6452. 642
+
6453. 642// test_cause:
+
6454. 642// ["if(0){break;}else{}", "stmt_if", "unexpected_a", "else", 14]
+
6455. 642
+
6456. 642 warn("unexpected_a", the_else);
+
6457. 642 }
+
6458. 642 }
+
6459. 3050 }
+
6460. 3050 return the_if;
+
6461. 3050 }
+
6462. 631
+
6463. 62 function stmt_import() {
+
6464. 62 const the_import = token_now;
+
6465. 62 let name;
+
6466. 62 let names;
+
6467. 62
+
6468. 62// PR-347 - Disable warning "unexpected_directive_a".
+
6469. 62//
+
6470. 62// if (typeof state.mode_module === "object") {
+
6471. 62//
+
6472. 62// // test_cause:
+
6473. 62// // ["
+
6474. 62// // /*global aa*/
+
6475. 62// // import aa from "aa"
+
6476. 62// // ", "stmt_import", "unexpected_directive_a", "global", 1]
+
6477. 62//
+
6478. 62// warn(
+
6479. 62// "unexpected_directive_a",
+
6480. 62// state.mode_module,
+
6481. 62// state.mode_module.directive
+
6482. 62// );
+
6483. 62// }
+
6484. 62
+
6485. 62 state.mode_module = true;
+
6486. 62
+
6487. 62// PR-436 - Add grammar for side-effect import-statement.
+
6488. 62
+
6489. 1 if (token_nxt.id === "(string)") {
+
6490. 1
+
6491. 1// test_cause:
+
6492. 1// ["import \"./aa.mjs\";", "stmt_import", "import_side_effect", "", 0]
+
6493. 1
+
6494. 1 test_cause("import_side_effect");
+
6495. 1 warn("expected_a_b", token_nxt, "{", artifact());
+
6496. 1 advance();
+
6497. 1 semicolon();
+
6498. 1 return the_import;
+
6499. 61 }
+
6500. 61 if (token_nxt.identifier) {
+
6501. 57 name = token_nxt;
+
6502. 57 advance();
+
6503. 57 if (name.id === "ignore") {
+
6504. 57
+
6505. 57// test_cause:
+
6506. 57// ["import ignore from \"aa\"", "stmt_import", "unexpected_a", "ignore", 8]
+
6507. 57
+
6508. 57 warn("unexpected_a", name);
+
6509. 57 }
+
6510. 57 enroll(name, "variable", true);
+
6511. 57 the_import.name = name;
+
6512. 57 } else {
+
6513. 4 names = [];
+
6514. 4 advance("{");
+
6515. 4 if (token_nxt.id !== "}") {
+
6516. 4 while (true) {
+
6517. 4 if (!token_nxt.identifier) {
+
6518. 4
+
6519. 4// test_cause:
+
6520. 4// ["import {", "stmt_import", "expected_identifier_a", "(end)", 1]
+
6521. 4
+
6522. 4 stop("expected_identifier_a");
+
6523. 4 }
+
6524. 4 name = token_nxt;
+
6525. 4 advance();
+
6526. 4 if (name.id === "ignore") {
+
6527. 4
+
6528. 4// test_cause:
+
6529. 4// ["import {ignore} from \"aa\"", "stmt_import", "unexpected_a", "ignore", 9]
+
6530. 4
+
6531. 4 warn("unexpected_a", name);
+
6532. 4 }
+
6533. 4 enroll(name, "variable", true);
+
6534. 4 names.push(name);
+
6535. 4 if (token_nxt.id !== ",") {
+
6536. 4 break;
+
6537. 4 }
+
6538. 4 advance(",");
+
6539. 4 }
+
6540. 4 }
+
6541. 4 advance("}");
+
6542. 4 the_import.name = names;
+
6543. 60 }
+
6544. 60 advance("from");
+
6545. 60 advance("(string)");
+
6546. 60 the_import.import = token_now;
+
6547. 60 if (!jslint_rgx_module.test(token_now.value)) {
+
6548. 1
+
6549. 1// test_cause:
+
6550. 1// ["import aa from \"!aa\"", "stmt_import", "bad_module_name_a", "!aa", 16]
+
6551. 1
+
6552. 1 warn("bad_module_name_a", token_now);
+
6553. 60 }
+
6554. 60 import_list.push(token_now.value);
+
6555. 60 semicolon();
+
6556. 60 return the_import;
+
6557. 60 }
+
6558. 631
+
6559. 5 function stmt_lbrace() {
+
6560. 5
+
6561. 5// test_cause:
+
6562. 5// [";{}", "stmt_lbrace", "naked_block", "{", 2]
+
6563. 5// ["class aa{}", "stmt_lbrace", "naked_block", "{", 9]
+
6564. 5
+
6565. 5 warn("naked_block", token_now);
+
6566. 5 return block("naked");
+
6567. 5 }
+
6568. 631
+
6569. 1761 function stmt_return() {
+
6570. 1761 const the_return = token_now;
+
6571. 1761 check_not_top_level(the_return);
+
6572. 1 if (functionage.finally > 0) {
+
6573. 1
+
6574. 1// test_cause:
+
6575. 1// ["
+
6576. 1// function aa(){try{}finally{return;}}
+
6577. 1// ", "stmt_return", "unexpected_a", "return", 28]
+
6578. 1
+
6579. 1 warn("unexpected_a", the_return);
+
6580. 1 }
+
6581. 1761 the_return.disrupt = true;
+
6582. 1509 if (token_nxt.id !== ";" && the_return.line === token_nxt.line) {
+
6583. 1509 the_return.expression = parse_expression(10);
+
6584. 1509 }
+
6585. 1761 advance(";");
+
6586. 1761 return the_return;
+
6587. 1761 }
+
6588. 631
+
6589. 5 function stmt_semicolon() {
+
6590. 5
+
6591. 5// test_cause:
+
6592. 5// [";", "stmt_semicolon", "unexpected_a", ";", 1]
+
6593. 5
+
6594. 5 warn("unexpected_a", token_now);
+
6595. 5 return token_now;
+
6596. 5 }
+
6597. 631
+
6598. 220 function stmt_switch() {
+
6599. 220 const the_cases = [];
+
6600. 220 const the_switch = token_now;
+
6601. 220 let dups = [];
+
6602. 220 let exp;
+
6603. 220 let last;
+
6604. 220 let stmts;
+
6605. 220 let the_case;
+
6606. 220 let the_default;
+
6607. 220 let the_disrupt = true;
+
6608. 220 let the_last;
+
6609. 23088 function is_dup(thing) {
+
6610. 23088 return is_equal(thing, exp);
+
6611. 23088 }
+
6612. 220 check_not_top_level(the_switch);
+
6613. 1 if (functionage.finally > 0) {
+
6614. 1
+
6615. 1// test_cause:
+
6616. 1// ["
+
6617. 1// function aa(){try{}finally{switch(0){}}}
+
6618. 1// ", "stmt_switch", "unexpected_a", "switch", 28]
+
6619. 1
+
6620. 1 warn("unexpected_a", the_switch);
+
6621. 1 }
+
6622. 220 functionage.switch += 1;
+
6623. 220 advance("(");
+
6624. 220 token_now.free = true;
+
6625. 220 the_switch.expression = parse_expression(0);
+
6626. 220 the_switch.block = the_cases;
+
6627. 220 advance(")");
+
6628. 220 advance("{");
+
6629. 1085 while (true) {
+
6630. 1085
+
6631. 1085// Loop through cases with breaks.
+
6632. 1085
+
6633. 1085 the_case = token_nxt;
+
6634. 1085 the_case.arity = "statement";
+
6635. 1085 the_case.expression = [];
+
6636. 1612 while (true) {
+
6637. 1612
+
6638. 1612// Loop through fallthrough cases.
+
6639. 1612
+
6640. 1612 advance("case");
+
6641. 1612 token_now.switch = true;
+
6642. 1612 exp = parse_expression(0);
+
6643. 1612 if (dups.some(is_dup)) {
+
6644. 1612
+
6645. 1612// test_cause:
+
6646. 1612// ["
+
6647. 1612// switch(0){case 0:break;case 0:break}
+
6648. 1612// ", "stmt_switch", "unexpected_a", "0", 29]
+
6649. 1612
+
6650. 1612 warn("unexpected_a", exp);
+
6651. 1612 }
+
6652. 1612 dups.push(exp);
+
6653. 1612 the_case.expression.push(exp);
+
6654. 1612 advance(":");
+
6655. 1612 if (token_nxt.id !== "case") {
+
6656. 1612 break;
+
6657. 1612 }
+
6658. 1612 }
+
6659. 1085
+
6660. 1085// test_cause:
+
6661. 1085// ["
+
6662. 1085// switch(0){case 1:case 0:break;}
+
6663. 1085// ", "check_ordered_case", "expected_a_b_before_c_d", "case-number", 23]
+
6664. 1085// ["
+
6665. 1085// switch(0){case "aa":case 0:break;}
+
6666. 1085// ", "check_ordered_case", "expected_a_b_before_c_d", "case-number", 26]
+
6667. 1085// ["
+
6668. 1085// switch(0){case "bb":case "aa":break;}
+
6669. 1085// ", "check_ordered_case", "expected_a_b_before_c_d", "aa", 26]
+
6670. 1085// ["
+
6671. 1085// switch(0){case aa:case "aa":break;}
+
6672. 1085// ", "check_ordered_case", "expected_a_b_before_c_d", "aa", 24]
+
6673. 1085// ["
+
6674. 1085// switch(0){case bb:case aa:break;}
+
6675. 1085// ", "check_ordered_case", "expected_a_b_before_c_d", "aa", 24]
+
6676. 1085
+
6677. 1085 check_ordered_case(the_case.expression);
+
6678. 1085 stmts = parse_statements();
+
6679. 1085 if (stmts.length < 1) {
+
6680. 1085
+
6681. 1085// test_cause:
+
6682. 1085// ["
+
6683. 1085// switch(0){case 0:default:}
+
6684. 1085// ", "stmt_switch", "expected_statements_a", "default", 18]
+
6685. 1085// ["switch(0){case 0:}", "stmt_switch", "expected_statements_a", "}", 18]
+
6686. 1085
+
6687. 1085 warn("expected_statements_a");
+
6688. 1085
+
6689. 1085// PR-359 - Bugfix - Fixes issue #358 - switch-statement crashes jslint.
+
6690. 1085
+
6691. 1085 break;
+
6692. 1085 }
+
6693. 1085 the_case.block = stmts;
+
6694. 1085 the_cases.push(the_case);
+
6695. 1085 last = stmts[stmts.length - 1];
+
6696. 1085 if (last.disrupt) {
+
6697. 1085 if (last.id === "break" && last.label === undefined) {
+
6698. 1085 the_disrupt = false;
+
6699. 1085 }
+
6700. 1085 } else {
+
6701. 1085 warn("expected_a_before_b", token_nxt, "break;", artifact());
+
6702. 1085 }
+
6703. 1085 if (token_nxt.id !== "case") {
+
6704. 1085 break;
+
6705. 1085 }
+
6706. 1085 }
+
6707. 217
+
6708. 217// test_cause:
+
6709. 217// ["
+
6710. 217// switch(0){case 1:break;case 0:break;}
+
6711. 217// ", "check_ordered_case", "expected_a_b_before_c_d", "case-number", 29]
+
6712. 217// ["
+
6713. 217// switch(0){case "aa":break;case 0:break;}
+
6714. 217// ", "check_ordered_case", "expected_a_b_before_c_d", "case-number", 32]
+
6715. 217// ["
+
6716. 217// switch(0){case "bb":break;case "aa":break;}
+
6717. 217// ", "check_ordered_case", "expected_a_b_before_c_d", "aa", 32]
+
6718. 217// ["
+
6719. 217// switch(0){case aa:break;case "aa":break;}
+
6720. 217// ", "check_ordered_case", "expected_a_b_before_c_d", "aa", 30]
+
6721. 217// ["
+
6722. 217// switch(0){case bb:break;case aa:break;}
+
6723. 217// ", "check_ordered_case", "expected_a_b_before_c_d", "aa", 30]
+
6724. 217
+
6725. 1080 check_ordered_case(the_cases.map(function ({
+
6726. 1080 expression
+
6727. 1080 }) {
+
6728. 1080 return expression[0];
+
6729. 1080 }));
+
6730. 217 dups = undefined;
+
6731. 217 if (token_nxt.id === "default") {
+
6732. 99 the_default = token_nxt;
+
6733. 99 advance("default");
+
6734. 99 token_now.switch = true;
+
6735. 99 advance(":");
+
6736. 99 the_switch.else = parse_statements();
+
6737. 99 if (the_switch.else.length < 1) {
+
6738. 99
+
6739. 99// test_cause:
+
6740. 99// ["
+
6741. 99// switch(0){case 0:break;default:}
+
6742. 99// ", "stmt_switch", "unexpected_a", "default", 24]
+
6743. 99
+
6744. 99 warn("unexpected_a", the_default);
+
6745. 99 the_disrupt = false;
+
6746. 99 } else {
+
6747. 99 the_last = the_switch.else[
+
6748. 99 the_switch.else.length - 1
+
6749. 99 ];
+
6750. 99 if (
+
6751. 99 the_last.id === "break"
+
6752. 99 && the_last.label === undefined
+
6753. 99 ) {
+
6754. 99
+
6755. 99// test_cause:
+
6756. 99// ["
+
6757. 99// switch(0){case 0:break;default:break;}
+
6758. 99// ", "stmt_switch", "unexpected_a", "break", 32]
+
6759. 99
+
6760. 99 warn("unexpected_a", the_last);
+
6761. 99 the_last.disrupt = false;
+
6762. 99 }
+
6763. 99 the_disrupt = the_disrupt && the_last.disrupt;
+
6764. 99 }
+
6765. 118 } else {
+
6766. 118 the_disrupt = false;
+
6767. 217 }
+
6768. 217 advance("}", the_switch);
+
6769. 217 functionage.switch -= 1;
+
6770. 217 the_switch.disrupt = the_disrupt;
+
6771. 217 return the_switch;
+
6772. 217 }
+
6773. 631
+
6774. 40 function stmt_throw() {
+
6775. 40 const the_throw = token_now;
+
6776. 40 the_throw.disrupt = true;
+
6777. 40 the_throw.expression = parse_expression(10);
+
6778. 40 semicolon();
+
6779. 1 if (functionage.try > 0) {
+
6780. 1
+
6781. 1// test_cause:
+
6782. 1// ["try{throw 0}catch(){}", "stmt_throw", "unexpected_a", "throw", 5]
+
6783. 1
+
6784. 1 warn("unexpected_a", the_throw);
+
6785. 1 }
+
6786. 40 return the_throw;
+
6787. 40 }
+
6788. 631
+
6789. 62 function stmt_try() {
+
6790. 62 const the_try = token_now;
+
6791. 62 let ignored;
+
6792. 62 let the_catch;
+
6793. 62 let the_disrupt;
+
6794. 1 if (functionage.try > 0) {
+
6795. 1
+
6796. 1// test_cause:
+
6797. 1// ["try{try{}catch(){}}catch(){}", "stmt_try", "unexpected_a", "try", 5]
+
6798. 1
+
6799. 1 warn("unexpected_a", the_try);
+
6800. 1 }
+
6801. 62 functionage.try += 1;
+
6802. 62 the_try.block = block();
+
6803. 62 the_disrupt = the_try.block.disrupt;
+
6804. 57 if (token_nxt.id === "catch") {
+
6805. 57 ignored = "ignore";
+
6806. 57 the_catch = token_nxt;
+
6807. 57 the_try.catch = the_catch;
+
6808. 57 advance("catch");
+
6809. 57
+
6810. 57// Create new catch-scope for catch-parameter.
+
6811. 57
+
6812. 57 catch_stack.push(catchage);
+
6813. 57 catchage = the_catch;
+
6814. 57 catch_list.push(catchage);
+
6815. 57 the_catch.context = empty();
+
6816. 57 if (token_nxt.id === "(") {
+
6817. 57 advance("(");
+
6818. 57 if (!token_nxt.identifier) {
+
6819. 57
+
6820. 57// test_cause:
+
6821. 57// ["try{}catch(){}", "stmt_try", "expected_identifier_a", ")", 12]
+
6822. 57
+
6823. 57 return stop("expected_identifier_a");
+
6824. 57 }
+
6825. 57 if (token_nxt.id !== "ignore") {
+
6826. 57 ignored = undefined;
+
6827. 57 the_catch.name = token_nxt;
+
6828. 57 enroll(token_nxt, "exception", true);
+
6829. 57 }
+
6830. 57 advance();
+
6831. 57 advance(")");
+
6832. 57 }
+
6833. 57 the_catch.block = block(ignored);
+
6834. 57 if (the_catch.block.disrupt !== true) {
+
6835. 57 the_disrupt = false;
+
6836. 57 }
+
6837. 57
+
6838. 57// Restore previous catch-scope after catch-block.
+
6839. 57
+
6840. 57 catchage = catch_stack.pop();
+
6841. 57
+
6842. 57// PR-404 - Relax warning about missing `catch` in `try...finally` statement.
+
6843. 57//
+
6844. 57// } else {
+
6845. 57//
+
6846. 57// // test_cause:
+
6847. 57// // ["try{}finally{break;}", "stmt_try", "expected_a_before_b", "finally", 6]
+
6848. 57//
+
6849. 57// warn("expected_a_before_b", token_nxt, "catch", artifact());
+
6850. 57
+
6851. 58 }
+
6852. 58 if (token_nxt.id === "finally") {
+
6853. 4 functionage.finally += 1;
+
6854. 4 advance("finally");
+
6855. 4 the_try.else = block();
+
6856. 4 the_disrupt = the_try.else.disrupt;
+
6857. 4 functionage.finally -= 1;
+
6858. 56 }
+
6859. 56 the_try.disrupt = the_disrupt;
+
6860. 56 functionage.try -= 1;
+
6861. 56 return the_try;
+
6862. 56 }
+
6863. 631
+
6864. 2334 function stmt_var() {
+
6865. 2334 let ellipsis;
+
6866. 2334 let mode_const;
+
6867. 2334 let name;
+
6868. 2334 let the_brace;
+
6869. 2334 let the_bracket;
+
6870. 2334 let the_variable = token_now;
+
6871. 2334 let variable_prv;
+
6872. 2334 mode_const = the_variable.id === "const";
+
6873. 2334 the_variable.names = [];
+
6874. 2334
+
6875. 2334// A program may use var or let, but not both.
+
6876. 2334
+
6877. 2058 if (!mode_const) {
+
6878. 2058 if (mode_var === undefined) {
+
6879. 2058 mode_var = the_variable.id;
+
6880. 2058 } else if (the_variable.id !== mode_var) {
+
6881. 2058
+
6882. 2058// test_cause:
+
6883. 2058// ["let aa;var aa", "stmt_var", "expected_a_b", "var", 8]
+
6884. 2058
+
6885. 2058 warn("expected_a_b", the_variable, mode_var, the_variable.id);
+
6886. 2058 }
+
6887. 2058 }
+
6888. 2334
+
6889. 2334// We don't expect to see variables created in switch statements.
+
6890. 2334
+
6891. 1 if (functionage.switch > 0) {
+
6892. 1
+
6893. 1// test_cause:
+
6894. 1// ["switch(0){case 0:var aa}", "stmt_var", "var_switch", "var", 18]
+
6895. 1
+
6896. 1 warn("var_switch", the_variable);
+
6897. 1 }
+
6898. 2334 switch (
+
6899. 2334 Boolean(functionage.statement_prv)
+
6900. 1449 && functionage.statement_prv.id
+
6901. 2334 ) {
+
6902. 107 case "const":
+
6903. 1437 case "let":
+
6904. 1439 case "var":
+
6905. 1439
+
6906. 1439// test_cause:
+
6907. 1439// ["const aa=0;const bb=0;", "stmt_var", "var_prv", "const", 0]
+
6908. 1439// ["let aa=0;let bb=0;", "stmt_var", "var_prv", "let", 0]
+
6909. 1439// ["var aa=0;var bb=0;", "stmt_var", "var_prv", "var", 0]
+
6910. 1439
+
6911. 1439 test_cause("var_prv", functionage.statement_prv.id);
+
6912. 1439 variable_prv = functionage.statement_prv;
+
6913. 1439 break;
+
6914. 3 case "import":
+
6915. 3
+
6916. 3// test_cause:
+
6917. 3// ["import aa from \"aa\";\nlet bb=0;", "stmt_var", "import_prv", "", 0]
+
6918. 3
+
6919. 3 test_cause("import_prv");
+
6920. 3 break;
+
6921. 885 case false:
+
6922. 885 break;
+
6923. 7 default:
+
6924. 7 if (
+
6925. 7 (option_dict.beta && !option_dict.variable)
+
6926. 7 || the_variable.id === "var"
+
6927. 7 ) {
+
6928. 7
+
6929. 7// test_cause:
+
6930. 7// ["console.log();let aa=0;", "stmt_var", "var_on_top", "let", 15]
+
6931. 7// ["console.log();var aa=0;", "stmt_var", "var_on_top", "var", 15]
+
6932. 7// ["try{aa();}catch(aa){var aa=0;}", "stmt_var", "var_on_top", "var", 21]
+
6933. 7// ["while(0){var aa;}", "stmt_var", "var_on_top", "var", 10]
+
6934. 7
+
6935. 7 warn("var_on_top", token_now);
+
6936. 7 }
+
6937. 2334 }
+
6938. 2335 while (true) {
+
6939. 2335 if (token_nxt.id === "{") {
+
6940. 2335 if (the_variable.id === "var") {
+
6941. 2335
+
6942. 2335// test_cause:
+
6943. 2335// ["var{aa}=0", "stmt_var", "unexpected_a", "var", 1]
+
6944. 2335
+
6945. 2335 warn("unexpected_a", the_variable);
+
6946. 2335 }
+
6947. 2335 the_brace = token_nxt;
+
6948. 2335 advance("{");
+
6949. 2335 while (true) {
+
6950. 2335 name = token_nxt;
+
6951. 2335 if (!name.identifier) {
+
6952. 2335
+
6953. 2335// test_cause:
+
6954. 2335// ["let {0}", "stmt_var", "expected_identifier_a", "0", 6]
+
6955. 2335
+
6956. 2335 return stop("expected_identifier_a");
+
6957. 2335 }
+
6958. 2335 survey(name);
+
6959. 2335 advance();
+
6960. 2335 if (token_nxt.id === ":") {
+
6961. 2335 advance(":");
+
6962. 2335 if (!token_nxt.identifier) {
+
6963. 2335
+
6964. 2335// test_cause:
+
6965. 2335// ["let {aa:0}", "stmt_var", "expected_identifier_a", "0", 9]
+
6966. 2335// ["let {aa:{aa}}", "stmt_var", "expected_identifier_a", "{", 9]
+
6967. 2335
+
6968. 2335 return stop("expected_identifier_a");
+
6969. 2335 }
+
6970. 2335
+
6971. 2335// PR-363 - Bugfix
+
6972. 2335// Add test against false-warning <uninitialized 'bb'> in code
+
6973. 2335// '/*jslint node*/\nlet {aa:bb} = {}; bb();'.
+
6974. 2335//
+
6975. 2335// token_nxt.label = name;
+
6976. 2335// the_variable.names.push(token_nxt);
+
6977. 2335// enroll(token_nxt, "variable", mode_const);
+
6978. 2335
+
6979. 2335 name = token_nxt;
+
6980. 2335 the_variable.names.push(name);
+
6981. 2335 survey(name);
+
6982. 2335 enroll(name, "variable", mode_const);
+
6983. 2335
+
6984. 2335 advance();
+
6985. 2335 the_brace.open = true;
+
6986. 2335 } else {
+
6987. 2335 the_variable.names.push(name);
+
6988. 2335 enroll(name, "variable", mode_const);
+
6989. 2335 }
+
6990. 2335 name.dead = false;
+
6991. 2335 name.init = true;
+
6992. 2335 if (token_nxt.id === "=") {
+
6993. 2335
+
6994. 2335// test_cause:
+
6995. 2335// ["let {aa=0}", "stmt_var", "assign", "", 0]
+
6996. 2335
+
6997. 2335 test_cause("assign");
+
6998. 2335 advance("=");
+
6999. 2335 name.expression = parse_expression();
+
7000. 2335 the_brace.open = true;
+
7001. 2335 }
+
7002. 2335 if (token_nxt.id !== ",") {
+
7003. 2335 break;
+
7004. 2335 }
+
7005. 2335 advance(",");
+
7006. 2335 }
+
7007. 2335
+
7008. 2335// test_cause:
+
7009. 2335// ["let{bb,aa}", "check_ordered", "expected_a_b_before_c_d", "aa", 8]
+
7010. 2335
+
7011. 2335 check_ordered(the_variable.id, the_variable.names);
+
7012. 2335 advance("}");
+
7013. 2335 advance("=");
+
7014. 2335 the_variable.expression = parse_expression(0);
+
7015. 2335 } else if (token_nxt.id === "[") {
+
7016. 2335 if (the_variable.id === "var") {
+
7017. 2335
+
7018. 2335// test_cause:
+
7019. 2335// ["var[aa]=0", "stmt_var", "unexpected_a", "var", 1]
+
7020. 2335
+
7021. 2335 warn("unexpected_a", the_variable);
+
7022. 2335 }
+
7023. 2335 the_bracket = token_nxt;
+
7024. 2335 advance("[");
+
7025. 2335 while (true) {
+
7026. 2335 ellipsis = false;
+
7027. 2335 if (token_nxt.id === "...") {
+
7028. 2335 ellipsis = true;
+
7029. 2335 advance("...");
+
7030. 2335 }
+
7031. 2335 if (!token_nxt.identifier) {
+
7032. 2335
+
7033. 2335// test_cause:
+
7034. 2335// ["let[]", "stmt_var", "expected_identifier_a", "]", 5]
+
7035. 2335
+
7036. 2335 return stop("expected_identifier_a");
+
7037. 2335 }
+
7038. 2335 name = token_nxt;
+
7039. 2335 advance();
+
7040. 2335 the_variable.names.push(name);
+
7041. 2335 enroll(name, "variable", mode_const);
+
7042. 2335 name.dead = false;
+
7043. 2335 name.init = true;
+
7044. 2335 if (ellipsis) {
+
7045. 2335 name.ellipsis = true;
+
7046. 2335 break;
+
7047. 2335 }
+
7048. 2335 if (token_nxt.id === "=") {
+
7049. 2335 advance("=");
+
7050. 2335 name.expression = parse_expression();
+
7051. 2335 the_bracket.open = true;
+
7052. 2335 }
+
7053. 2335 if (token_nxt.id !== ",") {
+
7054. 2335 break;
+
7055. 2335 }
+
7056. 2335 advance(",");
+
7057. 2335 }
+
7058. 2335 advance("]");
+
7059. 2335 advance("=");
+
7060. 2335 the_variable.expression = parse_expression(0);
+
7061. 2335 } else if (token_nxt.identifier) {
+
7062. 2335 name = token_nxt;
+
7063. 2335 advance();
+
7064. 2335 if (name.id === "ignore") {
+
7065. 2335
+
7066. 2335// test_cause:
+
7067. 2335// ["
+
7068. 2335// let ignore;function aa(ignore) {}
+
7069. 2335// ", "stmt_var", "unexpected_a", "ignore", 5]
+
7070. 2335
+
7071. 2335 warn("unexpected_a", name);
+
7072. 2335 }
+
7073. 2335 enroll(name, "variable", mode_const);
+
7074. 2335 if (token_nxt.id === "=" || mode_const) {
+
7075. 2335 advance("=");
+
7076. 2335 name.dead = false;
+
7077. 2335 name.init = true;
+
7078. 2335 name.expression = parse_expression(0);
+
7079. 2335 }
+
7080. 2335 the_variable.names.push(name);
+
7081. 2335 } else {
+
7082. 2335
+
7083. 2335// test_cause:
+
7084. 2335// ["let 0", "stmt_var", "expected_identifier_a", "0", 5]
+
7085. 2335// ["var{aa:{aa}}", "stmt_var", "expected_identifier_a", "{", 8]
+
7086. 2335
+
7087. 2335 return stop("expected_identifier_a");
+
7088. 2335 }
+
7089. 2335 if (token_nxt.id !== ",") {
+
7090. 2335 break;
+
7091. 2335 }
+
7092. 2335
+
7093. 2335// test_cause:
+
7094. 2335// ["let aa,bb;", "stmt_var", "expected_a_b", ",", 7]
+
7095. 2335
+
7096. 2335 warn("expected_a_b", token_nxt, ";", ",");
+
7097. 2335 advance(",");
+
7098. 2335 }
+
7099. 2320
+
7100. 2320// Warn if variable declarations are unordered.
+
7101. 2320
+
7102. 2320 if (
+
7103. 2320 option_dict.beta
+
7104. 2320 && !option_dict.unordered
+
7105. 2315 && !option_dict.variable
+
7106. 2309 && variable_prv
+
7107. 1437 && (
+
7108. 1437 variable_prv.id + " " + variable_prv.names[0].id
+
7109. 1437 > the_variable.id + " " + the_variable.names[0].id
+
7110. 1437 )
+
7111. 3 ) {
+
7112. 3
+
7113. 3// test_cause:
+
7114. 3// ["const bb=0;const aa=0;", "stmt_var", "expected_a_b_before_c_d", "aa", 12]
+
7115. 3// ["let bb;let aa;", "stmt_var", "expected_a_b_before_c_d", "aa", 8]
+
7116. 3// ["var bb;var aa;", "stmt_var", "expected_a_b_before_c_d", "aa", 8]
+
7117. 3
+
7118. 3 warn(
+
7119. 3 "expected_a_b_before_c_d",
+
7120. 3 the_variable,
+
7121. 3 the_variable.id,
+
7122. 3 the_variable.names[0].id,
+
7123. 3 variable_prv.id,
+
7124. 3 variable_prv.names[0].id
+
7125. 3 );
+
7126. 2320 }
+
7127. 2320 semicolon();
+
7128. 2320 return the_variable;
+
7129. 2320 }
+
7130. 631
+
7131. 208 function stmt_while() {
+
7132. 208 const the_while = token_now;
+
7133. 208 check_not_top_level(the_while);
+
7134. 208 functionage.loop += 1;
+
7135. 208 the_while.expression = condition();
+
7136. 208 the_while.block = block();
+
7137. 1 if (the_while.block.disrupt === true) {
+
7138. 1
+
7139. 1// test_cause:
+
7140. 1// ["function aa(){while(0){break;}}", "stmt_while", "weird_loop", "while", 15]
+
7141. 1
+
7142. 1 warn("weird_loop", the_while);
+
7143. 205 }
+
7144. 205 functionage.loop -= 1;
+
7145. 205 return the_while;
+
7146. 205 }
+
7147. 631
+
7148. 1 function stmt_with() {
+
7149. 1
+
7150. 1// test_cause:
+
7151. 1// ["with", "stmt_with", "unexpected_a", "with", 1]
+
7152. 1
+
7153. 1 stop("unexpected_a", token_now);
+
7154. 1 }
+
7155. 631
+
7156. 14600 function survey(name) {
+
7157. 14600 let id = name.id;
+
7158. 14600
+
7159. 14600// Tally the property name. If it is a string, only tally strings that conform
+
7160. 14600// to the identifier rules.
+
7161. 14600
+
7162. 183 if (id === "(string)") {
+
7163. 183 id = name.value;
+
7164. 183 if (!jslint_rgx_identifier.test(id)) {
+
7165. 183 return id;
+
7166. 183 }
+
7167. 14417 } else if (id === "`") {
+
7168. 14417 if (name.value.length === 1) {
+
7169. 14417 id = name.value[0].value;
+
7170. 14417 if (!jslint_rgx_identifier.test(id)) {
+
7171. 14417 return id;
+
7172. 14417 }
+
7173. 14417 }
+
7174. 14417 } else if (!name.identifier) {
+
7175. 14417
+
7176. 14417// test_cause:
+
7177. 14417// ["let aa={0:0}", "survey", "expected_identifier_a", "0", 9]
+
7178. 14417
+
7179. 14417 return stop("expected_identifier_a", name);
+
7180. 14513 }
+
7181. 14513
+
7182. 14513// If we have seen this name before, increment its count.
+
7183. 14513
+
7184. 14513 if (typeof property_dict[id] === "number") {
+
7185. 12086 property_dict[id] += 1;
+
7186. 12086
+
7187. 12086// If this is the first time seeing this property name, and if there is a
+
7188. 12086// tenure list, then it must be on the list. Otherwise, it must conform to
+
7189. 12086// the rules for good property names.
+
7190. 12086
+
7191. 12086 } else {
+
7192. 2427 if (state.mode_property) {
+
7193. 2427 if (tenure[id] !== true) {
+
7194. 2427
+
7195. 2427// test_cause:
+
7196. 2427// ["/*property aa*/\naa.bb", "survey", "unregistered_property_a", "bb", 4]
+
7197. 2427
+
7198. 2427 warn("unregistered_property_a", name);
+
7199. 2427 }
+
7200. 2427 } else if (
+
7201. 2427 !option_dict.nomen
+
7202. 2427 && name.identifier
+
7203. 2427 && jslint_rgx_weird_property.test(id)
+
7204. 2427 ) {
+
7205. 2427
+
7206. 2427// test_cause:
+
7207. 2427// ["aa.$", "survey", "weird_property_a", "$", 4]
+
7208. 2427// ["aa._", "survey", "weird_property_a", "_", 4]
+
7209. 2427// ["aa._aa", "survey", "weird_property_a", "_aa", 4]
+
7210. 2427// ["aa.aaSync", "survey", "weird_property_a", "aaSync", 4]
+
7211. 2427// ["aa.aa_", "survey", "weird_property_a", "aa_", 4]
+
7212. 2427
+
7213. 2427 warn("weird_property_a", name);
+
7214. 2427 }
+
7215. 2427 property_dict[id] = 1;
+
7216. 14513 }
+
7217. 14513 return id;
+
7218. 14513 }
+
7219. 631
+
7220. 631// These functions are used to specify the grammar of our language:
+
7221. 631
+
7222. 82030 function symbol(id, bp) {
+
7223. 82030
+
7224. 82030// Create a symbol if it does not already exist in the language's syntax.
+
7225. 82030
+
7226. 82030 let the_symbol = syntax_dict[id];
+
7227. 71303 if (the_symbol === undefined) {
+
7228. 71303 the_symbol = empty();
+
7229. 71303 the_symbol.id = id;
+
7230. 71303 the_symbol.lbp = bp || 0;
+
7231. 71303 syntax_dict[id] = the_symbol;
+
7232. 71303 }
+
7233. 82030 return the_symbol;
+
7234. 82030 }
+
7235. 631
+
7236. 631 function ternary(id1, id2) {
+
7237. 631
+
7238. 631// Create a ternary operator.
+
7239. 631
+
7240. 631 const the_symbol = symbol(id1, 30);
+
7241. 213 the_symbol.led_infix = function parse_ternary_led(left) {
+
7242. 213 const the_token = token_now;
+
7243. 213 let second;
+
7244. 213 second = parse_expression(20);
+
7245. 213 advance(id2);
+
7246. 213 token_now.arity = "ternary";
+
7247. 213 the_token.arity = "ternary";
+
7248. 213 the_token.expression = [left, second, parse_expression(10)];
+
7249. 5 if (token_nxt.id !== ")") {
+
7250. 5
+
7251. 5// test_cause:
+
7252. 5// ["0?0:0", "parse_ternary_led", "use_open", "?", 2]
+
7253. 5
+
7254. 5 warn("use_open", the_token);
+
7255. 5 }
+
7256. 213 return the_token;
+
7257. 213 };
+
7258. 631 return the_symbol;
+
7259. 631 }
+
7260. 631
+
7261. 631// Now we parse JavaScript.
+
7262. 631// Begin defining the language.
+
7263. 631
+
7264. 631 assignment("%=");
+
7265. 631 assignment("&=");
+
7266. 631 assignment("*=");
+
7267. 631 assignment("+=");
+
7268. 631 assignment("-=");
+
7269. 631 assignment("/=");
+
7270. 631 assignment("<<=");
+
7271. 631 assignment("=");
+
7272. 631 assignment(">>=");
+
7273. 631 assignment(">>>=");
+
7274. 631 assignment("^=");
+
7275. 631 assignment("|=");
+
7276. 631 constant("(number)", "number");
+
7277. 631 constant("(regexp)", "regexp");
+
7278. 631 constant("(string)", "string");
+
7279. 631 constant("Function", "function", constant_Function);
+
7280. 631 constant("Infinity", "number", Infinity);
+
7281. 631 constant("NaN", "number", NaN);
+
7282. 631 constant("arguments", "object", constant_arguments);
+
7283. 631 constant("eval", "function", constant_eval);
+
7284. 631 constant("false", "boolean", false);
+
7285. 631 constant("ignore", "undefined", constant_ignore);
+
7286. 631 constant("isFinite", "function", constant_isInfinite);
+
7287. 631 constant("isNaN", "function", constant_isNaN);
+
7288. 631 constant("null", "null", null);
+
7289. 631 constant("this", "object", constant_this);
+
7290. 631 constant("true", "boolean", true);
+
7291. 631 constant("undefined", "undefined");
+
7292. 631 infix(100, "!=");
+
7293. 631 infix(100, "!==");
+
7294. 631 infix(100, "==");
+
7295. 631 infix(100, "===");
+
7296. 631 infix(110, "<");
+
7297. 631 infix(110, "<=");
+
7298. 631 infix(110, ">");
+
7299. 631 infix(110, ">=");
+
7300. 631 infix(110, "in");
+
7301. 631 infix(110, "instanceof");
+
7302. 631 infix(120, "<<");
+
7303. 631 infix(120, ">>");
+
7304. 631 infix(120, ">>>");
+
7305. 631 infix(130, "+");
+
7306. 631 infix(130, "-");
+
7307. 631 infix(140, "%");
+
7308. 631 infix(140, "*");
+
7309. 631 infix(140, "/");
+
7310. 631 infix(160, "(", infix_lparen);
+
7311. 631 infix(160, "`", infix_grave);
+
7312. 631 infix(170, ".", infix_dot);
+
7313. 631 infix(170, "=>", infix_fart_unwrapped);
+
7314. 631 infix(170, "?.", infix_option_chain);
+
7315. 631 infix(170, "[", infix_lbracket);
+
7316. 631 infix(35, "??");
+
7317. 631 infix(40, "||");
+
7318. 631 infix(50, "&&");
+
7319. 631 infix(70, "|");
+
7320. 631 infix(80, "^");
+
7321. 631 infix(90, "&");
+
7322. 631 infixr(150, "**");
+
7323. 631 postassign("++");
+
7324. 631 postassign("--");
+
7325. 631 preassign("++");
+
7326. 631 preassign("--");
+
7327. 631 prefix("!!");
+
7328. 631 prefix("!");
+
7329. 631 prefix("(", prefix_lparen);
+
7330. 631 prefix("+");
+
7331. 631 prefix("-");
+
7332. 631 prefix("/=", prefix_assign_divide);
+
7333. 631 prefix("=>", prefix_fart);
+
7334. 631 prefix("[", prefix_lbracket);
+
7335. 631 prefix("`", prefix_tick);
+
7336. 631 prefix("async", prefix_async);
+
7337. 631 prefix("await", prefix_await);
+
7338. 631 prefix("function", prefix_function);
+
7339. 631 prefix("new", prefix_new);
+
7340. 631 prefix("typeof");
+
7341. 631 prefix("void", prefix_void);
+
7342. 631 prefix("{", prefix_lbrace);
+
7343. 631 prefix("~");
+
7344. 631 stmt(";", stmt_semicolon);
+
7345. 631 stmt("async", prefix_async);
+
7346. 631 stmt("await", prefix_await);
+
7347. 631 stmt("break", stmt_break);
+
7348. 631 stmt("const", stmt_var);
+
7349. 631 stmt("continue", stmt_continue);
+
7350. 631 stmt("debugger", stmt_debugger);
+
7351. 631 stmt("delete", stmt_delete);
+
7352. 631 stmt("do", stmt_do);
+
7353. 631 stmt("export", stmt_export);
+
7354. 631 stmt("for", stmt_for);
+
7355. 631 stmt("function", prefix_function);
+
7356. 631 stmt("if", stmt_if);
+
7357. 631 stmt("import", stmt_import);
+
7358. 631 stmt("let", stmt_var);
+
7359. 631 stmt("return", stmt_return);
+
7360. 631 stmt("switch", stmt_switch);
+
7361. 631 stmt("throw", stmt_throw);
+
7362. 631 stmt("try", stmt_try);
+
7363. 631 stmt("var", stmt_var);
+
7364. 631 stmt("while", stmt_while);
+
7365. 631 stmt("with", stmt_with);
+
7366. 631 stmt("{", stmt_lbrace);
+
7367. 631 symbol(")");
+
7368. 631 symbol("*/");
+
7369. 631 symbol(",");
+
7370. 631 symbol(":");
+
7371. 631 symbol(";");
+
7372. 631 symbol("]");
+
7373. 631 symbol("async");
+
7374. 631 symbol("await");
+
7375. 631 symbol("case");
+
7376. 631 symbol("catch");
+
7377. 631 symbol("class");
+
7378. 631 symbol("default");
+
7379. 631 symbol("else");
+
7380. 631 symbol("enum");
+
7381. 631 symbol("finally");
+
7382. 631 symbol("implements");
+
7383. 631 symbol("interface");
+
7384. 631 symbol("package");
+
7385. 631 symbol("private");
+
7386. 631 symbol("protected");
+
7387. 631 symbol("public");
+
7388. 631 symbol("static");
+
7389. 631 symbol("super");
+
7390. 631 symbol("void");
+
7391. 631 symbol("yield");
+
7392. 631 symbol("}");
+
7393. 631 ternary("?", ":");
+
7394. 631
+
7395. 631// Init token_nxt.
+
7396. 631
+
7397. 631 advance();
+
7398. 631
+
7399. 631// Parsing of JSON is simple:
+
7400. 631
+
7401. 25 if (state.mode_json) {
+
7402. 25 state.token_tree = parse_json();
+
7403. 25 advance("(end)");
+
7404. 25 return;
+
7405. 606 }
+
7406. 606
+
7407. 606// Because browsers encourage combining of script files, the first token might
+
7408. 606// be a semicolon to defend against a missing semicolon in the preceding file.
+
7409. 606
+
7410. 606 if (option_dict.browser) {
+
7411. 5 if (token_nxt.id === ";") {
+
7412. 5 advance(";");
+
7413. 5 }
+
7414. 5
+
7415. 5// If we are not in a browser, then the file form of strict pragma may be used.
+
7416. 5
+
7417. 601 } else if (token_nxt.value === "use strict") {
+
7418. 601 advance("(string)");
+
7419. 601 advance(";");
+
7420. 606 }
+
7421. 606 state.token_tree = parse_statements();
+
7422. 606 advance("(end)");
+
7423. 606
+
7424. 606// Check global functions are ordered.
+
7425. 606
+
7426. 606 check_ordered(
+
7427. 606 "function",
+
7428. 2001 function_list.map(function ({
+
7429. 2001 level,
+
7430. 2001 name
+
7431. 2001 }) {
+
7432. 606 return (level === 1) && name;
+
7433. 2001 }).filter(function (name) {
+
7434. 1992 return option_dict.beta && name && name.id;
+
7435. 2001 })
+
7436. 606 );
+
7437. 606}
+
7438. 1
+
7439. 518function jslint_phase4_walk(state) {
+
7440. 518
+
7441. 518// PHASE 4. Walk <token_tree>, traversing all nodes of the tree. It is a
+
7442. 518// recursive traversal. Each node may be processed on the way down
+
7443. 518// (preaction) and on the way up (postaction).
+
7444. 518
+
7445. 518 let {
+
7446. 518 artifact,
+
7447. 518 catch_stack,
+
7448. 518 function_stack,
+
7449. 518 global_dict,
+
7450. 518 is_equal,
+
7451. 518 is_weird,
+
7452. 518 option_dict,
+
7453. 518 syntax_dict,
+
7454. 518 test_cause,
+
7455. 518 token_global,
+
7456. 518 warn
+
7457. 518 } = state;
+
7458. 518 let block_stack = []; // The stack of blocks.
+
7459. 518 let blockage = token_global; // The current block.
+
7460. 518 let catchage = catch_stack[0]; // The current catch-block.
+
7461. 518 let functionage = token_global; // The current function.
+
7462. 518 let postaction;
+
7463. 518 let postamble;
+
7464. 518 let posts = empty();
+
7465. 518 let preaction;
+
7466. 518 let preamble;
+
7467. 518 let pres = empty();
+
7468. 518
+
7469. 518// The relational operators.
+
7470. 518
+
7471. 518 let relationop = object_assign_from_list(empty(), [
+
7472. 518 "!=", "!==", "<", "<=", "==", "===", ">", ">="
+
7473. 518 ], true);
+
7474. 518
+
7475. 518// Ambulation of the parse tree.
+
7476. 518
+
7477. 1036 function action(when) {
+
7478. 1036
+
7479. 1036// Produce a function that will register task functions that will be called as
+
7480. 1036// the tree is traversed.
+
7481. 1036
+
7482. 19684 return function (arity, id, task) {
+
7483. 19684 let a_set = when[arity];
+
7484. 19684 let i_set;
+
7485. 19684
+
7486. 19684// The id parameter is optional. If excluded, the task will be applied to all
+
7487. 19684// ids.
+
7488. 19684
+
7489. 4144 if (typeof id !== "string") {
+
7490. 4144 task = id;
+
7491. 4144 id = "(all)";
+
7492. 4144 }
+
7493. 19684
+
7494. 19684// If this arity has no registrations yet, then create a set object to hold
+
7495. 19684// them.
+
7496. 19684
+
7497. 5180 if (a_set === undefined) {
+
7498. 5180 a_set = empty();
+
7499. 5180 when[arity] = a_set;
+
7500. 5180 }
+
7501. 19684
+
7502. 19684// If this id has no registrations yet, then create a set array to hold them.
+
7503. 19684
+
7504. 19684 i_set = a_set[id];
+
7505. 19166 if (i_set === undefined) {
+
7506. 19166 i_set = [];
+
7507. 19166 a_set[id] = i_set;
+
7508. 19166 }
+
7509. 19684
+
7510. 19684// Register the task with the arity and the id.
+
7511. 19684
+
7512. 19684 i_set.push(task);
+
7513. 19684 };
+
7514. 1036 }
+
7515. 518
+
7516. 1036 function amble(when) {
+
7517. 1036
+
7518. 1036// Produce a function that will act on the tasks registered by an action
+
7519. 1036// function while walking the tree.
+
7520. 1036
+
7521. 210942 return function (the_token) {
+
7522. 210942
+
7523. 210942// Given a task set that was built by an action function, run all
+
7524. 210942// relevant tasks on the token.
+
7525. 210942
+
7526. 210942 let a_set = when[the_token.arity];
+
7527. 210942 let i_set;
+
7528. 210942
+
7529. 210942// If there are tasks associated with the token's arity...
+
7530. 210942
+
7531. 144702 if (a_set !== undefined) {
+
7532. 144702
+
7533. 144702// If there are tasks associated with the token's id...
+
7534. 144702
+
7535. 144702 i_set = a_set[the_token.id];
+
7536. 144702 if (i_set !== undefined) {
+
7537. 144702 i_set.forEach(function (task) {
+
7538. 144702 task(the_token);
+
7539. 144702 });
+
7540. 144702 }
+
7541. 144702
+
7542. 144702// If there are tasks for all ids.
+
7543. 144702
+
7544. 144702 i_set = a_set["(all)"];
+
7545. 144702 if (i_set !== undefined) {
+
7546. 144702 i_set.forEach(function (task) {
+
7547. 144702 task(the_token);
+
7548. 144702 });
+
7549. 144702 }
+
7550. 144702 }
+
7551. 210942 };
+
7552. 1036 }
+
7553. 518
+
7554. 2818 function init_variable(name) {
+
7555. 2818 let the_variable = lookup(name);
+
7556. 2759 if (!the_variable || the_variable.readonly) {
+
7557. 61 warn("bad_assignment_a", name);
+
7558. 61 return;
+
7559. 2757 }
+
7560. 2757 the_variable.init = true;
+
7561. 2757 }
+
7562. 518
+
7563. 31509 function lookup(thing) {
+
7564. 31509 let id = thing.id;
+
7565. 31509 let the_variable;
+
7566. 1 if (thing.arity !== "variable") {
+
7567. 1 return;
+
7568. 31508 }
+
7569. 31508
+
7570. 31508// Look up the variable in the current context.
+
7571. 31508
+
7572. 31508 the_variable = functionage.context[id] || catchage.context[id];
+
7573. 31509
+
7574. 31509// If it isn't local, search all the other contexts. If there are name
+
7575. 31509// collisions, take the most recent.
+
7576. 31509
+
7577. 24629 if (the_variable && the_variable.role === "label") {
+
7578. 1
+
7579. 1// test_cause:
+
7580. 1// ["aa:while(0){aa;}", "lookup", "label_a", "aa", 13]
+
7581. 1
+
7582. 1 warn("label_a", thing);
+
7583. 1 return the_variable;
+
7584. 31507 }
+
7585. 31507 if (!the_variable) {
+
7586. 14775 function_stack.forEach(function ({
+
7587. 14775 context
+
7588. 14775 }) {
+
7589. 6879 if (context[id] && context[id].role !== "label") {
+
7590. 6879 the_variable = context[id];
+
7591. 6879 }
+
7592. 14775 });
+
7593. 6879
+
7594. 6879// If it isn't in any of those either, perhaps it is a predefined global.
+
7595. 6879// If so, add it to the global context.
+
7596. 6879
+
7597. 6879 if (!the_variable && global_dict[id] === undefined) {
+
7598. 6879
+
7599. 6879// test_cause:
+
7600. 6879// ["aa", "lookup", "undeclared_a", "aa", 1]
+
7601. 6879// ["class aa{}", "lookup", "undeclared_a", "aa", 7]
+
7602. 6879// ["
+
7603. 6879// let aa=0;try{aa();}catch(bb){bb();}bb();
+
7604. 6879// ", "lookup", "undeclared_a", "bb", 36]
+
7605. 6879// ["
+
7606. 6879// let aa=0;try{aa();}catch(ignore){bb();}
+
7607. 6879// ", "lookup", "undeclared_a", "bb", 34]
+
7608. 6879
+
7609. 6879 warn("undeclared_a", thing);
+
7610. 6879 return;
+
7611. 6879 }
+
7612. 6879 if (!the_variable) {
+
7613. 6879 the_variable = {
+
7614. 6879 dead: false,
+
7615. 6879 id,
+
7616. 6879 init: true,
+
7617. 6879 parent: token_global,
+
7618. 6879 readonly: true,
+
7619. 6879 role: "variable",
+
7620. 6879 used: 0
+
7621. 6879 };
+
7622. 6879 token_global.context[id] = the_variable;
+
7623. 6879 }
+
7624. 6879 the_variable.closure = true;
+
7625. 6879 functionage.context[id] = the_variable;
+
7626. 31370 }
+
7627. 31370 if (
+
7628. 31370 (
+
7629. 31370 the_variable.calls === undefined
+
7630. 31370 || functionage.name === undefined
+
7631. 4364 || the_variable.calls[functionage.name.id] === undefined
+
7632. 31509 )
+
7633. 31185 && the_variable.dead
+
7634. 3 ) {
+
7635. 3
+
7636. 3// test_cause:
+
7637. 3// ["let aa;if(aa){let bb;}bb;", "lookup", "out_of_scope_a", "bb", 23]
+
7638. 3
+
7639. 3 warn("out_of_scope_a", thing);
+
7640. 31370 }
+
7641. 31370 return the_variable;
+
7642. 31370 }
+
7643. 518
+
7644. 5009 function post_a(thing) {
+
7645. 5009
+
7646. 5009// Assignment using = sets the init property of a variable. No other assignment
+
7647. 5009// operator can do this. A = token keeps that variable (or array of variables
+
7648. 5009// in case of destructuring) in its name property.
+
7649. 5009
+
7650. 5009 const lvalue = thing.expression[0];
+
7651. 5009 let right;
+
7652. 4234 if (thing.id === "=") {
+
7653. 4234 if (thing.names !== undefined) {
+
7654. 4234
+
7655. 4234// test_cause:
+
7656. 4234// ["if(0){aa=0}", "post_a", "=", "", 0]
+
7657. 4234
+
7658. 4234 test_cause("=");
+
7659. 4234
+
7660. 4234// Probably deadcode.
+
7661. 4234// if (Array.isArray(thing.names)) {
+
7662. 4234// thing.names.forEach(init_variable);
+
7663. 4234// } else {
+
7664. 4234// init_variable(thing.names);
+
7665. 4234// }
+
7666. 4234
+
7667. 4234 jslint_assert(
+
7668. 4234 !Array.isArray(thing.names),
+
7669. 4234 `Expected !Array.isArray(thing.names).`
+
7670. 4234 );
+
7671. 4234 init_variable(thing.names);
+
7672. 4234 } else {
+
7673. 4234 if (lvalue.id === "[" || lvalue.id === "{") {
+
7674. 4234 lvalue.expression.forEach(function (thing) {
+
7675. 4234 if (thing.variable) {
+
7676. 4234 thing.variable.init = true;
+
7677. 4234 }
+
7678. 4234 });
+
7679. 4234 } else if (
+
7680. 4234 lvalue.id === "."
+
7681. 4234 && thing.expression[1].id === "undefined"
+
7682. 4234 ) {
+
7683. 4234
+
7684. 4234// test_cause:
+
7685. 4234// ["aa.aa=undefined", "post_a", "expected_a_b", "undefined", 1]
+
7686. 4234
+
7687. 4234 warn(
+
7688. 4234 "expected_a_b",
+
7689. 4234 lvalue.expression,
+
7690. 4234 "delete",
+
7691. 4234 "undefined"
+
7692. 4234 );
+
7693. 4234 }
+
7694. 4234 }
+
7695. 4234 } else {
+
7696. 775 if (lvalue.arity === "variable") {
+
7697. 775 if (!lvalue.variable || lvalue.variable.readonly) {
+
7698. 775 warn("bad_assignment_a", lvalue);
+
7699. 775 }
+
7700. 775 }
+
7701. 775 right = syntax_dict[thing.expression[1].id];
+
7702. 775 if (
+
7703. 775 right !== undefined
+
7704. 775 && (
+
7705. 775 right.id === "function"
+
7706. 775 || right.id === "=>"
+
7707. 775 || (
+
7708. 775 right.constant
+
7709. 775 && right.id !== "(number)"
+
7710. 775 && (right.id !== "(string)" || thing.id !== "+=")
+
7711. 775 )
+
7712. 775 )
+
7713. 775 ) {
+
7714. 775
+
7715. 775// test_cause:
+
7716. 775// ["aa+=undefined", "post_a", "unexpected_a", "undefined", 5]
+
7717. 775
+
7718. 775 warn("unexpected_a", thing.expression[1]);
+
7719. 775 }
+
7720. 775 }
+
7721. 5009 }
+
7722. 518
+
7723. 706 function post_a_pluseq(thing) {
+
7724. 706 const right = thing.expression[1];
+
7725. 396 if (right.constant) {
+
7726. 396 if (
+
7727. 396 right.value === ""
+
7728. 396 || (right.id === "(number)" && right.value === "0")
+
7729. 396 || right.id === "(boolean)"
+
7730. 396 || right.id === "null"
+
7731. 396 || right.id === "undefined"
+
7732. 396 || Number.isNaN(right.value)
+
7733. 396 ) {
+
7734. 396 warn("unexpected_a", right);
+
7735. 396 }
+
7736. 396 }
+
7737. 706 }
+
7738. 518
+
7739. 31933 function post_b(thing) {
+
7740. 31933 let right;
+
7741. 3960 if (relationop[thing.id]) {
+
7742. 3960 if (
+
7743. 3960 is_weird(thing.expression[0])
+
7744. 3960 || is_weird(thing.expression[1])
+
7745. 3960 || is_equal(thing.expression[0], thing.expression[1])
+
7746. 3960 || (
+
7747. 3960 thing.expression[0].constant === true
+
7748. 3960 && thing.expression[1].constant === true
+
7749. 3960 )
+
7750. 3960 ) {
+
7751. 3960
+
7752. 3960// test_cause:
+
7753. 3960// ["if(0===0){0}", "post_b", "weird_relation_a", "===", 5]
+
7754. 3960
+
7755. 3960 warn("weird_relation_a", thing);
+
7756. 3960 }
+
7757. 3960 }
+
7758. 2023 if (thing.id === "+") {
+
7759. 2023 if (!option_dict.convert) {
+
7760. 2023 if (thing.expression[0].value === "") {
+
7761. 2023
+
7762. 2023// test_cause:
+
7763. 2023// ["\"\"+0", "post_b", "expected_a_b", "\"\" +", 3]
+
7764. 2023
+
7765. 2023 warn("expected_a_b", thing, "String(...)", "\"\" +");
+
7766. 2023 } else if (thing.expression[1].value === "") {
+
7767. 2023
+
7768. 2023// test_cause:
+
7769. 2023// ["0+\"\"", "post_b", "expected_a_b", "+ \"\"", 2]
+
7770. 2023
+
7771. 2023 warn("expected_a_b", thing, "String(...)", "+ \"\"");
+
7772. 2023 }
+
7773. 2023 }
+
7774. 29910 } else if (thing.id === "[") {
+
7775. 29910 if (thing.expression[0].id === "window") {
+
7776. 29910
+
7777. 29910// test_cause:
+
7778. 29910// ["aa=window[0]", "post_b", "weird_expression_a", "window[...]", 10]
+
7779. 29910
+
7780. 29910 warn("weird_expression_a", thing, "window[...]");
+
7781. 29910 }
+
7782. 29910 if (thing.expression[0].id === "self") {
+
7783. 29910
+
7784. 29910// test_cause:
+
7785. 29910// ["aa=self[0]", "post_b", "weird_expression_a", "self[...]", 8]
+
7786. 29910
+
7787. 29910 warn("weird_expression_a", thing, "self[...]");
+
7788. 29910 }
+
7789. 29910 } else if (thing.id === "." || thing.id === "?.") {
+
7790. 29910 if (thing.expression.id === "RegExp") {
+
7791. 29910
+
7792. 29910// test_cause:
+
7793. 29910// ["aa=RegExp.aa", "post_b", "weird_expression_a", ".", 10]
+
7794. 29910
+
7795. 29910 warn("weird_expression_a", thing);
+
7796. 29910 }
+
7797. 29910 } else if (thing.id !== "=>" && thing.id !== "(") {
+
7798. 29910 right = thing.expression[1];
+
7799. 29910 if (
+
7800. 29910 (thing.id === "+" || thing.id === "-")
+
7801. 29910 && right.id === thing.id
+
7802. 29910 && right.arity === "unary"
+
7803. 29910 && !right.wrapped
+
7804. 29910 ) {
+
7805. 29910
+
7806. 29910// test_cause:
+
7807. 29910// ["0- -0", "post_b", "wrap_unary", "-", 4]
+
7808. 29910
+
7809. 29910 warn("wrap_unary", right);
+
7810. 29910 }
+
7811. 29910 if (
+
7812. 29910 thing.expression[0].constant === true
+
7813. 29910 && right.constant === true
+
7814. 29910 ) {
+
7815. 29910 thing.constant = true;
+
7816. 29910 }
+
7817. 29910 }
+
7818. 31933 }
+
7819. 518
+
7820. 1202 function post_b_and(thing) {
+
7821. 1202 if (
+
7822. 1202 is_weird(thing.expression[0])
+
7823. 1197 || is_equal(thing.expression[0], thing.expression[1])
+
7824. 1183 || thing.expression[0].constant === true
+
7825. 1181 || thing.expression[1].constant === true
+
7826. 21 ) {
+
7827. 21
+
7828. 21// test_cause:
+
7829. 21// ["aa=(()=>0)&&(()=>0)", "post_b_and", "weird_condition_a", "&&", 11]
+
7830. 21// ["aa=(``?``:``)&&(``?``:``)", "post_b_and", "weird_condition_a", "&&", 14]
+
7831. 21// ["aa=/./&&/./", "post_b_and", "weird_condition_a", "&&", 7]
+
7832. 21// ["aa=0&&0", "post_b_and", "weird_condition_a", "&&", 5]
+
7833. 21// ["aa=[]&&[]", "post_b_and", "weird_condition_a", "&&", 6]
+
7834. 21// ["aa=`${0}`&&`${0}`", "post_b_and", "weird_condition_a", "&&", 10]
+
7835. 21// ["
+
7836. 21// aa=function aa(){}&&function aa(){}
+
7837. 21// ", "post_b_and", "weird_condition_a", "&&", 19]
+
7838. 21// ["aa={}&&{}", "post_b_and", "weird_condition_a", "&&", 6]
+
7839. 21
+
7840. 21 warn("weird_condition_a", thing);
+
7841. 21 }
+
7842. 1202 }
+
7843. 518
+
7844. 1460 function post_b_lbracket(thing) {
+
7845. 1 if (thing.expression[0].id === "RegExp") {
+
7846. 1
+
7847. 1// test_cause:
+
7848. 1// ["aa=RegExp[0]", "post_b_lbracket", "weird_expression_a", "[", 10]
+
7849. 1
+
7850. 1 warn("weird_expression_a", thing);
+
7851. 1 }
+
7852. 1 if (is_weird(thing.expression[1])) {
+
7853. 1
+
7854. 1// test_cause:
+
7855. 1// ["aa[[0]]", "post_b_lbracket", "weird_expression_a", "[", 4]
+
7856. 1
+
7857. 1 warn("weird_expression_a", thing.expression[1]);
+
7858. 1 }
+
7859. 1460 }
+
7860. 518
+
7861. 10411 function post_b_lparen(thing) {
+
7862. 10411 let arg;
+
7863. 10411 let array;
+
7864. 10411 let cack;
+
7865. 10411 let left = thing.expression[0];
+
7866. 10411 let new_date;
+
7867. 10411 let paren;
+
7868. 10411 let the_new;
+
7869. 154 if (left.id === "new") {
+
7870. 154 the_new = left;
+
7871. 154 left = left.expression;
+
7872. 154 }
+
7873. 37 if (left.id === "function") {
+
7874. 37 if (!thing.wrapped) {
+
7875. 37
+
7876. 37// test_cause:
+
7877. 37// ["aa=function(){}()", "post_b_lparen", "wrap_immediate", "(", 16]
+
7878. 37
+
7879. 37 warn("wrap_immediate", thing);
+
7880. 37 }
+
7881. 10374 } else if (left.identifier) {
+
7882. 10374 if (the_new !== undefined) {
+
7883. 10374 if (
+
7884. 10374 left.id[0] > "Z"
+
7885. 10374 || left.id === "BigInt"
+
7886. 10374 || left.id === "Boolean"
+
7887. 10374 || left.id === "Number"
+
7888. 10374 || left.id === "String"
+
7889. 10374 || left.id === "Symbol"
+
7890. 10374 ) {
+
7891. 10374
+
7892. 10374// test_cause:
+
7893. 10374// ["new BigInt()", "post_b_lparen", "unexpected_a", "new", 1]
+
7894. 10374// ["new Boolean()", "post_b_lparen", "unexpected_a", "new", 1]
+
7895. 10374// ["new Number()", "post_b_lparen", "unexpected_a", "new", 1]
+
7896. 10374// ["new String()", "post_b_lparen", "unexpected_a", "new", 1]
+
7897. 10374// ["new Symbol()", "post_b_lparen", "unexpected_a", "new", 1]
+
7898. 10374// ["new aa()", "post_b_lparen", "unexpected_a", "new", 1]
+
7899. 10374
+
7900. 10374 warn("unexpected_a", the_new);
+
7901. 10374 } else if (left.id === "Function") {
+
7902. 10374 if (!option_dict.eval) {
+
7903. 10374
+
7904. 10374// test_cause:
+
7905. 10374// ["new Function()", "post_b_lparen", "unexpected_a", "new Function", 5]
+
7906. 10374
+
7907. 10374 warn("unexpected_a", left, "new Function");
+
7908. 10374 }
+
7909. 10374 } else if (left.id === "Array") {
+
7910. 10374 arg = thing.expression;
+
7911. 10374 if (arg.length !== 2 || arg[1].id === "(string)") {
+
7912. 10374
+
7913. 10374// test_cause:
+
7914. 10374// ["new Array()", "post_b_lparen", "expected_a_b", "new Array", 5]
+
7915. 10374
+
7916. 10374 warn("expected_a_b", left, "[]", "new Array");
+
7917. 10374 }
+
7918. 10374 } else if (left.id === "Object") {
+
7919. 10374
+
7920. 10374// test_cause:
+
7921. 10374// ["new Object()", "post_b_lparen", "expected_a_b", "new Object", 5]
+
7922. 10374
+
7923. 10374 warn(
+
7924. 10374 "expected_a_b",
+
7925. 10374 left,
+
7926. 10374 "Object.create(null)",
+
7927. 10374 "new Object"
+
7928. 10374 );
+
7929. 10374 }
+
7930. 10374 } else {
+
7931. 10374 if (
+
7932. 10374 left.id[0] >= "A"
+
7933. 10374 && left.id[0] <= "Z"
+
7934. 10374 && left.id !== "BigInt"
+
7935. 10374 && left.id !== "Boolean"
+
7936. 10374 && left.id !== "Number"
+
7937. 10374 && left.id !== "String"
+
7938. 10374 && left.id !== "Symbol"
+
7939. 10374 ) {
+
7940. 10374
+
7941. 10374// test_cause:
+
7942. 10374// ["let Aa=Aa()", "post_b_lparen", "expected_a_before_b", "Aa", 8]
+
7943. 10374
+
7944. 10374 warn("expected_a_before_b", left, "new", artifact(left));
+
7945. 10374 }
+
7946. 10374 }
+
7947. 10374 } else if (left.id === ".") {
+
7948. 10374 cack = the_new !== undefined;
+
7949. 10374 if (left.expression.id === "Date" && left.name.id === "UTC") {
+
7950. 10374
+
7951. 10374// test_cause:
+
7952. 10374// ["new Date.UTC()", "post_b_lparen", "cack", "", 0]
+
7953. 10374
+
7954. 10374 test_cause("cack");
+
7955. 10374 cack = !cack;
+
7956. 10374 }
+
7957. 10374 if (jslint_rgx_cap.test(left.name.id) !== cack) {
+
7958. 10374 if (the_new !== undefined) {
+
7959. 10374
+
7960. 10374// test_cause:
+
7961. 10374// ["new Date.UTC()", "post_b_lparen", "unexpected_a", "new", 1]
+
7962. 10374
+
7963. 10374 warn("unexpected_a", the_new);
+
7964. 10374 } else {
+
7965. 10374
+
7966. 10374// test_cause:
+
7967. 10374// ["let Aa=Aa.Aa()", "post_b_lparen", "expected_a_before_b", "Aa", 8]
+
7968. 10374
+
7969. 10374 warn(
+
7970. 10374 "expected_a_before_b",
+
7971. 10374 left.expression,
+
7972. 10374 "new",
+
7973. 10374 left.name.id
+
7974. 10374 );
+
7975. 10374 }
+
7976. 10374 }
+
7977. 10374 if (left.name.id === "getTime") {
+
7978. 10374 paren = left.expression;
+
7979. 10374 if (paren.id === "(") {
+
7980. 10374 array = paren.expression;
+
7981. 10374 if (array.length === 1) {
+
7982. 10374 new_date = array[0];
+
7983. 10374 if (
+
7984. 10374 new_date.id === "new"
+
7985. 10374 && new_date.expression.id === "Date"
+
7986. 10374 ) {
+
7987. 10374
+
7988. 10374// test_cause:
+
7989. 10374// ["
+
7990. 10374// new Date().getTime()
+
7991. 10374// ", "post_b_lparen", "expected_a_b", "new Date().getTime()", 1]
+
7992. 10374
+
7993. 10374 warn(
+
7994. 10374 "expected_a_b",
+
7995. 10374 new_date,
+
7996. 10374 "Date.now()",
+
7997. 10374 "new Date().getTime()"
+
7998. 10374 );
+
7999. 10374 }
+
8000. 10374 }
+
8001. 10374 }
+
8002. 10374 }
+
8003. 10374 }
+
8004. 10411 }
+
8005. 518
+
8006. 974 function post_b_or(thing) {
+
8007. 974 if (
+
8008. 974 is_weird(thing.expression[0])
+
8009. 974 || is_equal(thing.expression[0], thing.expression[1])
+
8010. 973 || thing.expression[0].constant === true
+
8011. 2 ) {
+
8012. 2
+
8013. 2// test_cause:
+
8014. 2// ["aa=0||0", "post_b_or", "weird_condition_a", "||", 5]
+
8015. 2
+
8016. 2 warn("weird_condition_a", thing);
+
8017. 2 }
+
8018. 974 }
+
8019. 518
+
8020. 78 function post_s_export(the_thing) {
+
8021. 78
+
8022. 78// Some features must be at the most outermost level.
+
8023. 78
+
8024. 1 if (blockage !== token_global) {
+
8025. 1
+
8026. 1// test_cause:
+
8027. 1// ["
+
8028. 1// if(0){import aa from "aa";}
+
8029. 1// ", "post_s_export", "misplaced_a", "import", 7]
+
8030. 1
+
8031. 1 warn("misplaced_a", the_thing);
+
8032. 1 }
+
8033. 78 }
+
8034. 518
+
8035. 8 function post_s_for(thing) {
+
8036. 8
+
8037. 8// Recurse walk_statement().
+
8038. 8
+
8039. 8 walk_statement(thing.inc);
+
8040. 8 }
+
8041. 518
+
8042. 2001 function post_s_function(thing) {
+
8043. 2001 delete functionage.async;
+
8044. 2001 delete functionage.finally;
+
8045. 2001 delete functionage.loop;
+
8046. 2001 delete functionage.statement_prv;
+
8047. 2001 delete functionage.switch;
+
8048. 2001 delete functionage.try;
+
8049. 2001 functionage = function_stack.pop();
+
8050. 3 if (thing.wrapped) {
+
8051. 3
+
8052. 3// test_cause:
+
8053. 3// ["aa=(function(){})", "post_s_function", "unexpected_parens", "function", 5]
+
8054. 3
+
8055. 3 warn("unexpected_parens", thing);
+
8056. 3 }
+
8057. 2001 return post_s_lbrace();
+
8058. 2001 }
+
8059. 518
+
8060. 61 function post_s_import(the_thing) {
+
8061. 61 const name = the_thing.name;
+
8062. 60 if (name) {
+
8063. 60 if (Array.isArray(name)) {
+
8064. 60 name.forEach(function (name) {
+
8065. 60 name.dead = false;
+
8066. 60 name.init = true;
+
8067. 60 blockage.live.push(name);
+
8068. 60 });
+
8069. 60 } else {
+
8070. 60 name.dead = false;
+
8071. 60 name.init = true;
+
8072. 60 blockage.live.push(name);
+
8073. 60 }
+
8074. 60 return post_s_export(the_thing);
+
8075. 60 }
+
8076. 61 }
+
8077. 518
+
8078. 7695 function post_s_lbrace() {
+
8079. 2987 blockage.live.forEach(function (name) {
+
8080. 2987 name.dead = true;
+
8081. 2987 });
+
8082. 7695 delete blockage.live;
+
8083. 7695 blockage = block_stack.pop();
+
8084. 7695 }
+
8085. 518
+
8086. 56 function post_s_try(thing) {
+
8087. 54 if (thing.catch) {
+
8088. 54 if (thing.catch.name) {
+
8089. 54 Object.assign(catchage.context[thing.catch.name.id], {
+
8090. 54 dead: false,
+
8091. 54 init: true
+
8092. 54 });
+
8093. 54 }
+
8094. 54
+
8095. 54// Recurse walk_statement().
+
8096. 54
+
8097. 54 walk_statement(thing.catch.block);
+
8098. 54
+
8099. 54// Restore previous catch-scope after catch-block.
+
8100. 54
+
8101. 54 catchage = catch_stack.pop();
+
8102. 54 }
+
8103. 56 }
+
8104. 518
+
8105. 2320 function post_s_var(thing) {
+
8106. 2635 thing.names.forEach(function (name) {
+
8107. 2635 name.dead = false;
+
8108. 1250 if (name.expression !== undefined) {
+
8109. 1250 walk_expression(name.expression);
+
8110. 1250
+
8111. 1250// Probably deadcode.
+
8112. 1250// if (name.id === "{" || name.id === "[") {
+
8113. 1250// name.names.forEach(subactivate);
+
8114. 1250// } else {
+
8115. 1250// name.init = true;
+
8116. 1250// }
+
8117. 1250
+
8118. 1250 jslint_assert(
+
8119. 1250 !(name.id === "{" || name.id === "["),
+
8120. 1250 `Expected !(name.id === "{" || name.id === "[").`
+
8121. 1250 );
+
8122. 1250 name.init = true;
+
8123. 1250 }
+
8124. 2635 blockage.live.push(name);
+
8125. 2635 });
+
8126. 2320 }
+
8127. 518
+
8128. 213 function post_t(thing) {
+
8129. 213 if (
+
8130. 213 is_weird(thing.expression[0])
+
8131. 213 || thing.expression[0].constant === true
+
8132. 206 || is_equal(thing.expression[1], thing.expression[2])
+
8133. 9 ) {
+
8134. 9
+
8135. 9// test_cause:
+
8136. 9// ["let aa=(aa?`${0}`:`${0}`);", "post_t", "unexpected_a", "?", 11]
+
8137. 9// ["let aa=(aa?`0`:`0`);", "post_t", "unexpected_a", "?", 11]
+
8138. 9
+
8139. 9 warn("unexpected_a", thing);
+
8140. 204 } else if (is_equal(thing.expression[0], thing.expression[1])) {
+
8141. 204
+
8142. 204// test_cause:
+
8143. 204// ["aa?aa:0", "post_t", "expected_a_b", "?", 3]
+
8144. 204
+
8145. 204 warn("expected_a_b", thing, "||", "?");
+
8146. 204 } else if (is_equal(thing.expression[0], thing.expression[2])) {
+
8147. 204
+
8148. 204// test_cause:
+
8149. 204// ["aa?0:aa", "post_t", "expected_a_b", "?", 3]
+
8150. 204
+
8151. 204 warn("expected_a_b", thing, "&&", "?");
+
8152. 204 } else if (
+
8153. 204 thing.expression[1].id === "true"
+
8154. 204 && thing.expression[2].id === "false"
+
8155. 204 ) {
+
8156. 204
+
8157. 204// test_cause:
+
8158. 204// ["aa?true:false", "post_t", "expected_a_b", "?", 3]
+
8159. 204
+
8160. 204 warn("expected_a_b", thing, "!!", "?");
+
8161. 204 } else if (
+
8162. 204 thing.expression[1].id === "false"
+
8163. 204 && thing.expression[2].id === "true"
+
8164. 204 ) {
+
8165. 204
+
8166. 204// test_cause:
+
8167. 204// ["aa?false:true", "post_t", "expected_a_b", "?", 3]
+
8168. 204
+
8169. 204 warn("expected_a_b", thing, "!", "?");
+
8170. 204 } else if (
+
8171. 204 thing.expression[0].wrapped !== true
+
8172. 204 && (
+
8173. 204 thing.expression[0].id === "||"
+
8174. 204 || thing.expression[0].id === "&&"
+
8175. 204 )
+
8176. 204 ) {
+
8177. 204
+
8178. 204// test_cause:
+
8179. 204// ["(aa&&!aa?0:1)", "post_t", "wrap_condition", "&&", 4]
+
8180. 204
+
8181. 204 warn("wrap_condition", thing.expression[0]);
+
8182. 204 }
+
8183. 213 }
+
8184. 518
+
8185. 4106 function post_u(thing) {
+
8186. 779 if (thing.id === "`") {
+
8187. 779 if (thing.expression.every(function (thing) {
+
8188. 779 return thing.constant;
+
8189. 779 })) {
+
8190. 779 thing.constant = true;
+
8191. 779 }
+
8192. 3327 } else if (thing.id === "!") {
+
8193. 3327 if (thing.expression.constant === true) {
+
8194. 3327 warn("unexpected_a", thing);
+
8195. 3327 }
+
8196. 3327 } else if (thing.id === "!!") {
+
8197. 3327 if (!option_dict.convert) {
+
8198. 3327
+
8199. 3327// test_cause:
+
8200. 3327// ["!!0", "post_u", "expected_a_b", "!!", 1]
+
8201. 3327
+
8202. 3327 warn("expected_a_b", thing, "Boolean(...)", "!!");
+
8203. 3327 }
+
8204. 3327 } else if (
+
8205. 3327 thing.id !== "["
+
8206. 3327 && thing.id !== "{"
+
8207. 3327 && thing.id !== "function"
+
8208. 3327 && thing.id !== "new"
+
8209. 3327 ) {
+
8210. 3327 if (thing.expression.constant === true) {
+
8211. 3327 thing.constant = true;
+
8212. 3327 }
+
8213. 3327 }
+
8214. 4106 }
+
8215. 518
+
8216. 7 function post_u_plus(thing) {
+
8217. 7 const right = thing.expression;
+
8218. 7 if (!option_dict.convert) {
+
8219. 7
+
8220. 7// test_cause:
+
8221. 7// ["aa=+0", "post_u_plus", "expected_a_b", "+", 4]
+
8222. 7
+
8223. 7 warn("expected_a_b", thing, "Number(...)", "+");
+
8224. 7 }
+
8225. 1 if (right.id === "(" && right.expression[0].id === "new") {
+
8226. 1 warn("unexpected_a_before_b", thing, "+", "new");
+
8227. 6 } else if (
+
8228. 6 right.constant
+
8229. 6 || right.id === "{"
+
8230. 6 || (right.id === "[" && right.arity !== "binary")
+
8231. 6 ) {
+
8232. 6 warn("unexpected_a", thing, "+");
+
8233. 6 }
+
8234. 7 }
+
8235. 518
+
8236. 36945 function pre_a_bitwise(thing) {
+
8237. 36945
+
8238. 36945// These are the bitwise operators.
+
8239. 36945
+
8240. 36943 switch (!option_dict.bitwise && thing.id) {
+
8241. 2 case "&":
+
8242. 3 case "&=":
+
8243. 5 case "<<":
+
8244. 6 case "<<=":
+
8245. 8 case ">>":
+
8246. 9 case ">>=":
+
8247. 11 case ">>>":
+
8248. 12 case ">>>=":
+
8249. 14 case "^":
+
8250. 15 case "^=":
+
8251. 17 case "|":
+
8252. 18 case "|=":
+
8253. 21 case "~":
+
8254. 21
+
8255. 21// test_cause:
+
8256. 21// ["0&0", "pre_a_bitwise", "unexpected_a", "&", 2]
+
8257. 21// ["0&=0", "pre_a_bitwise", "unexpected_a", "&=", 2]
+
8258. 21// ["0<<0", "pre_a_bitwise", "unexpected_a", "<<", 2]
+
8259. 21// ["0<<=0", "pre_a_bitwise", "unexpected_a", "<<=", 2]
+
8260. 21// ["0>>0", "pre_a_bitwise", "unexpected_a", ">>", 2]
+
8261. 21// ["0>>=0", "pre_a_bitwise", "unexpected_a", ">>=", 2]
+
8262. 21// ["0>>>0", "pre_a_bitwise", "unexpected_a", ">>>", 2]
+
8263. 21// ["0>>>=0", "pre_a_bitwise", "unexpected_a", ">>>=", 2]
+
8264. 21// ["0^0", "pre_a_bitwise", "unexpected_a", "^", 2]
+
8265. 21// ["0^=0", "pre_a_bitwise", "unexpected_a", "^=", 2]
+
8266. 21// ["0|0", "pre_a_bitwise", "unexpected_a", "|", 2]
+
8267. 21// ["0|=0", "pre_a_bitwise", "unexpected_a", "|=", 2]
+
8268. 21// ["~0", "pre_a_bitwise", "unexpected_a", "~", 1]
+
8269. 21
+
8270. 21 warn("unexpected_a", thing);
+
8271. 21 break;
+
8272. 36945 }
+
8273. 36945 if (
+
8274. 36945 thing.id !== "("
+
8275. 26534 && thing.id !== "&&"
+
8276. 25332 && thing.id !== "||"
+
8277. 24358 && thing.id !== "="
+
8278. 20124 && Array.isArray(thing.expression)
+
8279. 8506 && thing.expression.length === 2
+
8280. 8505 && (
+
8281. 8505 relationop[thing.expression[0].id] === true
+
8282. 8505 || relationop[thing.expression[1].id] === true
+
8283. 8505 )
+
8284. 1 ) {
+
8285. 1
+
8286. 1// test_cause:
+
8287. 1// ["0<0<0", "pre_a_bitwise", "unexpected_a", "<", 4]
+
8288. 1
+
8289. 1 warn("unexpected_a", thing);
+
8290. 1 }
+
8291. 36945 }
+
8292. 518
+
8293. 31933 function pre_b(thing) {
+
8294. 31933 let left;
+
8295. 31933 let right;
+
8296. 31933 let value;
+
8297. 3960 if (relationop[thing.id] === true) {
+
8298. 3960 left = thing.expression[0];
+
8299. 3960 right = thing.expression[1];
+
8300. 3960 if (left.id === "NaN" || right.id === "NaN") {
+
8301. 3960
+
8302. 3960// test_cause:
+
8303. 3960// ["NaN===NaN", "pre_b", "number_isNaN", "===", 4]
+
8304. 3960
+
8305. 3960 warn("number_isNaN", thing);
+
8306. 3960 } else if (left.id === "typeof") {
+
8307. 3960 if (right.id !== "(string)") {
+
8308. 3960 if (right.id !== "typeof") {
+
8309. 3960
+
8310. 3960// test_cause:
+
8311. 3960// ["typeof 0===0", "pre_b", "expected_string_a", "0", 12]
+
8312. 3960
+
8313. 3960 warn("expected_string_a", right);
+
8314. 3960 }
+
8315. 3960 } else {
+
8316. 3960 value = right.value;
+
8317. 3960 if (value === "null" || value === "undefined") {
+
8318. 3960
+
8319. 3960// test_cause:
+
8320. 3960// ["
+
8321. 3960// typeof aa==="undefined"
+
8322. 3960// ", "pre_b", "unexpected_typeof_a", "undefined", 13]
+
8323. 3960
+
8324. 3960 warn("unexpected_typeof_a", right, value);
+
8325. 3960 } else if (
+
8326. 3960 value !== "bigint"
+
8327. 3960 && value !== "boolean"
+
8328. 3960 && value !== "function"
+
8329. 3960 && value !== "number"
+
8330. 3960 && value !== "object"
+
8331. 3960 && value !== "string"
+
8332. 3960 && value !== "symbol"
+
8333. 3960 ) {
+
8334. 3960
+
8335. 3960// test_cause:
+
8336. 3960// ["typeof 0===\"aa\"", "pre_b", "expected_type_string_a", "aa", 12]
+
8337. 3960
+
8338. 3960 warn("expected_type_string_a", right, value);
+
8339. 3960 }
+
8340. 3960 }
+
8341. 3960 }
+
8342. 3960 }
+
8343. 31933 }
+
8344. 518
+
8345. 1 function pre_b_eqeq(thing) {
+
8346. 1
+
8347. 1// test_cause:
+
8348. 1// ["0==0", "pre_b_eqeq", "expected_a_b", "==", 2]
+
8349. 1
+
8350. 1 warn("expected_a_b", thing, "===", "==");
+
8351. 1 }
+
8352. 518
+
8353. 1 function pre_b_in(thing) {
+
8354. 1
+
8355. 1// test_cause:
+
8356. 1// ["aa in aa", "pre_b_in", "infix_in", "in", 4]
+
8357. 1
+
8358. 1 warn("infix_in", thing);
+
8359. 1 }
+
8360. 518
+
8361. 1 function pre_b_instanceof(thing) {
+
8362. 1
+
8363. 1// test_cause:
+
8364. 1// ["0 instanceof 0", "pre_b_instanceof", "unexpected_a", "instanceof", 3]
+
8365. 1
+
8366. 1 warn("unexpected_a", thing);
+
8367. 1 }
+
8368. 518
+
8369. 10411 function pre_b_lparen(thing) {
+
8370. 10411 const left = thing.expression[0];
+
8371. 10411 let left_variable;
+
8372. 10411 let parent;
+
8373. 10411 if (
+
8374. 10411 left.identifier
+
8375. 6658 && functionage.context[left.id] === undefined
+
8376. 3034 && typeof functionage.name === "object"
+
8377. 2395 ) {
+
8378. 2395 parent = functionage.name.parent;
+
8379. 2395 if (parent) {
+
8380. 2395 left_variable = parent.context[left.id];
+
8381. 2395 if (
+
8382. 2395 left_variable !== undefined
+
8383. 2395
+
8384. 2395// Probably deadcode.
+
8385. 2395// && left_variable.dead
+
8386. 2395
+
8387. 2395 && left_variable.parent === parent
+
8388. 2395 && left_variable.calls !== undefined
+
8389. 2395 && left_variable.calls[functionage.name.id] !== undefined
+
8390. 2395 ) {
+
8391. 2395 left_variable.dead = false;
+
8392. 2395 }
+
8393. 2395 }
+
8394. 2395 }
+
8395. 10411 }
+
8396. 518
+
8397. 1 function pre_b_noteq(thing) {
+
8398. 1
+
8399. 1// test_cause:
+
8400. 1// ["0!=0", "pre_b_noteq", "expected_a_b", "!=", 2]
+
8401. 1
+
8402. 1 warn("expected_a_b", thing, "!==", "!=");
+
8403. 1 }
+
8404. 518
+
8405. 974 function pre_b_or(thing) {
+
8406. 1948 thing.expression.forEach(function (thang) {
+
8407. 177 if (thang.id === "&&" && !thang.wrapped) {
+
8408. 1
+
8409. 1// test_cause:
+
8410. 1// ["0&&0||0", "pre_b_or", "and", "&&", 2]
+
8411. 1
+
8412. 1 warn("and", thang);
+
8413. 1 }
+
8414. 1948 });
+
8415. 974 }
+
8416. 518
+
8417. 8 function pre_s_for(thing) {
+
8418. 8 let the_variable;
+
8419. 2 if (thing.name !== undefined) {
+
8420. 2 thing.name.dead = false;
+
8421. 2 the_variable = lookup(thing.name);
+
8422. 2 if (the_variable !== undefined) {
+
8423. 2 if (the_variable.init && the_variable.readonly) {
+
8424. 2
+
8425. 2// test_cause:
+
8426. 2// ["const aa=0;for(aa in aa){}", "pre_s_for", "bad_assignment_a", "aa", 16]
+
8427. 2
+
8428. 2 warn("bad_assignment_a", thing.name);
+
8429. 2 }
+
8430. 2 the_variable.init = true;
+
8431. 2 }
+
8432. 2 }
+
8433. 8
+
8434. 8// Recurse walk_statement().
+
8435. 8
+
8436. 8 walk_statement(thing.initial);
+
8437. 8 }
+
8438. 518
+
8439. 2001 function pre_s_function(thing) {
+
8440. 2001
+
8441. 2001// test_cause:
+
8442. 2001// ["()=>0", "pre_s_function", "", "", 0]
+
8443. 2001// ["(function (){}())", "pre_s_function", "", "", 0]
+
8444. 2001// ["function aa(){}", "pre_s_function", "", "", 0]
+
8445. 2001
+
8446. 2001 test_cause("");
+
8447. 1057 if (thing.arity === "statement" && blockage.body !== true) {
+
8448. 1
+
8449. 1// test_cause:
+
8450. 1// ["if(0){function aa(){}\n}", "pre_s_function", "unexpected_a", "function", 7]
+
8451. 1
+
8452. 1 warn("unexpected_a", thing);
+
8453. 1 }
+
8454. 2001 function_stack.push(functionage);
+
8455. 2001 block_stack.push(blockage);
+
8456. 2001 functionage = thing;
+
8457. 2001 blockage = thing;
+
8458. 2001 thing.live = [];
+
8459. 1098 if (typeof thing.name === "object") {
+
8460. 1098 thing.name.dead = false;
+
8461. 1098 thing.name.init = true;
+
8462. 1098 }
+
8463. 7 if (thing.extra === "get") {
+
8464. 7 if (thing.parameters.length !== 0) {
+
8465. 7
+
8466. 7// test_cause:
+
8467. 7// ["
+
8468. 7// /*jslint getset*/
+
8469. 7// aa={get aa(aa){}}
+
8470. 7// ", "pre_s_function", "bad_get", "function", 9]
+
8471. 7
+
8472. 7 warn("bad_get", thing);
+
8473. 7 }
+
8474. 1994 } else if (thing.extra === "set") {
+
8475. 1994 if (thing.parameters.length !== 1) {
+
8476. 1994
+
8477. 1994// test_cause:
+
8478. 1994// ["
+
8479. 1994// /*jslint getset*/
+
8480. 1994// aa={set aa(){}}
+
8481. 1994// ", "pre_s_function", "bad_set", "function", 9]
+
8482. 1994
+
8483. 1994 warn("bad_set", thing);
+
8484. 1994 }
+
8485. 1994 }
+
8486. 2063 thing.parameters.forEach(function (name) {
+
8487. 2063 walk_expression(name.expression);
+
8488. 1840 if (name.id === "{" || name.id === "[") {
+
8489. 267 name.names.forEach(subactivate);
+
8490. 1796 } else {
+
8491. 1796 name.dead = false;
+
8492. 1796 name.init = true;
+
8493. 1796 }
+
8494. 2063 });
+
8495. 2001 }
+
8496. 518
+
8497. 5694 function pre_s_lbrace(thing) {
+
8498. 5694 block_stack.push(blockage);
+
8499. 5694 blockage = thing;
+
8500. 5694 thing.live = [];
+
8501. 5694 }
+
8502. 518
+
8503. 56 function pre_try(thing) {
+
8504. 54 if (thing.catch !== undefined) {
+
8505. 54
+
8506. 54// Create new catch-scope for catch-parameter.
+
8507. 54
+
8508. 54 catch_stack.push(catchage);
+
8509. 54 catchage = thing.catch;
+
8510. 54 }
+
8511. 56 }
+
8512. 518
+
8513. 28689 function pre_v(thing) {
+
8514. 28689 const the_variable = lookup(thing);
+
8515. 28611 if (the_variable !== undefined) {
+
8516. 28611 thing.variable = the_variable;
+
8517. 28611 the_variable.used += 1;
+
8518. 28611 }
+
8519. 28689 }
+
8520. 518
+
8521. 717 function subactivate(name) {
+
8522. 717 name.init = true;
+
8523. 717 name.dead = false;
+
8524. 717 blockage.live.push(name);
+
8525. 717 }
+
8526. 518
+
8527. 164534 function walk_expression(thing) {
+
8528. 103787 if (thing) {
+
8529. 103787 if (Array.isArray(thing)) {
+
8530. 103787
+
8531. 103787// test_cause:
+
8532. 103787// ["(function(){}())", "walk_expression", "isArray", "", 0]
+
8533. 103787// ["0&&0", "walk_expression", "isArray", "", 0]
+
8534. 103787
+
8535. 103787 test_cause("isArray");
+
8536. 103787 thing.forEach(walk_expression);
+
8537. 103787 } else {
+
8538. 103787 preamble(thing);
+
8539. 103787 walk_expression(thing.expression);
+
8540. 103787
+
8541. 103787// PR-414 - Bugfix - fix fart-body not being walked.
+
8542. 103787
+
8543. 103787 if (thing.id === "function" || thing.id === "=>") {
+
8544. 103787
+
8545. 103787// test_cause:
+
8546. 103787// ["aa=()=>0", "walk_expression", "function", "=>", 0]
+
8547. 103787// ["aa=function(){}", "walk_expression", "function", "function", 0]
+
8548. 103787
+
8549. 103787 test_cause("function", thing.id);
+
8550. 103787
+
8551. 103787// Recurse walk_statement().
+
8552. 103787
+
8553. 103787 walk_statement(thing.block);
+
8554. 103787 }
+
8555. 103787 if (
+
8556. 103787 thing.arity === "preassign" || thing.arity === "postassign"
+
8557. 103787 ) {
+
8558. 103787
+
8559. 103787// test_cause:
+
8560. 103787// ["aa=++aa", "walk_expression", "unexpected_a", "++", 4]
+
8561. 103787// ["aa=--aa", "walk_expression", "unexpected_a", "--", 4]
+
8562. 103787
+
8563. 103787 warn("unexpected_a", thing);
+
8564. 103787 } else if (
+
8565. 103787 thing.arity === "statement"
+
8566. 103787 || thing.arity === "assignment"
+
8567. 103787 ) {
+
8568. 103787
+
8569. 103787// test_cause:
+
8570. 103787// ["aa[aa=0]", "walk_expression", "unexpected_statement_a", "=", 6]
+
8571. 103787
+
8572. 103787 warn("unexpected_statement_a", thing);
+
8573. 103787 }
+
8574. 103787
+
8575. 103787// test_cause:
+
8576. 103787// ["aa=0", "walk_expression", "default", "", 0]
+
8577. 103787
+
8578. 103787 test_cause("default");
+
8579. 103787 postamble(thing);
+
8580. 103787 }
+
8581. 103787 }
+
8582. 164534 }
+
8583. 518
+
8584. 78303 function walk_statement(thing) {
+
8585. 43095 if (!thing) {
+
8586. 43095 return;
+
8587. 43095 }
+
8588. 35208 if (Array.isArray(thing)) {
+
8589. 7608
+
8590. 7608// test_cause:
+
8591. 7608// ["+[]", "walk_statement", "isArray", "", 0]
+
8592. 7608
+
8593. 7608 test_cause("isArray");
+
8594. 7608
+
8595. 7608// Recurse walk_statement().
+
8596. 7608
+
8597. 7608 thing.forEach(walk_statement);
+
8598. 7608 return;
+
8599. 27600 }
+
8600. 27600 preamble(thing);
+
8601. 27600 walk_expression(thing.expression);
+
8602. 27600 if (thing.arity === "binary") {
+
8603. 5665 if (thing.id !== "(") {
+
8604. 5665
+
8605. 5665// test_cause:
+
8606. 5665// ["0&&0", "walk_statement", "unexpected_expression_a", "&&", 2]
+
8607. 5665
+
8608. 5665 warn("unexpected_expression_a", thing);
+
8609. 5665 }
+
8610. 21935 } else if (
+
8611. 21935 thing.arity !== "statement"
+
8612. 21935 && thing.arity !== "assignment"
+
8613. 21935 && thing.id !== "import"
+
8614. 21935 ) {
+
8615. 21935
+
8616. 21935// test_cause:
+
8617. 21935// ["!0", "walk_statement", "unexpected_expression_a", "!", 1]
+
8618. 21935// ["+[]", "walk_statement", "unexpected_expression_a", "+", 1]
+
8619. 21935// ["+new aa()", "walk_statement", "unexpected_expression_a", "+", 1]
+
8620. 21935// ["0", "walk_statement", "unexpected_expression_a", "0", 1]
+
8621. 21935// ["typeof 0", "walk_statement", "unexpected_expression_a", "typeof", 1]
+
8622. 21935
+
8623. 21935 warn("unexpected_expression_a", thing);
+
8624. 27600 }
+
8625. 27600
+
8626. 27600// Recurse walk_statement().
+
8627. 27600
+
8628. 27600 walk_statement(thing.block);
+
8629. 27600 walk_statement(thing.else);
+
8630. 27600 postamble(thing);
+
8631. 27600 }
+
8632. 518
+
8633. 518 postaction = action(posts);
+
8634. 518 postamble = amble(posts);
+
8635. 518 preaction = action(pres);
+
8636. 518 preamble = amble(pres);
+
8637. 518 postaction("assignment", "+=", post_a_pluseq);
+
8638. 518 postaction("assignment", post_a);
+
8639. 518 postaction("binary", "&&", post_b_and);
+
8640. 518 postaction("binary", "(", post_b_lparen);
+
8641. 518 postaction("binary", "=>", post_s_function);
+
8642. 518 postaction("binary", "[", post_b_lbracket);
+
8643. 518 postaction("binary", "||", post_b_or);
+
8644. 518 postaction("binary", post_b);
+
8645. 518 postaction("statement", "const", post_s_var);
+
8646. 518 postaction("statement", "export", post_s_export);
+
8647. 518 postaction("statement", "for", post_s_for);
+
8648. 518 postaction("statement", "function", post_s_function);
+
8649. 518 postaction("statement", "import", post_s_import);
+
8650. 518 postaction("statement", "let", post_s_var);
+
8651. 518 postaction("statement", "try", post_s_try);
+
8652. 518 postaction("statement", "var", post_s_var);
+
8653. 518 postaction("statement", "{", post_s_lbrace);
+
8654. 518 postaction("ternary", post_t);
+
8655. 518 postaction("unary", "+", post_u_plus);
+
8656. 518 postaction("unary", "function", post_s_function);
+
8657. 518 postaction("unary", post_u);
+
8658. 518 preaction("assignment", pre_a_bitwise);
+
8659. 518 preaction("binary", "!=", pre_b_noteq);
+
8660. 518 preaction("binary", "(", pre_b_lparen);
+
8661. 518 preaction("binary", "==", pre_b_eqeq);
+
8662. 518 preaction("binary", "=>", pre_s_function);
+
8663. 518 preaction("binary", "in", pre_b_in);
+
8664. 518 preaction("binary", "instanceof", pre_b_instanceof);
+
8665. 518 preaction("binary", "||", pre_b_or);
+
8666. 518 preaction("binary", pre_b);
+
8667. 518 preaction("binary", pre_a_bitwise);
+
8668. 518 preaction("statement", "for", pre_s_for);
+
8669. 518 preaction("statement", "function", pre_s_function);
+
8670. 518 preaction("statement", "try", pre_try);
+
8671. 518 preaction("statement", "{", pre_s_lbrace);
+
8672. 518 preaction("unary", "function", pre_s_function);
+
8673. 518 preaction("unary", "~", pre_a_bitwise);
+
8674. 518 preaction("variable", pre_v);
+
8675. 518
+
8676. 518 walk_statement(state.token_tree);
+
8677. 518}
+
8678. 1
+
8679. 208function jslint_phase5_whitage(state) {
+
8680. 208
+
8681. 208// PHASE 5. Check whitespace between tokens in <token_list>.
+
8682. 208
+
8683. 208 let {
+
8684. 208 artifact,
+
8685. 208 catch_list,
+
8686. 208 function_list,
+
8687. 208 function_stack,
+
8688. 208 option_dict,
+
8689. 208 test_cause,
+
8690. 208 token_global,
+
8691. 208 token_list,
+
8692. 208 warn
+
8693. 208 } = state;
+
8694. 208 let closer = "(end)";
+
8695. 208 let free = false;
+
8696. 208
+
8697. 208// free = false
+
8698. 208
+
8699. 208// cause:
+
8700. 208// "()=>0"
+
8701. 208// "aa()"
+
8702. 208// "aa(0,0)"
+
8703. 208// "function(){}"
+
8704. 208
+
8705. 208// free = true
+
8706. 208
+
8707. 208// cause:
+
8708. 208// "(0)"
+
8709. 208// "(aa)"
+
8710. 208// "aa(0)"
+
8711. 208// "do{}while()"
+
8712. 208// "for(){}"
+
8713. 208// "if(){}"
+
8714. 208// "switch(){}"
+
8715. 208// "while(){}"
+
8716. 208
+
8717. 208 let left = token_global;
+
8718. 208 let margin = 0;
+
8719. 208 let mode_indent = (
+
8720. 208
+
8721. 208// PR-330 - Allow 2-space indent.
+
8722. 208
+
8723. 208 option_dict.indent2
+
8724. 5 ? 2
+
8725. 203 : 4
+
8726. 208 );
+
8727. 208 let nr_comments_skipped = 0;
+
8728. 208 let open = true;
+
8729. 208 let opening = true;
+
8730. 208 let right;
+
8731. 208
+
8732. 208// This is the set of infix operators that require a space on each side.
+
8733. 208
+
8734. 208 let spaceop = object_assign_from_list(empty(), [
+
8735. 208 "!=", "!==", "%", "%=", "&", "&&", "&=", "*", "*=", "+=", "-=", "/",
+
8736. 208 "/=", "<", "<<", "<<=", "<=", "=", "==", "===", "=>", ">", ">=", ">>",
+
8737. 208 ">>=", ">>>", ">>>=", "^", "^=", "|", "|=", "||"
+
8738. 208 ], true);
+
8739. 208
+
8740. 38092 function at_margin(fit) {
+
8741. 38092 const at = margin + fit;
+
8742. 21 if (right.from !== at) {
+
8743. 21 return expected_at(at);
+
8744. 21 }
+
8745. 38092 }
+
8746. 208
+
8747. 2057 function delve(the_function) {
+
8748. 13014 Object.keys(the_function.context).forEach(function (id) {
+
8749. 13014 const name = the_function.context[id];
+
8750. 12979 if (id !== "ignore" && name.parent === the_function) {
+
8751. 6286
+
8752. 6286// test_cause:
+
8753. 6286// ["function aa(aa) {return aa;}", "delve", "id", "", 0]
+
8754. 6286
+
8755. 6286 test_cause("id");
+
8756. 6286 if (
+
8757. 6286 name.used === 0
+
8758. 6286
+
8759. 6286// Probably deadcode.
+
8760. 6286// && (
+
8761. 6286// name.role !== "function"
+
8762. 6286// || name.parent.arity !== "unary"
+
8763. 6286// )
+
8764. 6286
+
8765. 6286 && jslint_assert(
+
8766. 6286 name.role !== "function",
+
8767. 6286 `Expected name.role !== "function".`
+
8768. 6286 )
+
8769. 6286 ) {
+
8770. 6286
+
8771. 6286// test_cause:
+
8772. 6286// ["/*jslint node*/\nlet aa;", "delve", "unused_a", "aa", 5]
+
8773. 6286// ["function aa(aa){return;}", "delve", "unused_a", "aa", 13]
+
8774. 6286// ["let aa=0;try{aa();}catch(bb){aa();}", "delve", "unused_a", "bb", 26]
+
8775. 6286
+
8776. 6286 warn("unused_a", name);
+
8777. 6286 } else if (!name.init) {
+
8778. 6286
+
8779. 6286// test_cause:
+
8780. 6286// ["/*jslint node*/\nlet aa;aa();", "delve", "uninitialized_a", "aa", 5]
+
8781. 6286
+
8782. 6286 warn("uninitialized_a", name);
+
8783. 6286 }
+
8784. 6286 }
+
8785. 13014 });
+
8786. 2057 }
+
8787. 208
+
8788. 25 function expected_at(at) {
+
8789. 25
+
8790. 25// Probably deadcode.
+
8791. 25// if (right === undefined) {
+
8792. 25// right = token_nxt;
+
8793. 25// }
+
8794. 25
+
8795. 25 jslint_assert(
+
8796. 25 !(right === undefined),
+
8797. 25 `Expected !(right === undefined).`
+
8798. 25 );
+
8799. 25 warn(
+
8800. 25 "expected_a_at_b_c",
+
8801. 25 right,
+
8802. 25 artifact(right),
+
8803. 25
+
8804. 25// Fudge column numbers in warning message.
+
8805. 25
+
8806. 25 at + jslint_fudge,
+
8807. 25 right.from + jslint_fudge
+
8808. 25 );
+
8809. 25 }
+
8810. 208
+
8811. 3095 function no_space() {
+
8812. 3094 if (left.line === right.line) {
+
8813. 3094
+
8814. 3094// from:
+
8815. 3094// if (left.line === right.line) {
+
8816. 3094// no_space();
+
8817. 3094// } else {
+
8818. 3094
+
8819. 3094 if (left.thru !== right.from && nr_comments_skipped === 0) {
+
8820. 3094
+
8821. 3094// test_cause:
+
8822. 3094// ["let aa = aa( );", "no_space", "unexpected_space_a_b", ")", 14]
+
8823. 3094
+
8824. 3094 warn(
+
8825. 3094 "unexpected_space_a_b",
+
8826. 3094 right,
+
8827. 3094 artifact(left),
+
8828. 3094 artifact(right)
+
8829. 3094 );
+
8830. 3094 }
+
8831. 3094 } else {
+
8832. 1
+
8833. 1// from:
+
8834. 1// } else if (
+
8835. 1// right.arity === "binary"
+
8836. 1// && right.id === "("
+
8837. 1// && free
+
8838. 1// ) {
+
8839. 1// no_space();
+
8840. 1// } else if (
+
8841. 1
+
8842. 1// Probably deadcode.
+
8843. 1// if (open) {
+
8844. 1// const at = (
+
8845. 1// free
+
8846. 1// ? margin
+
8847. 1// : margin + 8
+
8848. 1// );
+
8849. 1// if (right.from < at) {
+
8850. 1// expected_at(at);
+
8851. 1// }
+
8852. 1// } else {
+
8853. 1// if (right.from !== margin + 8) {
+
8854. 1// expected_at(margin + 8);
+
8855. 1// }
+
8856. 1// }
+
8857. 1
+
8858. 1 jslint_assert(open, `Expected open.`);
+
8859. 1 jslint_assert(free, `Expected free.`);
+
8860. 1 if (right.from < margin) {
+
8861. 1
+
8862. 1// test_cause:
+
8863. 1// ["let aa = aa(\naa\n()\n);", "expected_at", "expected_a_at_b_c", "5", 1]
+
8864. 1
+
8865. 1 expected_at(margin);
+
8866. 1 }
+
8867. 1 }
+
8868. 3095 }
+
8869. 208
+
8870. 96059 function no_space_only() {
+
8871. 96059 if (
+
8872. 96059 left.id !== "(global)"
+
8873. 96057 && left.nr + 1 === right.nr
+
8874. 96057 && (
+
8875. 96057 left.line !== right.line
+
8876. 96057 || left.thru !== right.from
+
8877. 96057 )
+
8878. 5 ) {
+
8879. 5 warn(
+
8880. 5 "unexpected_space_a_b",
+
8881. 5 right,
+
8882. 5 artifact(left),
+
8883. 5 artifact(right)
+
8884. 5 );
+
8885. 5 }
+
8886. 96059 }
+
8887. 208
+
8888. 46227 function one_space() {
+
8889. 44324 if (left.line === right.line || !open) {
+
8890. 44324 if (left.thru + 1 !== right.from && nr_comments_skipped === 0) {
+
8891. 44324 warn(
+
8892. 44324 "expected_space_a_b",
+
8893. 44324 right,
+
8894. 44324 artifact(left),
+
8895. 44324 artifact(right)
+
8896. 44324 );
+
8897. 44324 }
+
8898. 44324 } else {
+
8899. 1903 if (right.from !== margin) {
+
8900. 1903 expected_at(margin);
+
8901. 1903 }
+
8902. 1903 }
+
8903. 46227 }
+
8904. 208
+
8905. 9344 function one_space_only() {
+
8906. 8 if (left.line !== right.line || left.thru + 1 !== right.from) {
+
8907. 8 warn("expected_space_a_b", right, artifact(left), artifact(right));
+
8908. 8 }
+
8909. 9344 }
+
8910. 208
+
8911. 24667 function pop() {
+
8912. 24667 const previous = function_stack.pop();
+
8913. 24667 closer = previous.closer;
+
8914. 24667 free = previous.free;
+
8915. 24667 margin = previous.margin;
+
8916. 24667 open = previous.open;
+
8917. 24667 opening = previous.opening;
+
8918. 24667 }
+
8919. 208
+
8920. 24667 function push() {
+
8921. 24667 function_stack.push({
+
8922. 24667 closer,
+
8923. 24667 free,
+
8924. 24667 margin,
+
8925. 24667 open,
+
8926. 24667 opening
+
8927. 24667 });
+
8928. 24667 }
+
8929. 208
+
8930. 208// uninitialized_and_unused();
+
8931. 208// Delve into the functions looking for variables that were not initialized
+
8932. 208// or used. If the file imports or exports, then its global object is also
+
8933. 208// delved.
+
8934. 208
+
8935. 174 if (state.mode_module === true || option_dict.node) {
+
8936. 51 delve(token_global);
+
8937. 51 }
+
8938. 208 catch_list.forEach(delve);
+
8939. 208 function_list.forEach(delve);
+
8940. 208
+
8941. 2 if (option_dict.white) {
+
8942. 2 return;
+
8943. 206 }
+
8944. 206
+
8945. 206// whitage();
+
8946. 206// Go through the token list, looking at usage of whitespace.
+
8947. 206
+
8948. 207158 token_list.forEach(function whitage(the_token) {
+
8949. 207158 right = the_token;
+
8950. 195959 if (right.id === "(comment)" || right.id === "(end)") {
+
8951. 11407 nr_comments_skipped += 1;
+
8952. 195751 } else {
+
8953. 195751
+
8954. 195751// If left is an opener and right is not the closer, then push the previous
+
8955. 195751// state. If the token following the opener is on the next line, then this is
+
8956. 195751// an open form. If the tokens are on the same line, then it is a closed form.
+
8957. 195751// Open form is more readable, with each item (statement, argument, parameter,
+
8958. 195751// etc) starting on its own line. Closed form is more compact. Statement blocks
+
8959. 195751// are always in open form.
+
8960. 195751
+
8961. 195751// The open and close pairs.
+
8962. 195751
+
8963. 195751 switch (left.id) {
+
8964. 195751 case "${":
+
8965. 195751 case "(":
+
8966. 195751 case "[":
+
8967. 195751 case "{":
+
8968. 195751
+
8969. 195751// test_cause:
+
8970. 195751// ["let aa=[];", "whitage", "opener", "", 0]
+
8971. 195751// ["let aa=`${0}`;", "whitage", "opener", "", 0]
+
8972. 195751// ["let aa=aa();", "whitage", "opener", "", 0]
+
8973. 195751// ["let aa={};", "whitage", "opener", "", 0]
+
8974. 195751
+
8975. 195751 test_cause("opener");
+
8976. 195751
+
8977. 195751// Probably deadcode.
+
8978. 195751// case "${}":
+
8979. 195751
+
8980. 195751 jslint_assert(
+
8981. 195751 !(left.id + right.id === "${}"),
+
8982. 195751 "Expected !(left.id + right.id === \"${}\")."
+
8983. 195751 );
+
8984. 195751 switch (left.id + right.id) {
+
8985. 195751 case "()":
+
8986. 195751 case "[]":
+
8987. 195751 case "{}":
+
8988. 195751
+
8989. 195751// If left and right are opener and closer, then the placement of right depends
+
8990. 195751// on the openness. Illegal pairs (like '{]') have already been detected.
+
8991. 195751
+
8992. 195751// test_cause:
+
8993. 195751// ["let aa=[];", "whitage", "opener_closer", "", 0]
+
8994. 195751// ["let aa=aa();", "whitage", "opener_closer", "", 0]
+
8995. 195751// ["let aa={};", "whitage", "opener_closer", "", 0]
+
8996. 195751
+
8997. 195751 test_cause("opener_closer");
+
8998. 195751 if (left.line === right.line) {
+
8999. 195751
+
9000. 195751// test_cause:
+
9001. 195751// ["let aa = aa( );", "no_space", "unexpected_space_a_b", ")", 14]
+
9002. 195751
+
9003. 195751 no_space();
+
9004. 195751 } else {
+
9005. 195751
+
9006. 195751// test_cause:
+
9007. 195751// ["let aa = aa(\n );", "expected_at", "expected_a_at_b_c", "1", 2]
+
9008. 195751
+
9009. 195751 at_margin(0);
+
9010. 195751 }
+
9011. 195751 break;
+
9012. 195751 default:
+
9013. 195751
+
9014. 195751// test_cause:
+
9015. 195751// ["let aa=(0);", "whitage", "opener_operand", "", 0]
+
9016. 195751// ["let aa=[0];", "whitage", "opener_operand", "", 0]
+
9017. 195751// ["let aa=`${0}`;", "whitage", "opener_operand", "", 0]
+
9018. 195751// ["let aa=aa(0);", "whitage", "opener_operand", "", 0]
+
9019. 195751// ["let aa={aa:0};", "whitage", "opener_operand", "", 0]
+
9020. 195751
+
9021. 195751 test_cause("opener_operand");
+
9022. 195751 opening = left.open || (left.line !== right.line);
+
9023. 195751 push();
+
9024. 195751 switch (left.id) {
+
9025. 195751 case "${":
+
9026. 195751 closer = "}";
+
9027. 195751 break;
+
9028. 195751 case "(":
+
9029. 195751 closer = ")";
+
9030. 195751 break;
+
9031. 195751 case "[":
+
9032. 195751 closer = "]";
+
9033. 195751 break;
+
9034. 195751 case "{":
+
9035. 195751 closer = "}";
+
9036. 195751 break;
+
9037. 195751 }
+
9038. 195751 if (opening) {
+
9039. 195751
+
9040. 195751// test_cause:
+
9041. 195751// ["function aa(){\nreturn;\n}", "whitage", "opening", "", 0]
+
9042. 195751// ["let aa=(\n0\n);", "whitage", "opening", "", 0]
+
9043. 195751// ["let aa=[\n0\n];", "whitage", "opening", "", 0]
+
9044. 195751// ["let aa=`${\n0\n}`;", "whitage", "opening", "", 0]
+
9045. 195751// ["let aa={\naa:0\n};", "whitage", "opening", "", 0]
+
9046. 195751
+
9047. 195751 test_cause("opening");
+
9048. 195751 free = closer === ")" && left.free;
+
9049. 195751 open = true;
+
9050. 195751 margin += mode_indent;
+
9051. 195751 if (right.role === "label") {
+
9052. 195751 if (right.from !== 0) {
+
9053. 195751
+
9054. 195751// test_cause:
+
9055. 195751// ["
+
9056. 195751// function aa() {
+
9057. 195751// bb:
+
9058. 195751// while (aa) {
+
9059. 195751// if (aa) {
+
9060. 195751// break bb;
+
9061. 195751// }
+
9062. 195751// }
+
9063. 195751// }
+
9064. 195751// ", "expected_at", "expected_a_at_b_c", "1", 2]
+
9065. 195751
+
9066. 195751 expected_at(0);
+
9067. 195751 }
+
9068. 195751 } else if (right.switch) {
+
9069. 195751 at_margin(-mode_indent);
+
9070. 195751 } else {
+
9071. 195751 at_margin(0);
+
9072. 195751 }
+
9073. 195751 } else {
+
9074. 195751 if (right.statement || right.role === "label") {
+
9075. 195751
+
9076. 195751// test_cause:
+
9077. 195751// ["
+
9078. 195751// function aa() {bb:
+
9079. 195751// while (aa) {
+
9080. 195751// aa();
+
9081. 195751// }
+
9082. 195751// }
+
9083. 195751// ", "whitage", "expected_line_break_a_b", "bb", 16]
+
9084. 195751
+
9085. 195751 warn(
+
9086. 195751 "expected_line_break_a_b",
+
9087. 195751 right,
+
9088. 195751 artifact(left),
+
9089. 195751 artifact(right)
+
9090. 195751 );
+
9091. 195751 }
+
9092. 195751
+
9093. 195751// test_cause:
+
9094. 195751// ["let aa=(0);", "whitage", "not_free", "", 0]
+
9095. 195751// ["let aa=[0];", "whitage", "not_free", "", 0]
+
9096. 195751// ["let aa=`${0}`;", "whitage", "not_free", "", 0]
+
9097. 195751// ["let aa={aa:0};", "whitage", "not_free", "", 0]
+
9098. 195751
+
9099. 195751 test_cause("not_free");
+
9100. 195751 free = false;
+
9101. 195751 open = false;
+
9102. 195751
+
9103. 195751// test_cause:
+
9104. 195751// ["let aa = ( 0 );", "no_space_only", "unexpected_space_a_b", "0", 12]
+
9105. 195751
+
9106. 195751 no_space_only();
+
9107. 195751 }
+
9108. 195751 }
+
9109. 195751 break;
+
9110. 195751 default:
+
9111. 195751 if (right.statement === true) {
+
9112. 195751 if (left.id === "else") {
+
9113. 195751
+
9114. 195751// test_cause:
+
9115. 195751// ["
+
9116. 195751// let aa = 0;
+
9117. 195751// if (aa) {
+
9118. 195751// aa();
+
9119. 195751// } else if (aa) {
+
9120. 195751// aa();
+
9121. 195751// }
+
9122. 195751// ", "one_space_only", "expected_space_a_b", "if", 9]
+
9123. 195751
+
9124. 195751 one_space_only();
+
9125. 195751 } else {
+
9126. 195751
+
9127. 195751// test_cause:
+
9128. 195751// [" let aa = 0;", "expected_at", "expected_a_at_b_c", "1", 2]
+
9129. 195751
+
9130. 195751 at_margin(0);
+
9131. 195751 open = false;
+
9132. 195751 }
+
9133. 195751
+
9134. 195751// If right is a closer, then pop the previous state.
+
9135. 195751
+
9136. 195751 } else if (right.id === closer) {
+
9137. 195751 pop();
+
9138. 195751 if (opening && right.id !== ";") {
+
9139. 195751 at_margin(0);
+
9140. 195751 } else {
+
9141. 195751 no_space_only();
+
9142. 195751 }
+
9143. 195751 } else {
+
9144. 195751
+
9145. 195751// Left is not an opener, and right is not a closer.
+
9146. 195751// The nature of left and right will determine the space between them.
+
9147. 195751
+
9148. 195751// If left is ',' or ';' or right is a statement then if open,
+
9149. 195751// right must go at the margin, or if closed, a space between.
+
9150. 195751
+
9151. 195751 if (right.switch) {
+
9152. 195751 at_margin(-mode_indent);
+
9153. 195751 } else if (right.role === "label") {
+
9154. 195751 if (right.from !== 0) {
+
9155. 195751
+
9156. 195751// test_cause:
+
9157. 195751// ["
+
9158. 195751// function aa() {
+
9159. 195751// aa();cc:
+
9160. 195751// while (aa) {
+
9161. 195751// if (aa) {
+
9162. 195751// break cc;
+
9163. 195751// }
+
9164. 195751// }
+
9165. 195751// }
+
9166. 195751// ", "expected_at", "expected_a_at_b_c", "1", 10]
+
9167. 195751
+
9168. 195751 expected_at(0);
+
9169. 195751 }
+
9170. 195751 } else if (left.id === ",") {
+
9171. 195751 if (!open || (
+
9172. 195751 (free || closer === "]")
+
9173. 195751 && left.line === right.line
+
9174. 195751 )) {
+
9175. 195751
+
9176. 195751// test_cause:
+
9177. 195751// ["let {aa,bb} = 0;", "one_space", "expected_space_a_b", "bb", 9]
+
9178. 195751
+
9179. 195751 one_space();
+
9180. 195751 } else {
+
9181. 195751
+
9182. 195751// test_cause:
+
9183. 195751// ["
+
9184. 195751// function aa() {
+
9185. 195751// aa(
+
9186. 195751// 0,0
+
9187. 195751// );
+
9188. 195751// }
+
9189. 195751// ", "expected_at", "expected_a_at_b_c", "9", 11]
+
9190. 195751
+
9191. 195751 at_margin(0);
+
9192. 195751 }
+
9193. 195751
+
9194. 195751// If right is a ternary operator, line it up on the margin.
+
9195. 195751
+
9196. 195751 } else if (right.arity === "ternary") {
+
9197. 195751 if (open) {
+
9198. 195751
+
9199. 195751// test_cause:
+
9200. 195751// ["
+
9201. 195751// let aa = (
+
9202. 195751// aa
+
9203. 195751// ? 0
+
9204. 195751// : 1
+
9205. 195751// );
+
9206. 195751// ", "expected_at", "expected_a_at_b_c", "5", 1]
+
9207. 195751
+
9208. 195751 at_margin(0);
+
9209. 195751 } else {
+
9210. 195751
+
9211. 195751// test_cause:
+
9212. 195751// ["let aa = (aa ? 0 : 1);", "whitage", "use_open", "?", 14]
+
9213. 195751
+
9214. 195751 warn("use_open", right);
+
9215. 195751 }
+
9216. 195751 } else if (
+
9217. 195751 right.arity === "binary"
+
9218. 195751 && right.id === "("
+
9219. 195751 && free
+
9220. 195751 ) {
+
9221. 195751
+
9222. 195751// test_cause:
+
9223. 195751// ["let aa = aa(\naa ()\n);", "no_space", "unexpected_space_a_b", "(", 4]
+
9224. 195751
+
9225. 195751 no_space();
+
9226. 195751 } else if (
+
9227. 195751 left.id === "."
+
9228. 195751 || left.id === "?."
+
9229. 195751 || left.id === "..."
+
9230. 195751 || right.id === ","
+
9231. 195751 || right.id === ";"
+
9232. 195751 || right.id === ":"
+
9233. 195751 || (
+
9234. 195751 right.arity === "binary"
+
9235. 195751 && (right.id === "(" || right.id === "[")
+
9236. 195751 )
+
9237. 195751 || (
+
9238. 195751 right.arity === "function"
+
9239. 195751 && left.id !== "function"
+
9240. 195751 )
+
9241. 195751 || (right.id === "." || right.id === "?.")
+
9242. 195751 ) {
+
9243. 195751
+
9244. 195751// test_cause:
+
9245. 195751// ["let aa = 0 ;", "no_space_only", "unexpected_space_a_b", ";", 12]
+
9246. 195751// ["let aa = aa ?.aa;", "no_space_only", "unexpected_space_a_b", "?.", 13]
+
9247. 195751
+
9248. 195751 no_space_only();
+
9249. 195751 } else if (left.id === ";") {
+
9250. 195751
+
9251. 195751// test_cause:
+
9252. 195751// ["
+
9253. 195751// /*jslint for*/
+
9254. 195751// function aa() {
+
9255. 195751// for (
+
9256. 195751// aa();
+
9257. 195751// aa;
+
9258. 195751// aa()
+
9259. 195751// ) {
+
9260. 195751// aa();
+
9261. 195751// }
+
9262. 195751// }
+
9263. 195751// ", "expected_at", "expected_a_at_b_c", "9", 1]
+
9264. 195751
+
9265. 195751 if (open) {
+
9266. 195751 at_margin(0);
+
9267. 195751 }
+
9268. 195751 } else if (
+
9269. 195751 left.arity === "ternary"
+
9270. 195751 || left.id === "case"
+
9271. 195751 || left.id === "catch"
+
9272. 195751 || left.id === "else"
+
9273. 195751 || left.id === "finally"
+
9274. 195751 || left.id === "while"
+
9275. 195751 || left.id === "await"
+
9276. 195751 || right.id === "catch"
+
9277. 195751 || right.id === "else"
+
9278. 195751 || right.id === "finally"
+
9279. 195751 || (right.id === "while" && !right.statement)
+
9280. 195751 || (left.id === ")" && right.id === "{")
+
9281. 195751 ) {
+
9282. 195751
+
9283. 195751// test_cause:
+
9284. 195751// ["
+
9285. 195751// function aa() {
+
9286. 195751// do {
+
9287. 195751// aa();
+
9288. 195751// } while(aa());
+
9289. 195751// }
+
9290. 195751// ", "one_space_only", "expected_space_a_b", "(", 12]
+
9291. 195751
+
9292. 195751 one_space_only();
+
9293. 195751 } else if (
+
9294. 195751
+
9295. 195751// There is a space between left and right.
+
9296. 195751
+
9297. 195751 spaceop[left.id] === true
+
9298. 195751 || spaceop[right.id] === true
+
9299. 195751 || (
+
9300. 195751 left.arity === "binary"
+
9301. 195751 && (left.id === "+" || left.id === "-")
+
9302. 195751 )
+
9303. 195751 || (
+
9304. 195751 right.arity === "binary"
+
9305. 195751 && (right.id === "+" || right.id === "-")
+
9306. 195751 )
+
9307. 195751 || left.id === "function"
+
9308. 195751 || left.id === ":"
+
9309. 195751 || left.id === "async"
+
9310. 195751 || (
+
9311. 195751 (
+
9312. 195751 left.identifier
+
9313. 195751 || left.id === "(string)"
+
9314. 195751 || left.id === "(number)"
+
9315. 195751 )
+
9316. 195751 && (
+
9317. 195751 right.identifier
+
9318. 195751 || right.id === "(string)"
+
9319. 195751 || right.id === "(number)"
+
9320. 195751 )
+
9321. 195751 )
+
9322. 195751 || (left.arity === "statement" && right.id !== ";")
+
9323. 195751 ) {
+
9324. 195751
+
9325. 195751// test_cause:
+
9326. 195751// ["let aa=0;", "one_space", "expected_space_a_b", "0", 8]
+
9327. 195751// ["let aa={\naa:\n0\n};", "expected_at", "expected_a_at_b_c", "5", 1]
+
9328. 195751
+
9329. 195751 one_space();
+
9330. 195751 } else if (left.arity === "unary" && left.id !== "`") {
+
9331. 195751 no_space_only();
+
9332. 195751 }
+
9333. 195751 }
+
9334. 195751 }
+
9335. 195751 nr_comments_skipped = 0;
+
9336. 195751 delete left.calls;
+
9337. 195751 delete left.dead;
+
9338. 195751 delete left.free;
+
9339. 195751 delete left.init;
+
9340. 195751 delete left.open;
+
9341. 195751 delete left.used;
+
9342. 195751 left = right;
+
9343. 195751 }
+
9344. 207158 });
+
9345. 206}
+
9346. 1
+
9347. 6function jslint_report({
+
9348. 6 exports,
+
9349. 6 froms,
+
9350. 6 functions,
+
9351. 6 global,
+
9352. 6 json,
+
9353. 6 module,
+
9354. 6 property,
+
9355. 6 stop,
+
9356. 6 warnings
+
9357. 6}) {
+
9358. 6
+
9359. 6// This function will create human-readable, html-report
+
9360. 6// for warnings, properties, and functions from jslint-result-object.
+
9361. 6//
+
9362. 6// Example usage:
+
9363. 6// let result = jslint("console.log('hello world')");
+
9364. 6// let html = jslint_report(result);
+
9365. 6
+
9366. 6 let html = "";
+
9367. 6 let length_80 = 1111;
+
9368. 6
+
9369. 328 function address(line = 1, column = 1) {
+
9370. 328
+
9371. 328// This function will create HTML address element from <line> and <column>
+
9372. 328
+
9373. 328 return `<address>${Number(line)}: ${Number(column)}</address>`;
+
9374. 328
+
9375. 328 }
+
9376. 6
+
9377. 2256 function detail(title, list) {
+
9378. 2256 return (
+
9379. 2256 (Array.isArray(list) && list.length > 0)
+
9380. 781 ? (
+
9381. 781
+
9382. 781// Google Lighthouse Accessibility - <dl>'s do not contain only properly-ordered
+
9383. 781// <dt> and <dd> groups, <script>, <template> or <div> elements.
+
9384. 781
+
9385. 781 "<dl>"
+
9386. 781 + "<dt>" + htmlEscape(title) + "</dt>"
+
9387. 781 + "<dd>" + list.join(", ") + "</dd>"
+
9388. 781 + "</dl>"
+
9389. 781 )
+
9390. 1475 : ""
+
9391. 2256 );
+
9392. 2256 }
+
9393. 6
+
9394. 6 html += String(`
+
9395. 6<style class="JSLINT_REPORT_STYLE">
+
9396. 6/* jslint utility2:true */
+
9397. 6/*csslint box-model: false, ids:false */
+
9398. 6/*csslint ignore:start*/
+
9399. 6@font-face {
+
9400. 6 font-display: swap;
+
9401. 6 font-family: "Daley";
+
9402. 6 src: url(
+
9403. 6"data:font/woff2;base64,d09GMgABAAAAABy4AA4AAAAAThwAABxiAAEAAAAAAAAAAAAA\
+
9404. 6AAAAAAAAAAAAAAAABmAAgiQINAmcDBEICuc41DEBNgIkA4R2C4I+AAQgBYkuByAMgScfYUIF\
+
9405. 67NgjsHGAbcDVFkXZ5Jwd+P96IGPc9rl9ETBEaCzCJkvY2UpziRZ7zftZWk8052U9+NqX6vXL\
+
9406. 6KDflSQnlJ0bP+QnPQAy744n9mup6H9PaCDFwM5zjf8exB89bZ1cdrYOP0NgnuRDRWlk9u/fE\
+
9407. 6llkxqmfH8lmRQ/DAmER9opk9wR6suc1LvTiXNEe1vbhUCH2USgnEwH3vUm05JQqejGvZvOtz\
+
9408. 67sIKEGgLdDNl/IrfqWVZG/wr42ekomEm91VA1p4LhHBuFzHF8//u7vvbREHMQqGtNLmiOOD/\
+
9409. 6X7WWiwqyCE98qt0jk5JJmgR5WJJElBmzRb1F7a66MmSLTNWZ2XSHfKBSKHoVteSEJ6EOdvVw\
+
9410. 6fNZOtXKDe39jXdRlkmMnOWIOFBgeEK/b0mFsgffnPyyAitNyutKky7J8a8MSEkAKGLgfptnS\
+
9411. 6/gDRSo7vwdNUmQDB7oP6pK7QF5d9SrY8M/tkrXcurSIQAmX7tz7pd33LIB7GQkBQ/k81s/0D\
+
9412. 6gpt4gbw7x0Cn/PocitK5KIGPGQIzQzAMuCeC2ERAidx9TySVqX06goT0SFFOOV9Kuxdi5Rg7\
+
9413. 6l6n3c+nKRemidOm2dtFV1jXMk4rP2m6RJ8xEdPYONLTbeMgaJ1nwS2W4su3MHwqkkvJ2PdDU\
+
9414. 6r7pgAnVRt4Kh789FXlD0r3p6jUtNO19O1s74U9pnIxqFpw+mBgF+8y30PAyw1dzlknLLVcSB\
+
9415. 6J2OuCr9eV5Efew6cOGd47ZEfhrW7HXI+FBNFvWgWnugUU4UvlrV63niv2ZPeKu8M76y/HQaG\
+
9416. 6weU+4Gzp+Y+cfb9R9djDWcd1Svr1xG7l+j/yf3eM996548qlC+dOzOqQ8//Lo0uaSEQCFuLD\
+
9417. 6/bXyWhJ6aPmyaRonVPxGABFL4/0slcKI6f+PmT0M+QRsplmWnv4F49VT+JsPifoa6aeyr2Hz\
+
9418. 6EeLdP1FEOV/ZN+c9sAuoNh0BRS0xgCCc9wME5s0HOKj/wc0fWYsTbFQpsZL5SayJPkL45kDo\
+
9419. 6DcJJ10MvD0ZSq7FEIr1TfqZ7NC6s75zSp8viaNO5/PczYCV9z6NTa0KBdnGBg6kbdeBkRLfU\
+
9420. 6qRd3D9Pqw5jWCc5WM/i95OE8731MBd1u2EmsXIa5dCvavY32U1Ytza4nfbERg6OVRZka7jq0\
+
9421. 6r2FcXNDyEhXheaHtaU1o1kvO9MuBOHqugLUEzN+4jznu0oK9wZPur1lWVFfxl8lZzn2XwcjZ\
+
9422. 6Csg/RJy0mAMMmgnqXS8ELhOCRUSLzvsM5gAPudEh2lVoRxGgyUVnArZMruE0YS1PqFMD3upb\
+
9423. 6jVoecGj1KpWl6/ZysuyzkG4SGA4bps6FBQSg4e4IxNUgdmosmoDn0TpIex/s1BFau6GBNO4z\
+
9424. 6cvWXypm4hEg5k3llelySFqNmUtRZ3PHBA7p4MBX1nK4awwAV6kWzIVbUA67A55QKYbMsgVaH\
+
9425. 6c1ZxKuZ0DCyqxCsJjLyCEY36gf0wjAu3t0zemc87PmBCJbU9Lso0YAaYJUx8wsR02hYz5hGy\
+
9426. 6Js0+A4uHGZgfuf5SOR9iBQuLhpOExaIFrHj6JlXanebzGHp2ELDh6av09PVE1fmdsj2oHRWs\
+
9427. 6fOtYrV6wRCyx7XogHqvpnZiPBBdNcL6kIoS9UI/DOIlumlveSgv9oqMBYp7WZ2fGxAXmZmaG\
+
9428. 6OCyJG6+wAszZFCQw/EXVjx+YA2uVyN6bhNWiZhgtYjAwR5U/7uV1scghiTGiAPZbA5ZqHw5u\
+
9429. 6Yu1cDjhRwREBFyq2wa0R8GgceDUKPo2BX+MhoAkQ1EQIaZqVHMwH3xM+P32TTA34tmOMNZ4n\
+
9430. 6mHXqn49fmE3qX1+wMNYoYetOsPx6wxKzkURImERJIjGSSJwkkiCJJEkiKZJImiSSIYlkSYqK\
+
9431. 6UBu0UOopuLMmasiJW0PMFOO2UgbDif2NaQUqkBbyaGjdTUvuyamEQwCq9DWsxsG9qPt+VFqV\
+
9432. 66cIsXcyWujWIEtNFdeia9ssNrJUpe3IDMPQZOReC8x+qvt17drPWdcHeL0gTarWwoQ6o828o\
+
9433. 60EJzrA20yZsgVyVHdlCJOF3NaACxHbP38TA+MGx3St9c5t2CxbGtunB4J9AF4Px2rSr1wyK9\
+
9434. 69KoXBR13vw9Fk9qhTX0ivZoanrvhLa5oiJO8cqR0lX7QtJ2c1a62V3PMtutaaoit+hxtXuC5\
+
9435. 6ZUXJePSR6btQlt5g7PqPQ822g7F8D123pc4kaGXz7qYztJxDXCxJr7foKqxwy4rikI/NvINx\
+
9436. 6bkArRTTnnMWy6YA8J39LfTweThKsqlt7Mz078NDSOPOGgtGTpeG8ZRBF+xKBjdSoNe8gE6uC\
+
9437. 6ucOH98jE4+cv1JEjI555TFjYj4+0KdFlojzJGWp2wc1tCaYGSeO8dBfT0u3lpDY3tazzu4wn\
+
9438. 6lF9wzy2nK+sTr/qEVdANoZ0ToBdD+MY4ewOHNnkXPBvKVXLSbEGfGVD0Nzr0Fs3HID3Y1Kqx\
+
9439. 6mzJ6p1C1/R6Xneyw/q9YRDLahbnsI1u76XzMLPqsK0yvQDeQ4TMR41709sIssmEgs0XH1lcj\
+
9440. 67HLnUG6u2Xpy5vbOowIGqrR6cwF0TLGI5PF7pkbzIVYQU0sIaoNgul3LGAH2B1nREFYXUMia\
+
9441. 6prCeAzggGxrC5gIK2dK0exs/AIRKdlIIuxkUspdSsU+rqXagqXaooXakqTiWS/a0E7zA6QIK\
+
9442. 6OdMUznMAh+RCQ7hcQCFXmspr3ciuds/6gPsZFPIgpfJhwUIepRAeZ1DIk5Tue4oKfSfKZyNV\
+
9443. 6pKU/J7J4Abx1EMV5mXSRDl6lMfU6jfBmBww4k7f6gLzTB+J9od/kA/uGj2mET2nkn7+zQ/JF\
+
9444. 6H5Kv+pB804fkOyvwI43wM438V5sdkd/6iPzRR+SvPiL/WIH/aYRxGqMb/Oqe3d54+LWR1vr2\
+
9445. 6knnnc467iD247eXBA3YYBAiFfierClXz/8jyL3Qh/zP8y+Y/1eN8jq+SKZAML/lIidjwZ8N4\
+
9446. 6aLthvhxGUkGPo+p0eHKZ0sT5FsqJcQCy9UhHIvcJFIlIvANTPFWUTUhSiVdsNRnvwEQxm5uc\
+
9447. 6ksjdv5evJfpOgI6c7juH8pnG2RKwlXaDYe9g8rMwYfML3A2SMWeBDopJJsmS5dUE2KttnmQa\
+
9448. 6JZlMspvEpJioiEDFNpPUTbwqG3Zjhx2VCeJrIf60s2mI6blZMZVyAyYzI+1a2Y0AIqcbLUgR\
+
9449. 66iRbNtnp82GrImXW0YbcbczDgqQDWNdTenvtTAlT9iPHenluV+d3eed1/5MjMBrX2LgrK2ml\
+
9450. 6FuoDOz036n/kaHbAeszR3jHoI4NWB3lusTfuVgkMUkLQaH0F6+pSCS11fXRwT421vs9s7axd\
+
9451. 6nvtF7/eeIeq9s1aCLsLWdh+w7sXz3IYdEsSQ0LVsebmES/vXDU9k653W4MiNq8bMj5nLioCY\
+
9452. 6edGgOT6tmYwqiOW1ugiEmew6iwjvvYb3SaeZJb7XNufOo9oH8FTneWGL+BLiclptpnhPwcui\
+
9453. 6T+rzcF34+ycsL7p3AveuML9i9h13beylyg8CzEz5HppadqmmDxKrAquG9L3ztedRoWxEsAYt\
+
9454. 6OM1Eu0G0gyTHkxf7cSkHJQRbA4xmlqHWkv1C0KhFhBq1z81Wq1CZoWic8TJ570WfSj5qsM+Q\
+
9455. 6nl4k3H5+P+P3zlv9ltQrzv41qyiSwV/gOadyQBchsmwDGu/JI8tXflE8jqUVA0Zw0SKbdDC9\
+
9456. 6c4FR+fak95SdF7uqpoRe9z6YRv+85YUzF4qJy6Q8GOVNwUn/ymyjNNbmcuVfXYeH2osLdCte\
+
9457. 6ebmZRyUfQQZA1BSCLK4PWA/z1kBvDZm0t+i3or1LkMD6en95pGG0UOa8ZJXgS9TdEA1I2mZw\
+
9458. 61JOWWxDu0NEh4rM19H55rvueMBUZV1RjkmB3oxkXhAckpa5gzzxUDA2VLOrWFAXx+4gmfU17\
+
9459. 65o3v9H7EYdvGFuM+tDB3TA4ITjVUKduO/R4bXRAcPXZusWkN+t59sFz7Hyi0FkSdzrHXQVFq\
+
9460. 6b8c9k9eLRjVlBbNvt4172CanYg/F3Rket1zCTc77UZ61Gq/Be9J8hrKrxbDZMEotf5o8zHDc\
+
9461. 6/UJaEtdhgwHEcBEQKM+6NBWIewLmI1sHuWYAedZCw8U1hJfSWcld+2tv3jpCFc5FnosLWC0+\
+
9462. 6DnAlnOXUXLoMXrmCVerNQkZHvRm8YtE12vG8+N/vOnPcu3vM1uOnzE3u3VP2ppmLZawm2NuO\
+
9463. 6tPa7xwHFCgVKpox5PVrOmaDHrThk1tX864a2+/qhJd3nCFRQ+bfUKI4O+Wgk5byB3saMcUfV\
+
9464. 6C8G137yMd16zRm3ZSq+UrDlk5ha3TiAj0b74prWO/vYG+RC+ronP1/McDtefBtY1XhZE0PIB\
+
9465. 6wTe7CBTte2U6KPbYd5GffApQlDGssdfmxYGSlnHrQt7++KEwUg3ikkoQyKPixgUDB6Lozjv5\
+
9466. 6vM5PBnllt+UzMnP6DStFsOfossbXOefWhQApACCNpkTYGAONIowDfndqDKRFuzn685nthZPe\
+
9467. 6vEL7TIWkXAG2yxKBH90+yMzuRzWn3KMmyKGwZWnIErlJ9Vwt8OtR6+4TKad5y9+ViBtTzVG+\
+
9468. 6tpv/xiLrcGKJRtYvCUlGeL4Dwy1jo1CSQe0X71EXK1YG44ztxTONjIslL8SwY0Cki0k0vsX/\
+
9469. 6/xz7CxkAc9dEdJZhMy/JCGzD2FAGtUcag0tc2e2miJkp477V2qTKB+nFnDl/noxpXJ+yqVdO\
+
9470. 6wNjbplmeiuburg9ii1Z1zwtG8QjcJAiVPSOV2mHzq1Qt7p2+YCcIKPmFusE5O+m8s+Wd8o3t\
+
9471. 6qO1b1IZF8N0tx6RQnZ9Ux3gXijHlolixst6vhJV6ao0ZFzSprfAc3x0MLvxU0OsmXEVddMVK\
+
9472. 629CC6mPgPtXTUW7tVnZxwm0DTJwNOeVRV4axMSPlpgyv1Va1MQhQqWwUOb0s+gVLOecos4Nf\
+
9473. 6eqlFW3fLQrlP86R4XRxrDHF0VIx6ArM5/sTWtObY6U2aosgxbN6FUa1iNTUpMThk1sUfJOC6\
+
9474. 6s1SKo9D0g1NfiVmavyful/K7nZdDgutV1A26i7FR3r16bv3zz1cGw+ta17IX/+ripyutix3C\
+
9475. 6xNmCxs7uiqKu9/Zjjn06tblXpJxlaLF5Od0d5W9QhQrs2u6UN0trQlCyEK2j9VYgCEIDrhQN\
+
9476. 6c00rxg/FOfZ1N+nLV7RXDsYP+p0EzqKcuPujzuzEQsu2mFf4nYvf3Yp32rq/RYLetDLuOOTc\
+
9477. 60WXBtgoech7AHUxAxPBg81qWCsYlzTofRU5/MpuyNoegR6mCJO5ckrLOhWbG7xo/VGwGgpRb\
+
9478. 6+Ch+TmlcuY6Qct/2x3gxzeDUU9u+ltexrjelJ0VRR9KXH/AqrbYxHa0vmQ/kBnE5EORBK1ZH\
+
9479. 6mTSy7A8DJMgzzqDsu9ML5J3ufkuUNDCfN5UKAjBgw2I/QlS8MQ6o/ll9dTAdoM7HYtV4cNWE\
+
9480. 6U4pOl5Y4SIzdMbNSjXFmsBV1uXXf7GaBZZslpFGFiIpokSzxWj4hjlGl4VKJDACo7ScxQf29\
+
9481. 6kM8gHD3nUJkwkN2aW2TGttqwOrygJ7r9nYX2tYqy7Z3TQV5ocWzUI8l871y3LsQLoTgEO76B\
+
9482. 6Upp69hy6VKRpZvpvgfQ2T06qgXjxh38eatREitX6bzKggIYmN4sAkA3a5oeJZDK3ahQrVJwa\
+
9483. 6AD65cEGBkS/tKH9TtybiREEWCMcKD0HH0gELtjB+KNSk7bspmpr6eb0CscIiFyZpmXu8+gxw\
+
9484. 6O7pJNbAK2h9q2c5dMHBaoi5DylbNGdweVVdN3Jm9u6YXXlmx4nYY2vIPfSkrE/vyv9gn/Z+j\
+
9485. 6R3HKExaUhdV0Az77YWbQPhNfjw+F0vTteSMin+wIfxyPe0DEoI4uz6o2IXwsZC7sg8MicQ3o\
+
9486. 6wys+NJYKVW72YiVQ5LKDVwrEg2jNVM6XdNjbsHlRDcAkD08o5iWtFB2dVoydRmmDRLalE+4t\
+
9487. 63gBbAPa7n7qXXXbTZTJXZKy5+1W0K7dgYEcIlu90ovC0C+5gxXiKtZisT14qDJ7f2ksyK59U\
+
9488. 6r3QeHtBb24mPz7YDB3rgMTyUZ/fxM8h2i1Z21B8/VA5+9l7BKaOJZ15lWsyPv/z6CjU32ZKq\
+
9489. 6+QFeyUywxYnUxUmcQfGc1Sp69oE2n6zFL8BXf5rc3cJMM6S97gagTT1bi7cmAV4MibkC4rz/\
+
9490. 6icmmFtMlo5aN1Wp3uxsBfd4+9T42xmxvd79FV/hfuviBcrIaX092PrY5rle9FR4wTnDzrwj4\
+
9491. 67frD2d0KsMcdcADQ1Yu1LECg9Wj3yOS8OhrJdQBqXqsam17vmt2wjjjouHE/EO9sGPdqt23v\
+
9492. 6j8rL6wid6ulagtNK5p1hjRkFtUxTIaZnIXk63Zb3P0t5MQ+3vxHIFrmgAdWwiDuA67tbVIF6\
+
9493. 6wJ53z0uhyhsfH9bgF0kPT9v2hrT3HKIBgUXIYoxsVU+uryemiUiQEwh+BfxP//qLShlumR26\
+
9494. 6I8OqjD+x3hHDj/IrEWmvyL6ioG/atfxe+5GzIqRgfaoayWOiTk+YixO15KDO6Os3XACDjboe\
+
9495. 6ryXXOuEmTpDsc7czk+H04Kw1PNJazW32CAURHwBldqK0/nqYHtcrtLyyTYmoD8hbcnJUfa3U\
+
9496. 63FxWNus7uic3Qm1BzEecJW0MAz+W2CyN9FLIy+EpSy6CjkXsllZw1uBs1SxrQWM97/vnHu7m\
+
9497. 6OtrkRl8AtBN3RDxI/fg7dZLLtDFYuCYYPMwXiO6ZIpwJ1GGydI9oUYYgnQQKDKoMTcwsjrfe\
+
9498. 6Tcht6y18bLcpNfX41WE27447vLNzHuF+j15co5N7Py8vKUpTCoghHMEYKkM6y02lvX+9XiFg\
+
9499. 6xBKMRNiwX69+LJb2Xa5WGqo7Rlk0cxsLVd0l2UXAW5jORg31sFMKYWXsDcRUKRDP8Q87OjiM\
+
9500. 6dI1hNEt43netf8rOyfp+L58fq3holY9gxXwRJLY6gahgLQi4hS8w9LS+rFcJtdSCBrQLWsMs\
+
9501. 6aDg/n8/P8/N+fcyoLepYr3W/CIUT7HsRQTtkduddbVfbo6Twt6fyJVPRrUGqRkWp3rdry65v\
+
9502. 6sPYInyq1mPHrQDrqGJYI/LzA/QAzAXLnx+lu9uxHTEka9xgWgRvqEioskh+UWgD4nDvTAxaz\
+
9503. 63v9BqqmFuQwy1wSXye1Df1NXVF7G8bUFxUE4F9axG5fm+vFQJvP8iuYjrFveB6++AqmJTQJ0\
+
9504. 69GHjbPhzdSzkZGxokQzONVs0R0FCPJz1hJKbvDKsaj9hT0vp/gH5oiT8pAbWsBChwAbxHgDd\
+
9505. 659iJVZE3bAzPRN1RuG+MT7th+J3i6KFwVJvPvsGRDIZW4P2rVfiKjDVBM2Va+w6PgI0c5u3K\
+
9506. 6O7MrWryPhXFFdBoAwi2JCaW9sZ3fTagQ4Tld6u4djwcWzeCdiYoeNbfalsRYo740afYQ1Rid\
+
9507. 6Bp/E9mbcTemEjoWWXIU7I5nK5H/BEqmZnPMyhDV234BTLQKCe6nhU+frwQo1gNFWf+eQGN62\
+
9508. 6aeF7BuzaN/94W2xlKd8t8KMA/3uoxymFt19OlCjYZeaMWbTKM9Yog9zDhptYMOzIQAoO7kn6\
+
9509. 6nTao8CxjrRRgjKe7mKa+tzuufhAAZtgjA92THkulWvIzEi0++j1DvXMnupDUS8aVusWain+c\
+
9510. 6CcvmR5orC+RcJs3wVahLYyEcqbvAS2e0QJ6BlU36R/IEd9Aol9q+M+UGvlo8EyRzISvqusNS\
+
9511. 67ePQ6cQzG1s725db4jNYNHAfF3KFG8wHqDwZDpWDsJ5qRLXR1ulFx85GhkypPubYaCiOQ5DR\
+
9512. 6PQUiNpgk4fLJHenSMLMiswXsqW4Cpln1rFoHzpOoBbuZIixmVyhKajeqlFmp8zNAEsbEJz0g\
+
9513. 6X0qlQuykZhf82pkhq2hWtCtYUdBODn6iPTBJT5Zk8IqFxqfBeFKjXk/sMeumhT8muOtq2Bgn\
+
9514. 6dR4fj6RoOi0zI25kajAXlDZhUhS39jipk39h/69AfDPBLmOxhDj7Lg/WUTbOwJiJ3p7WtOpm\
+
9515. 6ypARmhorQifINNm1CNS99GfDcLbD8sn8Fvlmvn7CmW65Pdmu6bKtuE0tn7NglIX1e/JAJP+G\
+
9516. 6gB3At7cSOp92rl0lp0pp0xVb5YaQedwGgcJA1pT4cy24lS+jvzDw86YTfb2igJm5MysHmejW\
+
9517. 6ZTGXpoAoLBLucUGEz/DwbjqOdzGAl5jy5VoCQws5zNYl4SVt030aZulYMgpDBPZd+kL0wV+w\
+
9518. 6nob2LPRDQGEbdUoeFm4fEKio9c/ferVlpSO8Bx7OFZyHip1PIizvoqFe02kpmS17TvIOty42\
+
9519. 6+Q0QaCnOpeLsPwwo+vixIeIeUjucUsKejVlez35qyuC0mm5pJJJLEVP2JAe/LTOwUUfKJkNy\
+
9520. 6lEe3Kdth241ZNQmkVcAIh6DZJBzvQov5fn3JZA0phBWdNq5iTsm5N2D8gyve3V3X2o3zF3VY\
+
9521. 6OqEBgTIADAbC69z7vOKJjGOzHRmUUwLU66iabtIbqR6SPOHCL+fCTfvpKcB/oG2p3wRKErEJ\
+
9522. 6v1YOfu9iaKEMLXS3ptdH8fwN2Rdww9bZ7rFa2bwrzcyux3o+hPV6bJZpb71j7lLAdzge3VX7\
+
9523. 69uSCdz6f/FDb7+wzWnbbDSPj9R20+PybDUm/lVAsTuF0aycFQwJfPCUwcBvCGWEq6xoTIEOy\
+
9524. 6b0bLta20+LYRYdyEceX7ypfezQKIy5OvJTAHCJy/WyOYaDVyPucMsHnZ0GCH75Cd//te1Bv2\
+
9525. 6RkMykqYurBiNbuH3Xfuprirr4Dd453O6abAYGb5tw1d6wrBL8p1J1Sx9Lgw7yxqYn0FTrc0y\
+
9526. 659yLlV+4zIkLfZlPFRVnanHpTyrIlpn4lGkt269+JXnIWhEQWNvuVsrt531jr+8AHkVZfQU8\
+
9527. 68U/4AUZMuOj5iliigFrof/usmloYEI1f8erhJku75snYW7YmFmUcoC7UtG/KfJRuz6j0tWPa\
+
9528. 656J5QA0rJHwSIhNT4GWvez19HT2lia+Pz7/+MVEWlvjY6+9P85a0y9qWkTzQ7nF0wDXpQpw3\
+
9529. 6K4xnfK2L08b5MrxdeI+DDfVDeV2JY0Fp6KH602tj2MbxxKM8oG+wTkE/dr8jyo4Sfs/IV6uf\
+
9530. 6+IIXpH2Nca1+WCJV5qEv193bcUELLR4iFu83xUedKy9353tn+3o01dF2bNEQ3fK9Q5tCXrCi\
+
9531. 6La+woCuvEeYrr+PiN2+i2V/eDJck580pyra8BV5ZIZbpe3kr5vJD3pqoGsnbcl/d+ndvR23b\
+
9532. 6K41M4dKwaAwDaMA1gZGBoQWAcYE9mYkmQOnAjkaG41FkGkIP2BAIgKvUvzhpE5JbA6lze2iL\
+
9533. 65Nr+AwiDo2W4BStvK30dKy0JGNbzAY5akexsrV0xo5K8rY50LOTLvDyukIZNbRLKOCk18mD3\
+
9534. 6WxmZGlsCMxNdGFYGNJnetUWyCPgo4BONEL4I9b8UeEBGYXuCdCd+DkctrqVLYXGSfE46kvAu\
+
9535. 6+ltK5SRxQPnjUqyJXsSYs6VY6WPKfns9+IXjHhd5wQvGipgFdMwVEQ+A7a2AAS0clQwH7KHW\
+
9536. 6SEGjhnklSVRghMtPy6gEtJRIKJeYkpQyQiequQunFOOU4BLdK1yp55olZS6npyPhMnvK7xIa\
+
9537. 6pyNj+JctcQLXenBOCms46aMkenIx45WpXqxxVJQLz/vgpmAVa0fmDv6Pue9xVTBPfVxCUGfj\
+
9538. 61R8uVi8Zu9nRFqk/t0gR6wmWOlzuKRqk33HpO8qQ+nbGoEZLL/0Va156SJ+u+t86/os7ic49\
+
9539. 6/7xoEqvL+2E8VOyCTuT/7j269Zy4jUtN+g4="
+
9540. 6 ) format("woff2");
+
9541. 6}
+
9542. 6.JSLINT_,
+
9543. 6.JSLINT_ address,
+
9544. 6.JSLINT_ button,
+
9545. 6.JSLINT_ cite,
+
9546. 6.JSLINT_ dd,
+
9547. 6.JSLINT_ dfn,
+
9548. 6.JSLINT_ dl,
+
9549. 6.JSLINT_ dt,
+
9550. 6.JSLINT_ fieldset,
+
9551. 6.JSLINT_ fieldset > div,
+
9552. 6.JSLINT_ input,
+
9553. 6.JSLINT_ label,
+
9554. 6.JSLINT_ legend,
+
9555. 6.JSLINT_ ol,
+
9556. 6.JSLINT_ samp,
+
9557. 6.JSLINT_ style,
+
9558. 6.JSLINT_ textarea,
+
9559. 6.JSLINT_ ul {
+
9560. 6 border: 0;
+
9561. 6 box-sizing: border-box;
+
9562. 6 margin: 0;
+
9563. 6 padding: 0;
+
9564. 6}
+
9565. 6/* disable text inflation algorithm used on some smartphones and tablets */
+
9566. 6.JSLINT_ {
+
9567. 6 -ms-text-size-adjust: none;
+
9568. 6 -webkit-text-size-adjust: none;
+
9569. 6 text-size-adjust: none;
+
9570. 6}
+
9571. 6.JSLINT_REPORT_ div {
+
9572. 6 box-sizing: border-box;
+
9573. 6}
+
9574. 6/*csslint ignore:end*/
+
9575. 6
+
9576. 6/* css - jslint_report - font */
+
9577. 6.JSLINT_,
+
9578. 6.JSLINT_ fieldset legend,
+
9579. 6.JSLINT_ .center {
+
9580. 6 font-family: daley, sans-serif;
+
9581. 6 font-size: 14px;
+
9582. 6}
+
9583. 6.JSLINT_ fieldset textarea,
+
9584. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS dt,
+
9585. 6.JSLINT_ #JSLINT_REPORT_WARNINGS samp {
+
9586. 6 font-size: 12px;
+
9587. 6}
+
9588. 6.JSLINT_ fieldset textarea,
+
9589. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS > div {
+
9590. 6 font-family: monospace;
+
9591. 6}
+
9592. 6.JSLINT_ fieldset > div {
+
9593. 6 font-family: sans-serif;
+
9594. 6}
+
9595. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level dfn {
+
9596. 6 font-style: normal;
+
9597. 6 font-weight: bold;
+
9598. 6}
+
9599. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level dt {
+
9600. 6 font-style: italic;
+
9601. 6}
+
9602. 6.JSLINT_ #JSLINT_REPORT_TITLE {
+
9603. 6 font-size: 32px;
+
9604. 6}
+
9605. 6
+
9606. 6/* css - jslint_report - general */
+
9607. 6.JSLINT_ {
+
9608. 6 background: antiquewhite;
+
9609. 6}
+
9610. 6.JSLINT_ fieldset {
+
9611. 6 background: gainsboro;
+
9612. 6 clear: both;
+
9613. 6 margin: 16px 40px;
+
9614. 6 width: auto;
+
9615. 6}
+
9616. 6.JSLINT_ fieldset address {
+
9617. 6 float: right;
+
9618. 6}
+
9619. 6.JSLINT_ fieldset legend,
+
9620. 6.JSLINT_ .center {
+
9621. 6 text-align: center;
+
9622. 6}
+
9623. 6.JSLINT_ fieldset legend {
+
9624. 6 background: darkslategray;
+
9625. 6 color: white;
+
9626. 6 padding: 4px 0;
+
9627. 6 width: 100%;
+
9628. 6}
+
9629. 6.JSLINT_ fieldset textarea {
+
9630. 6 padding: 4px;
+
9631. 6 resize: none;
+
9632. 6 white-space: pre;
+
9633. 6 width: 100%;
+
9634. 6}
+
9635. 6.JSLINT_ fieldset textarea::selection {
+
9636. 6 background: wheat;
+
9637. 6}
+
9638. 6.JSLINT_ fieldset > div {
+
9639. 6 padding: 16px;
+
9640. 6 width: 100%;
+
9641. 6 word-wrap: break-word;
+
9642. 6}
+
9643. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level {
+
9644. 6 background: cornsilk;
+
9645. 6 padding: 8px 16px;
+
9646. 6}
+
9647. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level dd {
+
9648. 6 line-height: 20px;
+
9649. 6 padding-left: 120px;
+
9650. 6}
+
9651. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level dfn {
+
9652. 6 display: block;
+
9653. 6 line-height: 20px;
+
9654. 6}
+
9655. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level dl {
+
9656. 6 position: relative
+
9657. 6}
+
9658. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level dt {
+
9659. 6 line-height: 20px;
+
9660. 6 position: absolute;
+
9661. 6 text-align: right;
+
9662. 6 width: 100px;
+
9663. 6}
+
9664. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level0 {
+
9665. 6 background: white;
+
9666. 6}
+
9667. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level1 {
+
9668. 6 /* yellow */
+
9669. 6 background: #ffffe0;
+
9670. 6 margin-left: 16px;
+
9671. 6}
+
9672. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level2 {
+
9673. 6 /* green */
+
9674. 6 background: #e0ffe0;
+
9675. 6 margin-left: 32px;
+
9676. 6}
+
9677. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level3 {
+
9678. 6 /* blue */
+
9679. 6 background: #D0D0ff;
+
9680. 6 margin-left: 48px;
+
9681. 6}
+
9682. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level4 {
+
9683. 6 /* purple */
+
9684. 6 background: #ffe0ff;
+
9685. 6 margin-left: 64px;
+
9686. 6}
+
9687. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level5 {
+
9688. 6 /* red */
+
9689. 6 background: #ffe0e0;
+
9690. 6 margin-left: 80px;
+
9691. 6}
+
9692. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level6 {
+
9693. 6 /* orange */
+
9694. 6 background: #ffe390;
+
9695. 6 margin-left: 96px;
+
9696. 6}
+
9697. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level7 {
+
9698. 6 /* gray */
+
9699. 6 background: #e0e0e0;
+
9700. 6 margin-left: 112px;
+
9701. 6}
+
9702. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level8 {
+
9703. 6 margin-left: 128px;
+
9704. 6}
+
9705. 6.JSLINT_ #JSLINT_REPORT_FUNCTIONS .level9 {
+
9706. 6 margin-left: 144px;
+
9707. 6}
+
9708. 6.JSLINT_ #JSLINT_REPORT_PROPERTIES {
+
9709. 6 background: transparent;
+
9710. 6}
+
9711. 6.JSLINT_ #JSLINT_REPORT_PROPERTIES textarea {
+
9712. 6 background: honeydew;
+
9713. 6 height: 100px;
+
9714. 6}
+
9715. 6.JSLINT_ #JSLINT_REPORT_TITLE {
+
9716. 6 color: darkslategray;
+
9717. 6 padding-top: 16px;
+
9718. 6}
+
9719. 6.JSLINT_ #JSLINT_REPORT_WARNINGS cite {
+
9720. 6 display: block;
+
9721. 6 margin: 16px 0 4px 0;
+
9722. 6 overflow-x: hidden;
+
9723. 6 white-space: pre-line;
+
9724. 6}
+
9725. 6.JSLINT_ #JSLINT_REPORT_WARNINGS cite:nth-child(1) {
+
9726. 6 margin-top: 0;
+
9727. 6}
+
9728. 6.JSLINT_ #JSLINT_REPORT_WARNINGS samp {
+
9729. 6 background: lavenderblush;
+
9730. 6 display: block;
+
9731. 6 padding: 4px;
+
9732. 6 white-space: pre-wrap;
+
9733. 6}
+
9734. 6.JSLINT_ #JSLINT_REPORT_WARNINGS > div {
+
9735. 6 background: pink;
+
9736. 6 max-height: 400px;
+
9737. 6 overflow-y: auto;
+
9738. 6}
+
9739. 6.JSLINT_ #JSLINT_REPORT_WARNINGS > legend {
+
9740. 6/* Google Lighthouse Accessibility - Background and foreground colors do not */
+
9741. 6/* have a sufficient contrast ratio. */
+
9742. 6 /* background: indianred; */
+
9743. 6 background: #b44;
+
9744. 6}
+
9745. 6</style>
+
9746. 6 `).trim() + "\n";
+
9747. 6
+
9748. 6// Produce the Title.
+
9749. 6
+
9750. 6 html += "<div class=\"center\" id=\"JSLINT_REPORT_TITLE\">\n";
+
9751. 6 html += "JSLint Report\n";
+
9752. 6 html += "</div>\n";
+
9753. 6
+
9754. 6// Produce the HTML Error Report.
+
9755. 6// <cite>
+
9756. 6// <address>LINE_NUMBER</address>
+
9757. 6// MESSAGE
+
9758. 6// </cite>
+
9759. 6// <samp>EVIDENCE</samp>
+
9760. 6
+
9761. 6 html += "<fieldset id=\"JSLINT_REPORT_WARNINGS\">\n";
+
9762. 6 html += "<legend>Report: Warnings (" + warnings.length + ")</legend>\n";
+
9763. 6 html += "<div>\n";
+
9764. 1 if (stop) {
+
9765. 1 html += "<div class=\"center\">JSLint was unable to finish.</div>\n";
+
9766. 1 }
+
9767. 7 warnings.forEach(function ({
+
9768. 7 column,
+
9769. 7 line,
+
9770. 7 line_source,
+
9771. 7 message,
+
9772. 7 stack_trace = ""
+
9773. 7 }, ii) {
+
9774. 7 html += (
+
9775. 7 "<cite>"
+
9776. 7 + address(line, column)
+
9777. 7 + htmlEscape((ii + 1) + ". " + message)
+
9778. 7 + "</cite>"
+
9779. 7 + "<samp>"
+
9780. 7 + htmlEscape(line_source.slice(0, 400) + "\n" + stack_trace)
+
9781. 7 + "</samp>\n"
+
9782. 7 );
+
9783. 7 });
+
9784. 3 if (warnings.length === 0) {
+
9785. 3 html += "<div class=\"center\">There are no warnings.</div>\n";
+
9786. 3 }
+
9787. 6 html += "</div>\n";
+
9788. 6 html += "</fieldset>\n";
+
9789. 6
+
9790. 6// Produce the /*property*/ directive.
+
9791. 6
+
9792. 6 html += "<fieldset id=\"JSLINT_REPORT_PROPERTIES\">\n";
+
9793. 6 html += (
+
9794. 6 "<legend>Report: Properties ("
+
9795. 6 + Object.keys(property).length
+
9796. 6 + ")</legend>\n"
+
9797. 6 );
+
9798. 6 html += "<label>\n";
+
9799. 6 html += "<textarea readonly>";
+
9800. 6 html += "/*property";
+
9801. 301 Object.keys(property).sort().forEach(function (key, ii) {
+
9802. 300 if (ii !== 0) {
+
9803. 300 html += ",";
+
9804. 300 length_80 += 2;
+
9805. 300 }
+
9806. 42 if (length_80 + key.length >= 80) {
+
9807. 42 length_80 = 4;
+
9808. 42 html += "\n ";
+
9809. 42 }
+
9810. 301 html += " " + key;
+
9811. 301 length_80 += key.length;
+
9812. 301 });
+
9813. 6 html += "\n*/\n";
+
9814. 6 html += "</textarea>\n";
+
9815. 6 html += "</label>\n";
+
9816. 6 html += "</fieldset>\n";
+
9817. 6
+
9818. 6// Produce the HTML Function Report.
+
9819. 6// <div class=LEVEL>
+
9820. 6// <address>LINE_NUMBER</address>
+
9821. 6// <dfn>FUNCTION_NAME_AND_SIGNATURE</dfn>
+
9822. 6// <dl>
+
9823. 6// <dt>DETAIL</dt>
+
9824. 6// <dd>NAMES</dd>
+
9825. 6// </dl>
+
9826. 6// </div>
+
9827. 6
+
9828. 6 html += "<fieldset id=\"JSLINT_REPORT_FUNCTIONS\">\n";
+
9829. 6 html += "<legend>Report: Functions (" + functions.length + ")</legend>\n";
+
9830. 6 html += "<div>\n";
+
9831. 2 if (json) {
+
9832. 2
+
9833. 2// Bugfix - fix website crashing when linting pure json-object.
+
9834. 2// return (
+
9835. 2
+
9836. 2 html += (
+
9837. 2 warnings.length === 0
+
9838. 2 ? "<div class=\"center\">JSON: good.</div>\n"
+
9839. 2 : "<div class=\"center\">JSON: bad.</div>\n"
+
9840. 2 );
+
9841. 4 } else if (functions.length === 0) {
+
9842. 4 html += "<div class=\"center\">There are no functions.</div>\n";
+
9843. 4 }
+
9844. 6 exports = Object.keys(exports).sort();
+
9845. 6 froms.sort();
+
9846. 6 global = Object.keys(global.context).sort();
+
9847. 6 module = (
+
9848. 6 module
+
9849. 1 ? "module"
+
9850. 5 : "global"
+
9851. 6 );
+
9852. 3 if (global.length + froms.length + exports.length > 0) {
+
9853. 3 if (functions.length === 0) {
+
9854. 3 html += "<br>\n";
+
9855. 3 }
+
9856. 3 html += "<div class=\"level level0\">\n";
+
9857. 3 html += detail(module, global);
+
9858. 3 html += detail("import from", froms);
+
9859. 3 html += detail("export", exports);
+
9860. 3 html += "</div>\n";
+
9861. 3 }
+
9862. 321 functions.forEach(function (the_function) {
+
9863. 321 let {
+
9864. 321 context,
+
9865. 321 from,
+
9866. 321 id,
+
9867. 321 level,
+
9868. 321 line,
+
9869. 321 name,
+
9870. 321
+
9871. 321// Bugfix - fix html-report from crashing if parameters is undefined.
+
9872. 321
+
9873. 321 parameters = [],
+
9874. 321 signature
+
9875. 321 } = the_function;
+
9876. 321 let list = Object.keys(context);
+
9877. 321 let params;
+
9878. 321 html += (
+
9879. 321 "<div class=\"level level" + htmlEscape(level) + "\">"
+
9880. 321 + address(line, from + 1)
+
9881. 321 + "<dfn>"
+
9882. 321 + (
+
9883. 321 id === "=>"
+
9884. 1 ? (
+
9885. 1 "\u00ab" + htmlEscape(name) + "\u00bb"
+
9886. 1 + htmlEscape(signature)
+
9887. 1 + " =>"
+
9888. 1 )
+
9889. 320 : (
+
9890. 320 typeof name === "string"
+
9891. 320 ? "\u00ab" + htmlEscape(name) + "\u00bb"
+
9892. 320 : htmlEscape(name.id)
+
9893. 320 ) + htmlEscape(signature)
+
9894. 321 )
+
9895. 321 + "</dfn>"
+
9896. 321 );
+
9897. 321 params = [];
+
9898. 470 parameters.forEach(function extract({
+
9899. 470 id,
+
9900. 470 names
+
9901. 470 }) {
+
9902. 470 switch (id) {
+
9903. 6 case "[":
+
9904. 42 case "{":
+
9905. 42
+
9906. 42// Recurse extract().
+
9907. 42
+
9908. 42 names.forEach(extract);
+
9909. 42 break;
+
9910. 4 case "ignore":
+
9911. 4 break;
+
9912. 424 default:
+
9913. 424 params.push(id);
+
9914. 470 }
+
9915. 470 });
+
9916. 321 html += detail("parameter", params.sort());
+
9917. 321 list.sort();
+
9918. 2203 html += detail("variable", list.filter(function (id) {
+
9919. 2203 return (
+
9920. 2203 context[id].role === "variable"
+
9921. 1693 && context[id].parent === the_function
+
9922. 2203 );
+
9923. 2203 }));
+
9924. 2203 html += detail("exception", list.filter(function (id) {
+
9925. 2203 return context[id].role === "exception";
+
9926. 2203 }));
+
9927. 2203 html += detail("closure", list.filter(function (id) {
+
9928. 2203 return (
+
9929. 2203 context[id].closure === true
+
9930. 1494 && context[id].parent === the_function
+
9931. 2203 );
+
9932. 2203 }));
+
9933. 2203 html += detail("outer", list.filter(function (id) {
+
9934. 2203 return (
+
9935. 2203 context[id].parent !== the_function
+
9936. 1190 && context[id].parent.id !== "(global)"
+
9937. 2203 );
+
9938. 2203 }));
+
9939. 2203 html += detail(module, list.filter(function (id) {
+
9940. 2203 return context[id].parent.id === "(global)";
+
9941. 2203 }));
+
9942. 2203 html += detail("label", list.filter(function (id) {
+
9943. 2203 return context[id].role === "label";
+
9944. 2203 }));
+
9945. 321 html += "</div>\n";
+
9946. 321 });
+
9947. 6 html += "</div>\n";
+
9948. 6 html += "</fieldset>\n";
+
9949. 6 return html;
+
9950. 6}
+
9951. 1
+
9952. 10async function jstestDescribe(description, testFunction) {
+
9953. 10
+
9954. 10// This function will create-and-run test-group <testFunction>
+
9955. 10// with given <description>.
+
9956. 10
+
9957. 10 let message;
+
9958. 10 let result;
+
9959. 10 let timerTimeout;
+
9960. 10
+
9961. 10// Init jstestTimeStart.
+
9962. 10
+
9963. 1 if (jstestTimeStart === undefined) {
+
9964. 1 jstestTimeStart = jstestTimeStart || Date.now();
+
9965. 1 process.on("exit", jstestOnExit);
+
9966. 1 }
+
9967. 10
+
9968. 10// PR-457 - Wait awhile for imports to initialize.
+
9969. 10
+
9970. 10 await new Promise(function (resolve) {
+
9971. 10 setTimeout(resolve);
+
9972. 10 });
+
9973. 10
+
9974. 10// Init jstestItList.
+
9975. 10
+
9976. 10 jstestItList = [];
+
9977. 10 testFunction();
+
9978. 10
+
9979. 10// Wait for jstestItList to resolve.
+
9980. 10
+
9981. 10 timerTimeout = setTimeout(noop, 0x7fffffff);
+
9982. 10 result = await Promise.all(jstestItList);
+
9983. 10 clearTimeout(timerTimeout);
+
9984. 10
+
9985. 10// Print test results.
+
9986. 10
+
9987. 10 message = (
+
9988. 10 "\n " + (Date.now() - jstestTimeStart) + "ms"
+
9989. 10 + " - test describe - " + description + "\n"
+
9990. 66 + result.map(function ([
+
9991. 66 err, description, mode
+
9992. 66 ]) {
+
9993. 66 jstestItCount += 1;
+
9994. 1 if (err) {
+
9995. 1 jstestCountFailed += 1;
+
9996. 1 err = (
+
9997. 1 " \u001b[31m\u2718 " + jstestItCount + ". test it - "
+
9998. 1 + description + "\n" + err.stack + "\u001b[39m"
+
9999. 1 );
+
10000. 1 if (mode === "pass") {
+
10001. 1 jstestCountFailed -= 1;
+
10002. 1 err = "";
+
10003. 1 }
+
10004. 1 }
+
10005. 66 return err || (
+
10006. 66 " \u001b[32m\u2714 " + jstestItCount + ". test it - "
+
10007. 66 + description + "\u001b[39m"
+
10008. 66 );
+
10009. 66 }).join("\n")
+
10010. 10 );
+
10011. 10 console.error(message);
+
10012. 10}
+
10013. 1
+
10014. 66function jstestIt(description, testFunction, mode) {
+
10015. 66
+
10016. 66// This function will create-and-run test-case <testFunction>
+
10017. 66// inside current test-group with given <description>.
+
10018. 66
+
10019. 66 jstestCountTotal += 1;
+
10020. 66 jstestItList.push(new Promise(async function (resolve) {
+
10021. 66 let err;
+
10022. 66 try {
+
10023. 65 await testFunction();
+
10024. 65 } catch (errCaught) {
+
10025. 1 err = errCaught;
+
10026. 1 }
+
10027. 66 resolve([err, description, mode]);
+
10028. 66 }));
+
10029. 66}
+
10030. 1
+
10031. 2function jstestOnExit(exitCode, mode) {
+
10032. 2
+
10033. 2// This function will on process-exit, print test-report
+
10034. 2// and exit with non-zero exit-code if any test failed.
+
10035. 2
+
10036. 2 let message = (
+
10037. 2 (
+
10038. 2 (jstestCountFailed || mode === "testsFailed")
+
10039. 1 ? "\n\u001b[31m"
+
10040. 1 : "\n\u001b[32m"
+
10041. 2 )
+
10042. 2 + " tests total - " + jstestCountTotal + "\n"
+
10043. 2 + " tests failed - " + jstestCountFailed + "\n"
+
10044. 2 + "\n"
+
10045. 2 + " time finished - "
+
10046. 2 + Number(Date.now() - jstestTimeStart).toLocaleString()
+
10047. 2 + " ms\n"
+
10048. 2 + "\u001b[39m"
+
10049. 2 );
+
10050. 1 if (mode !== "testsFailed") {
+
10051. 1 console.error(message);
+
10052. 1 }
+
10053. 2 process.exitCode = exitCode || jstestCountFailed;
+
10054. 2 return message;
+
10055. 2}
+
10056. 1
+
10057. 107async function moduleFsInit() {
+
10058. 107
+
10059. 107// This function will import nodejs builtin-modules if they have not yet been
+
10060. 107// imported.
+
10061. 107
+
10062. 107// State 3 - Modules already imported.
+
10063. 107
+
10064. 104 if (moduleFs !== undefined) {
+
10065. 104 return;
+
10066. 104 }
+
10067. 3
+
10068. 3// State 2 - Wait while modules are importing.
+
10069. 3
+
10070. 3 if (moduleFsInitResolveList !== undefined) {
+
10071. 2 return new Promise(function (resolve) {
+
10072. 2 moduleFsInitResolveList.push(resolve);
+
10073. 2 });
+
10074. 2 }
+
10075. 1
+
10076. 1// State 1 - Start importing modules.
+
10077. 1
+
10078. 1 moduleFsInitResolveList = [];
+
10079. 1 [
+
10080. 1 moduleChildProcess,
+
10081. 1 moduleFs,
+
10082. 1 modulePath,
+
10083. 1 moduleUrl
+
10084. 1 ] = await Promise.all([
+
10085. 1 import("child_process"),
+
10086. 1 import("fs"),
+
10087. 1 import("path"),
+
10088. 1 import("url")
+
10089. 1 ]);
+
10090. 2 while (moduleFsInitResolveList.length > 0) {
+
10091. 2 moduleFsInitResolveList.shift()();
+
10092. 2 }
+
10093. 107}
+
10094. 1
+
10095. 2728function noop(val) {
+
10096. 2728
+
10097. 2728// This function will do nothing except return <val>.
+
10098. 2728
+
10099. 2728 return val;
+
10100. 2728}
+
10101. 1
+
10102. 12919function objectDeepCopyWithKeysSorted(obj) {
+
10103. 12919
+
10104. 12919// This function will recursively deep-copy <obj> with keys sorted.
+
10105. 12919
+
10106. 12919 let sorted;
+
10107. 8995 if (typeof obj !== "object" || !obj) {
+
10108. 8995 return obj;
+
10109. 8995 }
+
10110. 3924
+
10111. 3924// Recursively deep-copy list with child-keys sorted.
+
10112. 3924
+
10113. 3924 if (Array.isArray(obj)) {
+
10114. 1338 return obj.map(objectDeepCopyWithKeysSorted);
+
10115. 2586 }
+
10116. 2586
+
10117. 2586// Recursively deep-copy obj with keys sorted.
+
10118. 2586
+
10119. 2586 sorted = Object.create(null);
+
10120. 7457 Object.keys(obj).sort().forEach(function (key) {
+
10121. 7457 sorted[key] = objectDeepCopyWithKeysSorted(obj[key]);
+
10122. 7457 });
+
10123. 2586 return sorted;
+
10124. 2586}
+
10125. 1
+
10126. 2791function object_assign_from_list(dict, list, val) {
+
10127. 2791
+
10128. 2791// Assign each property-name from <list> to <dict>.
+
10129. 2791
+
10130. 89862 list.forEach(function (key) {
+
10131. 89862 dict[key] = val;
+
10132. 89862 });
+
10133. 2791 return dict;
+
10134. 2791}
+
10135. 1
+
10136. 97function v8CoverageListMerge(processCovs) {
+
10137. 97
+
10138. 97// This function is derived from MIT Licensed v8-coverage at
+
10139. 97// https://github.com/demurgos/v8-coverage/tree/master/ts
+
10140. 97// https://github.com/demurgos/v8-coverage/blob/master/ts/LICENSE.md
+
10141. 97//
+
10142. 97// Merges a list of v8 process coverages.
+
10143. 97// The result is normalized.
+
10144. 97// The input values may be mutated, it is not safe to use them after passing
+
10145. 97// them to this function.
+
10146. 97// The computation is synchronous.
+
10147. 97// @param processCovs Process coverages to merge.
+
10148. 97// @return Merged process coverage.
+
10149. 97
+
10150. 97 let resultMerged = []; // List of merged scripts from processCovs.
+
10151. 97 let urlToScriptDict = new Map(); // Map scriptCov.url to scriptCovs.
+
10152. 97
+
10153. 1094 function compareRangeList(aa, bb) {
+
10154. 1094
+
10155. 1094// Compares two range coverages.
+
10156. 1094// The ranges are first ordered by ascending `startOffset` and then by
+
10157. 1094// descending `endOffset`.
+
10158. 1094// This corresponds to a pre-order tree traversal.
+
10159. 1094
+
10160. 1065 if (aa.startOffset !== bb.startOffset) {
+
10161. 1065 return aa.startOffset - bb.startOffset;
+
10162. 1065 }
+
10163. 29 return bb.endOffset - aa.endOffset;
+
10164. 29 }
+
10165. 97
+
10166. 1707 function dictKeyValueAppend(dict, key, val) {
+
10167. 1707
+
10168. 1707// This function will append <val> to list <dict>[<key>].
+
10169. 1707
+
10170. 1707 let list = dict.get(key);
+
10171. 1165 if (list === undefined) {
+
10172. 1165 list = [];
+
10173. 1165 dict.set(key, list);
+
10174. 1165 }
+
10175. 1707 list.push(val);
+
10176. 1707 }
+
10177. 97
+
10178. 384 function mergeTreeList(parentTrees) {
+
10179. 384
+
10180. 384// This function will return RangeTree object with <parentTrees> merged into
+
10181. 384// property-children.
+
10182. 384// @precondition Same `start` and `end` for all the parentTrees
+
10183. 384
+
10184. 119 if (parentTrees.length <= 1) {
+
10185. 119 return parentTrees[0];
+
10186. 265 }
+
10187. 265
+
10188. 265// new RangeTree().
+
10189. 265
+
10190. 265 return {
+
10191. 265
+
10192. 265// Merge parentTrees into property-children.
+
10193. 265
+
10194. 265 children: mergeTreeListToChildren(parentTrees),
+
10195. 669 delta: parentTrees.reduce(function (aa, bb) {
+
10196. 669 return aa + bb.delta;
+
10197. 669 }, 0),
+
10198. 265 end: parentTrees[0].end,
+
10199. 265 start: parentTrees[0].start
+
10200. 265 };
+
10201. 265 }
+
10202. 97
+
10203. 265 function mergeTreeListToChildren(parentTrees) {
+
10204. 265
+
10205. 265// This function will return <resultChildren> with <parentTrees> merged.
+
10206. 265
+
10207. 265 let openRange;
+
10208. 265 let parentToChildDict = new Map(); // Map parent to child.
+
10209. 265 let queueList;
+
10210. 265 let queueListIi = 0;
+
10211. 265 let queueOffset;
+
10212. 265 let queueTrees;
+
10213. 265 let resultChildren = [];
+
10214. 265 let startToTreeDict = new Map(); // Map tree.start to tree.
+
10215. 639 function nextXxx() {
+
10216. 639
+
10217. 639// Increment nextOffset, nextTrees.
+
10218. 639
+
10219. 639 let [
+
10220. 639 nextOffset, nextTrees
+
10221. 300 ] = queueList[queueListIi] || [];
+
10222. 639 let openRangeEnd;
+
10223. 583 if (queueTrees === undefined) {
+
10224. 583 queueListIi += 1;
+
10225. 583
+
10226. 583// Increment nextOffset, nextTrees.
+
10227. 583
+
10228. 583 } else if (nextOffset === undefined || nextOffset > queueOffset) {
+
10229. 56 nextOffset = queueOffset;
+
10230. 56 nextTrees = queueTrees;
+
10231. 56 queueTrees = undefined;
+
10232. 56
+
10233. 56// Concat queueTrees to nextTrees.
+
10234. 56
+
10235. 56 } else {
+
10236. 56 if (nextOffset === queueOffset) {
+
10237. 56 queueTrees.forEach(function (tree) {
+
10238. 56 nextTrees.push(tree);
+
10239. 56 });
+
10240. 56 queueTrees = undefined;
+
10241. 56 }
+
10242. 56 queueListIi += 1;
+
10243. 56 }
+
10244. 639
+
10245. 639// Reached end of queueList.
+
10246. 639
+
10247. 265 if (nextOffset === undefined) {
+
10248. 265 if (openRange !== undefined) {
+
10249. 265
+
10250. 265// Append nested-children from parentToChildDict (within openRange) to
+
10251. 265// resultChildren.
+
10252. 265
+
10253. 265 resultAppendNextChild();
+
10254. 265 }
+
10255. 265 return true;
+
10256. 374 }
+
10257. 374 if (openRange !== undefined && openRange.end <= nextOffset) {
+
10258. 129
+
10259. 129// Append nested-children from parentToChildDict (within openRange) to
+
10260. 129// resultChildren.
+
10261. 129
+
10262. 129 resultAppendNextChild();
+
10263. 129 openRange = undefined;
+
10264. 374 }
+
10265. 374 if (openRange === undefined) {
+
10266. 292 openRangeEnd = nextOffset + 1;
+
10267. 502 nextTrees.forEach(function ({
+
10268. 502 parentIi,
+
10269. 502 tree
+
10270. 502 }) {
+
10271. 502 openRangeEnd = Math.max(openRangeEnd, tree.end);
+
10272. 502
+
10273. 502// Append children from nextTrees to parentToChildDict.
+
10274. 502
+
10275. 502 dictKeyValueAppend(parentToChildDict, parentIi, tree);
+
10276. 502 });
+
10277. 292 queueOffset = openRangeEnd;
+
10278. 292 openRange = {
+
10279. 292 end: openRangeEnd,
+
10280. 292 start: nextOffset
+
10281. 292 };
+
10282. 292 } else {
+
10283. 114 nextTrees.forEach(function ({
+
10284. 114 parentIi,
+
10285. 114 tree
+
10286. 114 }) {
+
10287. 114 let right;
+
10288. 82 if (tree.end > openRange.end) {
+
10289. 82 right = treeSplit(tree, openRange.end);
+
10290. 82 if (queueTrees === undefined) {
+
10291. 82 queueTrees = [];
+
10292. 82 }
+
10293. 82
+
10294. 82// new RangeTreeWithParent().
+
10295. 82
+
10296. 82 queueTrees.push({
+
10297. 82 parentIi,
+
10298. 82 tree: right
+
10299. 82 });
+
10300. 82 }
+
10301. 114
+
10302. 114// Append children from nextTrees to parentToChildDict.
+
10303. 114
+
10304. 114 dictKeyValueAppend(parentToChildDict, parentIi, tree);
+
10305. 114 });
+
10306. 82 }
+
10307. 639 }
+
10308. 292 function resultAppendNextChild() {
+
10309. 292
+
10310. 292// This function will append next child to <resultChildren>.
+
10311. 292
+
10312. 292 let treesMatching = [];
+
10313. 589 parentToChildDict.forEach(function (nested) {
+
10314. 589 if (
+
10315. 589 nested.length === 1
+
10316. 563 && nested[0].start === openRange.start
+
10317. 480 && nested[0].end === openRange.end
+
10318. 468 ) {
+
10319. 468 treesMatching.push(nested[0]);
+
10320. 468 } else {
+
10321. 121
+
10322. 121// new rangeTreeCreate().
+
10323. 121
+
10324. 121 treesMatching.push({
+
10325. 121 children: nested,
+
10326. 121 delta: 0,
+
10327. 121 end: openRange.end,
+
10328. 121 start: openRange.start
+
10329. 121 });
+
10330. 121 }
+
10331. 589 });
+
10332. 292 parentToChildDict.clear();
+
10333. 292
+
10334. 292// Recurse mergeTreeList().
+
10335. 292
+
10336. 292 resultChildren.push(mergeTreeList(treesMatching));
+
10337. 292 }
+
10338. 75 function treeSplit(tree, offset) {
+
10339. 75
+
10340. 75// This function will split <tree> along <offset> and return the right-side.
+
10341. 75// @precondition `tree.start < offset && offset < tree.end`
+
10342. 75// @return RangeTree Right part
+
10343. 75
+
10344. 75 let child;
+
10345. 75 let ii = 0;
+
10346. 75 let leftChildLen = tree.children.length;
+
10347. 75 let mid;
+
10348. 75 let resultTree;
+
10349. 75 let rightChildren;
+
10350. 75
+
10351. 75// TODO(perf): Binary search (check overhead) //jslint-ignore-line
+
10352. 75
+
10353. 19 while (ii < tree.children.length) {
+
10354. 19 child = tree.children[ii];
+
10355. 19 if (child.start < offset && offset < child.end) {
+
10356. 19
+
10357. 19// Recurse treeSplit().
+
10358. 19
+
10359. 19 mid = treeSplit(child, offset);
+
10360. 19 leftChildLen = ii + 1;
+
10361. 19 break;
+
10362. 19 }
+
10363. 19 if (child.start >= offset) {
+
10364. 19 leftChildLen = ii;
+
10365. 19 break;
+
10366. 19 }
+
10367. 19 ii += 1;
+
10368. 19 }
+
10369. 75 rightChildren = tree.children.splice(
+
10370. 75 leftChildLen,
+
10371. 75 tree.children.length - leftChildLen
+
10372. 75 );
+
10373. 4 if (mid !== undefined) {
+
10374. 4 rightChildren.unshift(mid);
+
10375. 4 }
+
10376. 75
+
10377. 75// new rangeTreeCreate().
+
10378. 75
+
10379. 75 resultTree = {
+
10380. 75 children: rightChildren,
+
10381. 75 delta: tree.delta,
+
10382. 75 end: tree.end,
+
10383. 75 start: offset
+
10384. 75 };
+
10385. 75 tree.end = offset;
+
10386. 75 return resultTree;
+
10387. 75 }
+
10388. 265
+
10389. 265// Init startToTreeDict.
+
10390. 265
+
10391. 669 parentTrees.forEach(function (parentTree, parentIi) {
+
10392. 545 parentTree.children.forEach(function (child) {
+
10393. 545
+
10394. 545// Append child with child.start to startToTreeDict.
+
10395. 545
+
10396. 545 dictKeyValueAppend(startToTreeDict, child.start, {
+
10397. 545 parentIi,
+
10398. 545 tree: child
+
10399. 545 });
+
10400. 545 });
+
10401. 669 });
+
10402. 265
+
10403. 265// init queueList.
+
10404. 265
+
10405. 335 queueList = Array.from(startToTreeDict).map(function ([
+
10406. 335 startOffset, trees
+
10407. 335 ]) {
+
10408. 335
+
10409. 335// new StartEvent().
+
10410. 335
+
10411. 335 return [
+
10412. 335 startOffset, trees
+
10413. 335 ];
+
10414. 217 }).sort(function (aa, bb) {
+
10415. 217 return aa[0] - bb[0];
+
10416. 217 });
+
10417. 639 while (true) {
+
10418. 639 if (nextXxx()) {
+
10419. 639 break;
+
10420. 639 }
+
10421. 639 }
+
10422. 265 return resultChildren;
+
10423. 265 }
+
10424. 97
+
10425. 689 function sortFunc(funcCov) {
+
10426. 689
+
10427. 689// This function will normalize-and-sort <funcCov>.ranges.
+
10428. 689// Sorts the ranges (pre-order sort).
+
10429. 689// TODO: Tree-based normalization of the ranges. //jslint-ignore-line
+
10430. 689// @param funcCov Function coverage to normalize.
+
10431. 689
+
10432. 689 funcCov.ranges = treeToRanges(treeFromSortedRanges(
+
10433. 689 funcCov.ranges.sort(compareRangeList)
+
10434. 689 ));
+
10435. 689 return funcCov;
+
10436. 689 }
+
10437. 97
+
10438. 129 function sortScript(scriptCov) {
+
10439. 129
+
10440. 129// This function will normalize-and-sort <scriptCov>.functions.
+
10441. 129
+
10442. 129// Normalize-and-sort functions[xxx].ranges.
+
10443. 129
+
10444. 688 scriptCov.functions.forEach(function (funcCov) {
+
10445. 688 sortFunc(funcCov);
+
10446. 688 });
+
10447. 129
+
10448. 129// Sort functions by root range (pre-order sort).
+
10449. 129
+
10450. 559 scriptCov.functions.sort(function (aa, bb) {
+
10451. 559 return compareRangeList(aa.ranges[0], bb.ranges[0]);
+
10452. 559 });
+
10453. 129 return scriptCov;
+
10454. 129 }
+
10455. 97
+
10456. 888 function treeFromSortedRanges(ranges) {
+
10457. 888
+
10458. 888// @precondition `ranges` are well-formed and pre-order sorted
+
10459. 888
+
10460. 888 let root;
+
10461. 888 let stack = []; // Stack of parent trees and parent counts.
+
10462. 1856 ranges.forEach(function (range) {
+
10463. 1856
+
10464. 1856// new rangeTreeCreate().
+
10465. 1856
+
10466. 1856 let node = {
+
10467. 1856 children: [],
+
10468. 1856 delta: range.count,
+
10469. 1856 end: range.endOffset,
+
10470. 1856 start: range.startOffset
+
10471. 1856 };
+
10472. 1856 let parent;
+
10473. 1856 let parentCount;
+
10474. 888 if (root === undefined) {
+
10475. 888 root = node;
+
10476. 888 stack.push([
+
10477. 888 node, range.count
+
10478. 888 ]);
+
10479. 888 return;
+
10480. 968 }
+
10481. 1565 while (true) {
+
10482. 1565 [
+
10483. 1565 parent, parentCount
+
10484. 1565 ] = stack[stack.length - 1];
+
10485. 1565
+
10486. 1565// assert: `top !== undefined` (the ranges are sorted)
+
10487. 1565
+
10488. 1565 if (range.startOffset < parent.end) {
+
10489. 1565 break;
+
10490. 1565 }
+
10491. 1565 stack.pop();
+
10492. 1565 }
+
10493. 968 node.delta -= parentCount;
+
10494. 968 parent.children.push(node);
+
10495. 968 stack.push([
+
10496. 968 node, range.count
+
10497. 968 ]);
+
10498. 968 });
+
10499. 888 return root;
+
10500. 888 }
+
10501. 97
+
10502. 781 function treeToRanges(tree) {
+
10503. 781
+
10504. 781// Get the range coverages corresponding to the tree.
+
10505. 781// The ranges are pre-order sorted.
+
10506. 781
+
10507. 781 let count;
+
10508. 781 let cur;
+
10509. 781 let ii;
+
10510. 781 let parentCount;
+
10511. 781 let ranges = [];
+
10512. 781 let stack = [ // Stack of parent trees and counts.
+
10513. 781 [
+
10514. 781 tree, 0
+
10515. 781 ]
+
10516. 781 ];
+
10517. 1630 function normalizeRange(tree) {
+
10518. 1630
+
10519. 1630// @internal
+
10520. 1630
+
10521. 1630 let children = [];
+
10522. 1630 let curEnd;
+
10523. 1630 let head;
+
10524. 1630 let tail = [];
+
10525. 849 function endChain() {
+
10526. 18 if (tail.length !== 0) {
+
10527. 18 head.end = tail[tail.length - 1].end;
+
10528. 18 tail.forEach(function (tailTree) {
+
10529. 18 tailTree.children.forEach(function (subChild) {
+
10530. 18 subChild.delta += tailTree.delta - head.delta;
+
10531. 18 head.children.push(subChild);
+
10532. 18 });
+
10533. 18 });
+
10534. 18 tail.length = 0;
+
10535. 18 }
+
10536. 849
+
10537. 849// Recurse normalizeRange().
+
10538. 849
+
10539. 849 normalizeRange(head);
+
10540. 849 children.push(head);
+
10541. 849 }
+
10542. 867 tree.children.forEach(function (child) {
+
10543. 432 if (head === undefined) {
+
10544. 432 head = child;
+
10545. 435 } else if (
+
10546. 435 child.delta === head.delta && child.start === curEnd
+
10547. 435 ) {
+
10548. 435 tail.push(child);
+
10549. 435 } else {
+
10550. 435 endChain();
+
10551. 435 head = child;
+
10552. 435 }
+
10553. 867 curEnd = child.end;
+
10554. 867 });
+
10555. 432 if (head !== undefined) {
+
10556. 432 endChain();
+
10557. 432 }
+
10558. 238 if (children.length === 1) {
+
10559. 238 if (
+
10560. 238 children[0].start === tree.start
+
10561. 238 && children[0].end === tree.end
+
10562. 238 ) {
+
10563. 238 tree.delta += children[0].delta;
+
10564. 238 tree.children = children[0].children;
+
10565. 238
+
10566. 238// `.lazyCount` is zero for both (both are after normalization)
+
10567. 238
+
10568. 238 return;
+
10569. 238 }
+
10570. 1624 }
+
10571. 1624 tree.children = children;
+
10572. 1624 }
+
10573. 781 normalizeRange(tree);
+
10574. 1624 while (stack.length > 0) {
+
10575. 1624 [
+
10576. 1624 cur, parentCount
+
10577. 1624 ] = stack.pop();
+
10578. 1624 count = parentCount + cur.delta;
+
10579. 1624 ranges.push({
+
10580. 1624 count,
+
10581. 1624 endOffset: cur.end,
+
10582. 1624 startOffset: cur.start
+
10583. 1624 });
+
10584. 1624 ii = cur.children.length - 1;
+
10585. 1624 while (ii >= 0) {
+
10586. 1624 stack.push([
+
10587. 1624 cur.children[ii], count
+
10588. 1624 ]);
+
10589. 1624 ii -= 1;
+
10590. 1624 }
+
10591. 1624 }
+
10592. 781 return ranges;
+
10593. 781 }
+
10594. 97
+
10595. 1 if (processCovs.length === 0) {
+
10596. 1 return {
+
10597. 1 result: []
+
10598. 1 };
+
10599. 96 }
+
10600. 96
+
10601. 96// Init urlToScriptDict.
+
10602. 96
+
10603. 234 processCovs.forEach(function ({
+
10604. 234 result
+
10605. 234 }) {
+
10606. 269 result.forEach(function (scriptCov) {
+
10607. 269 dictKeyValueAppend(urlToScriptDict, scriptCov.url, scriptCov);
+
10608. 269 });
+
10609. 234 });
+
10610. 129 urlToScriptDict.forEach(function (scriptCovs) {
+
10611. 129
+
10612. 129// assert: `scriptCovs.length > 0`
+
10613. 129
+
10614. 129// function mergeScriptList(scriptCovs) {
+
10615. 129// Merges a list of matching script coverages.
+
10616. 129// Scripts are matching if they have the same `url`.
+
10617. 129// The result is normalized.
+
10618. 129// The input values may be mutated, it is not safe to use them after passing
+
10619. 129// them to this function.
+
10620. 129// The computation is synchronous.
+
10621. 129// @param scriptCovs Process coverages to merge.
+
10622. 129// @return Merged script coverage, or `undefined` if the input list was empty.
+
10623. 129
+
10624. 129 let functions = [];
+
10625. 129
+
10626. 129// Map funcCovRoot.startOffset:funcCovRoot.endOffset to funcCov.
+
10627. 129
+
10628. 129 let rangeToFuncDict = new Map();
+
10629. 129
+
10630. 129// Probably deadcode.
+
10631. 129// if (scriptCovs.length === 0) {
+
10632. 129// return undefined;
+
10633. 129// }
+
10634. 129
+
10635. 96 if (scriptCovs.length === 1) {
+
10636. 96 resultMerged.push(sortScript(scriptCovs[0]));
+
10637. 96 return;
+
10638. 96 }
+
10639. 96
+
10640. 96// Init rangeToFuncDict.
+
10641. 96// Map funcCovRoot.startOffset:funcCovRoot.endOffset to funcCov.
+
10642. 96
+
10643. 226 scriptCovs.forEach(function ({
+
10644. 226 functions
+
10645. 226 }) {
+
10646. 277 functions.forEach(function (funcCov) {
+
10647. 277 dictKeyValueAppend(
+
10648. 277 rangeToFuncDict,
+
10649. 277
+
10650. 277// This string can be used to match function with same root range.
+
10651. 277// The string is derived from the start and end offsets of the root range of
+
10652. 277// the function.
+
10653. 277// This assumes that `ranges` is non-empty (true for valid function coverages).
+
10654. 277
+
10655. 277 (
+
10656. 277 funcCov.ranges[0].startOffset
+
10657. 277 + ";" + funcCov.ranges[0].endOffset
+
10658. 277 ),
+
10659. 277 funcCov
+
10660. 277 );
+
10661. 277 });
+
10662. 226 });
+
10663. 112 rangeToFuncDict.forEach(function (funcCovs) {
+
10664. 112
+
10665. 112// assert: `funcCovs.length > 0`
+
10666. 112
+
10667. 112// function mergeFuncList(funcCovs) {
+
10668. 112// Merges a list of matching function coverages.
+
10669. 112// Functions are matching if their root ranges have the same span.
+
10670. 112// The result is normalized.
+
10671. 112// The input values may be mutated, it is not safe to use them after passing
+
10672. 112// them to this function.
+
10673. 112// The computation is synchronous.
+
10674. 112// @param funcCovs Function coverages to merge.
+
10675. 112// @return Merged function coverage, or `undefined` if the input list was empty.
+
10676. 112
+
10677. 112 let count = 0;
+
10678. 112 let isBlockCoverage;
+
10679. 112 let merged;
+
10680. 112 let ranges;
+
10681. 112 let trees = [];
+
10682. 112
+
10683. 112// Probably deadcode.
+
10684. 112// if (funcCovs.length === 0) {
+
10685. 112// return undefined;
+
10686. 112// }
+
10687. 112
+
10688. 96 if (funcCovs.length === 1) {
+
10689. 96 functions.push(sortFunc(funcCovs[0]));
+
10690. 96 return;
+
10691. 111 }
+
10692. 111
+
10693. 111// assert: `funcCovs[0].ranges.length > 0`
+
10694. 111
+
10695. 276 funcCovs.forEach(function (funcCov) {
+
10696. 276
+
10697. 276// assert: `funcCov.ranges.length > 0`
+
10698. 276// assert: `funcCov.ranges` is sorted
+
10699. 276
+
10700. 276 count += (
+
10701. 276 funcCov.count !== undefined
+
10702. 111 ? funcCov.count
+
10703. 274 : funcCov.ranges[0].count
+
10704. 276 );
+
10705. 199 if (funcCov.isBlockCoverage) {
+
10706. 199 trees.push(treeFromSortedRanges(funcCov.ranges));
+
10707. 199 }
+
10708. 276 });
+
10709. 111 if (trees.length > 0) {
+
10710. 96 isBlockCoverage = true;
+
10711. 96 ranges = treeToRanges(mergeTreeList(trees));
+
10712. 96 } else {
+
10713. 96 isBlockCoverage = false;
+
10714. 96 ranges = [
+
10715. 96 {
+
10716. 96 count,
+
10717. 96 endOffset: funcCovs[0].ranges[0].endOffset,
+
10718. 96 startOffset: funcCovs[0].ranges[0].startOffset
+
10719. 96 }
+
10720. 96 ];
+
10721. 111 }
+
10722. 111 merged = {
+
10723. 111 functionName: funcCovs[0].functionName,
+
10724. 111 isBlockCoverage,
+
10725. 111 ranges
+
10726. 111 };
+
10727. 111 if (count !== ranges[0].count) {
+
10728. 96 merged.count = count;
+
10729. 111 }
+
10730. 111
+
10731. 111// assert: `merged` is normalized
+
10732. 111
+
10733. 111 functions.push(merged);
+
10734. 111 });
+
10735. 96 resultMerged.push(sortScript({
+
10736. 96 functions,
+
10737. 96 scriptId: scriptCovs[0].scriptId,
+
10738. 96 url: scriptCovs[0].url
+
10739. 96 }));
+
10740. 96 });
+
10741. 96
+
10742. 96// Sorts the scripts alphabetically by `url`.
+
10743. 96// Reassigns script ids: the script at index `0` receives `"0"`, the script at
+
10744. 96// index `1` receives `"1"` etc.
+
10745. 96
+
10746. 96 Object.entries(resultMerged.sort(function (aa, bb) {
+
10747. 96 return (
+
10748. 96 aa.url > bb.url
+
10749. 96 ? 1
+
10750. 96 : -1
+
10751. 96 );
+
10752. 129 })).forEach(function ([
+
10753. 129 scriptId, scriptCov
+
10754. 129 ]) {
+
10755. 129 scriptCov.scriptId = scriptId.toString(10);
+
10756. 129 });
+
10757. 96 return {
+
10758. 96 result: resultMerged
+
10759. 96 };
+
10760. 96}
+
10761. 1
+
10762. 8async function v8CoverageReportCreate({
+
10763. 8 consoleError,
+
10764. 8 coverageDir,
+
10765. 8 processArgv = []
+
10766. 8}) {
+
10767. 8
+
10768. 8// This function will create html-coverage-reports directly from
+
10769. 8// v8-coverage-files in <coverageDir>.
+
10770. 8// 1. Spawn node.js program <processArgv> with NODE_V8_COVERAGE.
+
10771. 8// 2. Merge JSON v8-coverage-files in <coverageDir>.
+
10772. 8// 3. Create html-coverage-reports in <coverageDir>.
+
10773. 8
+
10774. 8 let cwd;
+
10775. 8 let excludeList = [];
+
10776. 8 let exitCode = 0;
+
10777. 8 let fileDict;
+
10778. 8 let includeList = [];
+
10779. 8 let modeIncludeNodeModules;
+
10780. 8 let processArgElem;
+
10781. 8 let promiseList = [];
+
10782. 8 let v8CoverageObj;
+
10783. 8
+
10784. 13 function htmlRender({
+
10785. 13 fileList,
+
10786. 13 lineList,
+
10787. 13 modeIndex,
+
10788. 13 pathname
+
10789. 13 }) {
+
10790. 13 let html;
+
10791. 13 let padLines;
+
10792. 13 let padPathname;
+
10793. 13 let txt;
+
10794. 13 let txtBorder;
+
10795. 13 html = "";
+
10796. 13 html += String(`
+
10797. 13<!DOCTYPE html>
+
10798. 13<html lang="en">
+
10799. 13<head>
+
10800. 13<title>V8 Coverage Report</title>
+
10801. 13<style>
+
10802. 13/* jslint utility2:true */
+
10803. 13/*csslint ignore:start*/
+
10804. 13.coverage,
+
10805. 13.coverage a,
+
10806. 13.coverage div,
+
10807. 13.coverage pre,
+
10808. 13.coverage span,
+
10809. 13.coverage table,
+
10810. 13.coverage tbody,
+
10811. 13.coverage td,
+
10812. 13.coverage th,
+
10813. 13.coverage thead,
+
10814. 13.coverage tr {
+
10815. 13 box-sizing: border-box;
+
10816. 13 font-family: monospace;
+
10817. 13}
+
10818. 13/*csslint ignore:end*/
+
10819. 13
+
10820. 13/* css - coverage_report - general */
+
10821. 13body {
+
10822. 13 margin: 0;
+
10823. 13}
+
10824. 13.coverage pre {
+
10825. 13 margin: 5px 0;
+
10826. 13}
+
10827. 13.coverage table {
+
10828. 13 border-collapse: collapse;
+
10829. 13}
+
10830. 13.coverage td,
+
10831. 13.coverage th {
+
10832. 13 border: 1px solid #777;
+
10833. 13 line-height: 20px;
+
10834. 13 margin: 0;
+
10835. 13 padding: 5px 10px;
+
10836. 13}
+
10837. 13.coverage td span {
+
10838. 13 display: inline-block;
+
10839. 13 width: 100%;
+
10840. 13}
+
10841. 13.coverage .content {
+
10842. 13 padding: 0 5px;
+
10843. 13}
+
10844. 13.coverage .content a {
+
10845. 13 text-decoration: none;
+
10846. 13}
+
10847. 13.coverage .count {
+
10848. 13 margin: 0 5px;
+
10849. 13 padding: 0 5px;
+
10850. 13}
+
10851. 13.coverage .footer,
+
10852. 13.coverage .header {
+
10853. 13 padding: 20px;
+
10854. 13}
+
10855. 13.coverage .footer {
+
10856. 13 text-align: center;
+
10857. 13}
+
10858. 13.coverage .percentbar {
+
10859. 13 height: 12px;
+
10860. 13 margin: 2px 0;
+
10861. 13 min-width: 200px;
+
10862. 13 position: relative;
+
10863. 13 width: 100%;
+
10864. 13}
+
10865. 13.coverage .percentbar div {
+
10866. 13 height: 100%;
+
10867. 13 position: absolute;
+
10868. 13}
+
10869. 13.coverage .title {
+
10870. 13 font-size: large;
+
10871. 13 font-weight: bold;
+
10872. 13 margin-bottom: 10px;
+
10873. 13}
+
10874. 13
+
10875. 13/* css - coverage_report - color */
+
10876. 13.coverage td,
+
10877. 13.coverage th {
+
10878. 13 background: #fff;
+
10879. 13}
+
10880. 13.coverage .count,
+
10881. 13.coverage .coverageHigh {
+
10882. 13 background: #9d9;
+
10883. 13}
+
10884. 13.coverage .count {
+
10885. 13 color: #666;
+
10886. 13}
+
10887. 13.coverage .coverageIgnore {
+
10888. 13 background: #ccc;
+
10889. 13}
+
10890. 13.coverage .coverageLow,
+
10891. 13.coverage .uncovered {
+
10892. 13 background: #ebb;
+
10893. 13}
+
10894. 13.coverage .coverageMedium {
+
10895. 13 background: #fd7;
+
10896. 13}
+
10897. 13.coverage .footer,
+
10898. 13.coverage .header,
+
10899. 13.coverage .lineno {
+
10900. 13 background: #ddd;
+
10901. 13}
+
10902. 13.coverage .percentbar {
+
10903. 13 background: #999;
+
10904. 13}
+
10905. 13.coverage .percentbar div {
+
10906. 13 background: #666;
+
10907. 13}
+
10908. 13
+
10909. 13/* css - coverage_report - important */
+
10910. 13.coverage pre:hover span,
+
10911. 13.coverage tr:hover td {
+
10912. 13 background: #7d7;
+
10913. 13}
+
10914. 13.coverage pre:hover span.uncovered,
+
10915. 13.coverage tr:hover td.coverageLow {
+
10916. 13 background: #f99;
+
10917. 13}
+
10918. 13</style>
+
10919. 13</head>
+
10920. 13<body class="coverage">
+
10921. 13<!-- header start -->
+
10922. 13<div class="header">
+
10923. 13<div class="title">V8 Coverage Report</div>
+
10924. 13<table>
+
10925. 13<thead>
+
10926. 13 <tr>
+
10927. 13 <th>Files covered</th>
+
10928. 13 <th>Lines</th>
+
10929. 13 <th>Remaining</th>
+
10930. 13 </tr>
+
10931. 13</thead>
+
10932. 13<tbody>
+
10933. 13 `).trim() + "\n";
+
10934. 7 if (modeIndex) {
+
10935. 7 padLines = String("(ignore) 100.00 %").length;
+
10936. 7 padPathname = 32;
+
10937. 7 fileList.unshift({
+
10938. 7 linesCovered: 0,
+
10939. 7 linesTotal: 0,
+
10940. 7 modeCoverageIgnoreFile: "",
+
10941. 7 pathname: "./"
+
10942. 7 });
+
10943. 7 fileList.slice(1).forEach(function ({
+
10944. 7 linesCovered,
+
10945. 7 linesTotal,
+
10946. 7 modeCoverageIgnoreFile,
+
10947. 7 pathname
+
10948. 7 }) {
+
10949. 7 if (!modeCoverageIgnoreFile) {
+
10950. 7 fileList[0].linesCovered += linesCovered;
+
10951. 7 fileList[0].linesTotal += linesTotal;
+
10952. 7 }
+
10953. 7 padPathname = Math.max(padPathname, pathname.length + 2);
+
10954. 7 padLines = Math.max(
+
10955. 7 padLines,
+
10956. 7 String(linesCovered + " / " + linesTotal).length
+
10957. 7 );
+
10958. 7 });
+
10959. 7 }
+
10960. 13 txtBorder = (
+
10961. 13 "+" + "-".repeat(padPathname + 2) + "+"
+
10962. 13 + "-".repeat(padLines + 2) + "+"
+
10963. 13 + "-".repeat(padLines + 2) + "+\n"
+
10964. 13 );
+
10965. 13 txt = "";
+
10966. 13 txt += "V8 Coverage Report\n";
+
10967. 13 txt += txtBorder;
+
10968. 13 txt += (
+
10969. 13 "| " + String("Files covered").padEnd(padPathname, " ") + " | "
+
10970. 13 + String("Lines").padStart(padLines, " ") + " | "
+
10971. 13 + String("Remaining").padStart(padLines, " ") + " |\n"
+
10972. 13 );
+
10973. 13 txt += txtBorder;
+
10974. 19 fileList.forEach(function ({
+
10975. 19 linesCovered,
+
10976. 19 linesTotal,
+
10977. 19 modeCoverageIgnoreFile,
+
10978. 19 pathname
+
10979. 19 }, ii) {
+
10980. 19 let coverageLevel;
+
10981. 19 let coveragePct;
+
10982. 19 let fill;
+
10983. 19 let str1;
+
10984. 19 let str2;
+
10985. 19 let xx1;
+
10986. 19 let xx2;
+
10987. 2 coveragePct = Math.floor(10000 * linesCovered / linesTotal || 0);
+
10988. 19 coverageLevel = (
+
10989. 19 modeCoverageIgnoreFile
+
10990. 2 ? "coverageIgnore"
+
10991. 17 : coveragePct >= 8000
+
10992. 17 ? "coverageHigh"
+
10993. 17 : coveragePct >= 5000
+
10994. 17 ? "coverageMedium"
+
10995. 17 : "coverageLow"
+
10996. 19 );
+
10997. 19 coveragePct = String(coveragePct).replace((
+
10998. 19 /..$/m
+
10999. 19 ), ".$&");
+
11000. 13 if (modeIndex && ii === 0) {
+
11001. 7 fill = (
+
11002. 7
+
11003. 7// Badge-color rgb-red.
+
11004. 7
+
11005. 7 "#" + Math.round(
+
11006. 7 (100 - Number(coveragePct)) * 2.21
+
11007. 7 ).toString(16).padStart(2, "0")
+
11008. 7
+
11009. 7// Badge-color rgb-green.
+
11010. 7
+
11011. 7 + Math.round(
+
11012. 7 Number(coveragePct) * 2.21
+
11013. 7 ).toString(16).padStart(2, "0")
+
11014. 7
+
11015. 7// Badge-color rgb-blue.
+
11016. 7
+
11017. 7 + "00"
+
11018. 7 );
+
11019. 7 str1 = "coverage";
+
11020. 7 str2 = coveragePct + " %";
+
11021. 7 xx1 = 6 * str1.length + 20;
+
11022. 7 xx2 = 6 * str2.length + 20;
+
11023. 7
+
11024. 7// Fs - write coverage_badge.svg.
+
11025. 7
+
11026. 7 promiseList.push(fsWriteFileWithParents((
+
11027. 7 coverageDir + "coverage_badge.svg"
+
11028. 7 ), String(`
+
11029. 7<svg height="20" width="${xx1 + xx2}" xmlns="http://www.w3.org/2000/svg">
+
11030. 7<rect fill="#555" height="20" width="${xx1 + xx2}"/>
+
11031. 7<rect fill="${fill}" height="20" width="${xx2}" x="${xx1}"/>
+
11032. 7<g
+
11033. 7 fill="#fff"
+
11034. 7 font-family="verdana, geneva, dejavu sans, sans-serif"
+
11035. 7 font-size="11"
+
11036. 7 font-weight="bold"
+
11037. 7 text-anchor="middle"
+
11038. 7>
+
11039. 7<text x="${0.5 * xx1}" y="14">${str1}</text>
+
11040. 7<text x="${xx1 + 0.5 * xx2}" y="14">${str2}</text>
+
11041. 7</g>
+
11042. 7</svg>
+
11043. 7 `).trim() + "\n"));
+
11044. 7 pathname = "";
+
11045. 7 }
+
11046. 19 txt += (
+
11047. 19 "| "
+
11048. 19 + String("./" + pathname).padEnd(padPathname, " ") + " | "
+
11049. 19 + String(
+
11050. 19 modeCoverageIgnoreFile + " " + coveragePct + " %"
+
11051. 19 ).padStart(padLines, " ") + " | "
+
11052. 19 + " ".repeat(padLines) + " |\n"
+
11053. 19 );
+
11054. 19 txt += (
+
11055. 19 "| " + "*".repeat(
+
11056. 19 Math.round(0.01 * coveragePct * padPathname)
+
11057. 19 ).padEnd(padPathname, "_") + " | "
+
11058. 19 + String(
+
11059. 19 linesCovered + " / " + linesTotal
+
11060. 19 ).padStart(padLines, " ") + " | "
+
11061. 19 + String(
+
11062. 19 (linesTotal - linesCovered) + " / " + linesTotal
+
11063. 19 ).padStart(padLines, " ") + " |\n"
+
11064. 19 );
+
11065. 19 txt += txtBorder;
+
11066. 19 pathname = htmlEscape(pathname);
+
11067. 19
+
11068. 19// CL-37251d17 - Bugfix - Fix incorrect http-link to index.html.
+
11069. 19
+
11070. 19 html += String(`
+
11071. 19 <tr>
+
11072. 19 <td class="${coverageLevel}">
+
11073. 19 ${(
+
11074. 19 modeIndex
+
11075. 13 ? (
+
11076. 13 "<a href=\"" + (pathname || "index") + ".html\">. / "
+
11077. 13 + pathname + "</a><br>"
+
11078. 13 )
+
11079. 6 : (
+
11080. 6 "<a href=\""
+
11081. 6 + "../".repeat(pathname.split("/").length - 1)
+
11082. 6 + "index.html\">. / </a>"
+
11083. 6 + pathname + "<br>"
+
11084. 6 )
+
11085. 19 )}
+
11086. 19 <div class="percentbar">
+
11087. 19 <div style="width: ${coveragePct}%;"></div>
+
11088. 19 </div>
+
11089. 19 </td>
+
11090. 19 <td style="text-align: right;">
+
11091. 19 ${modeCoverageIgnoreFile} ${coveragePct} %<br>
+
11092. 19 ${linesCovered} / ${linesTotal}
+
11093. 19 </td>
+
11094. 19 <td style="text-align: right;">
+
11095. 19 <br>
+
11096. 19 ${linesTotal - linesCovered} / ${linesTotal}
+
11097. 19 </td>
+
11098. 19 </tr>
+
11099. 19 `).trim() + "\n";
+
11100. 19 });
+
11101. 13 html += String(`
+
11102. 13</tbody>
+
11103. 13</table>
+
11104. 13</div>
+
11105. 13<!-- header end -->
+
11106. 13 `).trim() + "\n";
+
11107. 6 if (!modeIndex) {
+
11108. 6 html += String(`
+
11109. 6<!-- content start -->
+
11110. 6<div class="content">
+
11111. 6 `).trim() + "\n";
+
11112. 11853 lineList.forEach(function ({
+
11113. 11853 count,
+
11114. 11853 holeList,
+
11115. 11853 line,
+
11116. 11853 startOffset
+
11117. 11853 }, ii) {
+
11118. 11853 let chunk;
+
11119. 11853 let inHole;
+
11120. 11853 let lineHtml;
+
11121. 11853 let lineId;
+
11122. 11853 lineHtml = "";
+
11123. 11853 lineId = "line_" + (ii + 1);
+
11124. 11853 switch (count) {
+
11125. 32 case -1:
+
11126. 11219 case 0:
+
11127. 11219 if (holeList.length === 0) {
+
11128. 11219 lineHtml += "</span>";
+
11129. 11219 lineHtml += "<span class=\"uncovered\">";
+
11130. 11219 lineHtml += htmlEscape(line);
+
11131. 11219 break;
+
11132. 11219 }
+
11133. 11219 line = line.split("").map(function (char) {
+
11134. 11219 return {
+
11135. 11219 char,
+
11136. 11219 isHole: undefined
+
11137. 11219 };
+
11138. 11219 });
+
11139. 11219 holeList.forEach(function ([
+
11140. 11219 aa, bb
+
11141. 11219 ]) {
+
11142. 11219 aa = Math.max(aa - startOffset, 0);
+
11143. 11219 bb = Math.min(bb - startOffset, line.length);
+
11144. 11219 while (aa < bb) {
+
11145. 11219 line[aa].isHole = true;
+
11146. 11219 aa += 1;
+
11147. 11219 }
+
11148. 11219 });
+
11149. 11219 chunk = "";
+
11150. 11219 line.forEach(function ({
+
11151. 11219 char,
+
11152. 11219 isHole
+
11153. 11219 }) {
+
11154. 11219 if (inHole !== isHole) {
+
11155. 11219 lineHtml += htmlEscape(chunk);
+
11156. 11219 lineHtml += "</span><span";
+
11157. 11219
+
11158. 11219// Coverage-hack - Ugly-hack around possible deadcode where isHole is always
+
11159. 11219// true.
+
11160. 11219
+
11161. 11219 if (isHole) {
+
11162. 11219 lineHtml += " class=\"uncovered\"";
+
11163. 11219 }
+
11164. 11219 lineHtml += ">";
+
11165. 11219 chunk = "";
+
11166. 11219 inHole = isHole;
+
11167. 11219 }
+
11168. 11219 chunk += char;
+
11169. 11219 });
+
11170. 11219 lineHtml += htmlEscape(chunk);
+
11171. 11219 break;
+
11172. 634 default:
+
11173. 634 lineHtml += htmlEscape(line);
+
11174. 11853 }
+
11175. 11853 html += String(`
+
11176. 11853<pre>
+
11177. 11853<span class="lineno">
+
11178. 11853<a href="#${lineId}" id="${lineId}">${String(ii + 1).padStart(5, " ")}.</a>
+
11179. 11853</span>
+
11180. 11853<span class="count
+
11181. 11853 ${(
+
11182. 11853 count <= 0
+
11183. 11219 ? "uncovered"
+
11184. 634 : ""
+
11185. 11853 )}"
+
11186. 11853>
+
11187. 11187${String(count || "-0").padStart(7, " ")}
+
11188. 11853</span>
+
11189. 11853<span>${lineHtml}</span>
+
11190. 11853</pre>
+
11191. 11853 `).replace((
+
11192. 11853 /\n/g
+
11193. 11853 ), "").trim() + "\n";
+
11194. 11853 });
+
11195. 6 html += String(`
+
11196. 6</div>
+
11197. 6<!-- content end -->
+
11198. 6 `).trim() + "\n";
+
11199. 6 }
+
11200. 13 html += String(`
+
11201. 13<div class="footer">
+
11202. 13 [
+
11203. 13 This document was created with
+
11204. 13 <a href="https://github.com/jslint-org/jslint">JSLint</a>
+
11205. 13 ]
+
11206. 13</div>
+
11207. 13</body>
+
11208. 13</html>
+
11209. 13 `).trim() + "\n";
+
11210. 13
+
11211. 13// Fs - write <file>.html.
+
11212. 13
+
11213. 13 promiseList.push(fsWriteFileWithParents(pathname + ".html", html));
+
11214. 6 if (!modeIndex) {
+
11215. 6 return;
+
11216. 7 }
+
11217. 7
+
11218. 7// Fs - write coverage_report.txt.
+
11219. 7
+
11220. 7 consoleError("\n" + txt);
+
11221. 7 promiseList.push(fsWriteFileWithParents((
+
11222. 7 coverageDir + "coverage_report.txt"
+
11223. 7 ), txt));
+
11224. 7 }
+
11225. 8
+
11226. 8/*
+
11227. 8function sentinel() {}
+
11228. 8*/
+
11229. 8
+
11230. 8 await moduleFsInit();
+
11231. 1 consoleError = consoleError || console.error;
+
11232. 8 cwd = process.cwd().replace((
+
11233. 8 /\\/g
+
11234. 8 ), "/") + "/";
+
11235. 8
+
11236. 8// Init coverageDir.
+
11237. 8// Assert coverageDir is subdirectory of cwd.
+
11238. 8
+
11239. 8 assertOrThrow(coverageDir, "invalid coverageDir " + coverageDir);
+
11240. 8
+
11241. 8// CL-61b11012 - coverage - Relax requirement for coverageDir to be in cwd.
+
11242. 8// assertOrThrow(
+
11243. 8// pathnameRelativeCwd(coverageDir),
+
11244. 8// "coverageDir " + coverageDir + " is not subdirectory of cwd " + cwd
+
11245. 8// );
+
11246. 8
+
11247. 8 coverageDir = modulePath.resolve(coverageDir).replace((
+
11248. 8 /\\/g
+
11249. 8 ), "/") + "/";
+
11250. 8
+
11251. 8 processArgv = processArgv.slice();
+
11252. 9 while (processArgv[0] && processArgv[0][0] === "-") {
+
11253. 3 processArgElem = processArgv.shift().split("=");
+
11254. 3 processArgElem[1] = processArgElem.slice(1).join("=");
+
11255. 3 switch (processArgElem[0]) {
+
11256. 3
+
11257. 3// PR-371 - Add cli-option `--exclude=...`.
+
11258. 3
+
11259. 3 case "--exclude":
+
11260. 3 excludeList.push(processArgElem[1]);
+
11261. 3 break;
+
11262. 3
+
11263. 3// PR-371 - Add cli-option `--include=...`
+
11264. 3
+
11265. 3 case "--include":
+
11266. 3 includeList.push(processArgElem[1]);
+
11267. 3 break;
+
11268. 3
+
11269. 3// PR-400
+
11270. 3// Disable default-coverage of directory `node_modules`,
+
11271. 3// but allow override with cli-option `--include-node-modules=1`.
+
11272. 3
+
11273. 3 case "--include-node-modules":
+
11274. 3 modeIncludeNodeModules = !(
+
11275. 3 /0|false|null|undefined/
+
11276. 3 ).test(processArgElem[1]);
+
11277. 3 break;
+
11278. 3 }
+
11279. 7 }
+
11280. 7
+
11281. 7// 1. Spawn node.js program <processArgv> with coverage
+
11282. 7
+
11283. 7 if (processArgv.length > 0) {
+
11284. 6
+
11285. 6// Remove old coverage-files.
+
11286. 6
+
11287. 6 await fsWriteFileWithParents(coverageDir + "/touch.txt", "");
+
11288. 6 await Promise.all(Array.from(
+
11289. 6 await moduleFs.promises.readdir(coverageDir)
+
11290. 11 ).map(async function (file) {
+
11291. 11 if ((
+
11292. 11 /^coverage-\d+?-\d+?-\d+?\.json$/
+
11293. 6 ).test(file)) {
+
11294. 6 consoleError("rm file " + coverageDir + file);
+
11295. 6 await moduleFs.promises.unlink(coverageDir + file);
+
11296. 6 }
+
11297. 11 }));
+
11298. 6 exitCode = await new Promise(function (resolve) {
+
11299. 6 let processArgv0 = processArgv[0];
+
11300. 6
+
11301. 6// If win32 environment, then replace program npm with npm.cmd.
+
11302. 6// Coverage-hack - Ugly-hack to get test-coverage under both win32 and linux.
+
11303. 6
+
11304. 6 if (processArgv0 === "npm") {
+
11305. 6 processArgv0 = process.platform.replace(
+
11306. 6 "win32",
+
11307. 6 "npm.cmd"
+
11308. 6 ).replace(
+
11309. 6 process.platform,
+
11310. 6 "npm"
+
11311. 6 );
+
11312. 6 }
+
11313. 6 moduleChildProcess.spawn(
+
11314. 6 processArgv0,
+
11315. 6 processArgv.slice(1),
+
11316. 6 {
+
11317. 6 env: Object.assign({}, process.env, {
+
11318. 6 NODE_V8_COVERAGE: coverageDir
+
11319. 6 }),
+
11320. 6
+
11321. 6// PR-465
+
11322. 6// https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2
+
11323. 6// Node.js will now error with EINVAL if a .bat or .cmd file is passed to
+
11324. 6// child_process.spawn and child_process.spawnSync without the shell option set.
+
11325. 6
+
11326. 6 shell: (
+
11327. 6 processArgv0.endsWith(".bat")
+
11328. 6 || processArgv0.endsWith(".cmd")
+
11329. 6 ),
+
11330. 6 stdio: ["ignore", 1, 2]
+
11331. 6 }
+
11332. 6 ).on("exit", resolve);
+
11333. 6 });
+
11334. 6 consoleError(
+
11335. 6 `v8CoverageReportCreate - program exited with exitCode=${exitCode}`
+
11336. 6 );
+
11337. 7 }
+
11338. 7
+
11339. 7// 2. Merge JSON v8-coverage-files in <coverageDir>.
+
11340. 7
+
11341. 7 consoleError("v8CoverageReportCreate - merging coverage files...");
+
11342. 7 v8CoverageObj = await moduleFs.promises.readdir(coverageDir);
+
11343. 18 v8CoverageObj = v8CoverageObj.filter(function (file) {
+
11344. 18 return (
+
11345. 18 /^coverage-\d+?-\d+?-\d+?\.json$/
+
11346. 18 ).test(file);
+
11347. 18 });
+
11348. 7 v8CoverageObj = await Promise.all(v8CoverageObj.map(async function (file) {
+
11349. 7 let data;
+
11350. 7 let pathnameDict = Object.create(null);
+
11351. 7 data = await moduleFs.promises.readFile(coverageDir + file, "utf8");
+
11352. 7 data = JSON.parse(data);
+
11353. 473 data.result.forEach(function (scriptCov) {
+
11354. 473 let pathname = scriptCov.url;
+
11355. 473
+
11356. 473// Filter out internal coverages.
+
11357. 473
+
11358. 393 if (!pathname.startsWith("file:///")) {
+
11359. 393 return;
+
11360. 393 }
+
11361. 80
+
11362. 80// Normalize pathname.
+
11363. 80
+
11364. 80 pathname = moduleUrl.fileURLToPath(pathname);
+
11365. 80 pathname = modulePath.resolve(pathname).replace((
+
11366. 80 /\\/g
+
11367. 80 ), "/");
+
11368. 80
+
11369. 80// Filter files outside of cwd.
+
11370. 80
+
11371. 80 if (pathname.indexOf("[") >= 0 || !pathname.startsWith(cwd)) {
+
11372. 74 return;
+
11373. 74 }
+
11374. 7
+
11375. 7// Normalize pathname relative to cwd.
+
11376. 7
+
11377. 7 pathname = pathname.slice(cwd.length);
+
11378. 7 scriptCov.url = pathname;
+
11379. 7 pathnameDict[pathname] = scriptCov;
+
11380. 7 });
+
11381. 7
+
11382. 7// PR-400 - Filter directory `node_modules`.
+
11383. 7
+
11384. 7 if (!modeIncludeNodeModules) {
+
11385. 7 excludeList.push("node_modules/");
+
11386. 7 }
+
11387. 7
+
11388. 7// PR-400 - Filter files by glob-patterns in excludeList, includeList.
+
11389. 7
+
11390. 7 data.result = globExclude({
+
11391. 7 excludeList,
+
11392. 7 includeList,
+
11393. 7 pathnameList: Object.keys(pathnameDict)
+
11394. 7 }).pathnameList.map(function (pathname) {
+
11395. 7 return pathnameDict[pathname];
+
11396. 7 });
+
11397. 7 return data;
+
11398. 7 }));
+
11399. 7
+
11400. 7// Merge v8CoverageObj.
+
11401. 7
+
11402. 7 v8CoverageObj = v8CoverageListMerge(v8CoverageObj);
+
11403. 7
+
11404. 7// Debug v8CoverageObj.
+
11405. 7
+
11406. 7 await fsWriteFileWithParents(
+
11407. 7 coverageDir + "v8_coverage_merged.json",
+
11408. 7 JSON.stringify(v8CoverageObj, undefined, 1)
+
11409. 7 );
+
11410. 7
+
11411. 7// 3. Create html-coverage-reports in <coverageDir>.
+
11412. 7
+
11413. 7 consoleError("v8CoverageReportCreate - creating html-coverage-report...");
+
11414. 7 fileDict = Object.create(null);
+
11415. 7 await Promise.all(v8CoverageObj.result.map(async function ({
+
11416. 7 functions,
+
11417. 7 url: pathname
+
11418. 7 }) {
+
11419. 7 let lineList;
+
11420. 7 let linesCovered;
+
11421. 7 let linesTotal;
+
11422. 7 let source;
+
11423. 7 source = await moduleFs.promises.readFile(pathname, "utf8");
+
11424. 7 lineList = [{}];
+
11425. 7 source.replace((
+
11426. 7 /^.*$/gm
+
11427. 11853 ), function (line, startOffset) {
+
11428. 11853 lineList[lineList.length - 1].endOffset = startOffset - 1;
+
11429. 11853 lineList.push({
+
11430. 11853 count: -1,
+
11431. 11853 endOffset: 0,
+
11432. 11853 holeList: [],
+
11433. 11853 line,
+
11434. 11853 startOffset
+
11435. 11853 });
+
11436. 11853 return "";
+
11437. 11853 });
+
11438. 7 lineList.shift();
+
11439. 7 lineList[lineList.length - 1].endOffset = source.length;
+
11440. 41 functions.reverse().forEach(function ({
+
11441. 41 ranges
+
11442. 41 }) {
+
11443. 65 ranges.reverse().forEach(function ({
+
11444. 65 count,
+
11445. 65 endOffset,
+
11446. 65 startOffset
+
11447. 65 }, ii, list) {
+
11448. 580047 lineList.forEach(function (elem) {
+
11449. 580047 if (!(
+
11450. 580047 (
+
11451. 580047 elem.startOffset <= startOffset
+
11452. 205728 && startOffset <= elem.endOffset
+
11453. 579982 ) || (
+
11454. 579982 elem.startOffset <= endOffset
+
11455. 579982 && endOffset <= elem.endOffset
+
11456. 579982 ) || (
+
11457. 579926 startOffset <= elem.startOffset
+
11458. 579926 && elem.endOffset <= endOffset
+
11459. 579926 )
+
11460. 556497 )) {
+
11461. 556497 return;
+
11462. 556497 }
+
11463. 23550
+
11464. 23550// Handle tree-root.
+
11465. 23550
+
11466. 23550 if (ii + 1 === list.length) {
+
11467. 23281 if (elem.count === -1) {
+
11468. 23281 elem.count = count;
+
11469. 23281 }
+
11470. 23281 return;
+
11471. 23281 }
+
11472. 269
+
11473. 269// Handle tree-children.
+
11474. 269
+
11475. 269 if (elem.count !== 0) {
+
11476. 170 elem.count = Math.max(count, elem.count);
+
11477. 269 }
+
11478. 269 if (count === 0) {
+
11479. 203 elem.count = 0;
+
11480. 203 elem.holeList.push([
+
11481. 203 startOffset, endOffset
+
11482. 203 ]);
+
11483. 203 }
+
11484. 580047 });
+
11485. 65 });
+
11486. 41 });
+
11487. 7 linesTotal = lineList.length;
+
11488. 11853 linesCovered = lineList.filter(function ({
+
11489. 11853 count
+
11490. 11853 }) {
+
11491. 11853 return count > 0;
+
11492. 11853 }).length;
+
11493. 7 await moduleFs.promises.mkdir((
+
11494. 7 modulePath.dirname(coverageDir + pathname)
+
11495. 7 ), {
+
11496. 7 recursive: true
+
11497. 7 });
+
11498. 7 fileDict[pathname] = {
+
11499. 7 lineList,
+
11500. 7 linesCovered,
+
11501. 7 linesTotal,
+
11502. 7 modeCoverageIgnoreFile: (
+
11503. 7 (
+
11504. 7 /^\/\*coverage-ignore-file\*\/$/m
+
11505. 7 ).test(source.slice(0, 65536))
+
11506. 7 ? "(ignore)"
+
11507. 7 : ""
+
11508. 7 ),
+
11509. 7 pathname
+
11510. 7 };
+
11511. 7 htmlRender({
+
11512. 7 fileList: [
+
11513. 7 fileDict[pathname]
+
11514. 7 ],
+
11515. 7 lineList,
+
11516. 7 pathname: coverageDir + pathname
+
11517. 7 });
+
11518. 7 }));
+
11519. 7 htmlRender({
+
11520. 7 fileList: Object.keys(fileDict).sort().map(function (pathname) {
+
11521. 7 return fileDict[pathname];
+
11522. 7 }),
+
11523. 7 modeIndex: true,
+
11524. 7 pathname: coverageDir + "index"
+
11525. 7 });
+
11526. 7 await Promise.all(promiseList);
+
11527. 7 assertOrThrow(
+
11528. 7 exitCode === 0,
+
11529. 7 "v8CoverageReportCreate - nonzero exitCode " + exitCode
+
11530. 7 );
+
11531. 7}
+
11532. 1
+
11533. 1/*
+
11534. 1function sentinel() {}
+
11535. 1*/
+
11536. 1
+
11537. 1// Export jslint as cjs/esm.
+
11538. 1
+
11539. 1jslint_export = Object.freeze(Object.assign(jslint, {
+
11540. 1 assertErrorThrownAsync,
+
11541. 1 assertJsonEqual,
+
11542. 1 assertOrThrow,
+
11543. 1 debugInline,
+
11544. 1 fsWriteFileWithParents,
+
11545. 1 globExclude,
+
11546. 1 htmlEscape,
+
11547. 1 jslint,
+
11548. 1 jslint_apidoc,
+
11549. 1 jslint_assert,
+
11550. 1 jslint_charset_ascii,
+
11551. 1 jslint_cli,
+
11552. 1 jslint_edition,
+
11553. 1 jslint_phase1_split,
+
11554. 1 jslint_phase2_lex,
+
11555. 1 jslint_phase3_parse,
+
11556. 1 jslint_phase4_walk,
+
11557. 1 jslint_phase5_whitage,
+
11558. 1 jslint_report,
+
11559. 1 jstestDescribe,
+
11560. 1 jstestIt,
+
11561. 1 jstestOnExit,
+
11562. 1 moduleFsInit,
+
11563. 1 noop,
+
11564. 1 objectDeepCopyWithKeysSorted,
+
11565. 1 v8CoverageListMerge,
+
11566. 1 v8CoverageReportCreate
+
11567. 1}));
+
11568. 1// module.exports = jslint_export; // Export jslint as cjs.
+
11569. 1export default Object.freeze(jslint_export); // Export jslint as esm.
+
11570. 1jslint_import_meta_url = import.meta.url;
+
11571. 1
+
11572. 1// Run jslint_cli.
+
11573. 1jslint_cli({});
+
11574. 1
+
+
+
+
+
diff --git a/.artifact/coverage/jslint_wrapper_cjs.cjs.html b/.artifact/coverage/jslint_wrapper_cjs.cjs.html
new file mode 100644
index 000000000..7e2512946
--- /dev/null
+++ b/.artifact/coverage/jslint_wrapper_cjs.cjs.html
@@ -0,0 +1,217 @@
+
+
+
+