-
- Description and source-code:
async function assertErrorThrownAsync(asyncFunc, regexp) {
let err;
try {
await asyncFunc();
} catch (errCaught) {
err = errCaught;
}
assertOrThrow(err, "No error thrown.");
assertOrThrow(
!regexp || new RegExp(regexp).test(err.message),
err
);
}
- Example usage:
...
"npm", "--version"
]
});
});
jstestIt((
"test null-case handling-behavior"
), async function () {
await assertErrorThrownAsync(function () {
return v8CoverageReportCreate({});
}, "invalid coverageDir");
});
jstestIt((
"test report-fixture handling-behavior"
), async function () {
const fixtureList = [
...
-
- Description and source-code:
function assertJsonEqual(aa, bb, message) {
aa = JSON.stringify(objectDeepCopyWithKeysSorted(aa), undefined, 1);
bb = JSON.stringify(objectDeepCopyWithKeysSorted(bb), undefined, 1);
if (aa !== bb) {
throw new Error(
"\n" + aa + "\n!==\n" + bb +
(
typeof message === "string"
? " - " + message
: message
? " - " + JSON.stringify(message)
: ""
)
);
}
}
- Example usage:
...
}
]
});
});
jstestIt((
"test merge-unshared-function handling-behavior"
), function () {
assertJsonEqual(v8CoverageListMerge([
{
result: [
{
functions: [
{
functionName: "test",
isBlockCoverage: true,
...
-
- Description and source-code:
function assertOrThrow(condition, message) {
if (!condition) {
throw (
(!message || typeof message === "string")
? new Error(String(message).slice(0, 2048))
: message
);
}
}
- Example usage:
...
process_argv: [
"node", "jslint.mjs",
"v8_coverage_report=" + dir,
"node",
file
]
});
assertOrThrow((
await moduleFs.promises.readFile(dir + file + ".html", "utf8")
).includes(
"<span class=\"uncovered\">&& bb.cc</span><span>;</span>"
), "expected a hole closing mid-line in " + dir + file + ".html");
assertOrThrow((
await moduleFs.promises.readFile(dir + file + ".html", "utf8")
).includes(
...
-
- Description and source-code:
function debug(...argList) {
consoleError("\n\ndebugInline");
consoleError(...argList);
consoleError("\n");
if (consoleError === Object) {
consoleError = console.error;
}
return argList[0];
}
- Example usage:
...
if (consoleError === Object) {
consoleError = console.error;
}
return argList[0];
}
return debug;
}());
debugInline(); // coverage-hack
const jslint_autofix_warning_list = [ //jslint-ignore-line
"expected_a_at_b_c",
"expected_a_at_end",
"expected_line_break_a_b",
"expected_space_a_b",
"unexpected_space_a_b",
...
-
- Description and source-code:
async function fsWriteFileWithParents(pathname, data) {
await moduleFsInit();
// Try writing to pathname.
try {
await moduleFs.promises.writeFile(pathname, data);
} catch (ignore) {
// Lazy mkdirp.
await moduleFs.promises.mkdir(modulePath.dirname(pathname), {
recursive: true
});
// Retry writing to pathname.
await moduleFs.promises.writeFile(pathname, data);
}
console.error("wrote file " + pathname);
}
- Example usage:
...
]
];
await Promise.all(fixtureList.map(async function ([
file, data
], ii) {
const dir = ".tmp/coverage_" + ii + "/";
file = dir + file;
await fsWriteFileWithParents(file, data);
await jslint.jslint_cli({
console_error: noop, // comment to debug
mode_cli: true,
process_argv: [
"node", "jslint.mjs",
"v8_coverage_report=" + dir,
"node",
...
-
- Description and source-code:
function globExclude({
excludeList = [],
includeList = [],
pathnameList = []
}) {
function globAssertNotWeird(list, name) {
// This function will check if <list> of strings contain weird characters.
[
[
"\n", (
/^.*?([\u0000-\u0007\r]).*/gm
)
],
[
"\r", (
/^.*?([\n]).*/gm
)
]
].forEach(function ([
separator, rgx
]) {
list.join(separator).replace(rgx, function (match0, char) {
throw new Error(
"Weird character " +
JSON.stringify(char) +
" found in " + name + " " +
JSON.stringify(match0)
);
});
});
}
function globToRegexp(pattern) {
// This function will translate glob <pattern> to javascript-regexp,
// which javascript can then use to "glob" pathnames.
let ii = 0;
let isClass = false;
let strClass = "";
let strRegex = "";
pattern = pattern.replace((
/\/\/+/g
), "/");
pattern = pattern.replace((
/\*\*\*+/g
), "**");
pattern.replace((
/\\\\|\\\[|\\\]|\[|\]|./g
), function (match0) {
switch (match0) {
case "[":
if (isClass) {
strClass += "[";
return;
}
strClass += "\u0000";
strRegex += "\u0000";
isClass = true;
return;
case "]":
if (isClass) {
isClass = false;...
}
- Example usage:
...
"test/support/helper.js": (
/^test\/support\/helper\.js$/gm
)
}).forEach(function ([
pattern, rgx
]) {
assertJsonEqual(
globExclude({
excludeList: [
pattern
]
}).excludeList[0].source,
rgx.source
);
assertJsonEqual(
...
-
- Description and source-code:
function htmlEscape(str) {
return String(str)
.replace((/&/g), "&")
.replace((/</g), "<")
.replace((/>/g), ">");
}
- Example usage:
...
: "</span><span>"
);
chunk = "";
inHole = isHole;
}
chunk += char;
});
lineHtml += htmlEscape(chunk);
break;
default:
lineHtml += htmlEscape(line);
}
html += String(`
<pre>
<span class="lineno">
...
-
- Description and source-code:
function jslint(
source = "", // A text to analyze.
option_dict = empty(), // An object whose keys correspond to option
// ... names.
global_list = [] // An array of strings containing global
// ... variables that the file is allowed
// ... readonly access.
) {
const block_list = []; // The array containing all lexical-blocks.
const block_stack = []; // The stack of lexical-blocks.
const directive_list = []; // The directive comments.
const export_dict = empty(); // The exported names and values.
const function_list = []; // The array containing all functions.
const function_stack = []; // The stack of functions.
const global_dict = empty(); // The object containing the global
// ... declarations.
const import_list = []; // The array collecting all import-from strings.
const line_list = String( // The array containing source lines.
"\n" + source
).split(jslint_rgx_crlf).map(function (line_source) {
return {
line_source
};
});
const mode_autofix = (
option_dict.autofix === true
? 256
: Math.max(0, Number(option_dict.autofix) || 0)
);
const property_dict = empty(); // The object containing the tallied
// ... property names.
// jslint functions.
const state = empty(); // jslint state-object to be passed between
const syntax_dict = empty(); // The object containing the parser.
const tenure = empty(); // The predefined property registry.
const token_global = { // The global object; the outermost context.
async: 0,
context: empty(),
finally: 0,
from: 0,
function_body: tru...
}
- Example usage:
...
import fs from "fs";
(async function () {
let result;
let source = "function foo() {console.log(\u0027hello world\u0027);}\n";
// Create JSLint report from <source> in javascript.
result = jslint.jslint(source);
result = jslint.jslint_report(result);
result = `<body class="JSLINT_ JSLINT_REPORT_">\n${result}</body>\n`;
await fs.promises.mkdir(".artifact/", {recursive: true});
await fs.promises.writeFile(".artifact/jslint_report_hello.html", result);
console.error("wrote file .artifact/jslint_report_hello.html");
}());
...
-
- Description and source-code:
async function jslint_apidoc({
example_list,
github_repo,
module_list,
package_name,
pathname,
version
}) {
let elem_ii = 0;
let html;
function elem_create(moduleObj, key, moduleName) {
// This function will create a sub API Doc from elem <moduleObj>[<key>].
let example = "N/A";
let id = encodeURIComponent("apidoc.elem." + moduleName + "." + key);
let name;
let signature;
let source;
name = htmlEscape((typeof moduleObj[key]) + " " + key);
if (typeof moduleObj[key] !== "function") {
return {
name,
signature: (`
<a class="apidocElementLiA" href="#${id}">
${name}
</a>
`),
source: (`
<li>
<h2>
<a href="#${id}" id="${id}">
${name}
</a>
</h2>
</li>
`)
};
}
// init source
source = htmlEscape(trim_start(moduleObj[key].toString()));
// init signature
source = source.replace((
/(\([\S\s]*?\)) \{/
), function (match0, match1) {
signature = htmlEscape(
match1
.replace((/ *?\/\*[\S\s]*?\*\/ */g), "")
.replace((/ *?\/\/.*/g), "")
.replace((/\n{2,}/g), "\n")
);
return match0;
});
// init comment
source = source.replace((
/\n(?:\/\/.*?\n)+\n/
), "<span class=\"apidocCodeCommentSpan\">$&</span>");
// init example
example_list.some(function (example2) {
example2.replace(
new RegExp((
"((?:\\n.*?){8}(function )?)\\b" +
key +
"(\\((?:.*?\\n){8})"
), "g"),
function (ignore, header, isDeclarati...
}
- Example usage:
...
command[1] = command.slice(1).join("=");
switch (command[0]) {
// PR-362 - Add API Doc.
case "jslint_apidoc":
await jslint_apidoc({
...JSON.parse(process_argv[3]),
pathname: command[1]
});
return;
// PR-509 - Add command jslint_autofix.
...
-
- Description and source-code:
async function jslint_cli({
console_error,
console_log,
file,
import_meta_url,
mode_cli,
mode_noop,
option,
process_argv,
process_env,
process_exit,
source
}) {
let command;
let data;
let exit_code = 0;
let mode_autofix;
let mode_report;
let mode_wrapper_vim;
let result;
// PR-509 - Add command jslint_autofix.
function autofix_embedded({
code,
file,
mode_conditional,
option,
rgx,
suffix,
suffix_file
}) {
// This function will jslint each embedded block <rgx> matches, and return
// <code> with every autofixed block spliced back between the SAME delimiters
// - or undefined if no block was autofixed. <suffix> is the closing
// delimiter, which the capture deliberately excludes.
//
// A BLOCKED BLOCK IS LEFT AS IT WAS AND THE REST ARE STILL REPAIRED, unlike a
// blocked whole-file, which is not written at all.
const code_fixed = code.replace(rgx, function (match0, match1, ii) {
const result_embedded = jslint_from_file({
code: match1,
file: file + suffix_file,
line_offset: (
jslint_fudge +
// Count line-terminators the way <jslint_rgx_crlf> splits them, without
// materialising every preceding line.
(
code
.slice(0, ii)
.match(new RegExp(jslint_rgx_crlf, "g"))
?.length ||
0
)
),
mode_conditional,
option
});
if (
result_embedded === undefined ||
result_embedded.autofixed === undefined
) {
return match0;
}
return (
match0.slice(
...
}
- Example usage:
...
];
await Promise.all(fixtureList.map(async function ([
file, data
], ii) {
const dir = ".tmp/coverage_" + ii + "/";
file = dir + file;
await fsWriteFileWithParents(file, data);
await jslint.jslint_cli({
console_error: noop, // comment to debug
mode_cli: true,
process_argv: [
"node", "jslint.mjs",
"v8_coverage_report=" + dir,
"node",
file
...
-
- Description and source-code:
function jslint_phase1_split() {
return;
}
- Example usage:
...
warn_at,
warning_list
}
);
// PHASE 1. Split <source> by newlines into <line_list>.
jslint_phase1_split(state);
// PHASE 2. Lex <line_list> into <token_list>.
jslint_phase2_lex(state);
// PHASE 3. Parse <token_list> into <token_tree> using the Pratt-parser.
...
-
- Description and source-code:
function jslint_phase2_lex(state) {
const {
artifact,
directive_list,
global_dict,
global_list,
line_list,
option_dict,
stop,
stop_at,
tenure,
token_global,
token_list,
warn,
warn_at,
warning_list
} = state;
const mode_digits_numeric_separator = 1;
const mode_digits_regexp_quantifier = 2;
const mode_digits_unicode_escape = 3;
const opener_stack = []; // Stack of opener tokens: (, [, {, ${.
let char; // The current character being lexed.
let column = 0; // The column number of the next character.
let from; // The starting column number of the token.
let from_mega; // The starting column of megastring.
let line = 0; // The line number of the next character.
let line_disable; // The starting line of "/*jslint-disable*/".
let line_mega; // The starting line of megastring.
let line_source = ""; // The remaining line source string.
let line_whole = ""; // The whole line source string.
let mode_directive = true; // true if directives are still allowed.
let mode_mega = false; // true if currently parsing a megastring
// ... literal.
let mode_regexp; // true if regular expression literal seen on
// ... this line.
let opener_popped = empty(); // Last token popped from opener_stack.
let snippet = ""; // A piece of string.
let token_1; // The first token.
let token_prv = token_global; // The previous token including
// ... comments.
let token_prv_expr = token_global; // The previous token excluding
// ... comments....
}
- Example usage:
...
// PHASE 1. Split <source> by newlines into <line_list>.
jslint_phase1_split(state);
// PHASE 2. Lex <line_list> into <token_list>.
jslint_phase2_lex(state);
// PHASE 3. Parse <token_list> into <token_tree> using the Pratt-parser.
jslint_phase3_parse(state);
// PHASE 4. Walk <token_tree>, traversing all nodes of the tree. It is a
// recursive traversal. Each node may be processed on the way down
...
-
- Description and source-code:
function jslint_phase3_parse(state) {
// Parsing:
// Parsing weaves the tokens into an abstract syntax tree. During that process,
// a token may be given any of these properties:
// arity string
// name identifier
// name_alias identifier
// expression expressions
// block statements
// else statements (else, default, catch)
// Specialized tokens may have additional properties.
const {
artifact,
block_stack,
export_dict,
function_list,
function_stack,
global_dict,
import_list,
is_equal,
line_list,
option_dict,
property_dict,
scope_block_pop,
scope_block_push,
scope_function_pop,
scope_function_push,
scope_report_push,
stop,
syntax_dict,
tenure,
token_global,
token_list,
warn,
warn_at,
warning_list
} = state;
let anon = "anonymous"; // The guessed name for anonymous functions.
let mode_var; // "var" if using var; "let" if using let.
let scope_block; // The current block-scope.
let scope_function; // The current function-scope.
let token_ii = 0; // The index of the next token in <token_list>.
let token_now = token_global; // The current token being examined in
// ... the parse.
let token_nxt = token_global; // The next token to be examined in
// ... <token_list>.
let token_prv = token_global; // The previous token examined.
function advance(id, match) {
// Produce the next token.
// Attempt to give helpful names to anonymous functions.
if (
token_now.identifier &&
token_now.id !== "function" &&...
}
- Example usage:
...
// PHASE 2. Lex <line_list> into <token_list>.
jslint_phase2_lex(state);
// PHASE 3. Parse <token_list> into <token_tree> using the Pratt-parser.
jslint_phase3_parse(state);
// PHASE 4. Walk <token_tree>, traversing all nodes of the tree. It is a
// recursive traversal. Each node may be processed on the way down
// (preaction) and on the way up (postaction).
if (!state.mode_json) {
jslint_phase4_walk(state);
...
-
- Description and source-code:
function jslint_phase4_walk(state) {
const {
artifact,
block_stack,
function_stack,
global_dict,
is_equal,
is_weird,
option_dict,
scope_block_pop,
scope_block_push,
scope_function_pop,
scope_function_push,
scope_report_push,
syntax_dict,
token_global,
warn
} = state;
let postaction;
let postamble;
let posts = empty();
let preaction;
let preamble;
let pres = empty();
// The relational operators.
let relationop = object_assign_from_list(empty(), [
"!=", "!==", "<", "<=", "==", "===", ">", ">="
], true);
let scope_block; // The current block-scope.
let scope_function; // The current function-scope.
// Ambulation of the parse tree.
function action(when) {
// Produce a function that will register task functions that will be called as
// the tree is traversed.
return function (arity, id, task) {
let a_set = when[arity];
let i_set;
// If this arity has no registrations yet, then create a set object to hold
// them.
if (a_set === undefined) {
a_set = empty();
when[arity] = a_set;
}
// If this id has no registrations yet, then create a set array to hold them.
i_set = a_set[id];
if (i_set === undefined) {
i_set = [];
a_set[id] = i_set;
}
// Register the task with the arity and the id.
i_set.push(task);
};
}
function amble(when) {
// Produce a function that will act on the tasks registered by an action
// function while walking the tree.
return function (the_toke...
}
- Example usage:
...
jslint_phase3_parse(state);
// PHASE 4. Walk <token_tree>, traversing all nodes of the tree. It is a
// recursive traversal. Each node may be processed on the way down
// (preaction) and on the way up (postaction).
if (!state.mode_json) {
jslint_phase4_walk(state);
}
// PHASE 5. Check whitespace between tokens in <token_list>.
if (
!state.mode_json &&
!warning_list.some(function ({
...
-
- Description and source-code:
function jslint_phase5_whitage(state) {
const {
artifact,
block_list,
option_dict,
token_global,
token_list,
warn
} = state;
const indent_stack = [];
let closer = "(end)";
let dot_depth = 0;
let indentage;
let left = token_global;
let margin = 0;
let mode_indent = (
// PR-330 - Allow 2-space indent.
option_dict.indent2
? 2
: 4
);
let nr_comments_skipped = 0;
let open = true;
let opening = true;
let right;
// This is the set of infix operators that require a space on each side.
let spaceop = object_assign_from_list(empty(), [
"!=", "!==",
"%", "%=",
"&", "&&", "&&=", "&=",
"*", "**", "**=", "*=",
"+=",
"-=",
"/", "/=",
"<", "<<", "<<=", "<=",
"=", "==", "===", "=>",
">", ">=", ">>", ">>=", ">>>", ">>>=",
"??", "??=",
"^", "^=",
"|", "|=", "||", "||="
], true);
function at_margin(fit) {
const at = margin + fit;
if (right.from !== at) {
return expected_at(at);
}
}
function delve(the_block) {
Object.keys(the_block.context).forEach(function (id) {
const name = the_block.context[id];
if (id !== "ignore" && name.scope_declared === the_block) {
// test_cause:
// ["function aa(aa) {return aa;}", "delve", "(live)", "", 0]
if (!name.used) {
// test_cause:
// ["function aa(){bb:while(aa){aa();}}", "delve", "unused_a", "bb", 15]
// ["function aa(bb){return;}", "delve", "unused_a", "bb", 13]
// ["let aa;", "delve", "unused_a", "aa", 5]
// ["let aa=0;try{aa();}catch(bb){aa();}", "delve", "unused_a", "bb", 26]
warn("unused_a", name);
} else if (!name.assign...
}
- Example usage:
...
// PR-511 - jslint-autofix - Warning 'too_long' no longer blocks autofix.
return !jslint_autofix_warning_list.includes(code);
}
return true;
})
) {
jslint_phase5_whitage(state);
}
// PHASE 6. Autofix whitespace-warnings in <source>, and re-lint the result.
if (mode_autofix) {
autofixed = jslint_phase6_autofix(state) || state.source;
if (autofixed !== state.source) {
...
-
- Description and source-code:
function jslint_phase6_autofix(state) {
const line_crlf = jslint_rgx_crlf.exec(state.source)?.[0] || "\n";
const line_list = state.line_list.map(function ({
line_source
}) {
return line_source;
});
const warning_list = state.warning_list;
if (warning_list.length === 0) {
return;
}
for (const {code} of warning_list) {
if (!jslint_autofix_warning_list.includes(code)) {
return;
}
}
// Apply each fix RIGHT-TO-LEFT within a line, so an earlier fix cannot
// invalidate a later fix's column, and BOTTOM-UP across lines, so every line
// a splice shifts has already been visited.
warning_list.slice().sort(function (aa, bb) {
return bb.line - aa.line || bb.column - aa.column;
}).forEach(function ({
a,
b,
c,
code,
column,
d,
line
}) {
const ii = column - 1;
const line_source = line_list[line];
let indentage_at;
let jj = ii;
switch (code) {
case "expected_a_at_b_c":
// expected_a_at_b_c is indentation. <at_margin>, <one_space> and the two label
// callers of <expected_at> warn a token that belongs at a margin, and a label
// can be mid-line, such as 'cc:' after 'bb();'. Unless a warning such as
// weird_loop blocks autofix, that reaches here, so keep the mid-line branch.
indentage_at = line_source.length - line_source.trimStart().length;
// A MID-LINE token cannot be re-indented, but it does not need to be skipped,
// since all four callers warn a token that belongs AT a margin and therefore
// on its OWN line. So split first and indent the remainder, which also lands a
// trailing closer correctly, and is what line-breaks a single-line ternary.
if (ii !== indentage_at) {
line_list.splice(
line,
...
}
- Example usage:
...
) {
jslint_phase5_whitage(state);
}
// PHASE 6. Autofix whitespace-warnings in <source>, and re-lint the result.
if (mode_autofix) {
autofixed = jslint_phase6_autofix(state) || state.source;
if (autofixed !== state.source) {
// Recurse jslint.
result_autofix = jslint(
autofixed,
{
...
-
- Description and source-code:
function jslint_report({
autofix,
exports,
froms,
functions,
global,
json,
module,
property,
stop,
warnings
}) {
const autofix_blocked = autofix && warnings.some(function ({
code
}) {
return !jslint_autofix_warning_list.includes(code);
});
let html = "";
let length_80 = 1111;
function address(line = 1, column = 1) {
// This function will create HTML address element from <line> and <column>
return `<address>${Number(line)}: ${Number(column)}</address>`;
}
function detail(title, list) {
return (
(Array.isArray(list) && list.length > 0)
? (
// Google Lighthouse Accessibility - <dl>'s do not contain only properly-ordered
// <dt> and <dd> groups, <script>, <template> or <div> elements.
"<dl>" +
"<dt>" + htmlEscape(title) + "</dt>" +
"<dd>" + list.map(htmlEscape).join(", ") + "</dd>" +
"</dl>"
)
: ""
);
}
html += String(`
<style class="JSLINT_REPORT_STYLE">
/* jslint utility2:true */
/*csslint box-model: false, ids:false */
/*csslint ignore:start*/
@font-face {
font-display: swap;
font-family: "Daley";
src: url(
"data:font/woff2;base64,d09GMgABAAAAABy4AA4AAAAAThwAABxiAAEAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAABmAAgiQINAmcDBEICuc41DEBNgIkA4R2C4I+AAQgBYkuByAMgScfYUIF\
7NgjsHGAbcDVFkXZ5Jwd+P96IGPc9rl9ETBEaCzCJkvY2UpziRZ7zftZWk8052U9+NqX6vXL\
KDflSQnlJ0bP+QnPQAy744n9mup6H9PaCDFwM5zjf8exB89bZ1cdrYOP0NgnuRDRWlk9u/fE\
llkxqmfH8lmRQ/DAmER9opk9wR6suc1LvTiXNEe1vbhUCH2USgnEwH3vUm05JQqejGvZvOt...
}
- Example usage:
...
editor.on("lintJslintAfter", function (options) {
// Generate jslint-report from options.result.
document.querySelector(
".JSLINT_REPORT_"
).innerHTML = window.jslint.jslint_report(options.result);
});
// Manually trigger linter.
editor.performLint();
});
</script>
...
-
- Description and source-code:
async function jstestDescribe(description, testFunction) {
const describe = {
description,
itList: []
};
const describePrv = jstestDescribePrv;
const recordBody = {
describe: description,
description: "jstestDescribe body",
status: "pending"
};
let message;
let result;
// Record <description> before the first await, since describes then
// interleave and finish out of source order.
jstestDescribePrv = description;
// Init jstestTimeStart.
if (jstestTimeStart === undefined) {
jstestTimeStart = Date.now();
process.on("exit", jstestOnExit);
}
// PR-517 - Collect, then run. Record the body as pending, then await it, so a
// body that hangs before registering fails at exit instead of passing with 0
// tests. A body that throws crashes node as an unhandled rejection, leaving its
// record pending. A body that settles clean leaves no record.
jstestItRecordList.push(recordBody);
await jstestDescribeRun(describe, testFunction);
jstestItRecordList.splice(jstestItRecordList.indexOf(recordBody), 1);
// PR-517 - Assert this describe's tests, then this describe, are in ASCII
// order. Record them before any test runs, so a hung sibling cannot hide them
// at exit.
result = [
jstestOrderCheck(describe.itList.map(function (record) {
return record.description;
})),
jstestOrderCheck([describePrv, description])
].filter(Boolean).map(function ([err, descriptionIt]) {
return {
describe: description,
description: descriptionIt,
err,
status: "failed"
};
});
jstestItRecordList.push(...result);
await Promise.all(describe.itList.map(async function (record) {
try {
await record.testFunction();
record.status =...
}
- Example usage:
...
scriptId: "0"
}
]
});
});
});
jstestDescribe((
"test v8CoverageReportCreate handling-behavior"
), function () {
jstestIt((
"test coverage-hole-closing-midline handling-behavior"
), async function () {
// Pin two branches of <v8CoverageReportCreate> that line coverage cannot see.
...
-
- Description and source-code:
function jstestIt(description, testFunction) {
const describe = jstestDescribeNow;
// PR-517 - Throw outside a describe body's synchronous part, since no describe
// would run or report this test.
if (!describe) {
throw new Error(
"jstestIt " + JSON.stringify(description) +
" called outside a jstestDescribe body, or after an await"
);
}
// PR-517 - Run only a test whose "<describe> - <it>" matches opt-in regexp
// npm_config_mode_test_filter, e.g.
// npm_config_mode_test_filter="jstestXxx.*pending" npm test
// Prefer the env form, since npm 11 warns the flag form --mode-test-filter
// stops working in npm 12.
if (!new RegExp(
process.env.npm_config_mode_test_filter || ""
).test(describe.description + " - " + description)) {
return;
}
// PR-517 - Record this test as pending from registration, so <jstestReport>
// sees it even if its describe never runs or prints.
jstestItRecordList.push({
describe: describe.description,
description,
status: "pending",
testFunction
});
describe.itList.push(jstestItRecordList.at(-1));
}
- Example usage:
...
jstestIt((
"test null-case handling-behavior"
), async function () {
await assertErrorThrownAsync(function () {
return v8CoverageReportCreate({});
}, "invalid coverageDir");
});
jstestIt((
"test report-fixture handling-behavior"
), async function () {
const fixtureList = [
[
"v8CoverageReportCreate_high.js", (
"switch(0){\n" +
"case 0:break;\n" +
...
-
- Description and source-code:
async function moduleFsInit() {
// State 3 - Modules already imported.
if (moduleFs !== undefined) {
return;
}
// State 2 - Wait while modules are importing.
if (moduleFsInitResolveList !== undefined) {
return new Promise(function (resolve) {
moduleFsInitResolveList.push(resolve);
});
}
// State 1 - Start importing modules.
moduleFsInitResolveList = [];
[
moduleChildProcess,
moduleFs,
modulePath,
moduleUrl
] = await Promise.all([
import("child_process"),
import("fs"),
import("path"),
import("url")
]);
while (moduleFsInitResolveList.length > 0) {
moduleFsInitResolveList.shift()();
}
}
- Example usage:
...
});
}
await (async function init() {
// Coverage-hack - Ugly-hack to get test-coverage for all initialization-states.
moduleFsInit();
moduleFsInit();
// A runner that ended every async test before it ran would also pass the tests
// that check it, so check one async failure here, outside any jstestIt.
await childRun({}, String(`
jslint.jstestDescribe("aa", function () {
...
-
- Description and source-code:
function noop(value) {
return value;
}
- Example usage:
...
).includes(
"<span class=\"ignore\">&& ee.ff</span><span>;"
), "expected an ignored hole in " + dir + file + ".html");
});
jstestIt((
"test coverage-ignore handling-behavior"
), function () {
switch (noop() && noop()) { //coverage-ignore-line
case 1: //coverage-ignore-line
break; //coverage-ignore-line
/*coverage-disable*/
case 2:
break;
/*coverage-enable*/
case undefined:
...
-
- Description and source-code:
function objectDeepCopyWithKeysSorted(obj) {
let sorted;
if (typeof obj !== "object" || !obj) {
return obj;
}
// Recursively deep-copy list with child-keys sorted.
if (Array.isArray(obj)) {
return obj.map(objectDeepCopyWithKeysSorted);
}
// Recursively deep-copy obj with keys sorted.
sorted = Object.create(null);
Object.keys(obj).sort().forEach(function (key) {
sorted[key] = objectDeepCopyWithKeysSorted(obj[key]);
});
return sorted;
}
- Example usage:
...
];
data1 = v8CoverageListMerge(data1);
data1 = v8CoverageListMerge([data1]);
// Debug data1.
// await moduleFs.promises.writeFile(
// ".test_v8_coverage_node_sqlite_merged.json",
// JSON.stringify(objectDeepCopyWithKeysSorted(data1), undefined, 4) + "\n"
// );
assertJsonEqual(data1, data2);
});
jstestIt((
"test merge-one-list handling-behavior"
), function () {
...
-
- Description and source-code:
function v8CoverageListMerge(processCovs) {
let resultMerged = []; // List of merged scripts from processCovs.
let urlToScriptDict = new Map(); // Map scriptCov.url to scriptCovs.
function compareRangeList(aa, bb) {
// Compares two range coverages.
// The ranges are first ordered by ascending `startOffset` and then by
// descending `endOffset`.
// This corresponds to a pre-order tree traversal.
if (aa.startOffset !== bb.startOffset) {
return aa.startOffset - bb.startOffset;
}
return bb.endOffset - aa.endOffset;
}
function dictKeyValueAppend(dict, key, value) {
// This function will append <value> to list <dict>[<key>].
let list = dict.get(key);
if (list === undefined) {
list = [];
dict.set(key, list);
}
list.push(value);
}
function mergeTreeList(parentTrees) {
// This function will return RangeTree object with <parentTrees> merged into
// property-children.
// @precondition Same `start` and `end` for all the parentTrees
if (parentTrees.length <= 1) {
return parentTrees[0];
}
// new RangeTree().
return {
// Merge parentTrees into property-children.
children: mergeTreeListToChildren(parentTrees),
delta: parentTrees.reduce(function (aa, bb) {
return aa + bb.delta;
}, 0),
end: parentTrees[0].end,
start: parentTrees[0].sta...
}
- Example usage:
...
}
]
});
});
jstestIt((
"test merge-unshared-function handling-behavior"
), function () {
assertJsonEqual(v8CoverageListMerge([
{
result: [
{
functions: [
{
functionName: "test",
isBlockCoverage: true,
...
-
- Description and source-code:
async function v8CoverageReportCreate({
consoleError,
coverageDir,
processArgv = []
}) {
let cwd;
let excludeList = [];
let exitCode = 0;
let fileDict;
let includeList = [];
let modeIncludeNodeModules;
let processArgElem;
let promiseList = [];
let v8CoverageObj;
function htmlRender({
fileList,
lineList,
modeIndex,
pathname
}) {
let html;
let padLines;
let padPathname;
let txt;
let txtBorder;
html = "";
html += String(`
<!DOCTYPE html>
<html lang="en">
<head>
<title>V8 Coverage Report</title>
<style>
/* jslint utility2:true */
/*csslint ignore:start*/
.coverage,
.coverage a,
.coverage div,
.coverage pre,
.coverage span,
.coverage table,
.coverage tbody,
.coverage td,
.coverage th,
.coverage thead,
.coverage tr {
box-sizing: border-box;
font-family: monospace;
}
/*csslint ignore:end*/
/* css - coverage_report - general */
body {
margin: 0;
}
.coverage pre {
margin: 5px 0;
}
.coverage table {
border-collapse: collapse;
}
.coverage td,
.coverage th {
border: 1px solid #777;
line-height: 20px;
margin: 0;
padding: 5px 10px;
}
.coverage td span {
display: inline-block;
width: 100%;
}
.coverage .content {
padding: 0 5px;
}
.coverage .content a {
text-decoration: none;
}
.coverage .count {
margin: 0 5px;
padding: 0 5px;
}
.coverage .footer,
.coverage .header {
padding: 20px;
}
.coverage .footer {
text-align: center;
}
.coverage .percentbar {
height: 12px;
margin: 2px 0;
min-width: 200px;
position: relative;
width: 100%;...
}
- Example usage:
...
/*jslint node*/
import jslint from "../jslint.mjs";
(async function () {
// Create V8 coverage report from program `npm run test` in javascript.
await jslint.v8CoverageReportCreate({
coverageDir: "../.artifact/coverage_sqlite3_js/",
processArgv: [
"--exclude=tes?/",
"--exclude=tes[!0-9A-Z_a-z-]/",
"--exclude=tes[0-9A-Z_a-z-]/",
"--exclude=tes[^0-9A-Z_a-z-]/",
"--exclude=test/**/*.js",
...
-
-