├── .ci.sh ├── .gitconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── website_issue.md └── workflows │ ├── ci.yml │ ├── on_pull_request.yml │ └── publish.yml ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── asset_codemirror_rollup.js ├── asset_font_daley_bold.woff2 ├── asset_image_folder_open_solid.svg ├── asset_image_github_brands.svg ├── asset_image_jslint_wrapper_vim.png ├── asset_image_jslint_wrapper_vscode.png ├── asset_image_json_160.svg ├── asset_image_logo_256.html ├── asset_image_logo_256.png ├── asset_image_logo_256.svg ├── index.html ├── jslint.mjs ├── jslint_ci.sh ├── jslint_wrapper_cjs.cjs ├── jslint_wrapper_codemirror.html ├── jslint_wrapper_codemirror.js ├── jslint_wrapper_vim.vim ├── jslint_wrapper_vscode.js ├── package.json ├── test.mjs └── test_coverage_merge_data.json /.ci.sh: -------------------------------------------------------------------------------- 1 | shCiArtifactUploadCustom() {(set -e 2 | # this function will run custom-code to upload build-artifacts 3 | # .github_cache - restore 4 | if [ "$GITHUB_ACTION" ] && [ -d .github_cache ] 5 | then 6 | cp -a .github_cache/* . || true # js-hack - */ 7 | fi 8 | # add jslint.js 9 | cp jslint.mjs jslint.js 10 | git add -f jslint.js 11 | # seo - inline css-assets and invalidate cached-assets 12 | node --input-type=module --eval ' 13 | import moduleFs from "fs"; 14 | (async function () { 15 | let cacheKey = Math.random().toString(36).slice(-4); 16 | let fileDict = {}; 17 | await Promise.all([ 18 | "index.html" 19 | ].map(async function (file) { 20 | try { 21 | fileDict[file] = await moduleFs.promises.readFile(file, "utf8"); 22 | } catch (ignore) { 23 | process.exit(); 24 | } 25 | })); 26 | // invalidate cached-assets 27 | fileDict["index.html"] = fileDict["index.html"].replace(( 28 | /\b(?:href|src)=".+?\.(?:css|js|mjs)\b/g 29 | ), function (match0) { 30 | return `${match0}?cc=${cacheKey}`; 31 | }); 32 | // write file 33 | Object.entries(fileDict).map(function ([ 34 | file, data 35 | ]) { 36 | moduleFs.promises.writeFile(file, data); 37 | }); 38 | }()); 39 | ' "$@" # ' 40 | # screenshot quickstart 41 | node --input-type=module --eval ' 42 | import moduleFs from "fs"; 43 | import moduleChildProcess from "child_process"; 44 | (async function () { 45 | let fileDict = {}; 46 | let screenshotCurl; 47 | await Promise.all([ 48 | "README.md" 49 | ].map(async function (file) { 50 | fileDict[file] = await moduleFs.promises.readFile(file, "utf8"); 51 | })); 52 | screenshotCurl = await moduleFs.promises.stat("jslint.mjs"); 53 | screenshotCurl = String(` 54 | echo "\ 55 | % Total % Received % Xferd Average Speed Time Time Time Current 56 | Dload Upload Total Spent Left Speed 57 | 100 250k 100 250k 0 0 250k 0 0:00:01 --:--:-- 0:00:01 250k\ 58 | " 59 | `).trim().replace(( 60 | /250/g 61 | ), Math.floor(screenshotCurl.size / 1024)); 62 | // parallel-task - run-and-screenshot example-shell-commands in README.md 63 | await Promise.all(Array.from( 64 | fileDict["README.md"].matchAll( 65 | /\n```shell \n([\S\s]*?\n)```\n/g 66 | ) 67 | ).map(async function ([ 68 | ignore, file, script0 69 | ]) { 70 | let script = script0; 71 | // modify script - jslint install 72 | script = script.replace( 73 | "curl -L https://www.jslint.com/jslint.mjs > jslint.mjs", 74 | screenshotCurl 75 | ); 76 | // modify script - cd node-sqlite3 77 | script = script.replace(( 78 | /\n\ncd node-sqlite3-\w*?\n/g 79 | ), ( 80 | " 2>/dev/null || true\n" 81 | + "$&\n" 82 | + "git checkout 61194ec2aee4b56e8e17f757021434122772f145\n" 83 | )); 84 | // printf script 85 | script = ( 86 | "(set -e\n" 87 | + "printf \u0027" 88 | + script0.trim().replace(( 89 | /[%\\]/gm 90 | ), "$&$&").replace(( 91 | /\u0027/g 92 | ), "\u0027\"\u0027\"\u0027").replace(( 93 | /^/gm 94 | ), "> ") 95 | + "\n\n\n\u0027\n" 96 | + script 97 | + ")\n" 98 | ); 99 | await moduleFs.promises.writeFile(file + ".sh", script); 100 | await new Promise(function (resolve) { 101 | moduleChildProcess.spawn( 102 | "sh", 103 | [ 104 | "jslint_ci.sh", "shRunWithScreenshotTxt", file, 105 | "sh", file + ".sh" 106 | ], 107 | { 108 | env: Object.assign({ 109 | // limit stdout to xxx lines 110 | SH_RUN_WITH_SCREENSHOT_TXT_MAX_LINES: 64 111 | }, process.env), 112 | stdio: ["ignore", 1, 2] 113 | } 114 | ).on("exit", resolve); 115 | }); 116 | })); 117 | }()); 118 | ' "$@" # ' 119 | # background http-file-server to serve webpages for screenshot 120 | # PORT=8080 npm_config_timeout_exit=5000 shHttpFileServer & 121 | # screenshot html 122 | node --input-type=module --eval ' 123 | import moduleChildProcess from "child_process"; 124 | (async function () { 125 | let { 126 | GITHUB_BRANCH0, 127 | GITHUB_GITHUB_IO 128 | } = process.env; 129 | await Promise.all([ 130 | ( 131 | `https://${GITHUB_GITHUB_IO}/branch-${GITHUB_BRANCH0}` 132 | + `/jslint_wrapper_codemirror.html` 133 | ), 134 | ( 135 | `https://${GITHUB_GITHUB_IO}/branch-${GITHUB_BRANCH0}` 136 | + `/index.html` 137 | ), 138 | ".artifact/apidoc.html", 139 | ".artifact/coverage_sqlite3_js/index.html", 140 | ".artifact/coverage_sqlite3_js/lib/sqlite3.js.html", 141 | ".artifact/coverage_sqlite3_sh/index.html", 142 | ".artifact/coverage_sqlite3_sh/lib/sqlite3.js.html", 143 | ".artifact/jslint_report_hello.html" 144 | ].map(async function (url) { 145 | await new Promise(function (resolve) { 146 | moduleChildProcess.spawn( 147 | "sh", 148 | ["jslint_ci.sh", "shBrowserScreenshot", url], 149 | {stdio: ["ignore", 1, 2]} 150 | ).on("exit", resolve); 151 | }); 152 | })); 153 | }()); 154 | ' "$@" # ' 155 | # remove bloated json-coverage-files 156 | rm .artifact/coverage/*.json # js-hack - */ 157 | rm .artifact/coverage_sqlite3_*/*.json # js-hack - */ 158 | # jslint_wrapper_vscode - build 159 | shCiVscePackageJslintWrapperVscode 160 | # .github_cache - save 161 | if [ "$GITHUB_ACTION" ] && [ ! -d .github_cache ] 162 | then 163 | mkdir -p .github_cache 164 | cp -a node-sqlite3-* .github_cache 165 | fi 166 | )} 167 | 168 | shCiBaseCustom() {(set -e 169 | # this function will run custom-code for base-ci 170 | # update files 171 | if [ "$(git branch --show-current)" = alpha ] 172 | then 173 | node --input-type=module --eval ' 174 | import jslint from "./jslint.mjs"; 175 | import moduleFs from "fs"; 176 | (async function () { 177 | let fileDict = {}; 178 | let fileModified; 179 | let versionBeta; 180 | let versionMaster; 181 | await Promise.all([ 182 | ".ci.sh", 183 | "CHANGELOG.md", 184 | "README.md", 185 | "index.html", 186 | "jslint.mjs", 187 | "jslint_ci.sh", 188 | "jslint_wrapper_codemirror.html" 189 | ].map(async function (file) { 190 | fileDict[file] = await moduleFs.promises.readFile(file, "utf8"); 191 | })); 192 | Array.from(fileDict["CHANGELOG.md"].matchAll( 193 | /\n\n# v(\d\d\d\d\.\d\d?\.\d\d?(-.*?)?)\n/g 194 | )).slice(0, 2).forEach(function ([ 195 | ignore, version, isBeta 196 | ]) { 197 | versionBeta = versionBeta || version; 198 | versionMaster = versionMaster || (!isBeta && version); 199 | }); 200 | await Promise.all([ 201 | { 202 | file: ".ci.sh", 203 | // update version 204 | src: fileDict[".ci.sh"].replace(( 205 | / "version": "\d\d\d\d\.\d\d?\.\d\d?(?:-.*?)?"/ 206 | ), ` "version": "${versionBeta.split("-")[0]}"`) 207 | }, { 208 | file: "README.md", 209 | src: fileDict["README.md"].replace(( 210 | /\n```html \n[\S\s]*?\n```\n/ 211 | ), ( 212 | "\n```html \n" 213 | + fileDict["jslint_wrapper_codemirror.html"] 214 | + "```\n" 215 | )) 216 | }, { 217 | file: "index.html", 218 | src: fileDict["index.html"].replace(( 219 | /\n 427 | 428 | 429 | 430 | 431 |

CodeMirror: JSLint Demo

432 |

433 | This demo will auto-lint the code below, and auto-generate a report as you type. 434 |

435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 |
443 | 444 | 445 | 497 | 498 | 499 | ``` 500 | 3. Live example at https://www.jslint.com/jslint_wrapper_codemirror.html 501 | 502 | [![screenshot](https://jslint-org.github.io/jslint/branch-beta/.artifact/screenshot_browser__2fjslint_2fbranch-beta_2fjslint_wrapper_codemirror.html.png)](https://jslint-org.github.io/jslint/jslint_wrapper_codemirror.html) 503 | 504 | 505 |

506 | # Quickstart JSLint in Vim 507 | 1. Download and save [`jslint.mjs`](https://www.jslint.com/jslint.mjs), [`jslint_wrapper_vim.vim`](https://www.jslint.com/jslint_wrapper_vim.vim) to directory `~/.vim/` 508 | 2. Add vim-command `:source ~/.vim/jslint_wrapper_vim.vim` to file `~/.vimrc` 509 | - If above files were saved to custom-directory, then use that directory instead, e.g.: 510 | - save [`jslint.mjs`](https://www.jslint.com/jslint.mjs), [`jslint_wrapper_vim.vim`](https://www.jslint.com/jslint_wrapper_vim.vim) to directory `~/vimfiles/` 511 | - vim-command `:source ~/vimfiles/jslint_wrapper_vim.vim` 512 | 3. Vim can now jslint files (via nodejs): 513 | - with vim-command `:SaveAndJslint` 514 | - with vim-key-combo ` ` 515 | - screenshot 516 | 517 | [![screenshot](asset_image_jslint_wrapper_vim.png)](https://www.jslint.com/jslint_wrapper_vim.vim) 518 | 519 | 520 |

521 | # Quickstart JSLint in VSCode 522 | 1. In VSCode, search and install extension [`vscode-jslint`](https://marketplace.visualstudio.com/items?itemName=jslint.vscode-jslint) 523 | 2. In VSCode, while editing a javascript file: 524 | - right-click context-menu and select `[JSLint - Lint File]` 525 | - or use key-binding `[Ctrl + Shift + J], [L]` 526 | - or use key-binding `[ Cmd + Shift + J], [L]` for Mac 527 | - screenshot 528 | 529 | [![screenshot](https://jslint-org.github.io/jslint/asset_image_jslint_wrapper_vscode.png)](https://marketplace.visualstudio.com/items?itemName=jslint.vscode-jslint) 530 | 531 | 532 |

533 | # Documentation 534 | 535 | 536 | - [jslint.mjs](jslint.mjs) contains the jslint function. It parses and analyzes a source file, returning an object with information about the file. It can also take an object that sets options. 537 | 538 | - [index.html](index.html) runs the jslint.mjs function in a web page. 539 | 540 | JSLint can be run anywhere that JavaScript (or Java) can run. 541 | 542 | The place to express yourself in programming is in the quality of your ideas and 543 | the efficiency of their execution. The role of style in programming is the same 544 | as in literature: It makes for better reading. A great writer doesn't express 545 | herself by putting the spaces before her commas instead of after, or by putting 546 | extra spaces inside her parentheses. A great writer will slavishly conform to 547 | some rules of style, and that in no way constrains her power to express herself 548 | creatively. See for example William Strunk's The Elements of Style 549 | [https://www.crockford.com/style.html]. 550 | 551 | This applies to programming as well. Conforming to a consistent style improves 552 | readability, and frees you to express yourself in ways that matter. JSLint here 553 | plays the part of a stern but benevolent editor, helping you to get the style 554 | right so that you can focus your creative energy where it is most needed. 555 | 556 | 557 |

558 | ### API Doc 559 | - https://www.jslint.com/apidoc.html 560 | 561 | [![screenshot](https://jslint-org.github.io/jslint/branch-beta/.artifact/screenshot_browser__2f.artifact_2fapidoc.html.png)](https://www.jslint.com/apidoc.html) 562 | 563 | 564 |

565 | ### Directive `/*jslint*/` 566 | 567 |
568 | 569 | ##### `/*jslint beta*/` 570 | 571 | ```js 572 | /*jslint beta*/ 573 | // Enable experimental warnings. 574 | // Warn if global variables are redefined. 575 | // Warn if const / let statements are not declared at top of function or 576 | // script, similar to var statements. 577 | // Warn if const / let / var statements are not declared in ascii-order. 578 | // Warn if named-functions are not declared in ascii-order. 579 | // Warn if cases in switch-statements are not in ascii-order. 580 | ``` 581 | 582 |
583 | 584 | ##### `/*jslint bitwise*/` 585 | 586 | ```js 587 | /*jslint bitwise*/ 588 | // Allow bitwise operator. 589 | 590 | let foo = 0 | 1; 591 | ``` 592 | 593 |
594 | 595 | ##### `/*jslint browser*/` 596 | 597 | ```js 598 | /*jslint browser*/ 599 | // Assume browser environment. 600 | 601 | localStorage.getItem("foo"); 602 | ``` 603 | 604 |
605 | 606 | ##### `/*jslint convert*/` 607 | 608 | ```js 609 | /*jslint convert*/ 610 | // Allow conversion operator. 611 | 612 | let foo = new Date() + ""; 613 | let bar = !!0; 614 | ``` 615 | 616 |
617 | 618 | ##### `/*jslint couch*/` 619 | 620 | ```js 621 | /*jslint couch*/ 622 | // Assume CouchDb environment. 623 | 624 | registerType("text-json", "text/json"); 625 | ``` 626 | 627 |
628 | 629 | ##### `/*jslint devel*/` 630 | 631 | ```js 632 | /*jslint devel*/ 633 | // Allow console.log() and friends. 634 | 635 | console.log("hello"); 636 | ``` 637 | 638 |
639 | 640 | ##### `/*jslint eval*/` 641 | 642 | ```js 643 | /*jslint eval*/ 644 | // Allow eval(). 645 | 646 | eval("1"); 647 | ``` 648 | 649 |
650 | 651 | ##### `/*jslint fart*/` 652 | 653 | ```js 654 | /*jslint fart*/ 655 | // Allow complex fat-arrow. 656 | 657 | let foo = async ({bar, baz}) => { 658 | return await bar(baz); 659 | }; 660 | ``` 661 | 662 |
663 | 664 | ##### `/*jslint for*/` 665 | 666 | ```js 667 | /*jslint for*/ 668 | // Allow for-loop. 669 | 670 | function foo() { 671 | let ii; 672 | for (ii = 0; ii < 10; ii += 1) { 673 | foo(); 674 | } 675 | } 676 | ``` 677 | 678 |
679 | 680 | ##### `/*jslint getset*/` 681 | 682 | ```js 683 | /*jslint getset, this, devel*/ 684 | // Allow get() and set(). 685 | 686 | let foo = { 687 | bar: 0, 688 | get getBar() { 689 | return this.bar; 690 | }, 691 | set setBar(value) { 692 | this.bar = value; 693 | } 694 | }; 695 | console.log(foo.getBar); // 0 696 | foo.setBar = 1; 697 | console.log(foo.getBar); // 1 698 | ``` 699 | 700 |
701 | 702 | ##### `/*jslint indent2*/` 703 | 704 | ```js 705 | /*jslint indent2*/ 706 | // Use 2-space indent. 707 | 708 | function foo() { 709 | return; 710 | } 711 | ``` 712 | 713 |
714 | 715 | ##### `/*jslint long*/` 716 | 717 | ```js 718 | /*jslint long*/ 719 | // Allow long lines. 720 | 721 | let foo = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 722 | ``` 723 | 724 |
725 | 726 | ##### `/*jslint node*/` 727 | 728 | ```js 729 | /*jslint node*/ 730 | // Assume Node.js environment. 731 | 732 | require("fs"); 733 | ``` 734 | 735 |
736 | 737 | ##### `/*jslint nomen*/` 738 | 739 | ```js 740 | /*jslint nomen*/ 741 | // Allow weird property name. 742 | 743 | let foo = {}; 744 | foo._bar = 1; 745 | ``` 746 | 747 |
748 | 749 | ##### `/*jslint single*/` 750 | 751 | ```js 752 | /*jslint single*/ 753 | // Allow single-quote strings. 754 | 755 | let foo = ''; 756 | ``` 757 | 758 |
759 | 760 | ##### `/*jslint subscript*/` 761 | 762 | ```js 763 | /*jslint subscript*/ 764 | // Allow identifiers in subscript-notation. 765 | 766 | let foo = {}; 767 | foo["bar"] = 1; 768 | ``` 769 | 770 |
771 | 772 | ##### `/*jslint this*/` 773 | 774 | ```js 775 | /*jslint this*/ 776 | // Allow 'this'. 777 | 778 | function foo() { 779 | return this; 780 | } 781 | ``` 782 | 783 |
784 | 785 | ##### `/*jslint trace*/` 786 | 787 | ```js 788 | /*jslint trace*/ 789 | // Include jslint stack-trace in warnings. 790 | 791 | console.log('hello world'); 792 | /* 793 | 1. Undeclared 'console'. 794 | console.log('hello world'); 795 | Error 796 | at warn_at (...) 797 | at warn (...) 798 | at lookup (...) 799 | at pre_v (...) 800 | at jslint.mjs 801 | 2. Use double quotes, not single quotes. 802 | console.log(...); 803 | Error 804 | at warn_at (...) 805 | at lex_string (...) 806 | at lex_token (...) 807 | at jslint_phase2_lex (...) 808 | at Function.jslint (...) 809 | at jslint.mjs 810 | */ 811 | ``` 812 | 813 |
814 | 815 | ##### `/*jslint unordered*/` 816 | 817 | ```js 818 | /*jslint unordered*/ 819 | // Allow unordered cases, params, properties, variables, and exports. 820 | 821 | let foo = {bb: 1, aa: 0}; 822 | 823 | function bar({ 824 | bb = 1, 825 | aa = 0 826 | }) { 827 | return aa + bb; 828 | } 829 | 830 | export { 831 | foo, 832 | bar 833 | }; 834 | ``` 835 | 836 |
837 | 838 | ##### `/*jslint white*/` 839 | 840 | ```js 841 | /*jslint white*/ 842 | // Allow messy whitespace. 843 | 844 | let foo = 1; let bar = 2; 845 | ``` 846 | 847 | 848 |

849 | ### Directive `/*global*/` 850 | 851 | ```js 852 | /*global foo, bar*/ 853 | // Declare global variables foo, bar. 854 | 855 | foo(); 856 | bar(); 857 | ``` 858 | 859 | 860 |

861 | ### Directive `/*property*/` 862 | 863 | ```js 864 | /*property foo, bar*/ 865 | // Restrict property-access to only .foo, .bar. 866 | 867 | let aa = {bar: 1, foo: 2}; 868 | ``` 869 | 870 | 871 |

872 | ### Directive `/*jslint-disable*/.../*jslint-enable*/` 873 | 874 | ```js 875 | /*jslint-disable*/ 876 | 877 | JSLint will ignore and treat this region as blank-lines. 878 | Syntax error. 879 | 880 | /*jslint-enable*/ 881 | ``` 882 | 883 | 884 |

885 | ### Directive `//jslint-ignore-line` 886 | 887 | ```js 888 | // JSLint will ignore non-fatal warnings at given line. 889 | 890 | eval("1"); //jslint-ignore-line 891 | ``` 892 | 893 | 894 |

895 | # Package Listing 896 | ![screenshot_package_listing.svg](https://jslint-org.github.io/jslint/branch-beta/.artifact/screenshot_package_listing.svg) 897 | 898 | 899 |

900 | # Changelog 901 | - [Full CHANGELOG.md](CHANGELOG.md) 902 | 903 | ![screenshot_changelog.svg](https://jslint-org.github.io/jslint/branch-beta/.artifact/screenshot_changelog.svg) 904 | 905 | 906 |

907 | # License 908 | - JSLint is under [Unlicense License](LICENSE). 909 | - CodeMirror editor is under [MIT License](https://github.com/codemirror/codemirror5/blob/d0e3b2e727c41aa4fd89fbad0adfb3815339174c/LICENSE). 910 | - Function `v8CoverageListMerge` is derived from [MIT Licensed v8-coverage](https://github.com/demurgos/v8-coverage/blob/73446087dc38f61b09832c9867122a23f8577099/ts/LICENSE.md). 911 | 912 | 913 |

914 | # Devops Instruction 915 | 916 | 917 |

918 | ### pull-request merge 919 | - find highest issue-number at https://github.com/jslint-org/jslint/issues/, https://github.com/jslint-org/jslint/pulls/, and add +1 to it for PR-xxx 920 | - `shGitPullrequest beta beta` 921 | - verify ci-success for origin-branch-alpha 922 | - https://github.com/kaizhu256/jslint/actions 923 | - `git push upstream alpha -f` 924 | - verify ci-success for upstream-branch-alpha 925 | - https://github.com/jslint-org/jslint/actions 926 | - goto https://github.com/jslint-org/jslint/compare/beta...kaizhu256:jslint:branch-p2024.11.24 927 | - click `Create pull request` 928 | - input `Add your description here...` with: 929 | ``` 930 | Fixes #xxx. 931 | - 932 | 933 | This PR will ... 934 | 935 | This PR will additionally: 936 | - 937 | ... 938 | 939 | 940 | ``` 941 | - verify `commit into jslint-org:beta` 942 | - click `Create pull request` 943 | - verify ci-success for pull-request 944 | - https://github.com/jslint-org/jslint/actions/workflows/on_pull_request.yml 945 | - wait awhile before continuing ... 946 | - click `Rebase and merge` 947 | - verify ci-success for upstream-branch-beta 948 | - https://github.com/jslint-org/jslint/actions 949 | - `shGitPullrequestCleanup` 950 | - verify ci-success for origin-branch-alpha 951 | - https://github.com/kaizhu256/jslint/actions 952 | - `git push upstream alpha -f` 953 | - verify ci-success for upstream-branch-alpha 954 | - https://github.com/jslint-org/jslint/actions 955 | - click `Delete branch` 956 | 957 | 958 |

959 | ### branch-master commit 960 | - `shGitPullrequest master beta` 961 | - verify ci-success for origin-branch-alpha 962 | - https://github.com/kaizhu256/jslint/actions 963 | - `git push upstream alpha -f` 964 | - verify ci-success for upstream-branch-alpha 965 | - https://github.com/jslint-org/jslint/actions 966 | - goto https://github.com/jslint-org/jslint/compare/beta...kaizhu256:jslint:branch-v2025.3.31 967 | - click `Create pull request` 968 | - input `Add a title` with: `# v20yy.mm.dd` 969 | - input `Add a description` with: 970 | ``` 971 | - 972 | - 973 | ``` 974 | - verify `commit into jslint-org:beta` 975 | - click `Create pull request` 976 | - verify ci-success for pull-request 977 | - https://github.com/jslint-org/jslint/actions/workflows/on_pull_request.yml 978 | - wait awhile before continuing ... 979 | - click `Rebase and merge` 980 | - verify ci-success for upstream-branch-beta 981 | - https://github.com/jslint-org/jslint/actions 982 | - `shGitPullrequestCleanup` 983 | - verify ci-success for origin-branch-alpha 984 | - https://github.com/kaizhu256/jslint/actions 985 | - `git push upstream alpha -f` 986 | - verify ci-success for upstream-branch-alpha 987 | - https://github.com/jslint-org/jslint/actions 988 | - click `Delete branch` 989 | - `git push origin beta:master` 990 | - verify ci-success for origin-branch-master 991 | - https://github.com/kaizhu256/jslint/actions 992 | - `git push upstream beta:master` 993 | - verify ci-success for upstream-branch-master 994 | - https://github.com/jslint-org/jslint/actions 995 | 996 | 997 |

998 | ### branch-master publish 999 | - `git push upstream beta:master` 1000 | - verify ci-success for upstream-branch-master 1001 | - https://github.com/jslint-org/jslint/actions 1002 | - goto https://github.com/jslint-org/jslint/releases/new 1003 | - input `Choose a tag` with: `v20yy.mm.dd` 1004 | - click `Create new tag: v20yy.mm.dd on publish` 1005 | - verify correct-year `20yy` 1006 | - select `Target: master` 1007 | - select `Previous tag:auto` 1008 | - input `Release title` with: `v20yy.mm.dd - ` 1009 | - input `Describe this release` with: 1010 | ``` 1011 | - 1012 | - 1013 | ``` 1014 | - click `Generate release notes` 1015 | - click `Set as the latest release` 1016 | - click `Preview` and review 1017 | - click `Publish release` 1018 | - verify ci-success for upstream-branch-publish 1019 | - https://github.com/jslint-org/jslint/actions 1020 | - verify email-notification `Successfully published @jslint-org/jslint@20yy.mm.dd` 1021 | 1022 | 1023 |

1024 | ### vscode-jslint publish 1025 | - goto https://github.com/jslint-org/jslint/tree/gh-pages/branch-beta/.artifact/jslint_wrapper_vscode 1026 | - click `vscode-jslint-20yy.mm.dd.vsix` 1027 | - click `Raw` to download 1028 | - goto https://marketplace.visualstudio.com/manage/publishers/jslint 1029 | - right-click `Update` 1030 | - upload downloaded file `vscode-jslint-20yy.mm.dd.vsix` 1031 | - click 'Upload' 1032 | - verify email-notification `[Succeeded] Extension publish on Visual Studio Marketplace - vscode-jslint` 1033 | 1034 | 1035 | 1041 | -------------------------------------------------------------------------------- /asset_font_daley_bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jslint-org/jslint/73705ec6f07e4706ca2c16d8546b3b78bcada6f6/asset_font_daley_bold.woff2 -------------------------------------------------------------------------------- /asset_image_folder_open_solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /asset_image_github_brands.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /asset_image_jslint_wrapper_vim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jslint-org/jslint/73705ec6f07e4706ca2c16d8546b3b78bcada6f6/asset_image_jslint_wrapper_vim.png -------------------------------------------------------------------------------- /asset_image_jslint_wrapper_vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jslint-org/jslint/73705ec6f07e4706ca2c16d8546b3b78bcada6f6/asset_image_jslint_wrapper_vscode.png -------------------------------------------------------------------------------- /asset_image_json_160.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | JSON logo 17 | 19 | 21 | 25 | 29 | 30 | 39 | 48 | 49 | 96 | 100 | 104 | 105 | -------------------------------------------------------------------------------- /asset_image_logo_256.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | logo 5 | 186 | 187 | 188 |
189 |
JS
190 |
Lint
191 |
192 | 193 | 194 | -------------------------------------------------------------------------------- /asset_image_logo_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jslint-org/jslint/73705ec6f07e4706ca2c16d8546b3b78bcada6f6/asset_image_logo_256.png -------------------------------------------------------------------------------- /asset_image_logo_256.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 9 | 11 | 18 | 20 | 25 | 27 | 28 | 31 | 32 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /jslint_wrapper_cjs.cjs: -------------------------------------------------------------------------------- 1 | // The Unlicense 2 | // 3 | // This is free and unencumbered software released into the public domain. 4 | // 5 | // Anyone is free to copy, modify, publish, use, compile, sell, or 6 | // distribute this software, either in source code form or as a compiled 7 | // binary, for any purpose, commercial or non-commercial, and by any 8 | // means. 9 | // 10 | // In jurisdictions that recognize copyright laws, the author or authors 11 | // of this software dedicate any and all copyright interest in the 12 | // software to the public domain. We make this dedication for the benefit 13 | // of the public at large and to the detriment of our heirs and 14 | // successors. We intend this dedication to be an overt act of 15 | // relinquishment in perpetuity of all present and future rights to this 16 | // software under copyright law. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | // OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | 27 | /*jslint beta, node*/ 28 | /*property 29 | module, readFileSync, replace, runInNewContext 30 | */ 31 | require("vm").runInNewContext( 32 | ( 33 | "\"use strict\";" 34 | + require("fs").readFileSync( 35 | __dirname + "/jslint.mjs", 36 | "utf8" 37 | ).replace( 38 | "\nexport default Object.freeze(jslint_export);", 39 | "\nmodule.exports = jslint_export;" 40 | ).replace( 41 | "\njslint_import_meta_url = import.meta.url;", 42 | "\n// jslint_import_meta_url = import.meta.url;" 43 | ) 44 | ), 45 | { 46 | module 47 | } 48 | ); 49 | -------------------------------------------------------------------------------- /jslint_wrapper_codemirror.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CodeMirror: JSLint Demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 34 | 35 | 36 | 37 | 38 |

CodeMirror: JSLint Demo

39 |

40 | This demo will auto-lint the code below, and auto-generate a report as you type. 41 |

42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /jslint_wrapper_codemirror.js: -------------------------------------------------------------------------------- 1 | // The Unlicense 2 | // 3 | // This is free and unencumbered software released into the public domain. 4 | // 5 | // Anyone is free to copy, modify, publish, use, compile, sell, or 6 | // distribute this software, either in source code form or as a compiled 7 | // binary, for any purpose, commercial or non-commercial, and by any 8 | // means. 9 | // 10 | // In jurisdictions that recognize copyright laws, the author or authors 11 | // of this software dedicate any and all copyright interest in the 12 | // software to the public domain. We make this dedication for the benefit 13 | // of the public at large and to the detriment of our heirs and 14 | // successors. We intend this dedication to be an overt act of 15 | // relinquishment in perpetuity of all present and future rights to this 16 | // software under copyright law. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | // OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | 27 | // This wrapper will integrate JSLint with CodeMirror's lint.js addon. 28 | // Requires CodeMirror and JSLint. 29 | // 30 | // Example usage: 31 | /* 32 | 33 | 34 | 35 | 36 | 38 | 39 | 40 | 41 | 42 | 55 | 56 | */ 57 | 58 | /*jslint browser, devel*/ 59 | /*global CodeMirror define exports jslint module require*/ 60 | /*property 61 | Pos, amd, column, error, from, globals, jslint, line, map, message, 62 | mode_stop, registerHelper, result, severity, signal, source, to, warnings 63 | */ 64 | 65 | (function (mod) { 66 | "use strict"; 67 | 68 | // CommonJS 69 | 70 | if (typeof exports === "object" && typeof module === "object") { 71 | mod(require("../../lib/codemirror")); 72 | 73 | // AMD 74 | 75 | } else if (typeof define === "function" && define.amd) { 76 | define(["../../lib/codemirror"], mod); 77 | 78 | // Plain browser env 79 | 80 | } else { 81 | mod(CodeMirror); 82 | } 83 | }(function (CodeMirror) { 84 | "use strict"; 85 | if (!window.jslint) { 86 | console.error( 87 | "Error: window.jslint not defined," 88 | + " CodeMirror JavaScript linting cannot run." 89 | ); 90 | return []; 91 | } 92 | CodeMirror.registerHelper("lint", "javascript", function ( 93 | source, 94 | options, 95 | editor 96 | ) { 97 | let result; 98 | 99 | // Emit before linter is run, so it can be modified 100 | // before passing to jslint. 101 | // 102 | // Example usage: 103 | // editor.on("lintJslintBefore", function (options) { 104 | // options.browser = true; 105 | // options.node = true; 106 | // options.globals = ["caches", "indexedDb"]; 107 | // }); 108 | 109 | options.source = source; 110 | CodeMirror.signal(editor, "lintJslintBefore", options); 111 | 112 | // Run jslint. 113 | 114 | result = jslint.jslint(source, options, options.globals); 115 | 116 | // Emit after linter is run, so it can be used to generate reports. 117 | // 118 | // Example usage: 119 | // editor.on("lintJslintAfter", function (options) { 120 | // divReport.innerHTML = jslint.jslint_report(options.result); 121 | // }); 122 | 123 | options.result = result; 124 | CodeMirror.signal(editor, "lintJslintAfter", options); 125 | 126 | // Return warnings. 127 | 128 | return result.warnings.map(function ({ 129 | column, 130 | line, 131 | message, 132 | mode_stop 133 | }) { 134 | return { 135 | from: CodeMirror.Pos(line - 1, column - 1), //jslint-ignore-line 136 | message, 137 | severity: ( 138 | mode_stop 139 | ? "error" 140 | : "warning" 141 | ), 142 | to: CodeMirror.Pos(line - 1, column) //jslint-ignore-line 143 | }; 144 | }); 145 | }); 146 | })); 147 | -------------------------------------------------------------------------------- /jslint_wrapper_vim.vim: -------------------------------------------------------------------------------- 1 | "" The Unlicense 2 | "" 3 | "" This is free and unencumbered software released into the public domain. 4 | "" 5 | "" Anyone is free to copy, modify, publish, use, compile, sell, or 6 | "" distribute this software, either in source code form or as a compiled 7 | "" binary, for any purpose, commercial or non-commercial, and by any 8 | "" means. 9 | "" 10 | "" In jurisdictions that recognize copyright laws, the author or authors 11 | "" of this software dedicate any and all copyright interest in the 12 | "" software to the public domain. We make this dedication for the benefit 13 | "" of the public at large and to the detriment of our heirs and 14 | "" successors. We intend this dedication to be an overt act of 15 | "" relinquishment in perpetuity of all present and future rights to this 16 | "" software under copyright law. 17 | "" 18 | "" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | "" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | "" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | "" IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 | "" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 | "" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | "" OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | 27 | "" jslint_wrapper_vim.vim 28 | "" 29 | "" jslint wrapper for vim 30 | "" 31 | "" 1. Save this file and "jslint.mjs" to directory "~/.vim/" 32 | "" 2. Add vim-command ":source ~/.vim/jslint_wrapper_vim.vim" to file "~/.vimrc" 33 | "" 3. Vim can now jslint files (via nodejs): 34 | "" - with vim-command ":SaveAndJslint" 35 | "" - with vim-key-combo " " 36 | 37 | let s:dir = expand(":p:h") 38 | 39 | "" this function will save current file and jslint it (via nodejs) 40 | function! SaveAndJslint(bang) 41 | "" save file 42 | if a:bang == "!" | write! | else | write | endif 43 | "" jslint file (via nodejs) 44 | let &l:errorformat = 45 | \ "%f..js:%n:%l:%c:%m," . 46 | \ "%f:%n:%l:%c:%m" 47 | let &l:makeprg = "node" 48 | \ . " \"" . s:dir . "/jslint.mjs\"" 49 | \ . " jslint_wrapper_vim" 50 | \ . " \"" . fnamemodify(bufname("%"), ":p") . "\"" 51 | silent make! | cwindow | redraw! 52 | endfunction 53 | 54 | "" create vim-command ":SaveAndJslint" 55 | command! -nargs=* -bang SaveAndJslint call SaveAndJslint("") 56 | 57 | "" map vim-key-combo " " to ":SaveAndJslint" 58 | inoremap :SaveAndJslint 59 | nnoremap :SaveAndJslint 60 | -------------------------------------------------------------------------------- /jslint_wrapper_vscode.js: -------------------------------------------------------------------------------- 1 | // The Unlicense 2 | // 3 | // This is free and unencumbered software released into the public domain. 4 | // 5 | // Anyone is free to copy, modify, publish, use, compile, sell, or 6 | // distribute this software, either in source code form or as a compiled 7 | // binary, for any purpose, commercial or non-commercial, and by any 8 | // means. 9 | // 10 | // In jurisdictions that recognize copyright laws, the author or authors 11 | // of this software dedicate any and all copyright interest in the 12 | // software to the public domain. We make this dedication for the benefit 13 | // of the public at large and to the detriment of our heirs and 14 | // successors. We intend this dedication to be an overt act of 15 | // relinquishment in perpetuity of all present and future rights to this 16 | // software under copyright law. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | // OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | 27 | /*jslint beta, node*/ 28 | /*property 29 | Diagnostic, DiagnosticSeverity, ProgressLocation, Warning, Window, activate, 30 | cancellable, character, clear, column, commands, createDiagnosticCollection, 31 | document, end, endsWith, exports, fsPath, getText, increment, insert, 32 | isEmpty, jslint, languages, line, lineAt, location, map, message, module, 33 | promises, push, range, rangeIncludingLineBreak, readFileSync, 34 | registerTextEditorCommand, replace, report, runInNewContext, selection, set, 35 | slice, start, subscriptions, title, uri, warnings, window, withProgress, 36 | writeFile 37 | */ 38 | 39 | "use strict"; 40 | 41 | function activate({ 42 | subscriptions 43 | }) { 44 | /** 45 | * @param {vscode.ExtensionContext} context 46 | */ 47 | // This method is called when your extension is activated. 48 | // Your extension is activated the very first time the command is executed. 49 | 50 | // Directly print diagnostic without language-server. 51 | // https://stackoverflow.com/questions/35581332 52 | // /create-diagnostics-entries-without-language-server-in-visual-studio-code 53 | 54 | let diagnosticCollection; 55 | let jslint; 56 | let vscode; 57 | 58 | function jslintClear() { 59 | return vscode.window.withProgress({ 60 | cancellable: false, 61 | location: vscode.ProgressLocation.Window, 62 | title: "JSLint clear warnings ..." 63 | }, async function (progress) { 64 | progress.report({ 65 | increment: 0 66 | }); 67 | 68 | // Clear "Problems" tab. 69 | 70 | diagnosticCollection.clear(); 71 | 72 | // Wait awhile for flicker to give user visual confirmation "Problems" tab 73 | // is refreshed. 74 | 75 | await new Promise(function (resolve) { 76 | setTimeout(resolve, 500); 77 | }); 78 | 79 | progress.report({ 80 | increment: 100 81 | }); 82 | }); 83 | } 84 | 85 | function jslintDisableRegion({ 86 | document, 87 | selection 88 | }, edit) { 89 | let range; 90 | let text; 91 | edit.insert({ 92 | character: 0, 93 | line: selection.start.line 94 | }, "/*jslint-disable*/\n"); 95 | range = document.lineAt(selection.end).rangeIncludingLineBreak; 96 | text = document.getText(range); 97 | 98 | // If selection-end is EOL without preceding line-break, 99 | // then prepend line-break before directive. 100 | 101 | if (!text.endsWith("\n")) { 102 | text += "\n/*jslint-enable*/"; 103 | 104 | // If selection-end is start of a new line, then prepend directive before it. 105 | 106 | } else if (!selection.isEmpty && selection.end.character === 0) { 107 | text = "/*jslint-enable*/\n" + text; 108 | 109 | // Append directive to selection-end. 110 | 111 | } else { 112 | text += "/*jslint-enable*/\n"; 113 | } 114 | edit.replace(range, text); 115 | } 116 | 117 | function jslintIgnoreLine({ 118 | document, 119 | selection 120 | }, edit) { 121 | edit.insert({ 122 | character: document.lineAt(selection.end).range.end.character, 123 | line: selection.end.line 124 | }, " //jslint-ignore-line"); 125 | } 126 | 127 | function jslintLint({ 128 | document 129 | }) { 130 | return vscode.window.withProgress({ 131 | cancellable: false, 132 | location: vscode.ProgressLocation.Window, 133 | title: "JSLint lint file ..." 134 | }, async function (progress) { 135 | let result; 136 | progress.report({ 137 | increment: 0 138 | }); 139 | 140 | // Clear "Problems" tab. 141 | 142 | diagnosticCollection.clear(); 143 | result = document.getText(); 144 | result = jslint.jslint(result); 145 | result = result.warnings.slice(0, 100).map(function ({ 146 | column, 147 | line, 148 | // line_source, 149 | message 150 | }) { 151 | return new vscode.Diagnostic( 152 | // code: line_source, 153 | { 154 | end: { 155 | character: column - 1, 156 | line: line - 1 157 | }, 158 | start: { 159 | character: column - 1, 160 | line: line - 1 161 | } 162 | }, 163 | `JSLint - ${message}`, 164 | vscode.DiagnosticSeverity.Warning 165 | ); 166 | }); 167 | 168 | // Wait awhile for flicker to give user visual confirmation "Problems" tab 169 | // is refreshed. 170 | 171 | await new Promise(function (resolve) { 172 | setTimeout(resolve, 100); 173 | }); 174 | 175 | // Update "Problems" tab. 176 | 177 | diagnosticCollection.set(document.uri, result); 178 | progress.report({ 179 | increment: 100 180 | }); 181 | }); 182 | } 183 | 184 | // PR-429 - Add manual lint-on-save command. 185 | 186 | async function jslintLintAndSave({ 187 | document 188 | }) { 189 | jslintLint({ 190 | document 191 | }); 192 | await require("fs").promises.writeFile( 193 | document.uri.fsPath, 194 | document.getText() 195 | ); 196 | } 197 | 198 | // Initialize vscode and jslint. 199 | 200 | vscode = require("vscode"); 201 | diagnosticCollection = vscode.languages.createDiagnosticCollection( 202 | "jslint" 203 | ); 204 | require("vm").runInNewContext( 205 | ( 206 | "\"use strict\";" 207 | + require("fs").readFileSync( //jslint-ignore-line 208 | __dirname + "/jslint.mjs", 209 | "utf8" 210 | ).replace( 211 | "\nexport default Object.freeze(jslint_export);", 212 | "\nmodule.exports = jslint_export;" 213 | ).replace( 214 | "\njslint_import_meta_url = import.meta.url;", 215 | "\n// jslint_import_meta_url = import.meta.url;" 216 | ) 217 | ), 218 | { 219 | module 220 | } 221 | ); 222 | jslint = module.exports; 223 | 224 | // Register extension commands. 225 | 226 | subscriptions.push(vscode.commands.registerTextEditorCommand(( 227 | "jslint.clear" 228 | ), jslintClear)); 229 | subscriptions.push(vscode.commands.registerTextEditorCommand(( 230 | "jslint.disableRegion" 231 | ), jslintDisableRegion)); 232 | subscriptions.push(vscode.commands.registerTextEditorCommand(( 233 | "jslint.ignoreLine" 234 | ), jslintIgnoreLine)); 235 | subscriptions.push(vscode.commands.registerTextEditorCommand(( 236 | "jslint.lint" 237 | ), jslintLint)); 238 | subscriptions.push(vscode.commands.registerTextEditorCommand(( 239 | "jslint.lintAndSave" 240 | ), jslintLintAndSave)); 241 | } 242 | 243 | exports.activate = activate; 244 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "bin": { 3 | "jslint": "jslint.mjs" 4 | }, 5 | "bugs": { 6 | "url": "https://github.com/jslint-org/jslint/issues" 7 | }, 8 | "counter": 0, 9 | "description": "JSLint, The JavaScript Code Quality and Coverage Tool", 10 | "exports": { 11 | "default": "./jslint_wrapper_cjs.cjs", 12 | "import": "./jslint.mjs" 13 | }, 14 | "fileCount": 34, 15 | "keywords": [ 16 | "coverage-report", 17 | "javascript", 18 | "jslint", 19 | "linter", 20 | "zero-config", 21 | "zero-dependency" 22 | ], 23 | "license": "UNLICENSE", 24 | "main": "./jslint_wrapper_cjs.cjs", 25 | "module": "./jslint.mjs", 26 | "name": "@jslint-org/jslint", 27 | "repository": { 28 | "type": "git", 29 | "url": "git+https://github.com/jslint-org/jslint.git" 30 | }, 31 | "scripts": { 32 | "test": "node jslint.mjs v8_coverage_report=.artifact/coverage node test.mjs", 33 | "test2": "sh jslint_ci.sh shCiBase" 34 | }, 35 | "shCiArtifactUpload": 1, 36 | "shCiPublishNpm": 1, 37 | "type": "module", 38 | "version": "2025.3.31" 39 | } 40 | -------------------------------------------------------------------------------- /test.mjs: -------------------------------------------------------------------------------- 1 | /*jslint beta, node*/ 2 | import jslint from "./jslint.mjs"; 3 | import jslintCjs from "./jslint_wrapper_cjs.cjs"; 4 | import moduleFs from "fs"; 5 | import modulePath from "path"; 6 | 7 | let { 8 | assertErrorThrownAsync, 9 | assertJsonEqual, 10 | assertOrThrow, 11 | debugInline, 12 | fsWriteFileWithParents, 13 | globExclude, 14 | jstestDescribe, 15 | jstestIt, 16 | jstestOnExit, 17 | moduleFsInit, 18 | noop, 19 | v8CoverageListMerge, 20 | v8CoverageReportCreate 21 | } = jslint; 22 | let sourceJslintMjs; 23 | let testCoverageMergeData; 24 | 25 | await (async function init() { 26 | 27 | // Coverage-hack - Ugly-hack to get test-coverage for all initialization-states. 28 | 29 | moduleFsInit(); 30 | moduleFsInit(); 31 | 32 | // Cleanup directory .tmp 33 | 34 | await moduleFs.promises.rm(".tmp", { 35 | recursive: true 36 | }).catch(noop); 37 | 38 | // init sourceJslintMjs 39 | 40 | sourceJslintMjs = await moduleFs.promises.readFile("jslint.mjs", "utf8"); 41 | 42 | // init testCoverageMergeData 43 | 44 | testCoverageMergeData = JSON.parse( 45 | await moduleFs.promises.readFile( 46 | "test_coverage_merge_data.json", 47 | "utf8" 48 | ) 49 | ); 50 | }()); 51 | 52 | jstestDescribe(( 53 | "test fsXxx handling-behavior" 54 | ), function testBehaviorFsXxx() { 55 | jstestIt(( 56 | "test fsWriteFileWithParents handling-behavior" 57 | ), async function () { 58 | await Promise.all([ 59 | 1, 2, 3, 4 60 | ].map(async function () { 61 | await fsWriteFileWithParents( 62 | ".tmp/fsWriteFileWithParents/aa/bb/cc", 63 | "aa" 64 | ); 65 | })); 66 | assertJsonEqual( 67 | await moduleFs.promises.readFile( 68 | ".tmp/fsWriteFileWithParents/aa/bb/cc", 69 | "utf8" 70 | ), 71 | "aa" 72 | ); 73 | }); 74 | }); 75 | 76 | jstestDescribe(( 77 | "test globXxx handling-behavior" 78 | ), function testBehaviorGlobXxx() { 79 | jstestIt(( 80 | "test globAssertNotWeird-error handling-behavior" 81 | ), async function () { 82 | await Promise.all([ 83 | "\n", 84 | "\r", 85 | "\u0000" 86 | ].map(async function (char) { 87 | await assertErrorThrownAsync(function () { 88 | return globExclude({ 89 | pathnameList: [ 90 | "aa", 91 | `cc/${char}/dd`, 92 | "bb" 93 | ] 94 | }); 95 | }, ( 96 | "Weird character " 97 | + JSON.stringify(char).replace("\\", "\\\\") 98 | + " found in " 99 | )); 100 | })); 101 | }); 102 | jstestIt(( 103 | "test globExclude handling-behavior" 104 | ), function () { 105 | let pathnameList = [ 106 | ".dockerignore", 107 | ".eslintrc.js", 108 | ".gitignore", 109 | ".npmignore", 110 | ".travis.yml", 111 | "/node_modules/aa/bb/cc.js", 112 | "/node_modules/aa/bb/dd.js", 113 | "CHANGELOG.md", 114 | "CONTRIBUTING.md", 115 | "Dockerfile", 116 | "LICENSE", 117 | "Makefile", 118 | "README.md", 119 | "appveyor.yml", 120 | "benchmark/insert-transaction.sql", 121 | "benchmark/insert.js", 122 | "binding.gyp", 123 | "cloudformation/ci.template.js", 124 | "deps/common-sqlite.gypi", 125 | "deps/extract.py", 126 | "deps/sqlite-autoconf-3340000.tar.gz", 127 | "deps/sqlite3.gyp", 128 | "examples/simple-chaining.js", 129 | "lib/index.js", 130 | "lib/sqlite3-binding.js", 131 | "lib/sqlite3.js", 132 | "lib/trace.js", 133 | "node_modules/aa/bb/cc.js", 134 | "node_modules/aa/bb/dd.js", 135 | "package.json", 136 | "scripts/build-appveyor.bat", 137 | "scripts/build-local.bat", 138 | "scripts/build_against_electron.sh", 139 | "scripts/build_against_node.sh", 140 | "scripts/build_against_node_webkit.sh", 141 | "scripts/build_for_node_webkit.cmd", 142 | "scripts/install_node.sh", 143 | "scripts/validate_tag.sh", 144 | "sqlite3.js", 145 | "src/async.h", 146 | "src/backup.cc", 147 | "src/backup.h", 148 | "src/database.cc", 149 | "src/database.h", 150 | "src/gcc-preinclude.h", 151 | "src/macros.h", 152 | "src/node_sqlite3.cc", 153 | "src/statement.cc", 154 | "src/statement.h", 155 | "src/threading.h", 156 | "test/affected.test.js", 157 | "test/backup.test.js", 158 | "test/blob.test.js", 159 | "test/cache.test.js", 160 | "test/constants.test.js", 161 | "test/database_fail.test.js", 162 | "test/each.test.js", 163 | "test/exec.test.js", 164 | "test/extension.test.js", 165 | "test/fts-content.test.js", 166 | "test/interrupt.test.js", 167 | "test/issue-108.test.js", 168 | "test/json.test.js", 169 | "test/map.test.js", 170 | "test/named_columns.test.js", 171 | "test/named_params.test.js", 172 | "test/null_error.test.js", 173 | "test/nw/.gitignore", 174 | "test/nw/Makefile", 175 | "test/nw/index.html", 176 | "test/nw/package.json", 177 | "test/open_close.test.js", 178 | "test/other_objects.test.js", 179 | "test/parallel_insert.test.js", 180 | "test/prepare.test.js", 181 | "test/profile.test.js", 182 | "test/rerun.test.js", 183 | "test/scheduling.test.js", 184 | "test/serialization.test.js", 185 | "test/support/createdb-electron.js", 186 | "test/support/createdb.js", 187 | "test/support/elmo.png", 188 | "test/support/helper.js", 189 | "test/support/prepare.db", 190 | "test/support/script.sql", 191 | "test/trace.test.js", 192 | "test/unicode.test.js", 193 | "test/upsert.test.js", 194 | "test/verbose.test.js", 195 | "tools/docker/architecture/linux-arm/Dockerfile", 196 | "tools/docker/architecture/linux-arm/run.sh", 197 | "tools/docker/architecture/linux-arm64/Dockerfile", 198 | "tools/docker/architecture/linux-arm64/run.sh" 199 | ]; 200 | [ 201 | "tes?/", 202 | "tes[-t-]/", 203 | "tes[-t]/", 204 | "tes[0-9A-Z_a-z-]/", 205 | "tes[t-]/", 206 | "test/**/*.js" 207 | ].forEach(function (aa) { 208 | [ 209 | "li*/*.js", 210 | "li?/*.js", 211 | "lib/", 212 | "lib/*", 213 | "lib/**/*.js", 214 | "lib/*.js" 215 | ].forEach(function (bb) { 216 | [ 217 | "", 218 | "**/node_modules/", 219 | "node_modules/" 220 | ].forEach(function (cc) { 221 | assertJsonEqual( 222 | globExclude({ 223 | excludeList: [ 224 | "tes[!0-9A-Z_a-z-]/", 225 | "tes[^0-9A-Z_a-z-]/", 226 | "test/suppor*/*elper.js", 227 | "test/suppor?/?elper.js", 228 | "test/support/helper.js" 229 | ].concat(aa, cc), 230 | includeList: [ 231 | "**/*.cjs", 232 | "**/*.js", 233 | "**/*.mjs", 234 | "lib/sqlite3.js" 235 | ].concat(bb), 236 | pathnameList 237 | }).pathnameList, 238 | [ 239 | ".eslintrc.js", 240 | "benchmark/insert.js", 241 | "cloudformation/ci.template.js", 242 | "examples/simple-chaining.js", 243 | "lib/index.js", 244 | "lib/sqlite3-binding.js", 245 | "lib/sqlite3.js", 246 | "lib/trace.js", 247 | "sqlite3.js" 248 | ].concat( 249 | cc === "**/node_modules/" 250 | ? [ 251 | "node_modules/aa/bb/cc.js", 252 | "node_modules/aa/bb/dd.js" 253 | ] 254 | : cc === "node_modules/" 255 | ? [ 256 | "/node_modules/aa/bb/cc.js", 257 | "/node_modules/aa/bb/dd.js" 258 | ] 259 | : [ 260 | "/node_modules/aa/bb/cc.js", 261 | "/node_modules/aa/bb/dd.js", 262 | "node_modules/aa/bb/cc.js", 263 | "node_modules/aa/bb/dd.js" 264 | ] 265 | ).sort() 266 | ); 267 | }); 268 | }); 269 | }); 270 | }); 271 | jstestIt(( 272 | "test globToRegexp handling-behavior" 273 | ), function () { 274 | Object.entries({ 275 | "*": ( 276 | /^[^\/]*?$/gm 277 | ), 278 | "**": ( 279 | /^.*?$/gm 280 | ), 281 | "***": ( 282 | /^.*?$/gm 283 | ), 284 | "****": ( 285 | /^.*?$/gm 286 | ), 287 | "****////****": ( 288 | /^.*?$/gm 289 | ), 290 | "***///***": ( 291 | /^.*?$/gm 292 | ), 293 | "**/*": ( 294 | /^.*?$/gm 295 | ), 296 | "**/node_modules/": ( 297 | /^.*?\/node_modules\/.*?$/gm 298 | ), 299 | "**/node_modules/**/*": ( 300 | /^.*?\/node_modules\/.*?$/gm 301 | ), 302 | "?": ( 303 | /^[^\/]$/gm 304 | ), 305 | "[!0-9A-Za-z-]": ( 306 | /^[^0-9A-Za-z\-]$/gm 307 | ), 308 | "[0-9A-Za-z-]": ( 309 | /^[0-9A-Za-z\-]$/gm 310 | ), 311 | "[[]] ]][[": ( 312 | /^[\[]\] \]\][\[]$/gm 313 | ), 314 | "[]": ( 315 | /^$/gm 316 | ), 317 | "[^0-9A-Za-z-]": ( 318 | /^[^0-9A-Za-z\-]$/gm 319 | ), 320 | "aa/bb/cc": ( 321 | /^aa\/bb\/cc$/gm 322 | ), 323 | "aa/bb/cc/": ( 324 | /^aa\/bb\/cc\/.*?$/gm 325 | ), 326 | "li*/*": ( 327 | /^li[^\/]*?\/[^\/]*?$/gm 328 | ), 329 | "li?/*": ( 330 | /^li[^\/]\/[^\/]*?$/gm 331 | ), 332 | "lib/": ( 333 | /^lib\/.*?$/gm 334 | ), 335 | "lib/*": ( 336 | /^lib\/[^\/]*?$/gm 337 | ), 338 | "lib/**/*.js": ( 339 | /^lib\/.*?\.js$/gm 340 | ), 341 | "lib/*.js": ( 342 | /^lib\/[^\/]*?\.js$/gm 343 | ), 344 | "node_modules/": ( 345 | /^node_modules\/.*?$/gm 346 | ), 347 | "node_modules/**/*": ( 348 | /^node_modules\/.*?$/gm 349 | ), 350 | "tes[!0-9A-Z_a-z-]/**/*": ( 351 | /^tes[^0-9A-Z_a-z\-]\/.*?$/gm 352 | ), 353 | "tes[0-9A-Z_a-z-]/**/*": ( 354 | /^tes[0-9A-Z_a-z\-]\/.*?$/gm 355 | ), 356 | "tes[^0-9A-Z_a-z-]/**/*": ( 357 | /^tes[^0-9A-Z_a-z\-]\/.*?$/gm 358 | ), 359 | "test/**/*": ( 360 | /^test\/.*?$/gm 361 | ), 362 | "test/**/*.js": ( 363 | /^test\/.*?\.js$/gm 364 | ), 365 | "test/suppor*/*elper.js": ( 366 | /^test\/suppor[^\/]*?\/[^\/]*?elper\.js$/gm 367 | ), 368 | "test/suppor?/?elper.js": ( 369 | /^test\/suppor[^\/]\/[^\/]elper\.js$/gm 370 | ), 371 | "test/support/helper.js": ( 372 | /^test\/support\/helper\.js$/gm 373 | ) 374 | }).forEach(function ([ 375 | pattern, rgx 376 | ]) { 377 | assertJsonEqual( 378 | globExclude({ 379 | excludeList: [ 380 | pattern 381 | ] 382 | }).excludeList[0].source, 383 | rgx.source 384 | ); 385 | assertJsonEqual( 386 | globExclude({ 387 | includeList: [ 388 | pattern 389 | ] 390 | }).includeList[0].source, 391 | rgx.source 392 | ); 393 | }); 394 | }); 395 | }); 396 | 397 | jstestDescribe(( 398 | "test jslint's cli handling-behavior" 399 | ), function testBehaviorJslintCli() { 400 | function processExit0(exitCode) { 401 | assertOrThrow(exitCode === 0, exitCode); 402 | } 403 | function processExit1(exitCode) { 404 | assertOrThrow(exitCode === 1, exitCode); 405 | } 406 | jstestIt(( 407 | "test cli-null-case handling-behavior" 408 | ), function () { 409 | jslint.jslint_cli({ 410 | mode_noop: true, 411 | process_exit: processExit0 412 | }); 413 | }); 414 | jstestIt(( 415 | "test cli-window-jslint handling-behavior" 416 | ), function () { 417 | [ 418 | "&window_jslint=", 419 | "&window_jslint=12", 420 | "&window_jslint=1?", 421 | "&window_jslint=?", 422 | "?window_jslint=", 423 | "?window_jslint=12", 424 | "?window_jslint=1?", 425 | "?window_jslint=?", 426 | "window_jslint=1", 427 | "window_jslint=1&", 428 | "window_jslint=12", 429 | "window_jslint=1?" 430 | ].forEach(function (import_meta_url) { 431 | jslint.jslint_cli({ 432 | import_meta_url 433 | }); 434 | assertOrThrow(globalThis.jslint === undefined); 435 | }); 436 | [ 437 | "&window_jslint=1", 438 | "&window_jslint=1&", 439 | "?window_jslint=1", 440 | "?window_jslint=1&" 441 | ].forEach(function (import_meta_url) { 442 | jslint.jslint_cli({ 443 | import_meta_url 444 | }); 445 | assertOrThrow(globalThis.jslint === jslint); 446 | delete globalThis.jslint; 447 | }); 448 | }); 449 | jstestIt(( 450 | "test cli-cjs-and-invalid-file handling-behavior" 451 | ), async function () { 452 | await fsWriteFileWithParents(".test_dir.cjs/touch.txt", ""); 453 | [ 454 | ".", // test dir handling-behavior 455 | "jslint.mjs", // test file handling-behavior 456 | undefined // test file-undefined handling-behavior 457 | ].forEach(function (file) { 458 | jslint.jslint_cli({ 459 | file, 460 | mode_cli: true, 461 | process_env: { 462 | JSLINT_BETA: "1" 463 | }, 464 | process_exit: processExit0 465 | }); 466 | }); 467 | }); 468 | jstestIt(( 469 | "test cli-apidoc handling-behavior" 470 | ), function () { 471 | jslint.jslint_cli({ 472 | mode_cli: true, 473 | process_argv: [ 474 | "node", 475 | "jslint.mjs", 476 | "jslint_apidoc=.artifact/apidoc.html", 477 | JSON.stringify({ 478 | example_list: [ 479 | "README.md", 480 | "test.mjs", 481 | "jslint.mjs" 482 | ], 483 | github_repo: "https://github.com/jslint-org/jslint", 484 | module_list: [ 485 | { 486 | pathname: "./jslint.mjs" 487 | } 488 | ], 489 | package_name: "JSLint", 490 | version: jslint.jslint_edition 491 | }) 492 | ], 493 | process_exit: processExit0 494 | }); 495 | }); 496 | jstestIt(( 497 | "test cli-file-error handling-behavior" 498 | ), function () { 499 | jslint.jslint_cli({ 500 | // suppress error 501 | console_error: noop, 502 | file: "undefined", 503 | mode_cli: true, 504 | process_exit: processExit1 505 | }); 506 | }); 507 | jstestIt(( 508 | "test cli-syntax-error handling-behavior" 509 | ), function () { 510 | jslint.jslint_cli({ 511 | // suppress error 512 | console_error: noop, 513 | file: "syntax-error.js", 514 | mode_cli: true, 515 | option: { 516 | trace: true 517 | }, 518 | process_exit: processExit1, 519 | source: "syntax error" 520 | }); 521 | }); 522 | jstestIt(( 523 | "test cli-report handling-behavior" 524 | ), function () { 525 | jslint.jslint_cli({ 526 | // suppress error 527 | console_error: noop, 528 | mode_cli: true, 529 | process_argv: [ 530 | "node", 531 | "jslint.mjs", 532 | "jslint_report=.tmp/jslint_report.html", 533 | "jslint.mjs" 534 | ], 535 | process_exit: processExit0 536 | }); 537 | }); 538 | jstestIt(( 539 | "test cli-report-error handling-behavior" 540 | ), function () { 541 | jslint.jslint_cli({ 542 | // suppress error 543 | console_error: noop, 544 | mode_cli: true, 545 | process_argv: [ 546 | "node", 547 | "jslint.mjs", 548 | "jslint_report=.tmp/jslint_report.html", 549 | "syntax-error.js" 550 | ], 551 | process_exit: processExit1, 552 | source: "syntax error" 553 | }); 554 | }); 555 | jstestIt(( 556 | "test cli-report-json handling-behavior" 557 | ), function () { 558 | jslint.jslint_cli({ 559 | // suppress error 560 | console_error: noop, 561 | mode_cli: true, 562 | process_argv: [ 563 | "node", 564 | "jslint.mjs", 565 | "jslint_report=.tmp/jslint_report.html", 566 | "aa.json" 567 | ], 568 | process_exit: processExit0, 569 | source: "[]" 570 | }); 571 | }); 572 | jstestIt(( 573 | "test cli-report-json-error handling-behavior" 574 | ), function () { 575 | jslint.jslint_cli({ 576 | // suppress error 577 | console_error: noop, 578 | mode_cli: true, 579 | process_argv: [ 580 | "node", 581 | "jslint.mjs", 582 | "jslint_report=.tmp/jslint_report.html", 583 | "aa.json" 584 | ], 585 | process_exit: processExit1, 586 | source: "[" 587 | }); 588 | }); 589 | jstestIt(( 590 | "test cli-report-misc handling-behavior" 591 | ), function () { 592 | jslint.jslint_cli({ 593 | // suppress error 594 | console_error: noop, 595 | mode_cli: true, 596 | process_argv: [ 597 | "node", 598 | "jslint.mjs", 599 | "jslint_report=.tmp/jslint_report.html", 600 | "aa.js" 601 | ], 602 | process_exit: processExit0, 603 | source: "let aa = 0;" 604 | }); 605 | jslint.jslint_cli({ 606 | // suppress error 607 | console_error: noop, 608 | mode_cli: true, 609 | process_argv: [ 610 | "node", 611 | "jslint.mjs", 612 | "jslint_report=.tmp/jslint_report.html", 613 | "aa.js" 614 | ], 615 | process_exit: processExit1, 616 | source: "(aa)=>aa; function aa([aa]){}" 617 | }); 618 | }); 619 | jstestIt(( 620 | "test cli-jslint-wrapper-vim handling-behavior" 621 | ), function () { 622 | jslint.jslint_cli({ 623 | // suppress error 624 | console_error: noop, 625 | mode_cli: true, 626 | process_argv: [ 627 | "node", 628 | "jslint.mjs", 629 | "jslint_wrapper_vim", 630 | "syntax-error.js" 631 | ], 632 | process_exit: processExit1, 633 | source: "syntax error" 634 | }); 635 | }); 636 | }); 637 | 638 | jstestDescribe(( 639 | "test jslint's no-warnings handling-behavior" 640 | ), function testBehaviorJslintNoWarnings() { 641 | jstestIt(( 642 | "test jslint's no-warnings handling-behavior" 643 | ), function () { 644 | Object.values({ 645 | array: [ 646 | "new Array(0);" 647 | ], 648 | async_await: [ 649 | "async function aa() {\n await aa();\n}", 650 | 651 | // PR-405 - Bugfix - fix expression after "await" mis-identified as statement. 652 | 653 | "async function aa() {\n await aa;\n}", 654 | ( 655 | "async function aa() {\n" 656 | + " try {\n" 657 | + " aa();\n" 658 | + " } catch (err) {\n" 659 | + " await err();\n" 660 | + " }\n" 661 | + "}\n" 662 | ), 663 | ( 664 | "async function aa() {\n" 665 | + " try {\n" 666 | + " await aa();\n" 667 | + " } catch (err) {\n" 668 | + " await err();\n" 669 | + " }\n" 670 | + "}\n" 671 | ), 672 | 673 | // PR-370 - Add top-level-await support. 674 | 675 | "await String();\n" 676 | ], 677 | 678 | // PR-351 - Add BigInt support. 679 | 680 | bigint: [ 681 | "let aa = 0b0n;\n", 682 | "let aa = 0o0n;\n", 683 | "let aa = 0x0n;\n", 684 | "let aa = BigInt(0n);\n", 685 | "let aa = typeof aa === \"bigint\";\n" 686 | ], 687 | date: [ 688 | "Date.getTime();", 689 | "let aa = aa().getTime();", 690 | "let aa = aa.aa().getTime();" 691 | ], 692 | directive: [ 693 | "#!\n/*jslint browser:false, node*/\n\"use strict\";", 694 | "/*property aa bb*/" 695 | ], 696 | for: [ 697 | ( 698 | "/*jslint for*/\n" 699 | + "function aa(bb) {\n" 700 | + " for (bb = 0; bb < 0; bb += 1) {\n" 701 | + " bb();\n" 702 | + " }\n" 703 | + "}\n" 704 | ) 705 | ], 706 | jslint_disable: [ 707 | "/*jslint-disable*/\n0\n/*jslint-enable*/" 708 | ], 709 | jslint_ignore_line: [ 710 | "0 //jslint-ignore-line" 711 | ], 712 | json: [ 713 | "{\"aa\":[[],-0,null]}" 714 | ], 715 | label: [ 716 | ( 717 | "function aa() {\n" 718 | + "bb:\n" 719 | + " while (true) {\n" 720 | + " if (true) {\n" 721 | + " break bb;\n" 722 | + " }\n" 723 | + " }\n" 724 | + "}\n" 725 | ) 726 | ], 727 | loop: [ 728 | ( 729 | "function aa() {\n" 730 | + " do {\n" 731 | + " aa();\n" 732 | + " } while (aa());\n" 733 | + "}\n" 734 | ), 735 | 736 | // PR-378 - Relax warning "function_in_loop". 737 | 738 | ( 739 | "function aa() {\n" 740 | + " while (true) {\n" 741 | + " (function () {\n" 742 | + " return;\n" 743 | + " }());\n" 744 | + " }\n" 745 | + "}\n" 746 | ) 747 | ], 748 | module: [ 749 | "export default Object.freeze();", 750 | 751 | // PR-439 - Add grammar for "export async function ...". 752 | 753 | ( 754 | "export default Object.freeze(async function () {\n" 755 | + " return await 0;\n" 756 | + "});\n" 757 | ), 758 | "import {aa, bb} from \"aa\";\naa(bb);", 759 | "import {} from \"aa\";", 760 | "import(\"aa\").then(function () {\n return;\n});", 761 | ( 762 | "let aa = 0;\n" 763 | + "import(aa).then(aa).then(aa)" 764 | + ".catch(aa).finally(aa);\n" 765 | ) 766 | ], 767 | number: [ 768 | "let aa = 0.0e0;", 769 | "let aa = 0b0;", 770 | "let aa = 0o0;", 771 | "let aa = 0x0;" 772 | ], 773 | 774 | // PR-390 - Add numeric-separator support. 775 | 776 | numeric_separator: [ 777 | "let aa = 0.0_0_0;", 778 | "let aa = 0b0_1111_1111n;\n", 779 | "let aa = 0o0_1234_1234n;\n", 780 | "let aa = 0x0_1234_1234n;\n", 781 | "let aa = 1_234_234.1_234_234E1_234_234;" 782 | ], 783 | optional_chaining: [ 784 | "let aa = aa?.bb?.cc;" 785 | ], 786 | param: [ 787 | "function aa({aa, bb}) {\n return {aa, bb};\n}\n", 788 | ( 789 | "function aa({constructor}) {\n" 790 | + " return {constructor};\n" 791 | + "}\n" 792 | ) 793 | ], 794 | property: [ 795 | "let aa = aa[`!`];" 796 | ], 797 | regexp: [ 798 | "function aa() {\n return /./;\n}", 799 | "let aa = /(?!.)(?:.)(?=.)/;", 800 | "let aa = /./gimuy;", 801 | "let aa = /[\\--\\-]/;" 802 | ], 803 | ternary: [ 804 | ( 805 | "let aa = (\n" 806 | + " aa()\n" 807 | + " ? 0\n" 808 | + " : 1\n" 809 | + ") " 810 | + "&& (\n" 811 | + " aa()\n" 812 | + " ? 0\n" 813 | + " : 1\n" 814 | + ");" 815 | ), 816 | ( 817 | "let aa = (\n" 818 | + " aa()\n" 819 | + " ? `${0}`\n" 820 | + " : `${1}`\n" 821 | + ");" 822 | ), 823 | 824 | // PR-394 - Bugfix 825 | // Fix jslint falsely believing megastring literals `0` and `1` are similar. 826 | 827 | ( 828 | "let aa = (\n" 829 | + " aa()\n" 830 | + " ? `0`\n" 831 | + " : `1`\n" 832 | + ");" 833 | ) 834 | ], 835 | try_catch: [ 836 | ( 837 | "let aa = 0;\n" 838 | + "try {\n" 839 | + " aa();\n" 840 | + "} catch (err) {\n" 841 | + " aa = err;\n" 842 | + "}\n" 843 | + "try {\n" 844 | + " aa();\n" 845 | + "} catch (err) {\n" 846 | + " aa = err;\n" 847 | + "}\n" 848 | + "aa();\n" 849 | ) 850 | ], 851 | try_finally: [ 852 | ( 853 | "let aa = 0;\n" 854 | + "try {\n" 855 | + " aa();\n" 856 | + "} finally {\n" 857 | + " aa();\n" 858 | + "}\n" 859 | ) 860 | ], 861 | use_strict: [ 862 | ( 863 | "\"use strict\";\n" 864 | + "let aa = 0;\n" 865 | + "function bb() {\n" 866 | + " \"use strict\";\n" 867 | + " return aa;\n" 868 | + "}\n" 869 | ) 870 | ], 871 | var: [ 872 | 873 | // PR-363 - Bugfix 874 | // Add test against false-warning in code 875 | // '/*jslint node*/\nlet {aa:bb} = {}; bb();'. 876 | 877 | "/*jslint node*/\n", 878 | "" 879 | ].map(function (directive) { 880 | return [ 881 | "let [\n aa, bb = 0\n] = 0;\naa();\nbb();", 882 | "let aa = 0;\nlet [...bb] = [...aa];\nbb();", 883 | 884 | // PR-459 - Allow destructuring-assignment after function-definition. 885 | 886 | ( 887 | "let aa;\n" 888 | + "let bb;\n" 889 | + "function cc() {\n" 890 | + " return;\n" 891 | + "}\n" 892 | + "[aa, bb] = cc();\n" 893 | ), 894 | "let constructor = 0;\nconstructor();", 895 | "let {\n aa: bb\n} = 0;\nbb();", 896 | "let {\n aa: bb,\n bb: cc\n} = 0;\nbb();\ncc();", 897 | "let {aa, bb} = 0;\naa();\nbb();", 898 | "let {constructor} = 0;\nconstructor();" 899 | ].map(function (code) { 900 | return directive + code; 901 | }); 902 | }).flat() 903 | }).forEach(function (codeList) { 904 | let elemPrv = ""; 905 | codeList.forEach(function (code) { 906 | let warnings; 907 | // Assert codeList is sorted. 908 | assertOrThrow(elemPrv < code, JSON.stringify([ 909 | elemPrv, code 910 | ], undefined, 4)); 911 | elemPrv = code; 912 | [ 913 | jslint.jslint, 914 | jslintCjs.jslint 915 | ].forEach(function (jslint) { 916 | warnings = jslint(code, { 917 | beta: true 918 | }).warnings; 919 | assertOrThrow( 920 | warnings.length === 0, 921 | JSON.stringify([code, warnings]) 922 | ); 923 | }); 924 | }); 925 | }); 926 | }); 927 | }); 928 | 929 | jstestDescribe(( 930 | "test jslint's option handling-behavior" 931 | ), function testBehaviorJslintOption() { 932 | let elemPrv = ""; 933 | [ 934 | [ 935 | "let aa = aa | 0;", {bitwise: true}, [] 936 | ], [ 937 | ";\naa(new XMLHttpRequest());", {browser: true}, ["aa"] 938 | ], [ 939 | "let aa = \"aa\" + 0;", {convert: true}, [] 940 | ], [ 941 | "registerType();", {couch: true}, [] 942 | ], [ 943 | "debugger;", {devel: true}, [] 944 | ], [ 945 | 946 | // PR-404 - Alias "evil" to jslint-directive "eval" for backwards-compat. 947 | 948 | "new Function();\neval();", {eval: true, evil: true}, [] 949 | ], [ 950 | "let aa = () => 0;", {fart: true}, [] 951 | ], [ 952 | ( 953 | "let aa = async (bb, {cc, dd}, [ee, ff], ...gg) => {\n" 954 | + " bb += 1;\n" 955 | + " return await (bb + cc + dd + ee + ff + gg);\n" 956 | + "};\n" 957 | ), {fart: true}, [] 958 | ], [ 959 | ( 960 | "function aa(aa) {\n" 961 | + " for (aa = 0; aa < 0; aa += 1) {\n" 962 | + " aa();\n" 963 | + " }\n" 964 | + "}\n" 965 | ), {for: true}, [] 966 | ], [ 967 | "let aa = {get aa() {\n return;\n}};", {getset: true}, [] 968 | ], [ 969 | "let aa = {set aa(aa) {\n return aa;\n}};", {getset: true}, [] 970 | ], [ 971 | sourceJslintMjs.replace(( 972 | / /g 973 | ), " "), {indent2: true}, [] 974 | ], [ 975 | "function aa() {\n return;\n}", {indent2: true}, [] 976 | ], [ 977 | "/".repeat(100), {long: true}, [] 978 | ], [ 979 | 980 | // PR-404 - Alias "nomen" to jslint-directive "name" for backwards-compat. 981 | 982 | "let aa = aa._;", {name: true, nomen: true}, [] 983 | ], [ 984 | "require();", {node: true}, [] 985 | ], [ 986 | "let aa = 'aa';", {single: true}, [] 987 | ], [ 988 | 989 | // PR-404 - Add new directive "subscript" to play nice with Google Closure. 990 | 991 | "aa[\"aa\"] = 1;", {subscript: true}, ["aa"] 992 | ], [ 993 | "", {test_internal_error: true}, [] 994 | ], [ 995 | "let aa = this;", {this: true}, [] 996 | ], [ 997 | "", {trace: true}, [] 998 | ], [ 999 | ( 1000 | "function aa({bb, aa}) {\n" 1001 | + " switch (aa) {\n" 1002 | + " case 1:\n" 1003 | + " break;\n" 1004 | + " case 0:\n" 1005 | + " break;\n" 1006 | + " default:\n" 1007 | + " return {bb, aa};\n" 1008 | + " }\n" 1009 | + "}\n" 1010 | ), {unordered: true}, [] 1011 | ], [ 1012 | "let {bb, aa} = 0;", {unordered: true}, [] 1013 | ], [ 1014 | ( 1015 | "function aa() {\n" 1016 | + " if (aa) {\n" 1017 | + " let bb = 0;\n" 1018 | + " return bb;\n" 1019 | + " }\n" 1020 | + "}\n" 1021 | ), {variable: true}, [] 1022 | ], [ 1023 | "let bb = 0;\nlet aa = 0;", {variable: true}, [] 1024 | ], [ 1025 | "\t", {white: true}, [] 1026 | ] 1027 | ].forEach(function ([ 1028 | source, option_dict, global_list 1029 | ]) { 1030 | jstestIt(( 1031 | `test option=${JSON.stringify(option_dict)} handling-behavior` 1032 | ), function () { 1033 | let elemNow = JSON.stringify([ 1034 | option_dict, source, global_list 1035 | ]); 1036 | let warningsLength = ( 1037 | option_dict.test_internal_error 1038 | ? 1 1039 | : 0 1040 | ); 1041 | // Assert list is sorted. 1042 | assertOrThrow(elemPrv < elemNow, JSON.stringify([ 1043 | elemPrv, elemNow 1044 | ], undefined, 4)); 1045 | elemPrv = elemNow; 1046 | option_dict.beta = true; 1047 | [ 1048 | jslint.jslint, 1049 | jslintCjs.jslint 1050 | ].forEach(function (jslint) { 1051 | // test jslint's option handling-behavior 1052 | assertOrThrow( 1053 | jslint( 1054 | source, 1055 | option_dict, 1056 | global_list 1057 | ).warnings.length === warningsLength, 1058 | "jslint.jslint(" + JSON.stringify([ 1059 | source, option_dict, global_list 1060 | ]) + ")" 1061 | ); 1062 | // test jslint's directive handling-behavior 1063 | source = ( 1064 | "/*jslint " + JSON.stringify( 1065 | option_dict 1066 | ).slice(1, -1).replace(( 1067 | /"/g 1068 | ), "") + "*/\n" 1069 | + ( 1070 | global_list.length === 0 1071 | ? "" 1072 | : "/*global " + global_list.join(",") + "*/\n" 1073 | ) 1074 | + source.replace(( 1075 | /^#!/ 1076 | ), "//") 1077 | ); 1078 | assertOrThrow( 1079 | jslint(source).warnings.length === warningsLength, 1080 | source 1081 | ); 1082 | }); 1083 | }); 1084 | }); 1085 | }); 1086 | 1087 | jstestDescribe(( 1088 | "test jslint's warnings handling-behavior" 1089 | ), function testBehaviorJslintWarnings() { 1090 | jstestIt(( 1091 | "test jslint's warning handling-behavior" 1092 | ), function () { 1093 | 1094 | // this function will validate each jslint is raised with given 1095 | // malformed 1096 | 1097 | sourceJslintMjs.replace(( 1098 | /(\n\s*?\/\/\s*?test_cause:\s*?)(\S[\S\s]*?\S)(\n\n\s*?) *?\S/g 1099 | ), function (match0, header, causeList, footer) { 1100 | let tmp; 1101 | // console.error(match0); 1102 | // Validate header. 1103 | assertOrThrow(header === "\n\n// test_cause:\n", match0); 1104 | // Validate footer. 1105 | assertOrThrow(footer === "\n\n", match0); 1106 | // Validate causeList. 1107 | causeList = causeList.replace(( 1108 | /^\/\/ /gm 1109 | ), "").replace(( 1110 | /^\["\n([\S\s]*?)\n"(,.*?)$/gm 1111 | ), function (ignore, source, param) { 1112 | source = "[" + JSON.stringify(source) + param; 1113 | assertOrThrow(source.length > (80 - 3), source); 1114 | return source; 1115 | }).replace(( 1116 | / \/\/jslint-ignore-line$/gm 1117 | ), ""); 1118 | tmp = causeList.split("\n").map(function (cause) { 1119 | return ( 1120 | "[" 1121 | + JSON.parse(cause).map(function (elem) { 1122 | return JSON.stringify(elem); 1123 | }).join(", ") 1124 | + "]" 1125 | ); 1126 | }).sort().join("\n"); 1127 | assertOrThrow( 1128 | causeList === tmp, 1129 | "\n" + causeList + "\n\n" + tmp 1130 | ); 1131 | causeList.split("\n").forEach(function (cause) { 1132 | cause = JSON.parse(cause); 1133 | tmp = jslint.jslint(cause[0], { 1134 | beta: true, 1135 | test_cause: true 1136 | }).causes; 1137 | // Validate cause. 1138 | assertOrThrow( 1139 | tmp[JSON.stringify(cause.slice(1))], 1140 | ( 1141 | "\n" + JSON.stringify(cause) + "\n\n" 1142 | + Object.keys(tmp).sort().join("\n") 1143 | ) 1144 | ); 1145 | }); 1146 | return ""; 1147 | }); 1148 | }); 1149 | }); 1150 | 1151 | jstestDescribe(( 1152 | "test jstestXxx handling-behavior" 1153 | ), function testBehaviorJstestXxx() { 1154 | jstestIt(( 1155 | "test jstestDescribe error handling-behavior" 1156 | ), function () { 1157 | throw new Error(); 1158 | }, "pass"); 1159 | jstestIt(( 1160 | "test jstestOnExit tests-failed handling-behavior" 1161 | ), function () { 1162 | jstestOnExit(undefined, "testsFailed"); 1163 | }); 1164 | }); 1165 | 1166 | jstestDescribe(( 1167 | "test misc handling-behavior" 1168 | ), function testBehaviorMisc() { 1169 | jstestIt(( 1170 | "test misc handling-behavior" 1171 | ), async function () { 1172 | // test debugInline handling-behavior 1173 | noop(debugInline); 1174 | // test assertErrorThrownAsync error handling-behavior 1175 | await assertErrorThrownAsync(function () { 1176 | return assertErrorThrownAsync(noop); 1177 | }); 1178 | // test assertJsonEqual error handling-behavior 1179 | await assertErrorThrownAsync(function () { 1180 | assertJsonEqual(1, 2); 1181 | }); 1182 | await assertErrorThrownAsync(function () { 1183 | assertJsonEqual(1, 2, "undefined"); 1184 | }); 1185 | await assertErrorThrownAsync(function () { 1186 | assertJsonEqual(1, 2, {}); 1187 | }); 1188 | // test assertOrThrow error handling-behavior 1189 | await assertErrorThrownAsync(function () { 1190 | assertOrThrow(undefined, "undefined"); 1191 | }); 1192 | await assertErrorThrownAsync(function () { 1193 | assertOrThrow(undefined, new Error()); 1194 | }); 1195 | }); 1196 | }); 1197 | 1198 | jstestDescribe(( 1199 | "test v8CoverageListMerge handling-behavior" 1200 | ), function testBehaviorV8CoverageListMerge() { 1201 | let functionsInput = JSON.stringify([ 1202 | { 1203 | functionName: "test", 1204 | isBlockCoverage: true, 1205 | ranges: [ 1206 | { 1207 | count: 2, 1208 | endOffset: 4, 1209 | startOffset: 0 1210 | }, 1211 | { 1212 | count: 1, 1213 | endOffset: 2, 1214 | startOffset: 1 1215 | }, 1216 | { 1217 | count: 1, 1218 | endOffset: 3, 1219 | startOffset: 2 1220 | } 1221 | ] 1222 | } 1223 | ]); 1224 | jstestIt(( 1225 | "accepts empty arrays for `v8CoverageListMerge`" 1226 | ), function () { 1227 | assertJsonEqual(v8CoverageListMerge([]), { 1228 | result: [] 1229 | }); 1230 | }); 1231 | jstestIt(( 1232 | "funcCovs.length === 1" 1233 | ), function () { 1234 | assertJsonEqual(v8CoverageListMerge([ 1235 | { 1236 | result: [ 1237 | { 1238 | functions: [ 1239 | { 1240 | functionName: "test", 1241 | isBlockCoverage: true, 1242 | ranges: [ 1243 | { 1244 | count: 2, 1245 | endOffset: 4, 1246 | startOffset: 0 1247 | } 1248 | ] 1249 | } 1250 | ], 1251 | moduleUrl: "/lib.js", 1252 | scriptId: "1" 1253 | } 1254 | ] 1255 | }, 1256 | { 1257 | result: [ 1258 | { 1259 | functions: [], 1260 | moduleUrl: "/lib.js", 1261 | scriptId: "2" 1262 | } 1263 | ] 1264 | } 1265 | ]), { 1266 | result: [ 1267 | { 1268 | functions: [ 1269 | { 1270 | functionName: "test", 1271 | isBlockCoverage: true, 1272 | ranges: [ 1273 | { 1274 | count: 2, 1275 | endOffset: 4, 1276 | startOffset: 0 1277 | } 1278 | ] 1279 | } 1280 | ], 1281 | scriptId: "0" 1282 | } 1283 | ] 1284 | }); 1285 | }); 1286 | jstestIt(( 1287 | "accepts arrays with a single item for `v8CoverageListMerge`" 1288 | ), function () { 1289 | assertJsonEqual(v8CoverageListMerge([ 1290 | { 1291 | result: [ 1292 | { 1293 | functions: JSON.parse(functionsInput), 1294 | moduleUrl: "/lib.js", 1295 | scriptId: "123" 1296 | } 1297 | ] 1298 | } 1299 | ]), { 1300 | result: [ 1301 | { 1302 | functions: [ 1303 | { 1304 | functionName: "test", 1305 | isBlockCoverage: true, 1306 | ranges: [ 1307 | { 1308 | count: 2, 1309 | endOffset: 4, 1310 | startOffset: 0 1311 | }, 1312 | { 1313 | count: 1, 1314 | endOffset: 3, 1315 | startOffset: 1 1316 | } 1317 | ] 1318 | } 1319 | ], 1320 | moduleUrl: "/lib.js", 1321 | scriptId: "0" 1322 | } 1323 | ] 1324 | }); 1325 | }); 1326 | jstestIt(( 1327 | "accepts arrays with two identical items for" 1328 | + " `v8CoverageListMerge`" 1329 | ), function () { 1330 | assertJsonEqual(v8CoverageListMerge([ 1331 | { 1332 | result: [ 1333 | { 1334 | functions: JSON.parse(functionsInput), 1335 | scriptId: "123", 1336 | url: "/lib.js" 1337 | }, { 1338 | functions: JSON.parse(functionsInput), 1339 | scriptId: "123", 1340 | url: "/lib.js" 1341 | } 1342 | ] 1343 | } 1344 | ]), { 1345 | result: [ 1346 | { 1347 | functions: [ 1348 | { 1349 | functionName: "test", 1350 | isBlockCoverage: true, 1351 | ranges: [ 1352 | { 1353 | count: 4, 1354 | endOffset: 4, 1355 | startOffset: 0 1356 | }, 1357 | { 1358 | count: 2, 1359 | endOffset: 3, 1360 | startOffset: 1 1361 | } 1362 | ] 1363 | } 1364 | ], 1365 | scriptId: "0", 1366 | url: "/lib.js" 1367 | } 1368 | ] 1369 | }); 1370 | }); 1371 | [ 1372 | "test_coverage_merge_is_block_coverage_test.json", 1373 | "test_coverage_merge_issue_2_mixed_is_block_coverage_test.json", 1374 | "test_coverage_merge_node_10_internal_errors_one_of_test.json", 1375 | "test_coverage_merge_reduced_test.json", 1376 | "test_coverage_merge_simple_test.json", 1377 | "test_coverage_merge_various_test.json" 1378 | ].forEach(function (file) { 1379 | jstestIt(file, function () { 1380 | file = testCoverageMergeData[file]; 1381 | file.forEach(function ({ 1382 | expected, 1383 | inputs 1384 | }) { 1385 | assertJsonEqual(v8CoverageListMerge(inputs), expected); 1386 | }); 1387 | }); 1388 | }); 1389 | jstestIt(( 1390 | "merge multiple node-sqlite coverage files" 1391 | ), function () { 1392 | let data1 = [ 1393 | "test_v8_coverage_node_sqlite_9884_1633662346346_0.json", 1394 | "test_v8_coverage_node_sqlite_13216_1633662333140_0.json" 1395 | ].map(function (file) { 1396 | return testCoverageMergeData[file]; 1397 | }); 1398 | let data2 = testCoverageMergeData[ 1399 | "test_v8_coverage_node_sqlite_merged.json" 1400 | ]; 1401 | data1 = v8CoverageListMerge(data1); 1402 | data1 = v8CoverageListMerge([data1]); 1403 | 1404 | // Debug data1. 1405 | // await moduleFs.promises.writeFile( 1406 | // ".test_v8_coverage_node_sqlite_merged.json", 1407 | // JSON.stringify(objectDeepCopyWithKeysSorted(data1), undefined, 4) + "\n" 1408 | // ); 1409 | 1410 | assertJsonEqual(data1, data2); 1411 | }); 1412 | }); 1413 | 1414 | jstestDescribe(( 1415 | "test v8CoverageReportCreate handling-behavior" 1416 | ), function testBehaviorV8CoverageReportCreate() { 1417 | jstestIt(( 1418 | "test null-case handling-behavior" 1419 | ), async function () { 1420 | await assertErrorThrownAsync(function () { 1421 | return v8CoverageReportCreate({}); 1422 | }, "invalid coverageDir"); 1423 | }); 1424 | jstestIt(( 1425 | "test coverage-report jslint.mjs handling-behavior" 1426 | ), async function () { 1427 | // test remove-old-coverage handling-behavior 1428 | await fsWriteFileWithParents( 1429 | ".tmp/coverage_jslint/coverage-0-0-0.json", 1430 | "" 1431 | ); 1432 | await jslint.jslint_cli({ 1433 | console_error: noop, // comment to debug 1434 | mode_cli: true, 1435 | process_argv: [ 1436 | "node", "jslint.mjs", 1437 | "v8_coverage_report=.tmp/coverage_jslint", 1438 | "--exclude=aa.js", 1439 | "--include-node-modules=1", 1440 | "--include=jslint.mjs", 1441 | "node", "jslint.mjs" 1442 | ] 1443 | }); 1444 | }); 1445 | [ 1446 | [ 1447 | "v8CoverageReportCreate_high.js", ( 1448 | "switch(0){\n" 1449 | + "case 0:break;\n" 1450 | + "}\n" 1451 | ) 1452 | ], [ 1453 | "v8CoverageReportCreate_ignore.js", ( 1454 | "/*coverage-ignore-file*/\n" 1455 | + "switch(0){\n" 1456 | + "case 0:break;\n" 1457 | + "}\n" 1458 | ) 1459 | ], [ 1460 | "v8CoverageReportCreate_low.js", ( 1461 | "switch(0){\n" 1462 | + "case 1:break;\n" 1463 | + "case 2:break;\n" 1464 | + "case 3:break;\n" 1465 | + "case 4:break;\n" 1466 | + "}\n" 1467 | ) 1468 | ], [ 1469 | "v8CoverageReportCreate_medium.js", ( 1470 | "switch(0){\n" 1471 | + "case 0:break;\n" 1472 | + "case 1:break;\n" 1473 | + "case 2:break;\n" 1474 | + "}\n" 1475 | ) 1476 | ] 1477 | ].forEach(function ([ 1478 | file, data 1479 | ], ii) { 1480 | jstestIt(file, async function () { 1481 | let dir = ".tmp/coverage_" + ii + "/"; 1482 | file = dir + file; 1483 | await fsWriteFileWithParents(file, data); 1484 | await jslint.jslint_cli({ 1485 | console_error: noop, // comment to debug 1486 | mode_cli: true, 1487 | process_argv: [ 1488 | "node", "jslint.mjs", 1489 | "v8_coverage_report=" + dir, 1490 | "node", 1491 | file 1492 | ] 1493 | }); 1494 | }); 1495 | }); 1496 | jstestIt(( 1497 | "test npm handling-behavior" 1498 | ), async function () { 1499 | await jslint.jslint_cli({ 1500 | console_error: noop, // comment to debug 1501 | mode_cli: true, 1502 | process_argv: [ 1503 | "node", "jslint.mjs", 1504 | "v8_coverage_report=.tmp/coverage_npm", 1505 | "npm", "--version" 1506 | ] 1507 | }); 1508 | }); 1509 | jstestIt(( 1510 | "test misc handling-behavior" 1511 | ), async function () { 1512 | await Promise.all([ 1513 | [ 1514 | ".tmp/coverage_misc/aa.js", "\n".repeat(0x100) 1515 | ], [ 1516 | ".tmp/coverage_misc/coverage-0-0-0.json", JSON.stringify({ 1517 | "result": [ 1518 | { 1519 | "functions": [ 1520 | { 1521 | "functionName": "", 1522 | "isBlockCoverage": true, 1523 | "ranges": [ 1524 | { 1525 | "count": 1, 1526 | "endOffset": 0xf0, 1527 | "startOffset": 0x10 1528 | }, 1529 | { 1530 | "count": 1, 1531 | "endOffset": 0x40, 1532 | "startOffset": 0x20 1533 | }, 1534 | { 1535 | "count": 1, 1536 | "endOffset": 0x80, 1537 | "startOffset": 0x60 1538 | }, 1539 | { 1540 | "count": 0, 1541 | "endOffset": 0x45, 1542 | "startOffset": 0x25 1543 | }, 1544 | { 1545 | "count": 0, 1546 | "endOffset": 0x85, 1547 | "startOffset": 0x65 1548 | } 1549 | ] 1550 | } 1551 | ], 1552 | "scriptId": "0", 1553 | "url": "file:///" + modulePath.resolve( 1554 | ".tmp/coverage_misc/aa.js" 1555 | ) 1556 | } 1557 | ] 1558 | }, undefined, 4) 1559 | ] 1560 | ].map(async function ([ 1561 | file, data 1562 | ]) { 1563 | await fsWriteFileWithParents(file, data); 1564 | })); 1565 | await jslint.jslint_cli({ 1566 | console_error: noop, // comment to debug 1567 | mode_cli: true, 1568 | process_argv: [ 1569 | "node", "jslint.mjs", 1570 | "v8_coverage_report=.tmp/coverage_misc" 1571 | // "node", ".tmp/coverage_misc/aa.js" 1572 | ] 1573 | }); 1574 | }); 1575 | }); 1576 | --------------------------------------------------------------------------------