Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

View File

@ -0,0 +1,417 @@
'use strict';
const {
ArrayPrototypeJoin,
ArrayPrototypePop,
ArrayPrototypeSlice,
Error,
ErrorCaptureStackTrace,
ObjectAssign,
ObjectDefineProperty,
ObjectGetPrototypeOf,
ObjectPrototypeHasOwnProperty,
String,
StringPrototypeRepeat,
StringPrototypeSlice,
StringPrototypeSplit,
} = primordials;
const { isError } = require('internal/util');
const { inspect } = require('internal/util/inspect');
const colors = require('internal/util/colors');
const { validateObject } = require('internal/validators');
const { isErrorStackTraceLimitWritable } = require('internal/errors');
const { myersDiff, printMyersDiff, printSimpleMyersDiff } = require('internal/assert/myers_diff');
const kReadableOperator = {
deepStrictEqual: 'Expected values to be strictly deep-equal:',
partialDeepStrictEqual: 'Expected values to be partially and strictly deep-equal:',
strictEqual: 'Expected values to be strictly equal:',
strictEqualObject: 'Expected "actual" to be reference-equal to "expected":',
deepEqual: 'Expected values to be loosely deep-equal:',
notDeepStrictEqual: 'Expected "actual" not to be strictly deep-equal to:',
notStrictEqual: 'Expected "actual" to be strictly unequal to:',
notStrictEqualObject:
'Expected "actual" not to be reference-equal to "expected":',
notDeepEqual: 'Expected "actual" not to be loosely deep-equal to:',
notIdentical: 'Values have same structure but are not reference-equal:',
notDeepEqualUnequal: 'Expected values not to be loosely deep-equal:',
};
const kMaxShortStringLength = 12;
const kMaxLongStringLength = 512;
const kMethodsWithCustomMessageDiff = ['deepStrictEqual', 'strictEqual', 'partialDeepStrictEqual'];
function copyError(source) {
const target = ObjectAssign(
{ __proto__: ObjectGetPrototypeOf(source) },
source,
);
ObjectDefineProperty(target, 'message', {
__proto__: null,
value: source.message,
});
if (ObjectPrototypeHasOwnProperty(source, 'cause')) {
let { cause } = source;
if (isError(cause)) {
cause = copyError(cause);
}
ObjectDefineProperty(target, 'cause', { __proto__: null, value: cause });
}
return target;
}
function inspectValue(val) {
// The util.inspect default values could be changed. This makes sure the
// error messages contain the necessary information nevertheless.
return inspect(val, {
compact: false,
customInspect: false,
depth: 1000,
maxArrayLength: Infinity,
// Assert compares only enumerable properties (with a few exceptions).
showHidden: false,
// Assert does not detect proxies currently.
showProxy: false,
sorted: true,
// Inspect getters as we also check them when comparing entries.
getters: true,
});
}
function getErrorMessage(operator, message) {
return message || kReadableOperator[operator];
}
function checkOperator(actual, expected, operator) {
// In case both values are objects or functions explicitly mark them as not
// reference equal for the `strictEqual` operator.
if (
operator === 'strictEqual' &&
((typeof actual === 'object' &&
actual !== null &&
typeof expected === 'object' &&
expected !== null) ||
(typeof actual === 'function' && typeof expected === 'function'))
) {
operator = 'strictEqualObject';
}
return operator;
}
function getColoredMyersDiff(actual, expected) {
const header = `${colors.green}actual${colors.white} ${colors.red}expected${colors.white}`;
const skipped = false;
const diff = myersDiff(StringPrototypeSplit(actual, ''), StringPrototypeSplit(expected, ''));
let message = printSimpleMyersDiff(diff);
if (skipped) {
message += '...';
}
return { message, header, skipped };
}
function getStackedDiff(actual, expected) {
const isStringComparison = typeof actual === 'string' && typeof expected === 'string';
let message = `\n${colors.green}+${colors.white} ${actual}\n${colors.red}- ${colors.white}${expected}`;
const stringsLen = actual.length + expected.length;
const maxTerminalLength = process.stderr.isTTY ? process.stderr.columns : 80;
const showIndicator = isStringComparison && (stringsLen <= maxTerminalLength);
if (showIndicator) {
let indicatorIdx = -1;
for (let i = 0; i < actual.length; i++) {
if (actual[i] !== expected[i]) {
// Skip the indicator for the first 2 characters because the diff is immediately apparent
// It is 3 instead of 2 to account for the quotes
if (i >= 3) {
indicatorIdx = i;
}
break;
}
}
if (indicatorIdx !== -1) {
message += `\n${StringPrototypeRepeat(' ', indicatorIdx + 2)}^`;
}
}
return { message };
}
function getSimpleDiff(originalActual, actual, originalExpected, expected) {
let stringsLen = actual.length + expected.length;
// Accounting for the quotes wrapping strings
if (typeof originalActual === 'string') {
stringsLen -= 2;
}
if (typeof originalExpected === 'string') {
stringsLen -= 2;
}
if (stringsLen <= kMaxShortStringLength && (originalActual !== 0 || originalExpected !== 0)) {
return { message: `${actual} !== ${expected}`, header: '' };
}
const isStringComparison = typeof originalActual === 'string' && typeof originalExpected === 'string';
// colored myers diff
if (isStringComparison && colors.hasColors) {
return getColoredMyersDiff(actual, expected);
}
return getStackedDiff(actual, expected);
}
function isSimpleDiff(actual, inspectedActual, expected, inspectedExpected) {
if (inspectedActual.length > 1 || inspectedExpected.length > 1) {
return false;
}
return typeof actual !== 'object' || actual === null || typeof expected !== 'object' || expected === null;
}
function createErrDiff(actual, expected, operator, customMessage) {
operator = checkOperator(actual, expected, operator);
let skipped = false;
let message = '';
const inspectedActual = inspectValue(actual);
const inspectedExpected = inspectValue(expected);
const inspectedSplitActual = StringPrototypeSplit(inspectedActual, '\n');
const inspectedSplitExpected = StringPrototypeSplit(inspectedExpected, '\n');
const showSimpleDiff = isSimpleDiff(actual, inspectedSplitActual, expected, inspectedSplitExpected);
let header = `${colors.green}+ actual${colors.white} ${colors.red}- expected${colors.white}`;
if (showSimpleDiff) {
const simpleDiff = getSimpleDiff(actual, inspectedSplitActual[0], expected, inspectedSplitExpected[0]);
message = simpleDiff.message;
if (typeof simpleDiff.header !== 'undefined') {
header = simpleDiff.header;
}
if (simpleDiff.skipped) {
skipped = true;
}
} else if (inspectedActual === inspectedExpected) {
// Handles the case where the objects are structurally the same but different references
operator = 'notIdentical';
if (inspectedSplitActual.length > 50) {
message = `${ArrayPrototypeJoin(ArrayPrototypeSlice(inspectedSplitActual, 0, 50), '\n')}\n...}`;
skipped = true;
} else {
message = ArrayPrototypeJoin(inspectedSplitActual, '\n');
}
header = '';
} else {
const checkCommaDisparity = actual != null && typeof actual === 'object';
const diff = myersDiff(inspectedSplitActual, inspectedSplitExpected, checkCommaDisparity);
const myersDiffMessage = printMyersDiff(diff, operator);
message = myersDiffMessage.message;
if (operator === 'partialDeepStrictEqual') {
header = `${colors.gray}${colors.hasColors ? '' : '+ '}actual${colors.white} ${colors.red}- expected${colors.white}`;
}
if (myersDiffMessage.skipped) {
skipped = true;
}
}
const headerMessage = `${getErrorMessage(operator, customMessage)}\n${header}`;
const skippedMessage = skipped ? '\n... Skipped lines' : '';
return `${headerMessage}${skippedMessage}\n${message}\n`;
}
function addEllipsis(string) {
const lines = StringPrototypeSplit(string, '\n', 11);
if (lines.length > 10) {
lines.length = 10;
return `${ArrayPrototypeJoin(lines, '\n')}\n...`;
} else if (string.length > kMaxLongStringLength) {
return `${StringPrototypeSlice(string, kMaxLongStringLength)}...`;
}
return string;
}
class AssertionError extends Error {
constructor(options) {
validateObject(options, 'options');
const {
message,
operator,
stackStartFn,
details,
// Compatibility with older versions.
stackStartFunction,
} = options;
let {
actual,
expected,
} = options;
const limit = Error.stackTraceLimit;
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = 0;
if (message != null) {
if (kMethodsWithCustomMessageDiff.includes(operator)) {
super(createErrDiff(actual, expected, operator, message));
} else {
super(String(message));
}
} else {
// Reset colors on each call to make sure we handle dynamically set environment
// variables correct.
colors.refresh();
// Prevent the error stack from being visible by duplicating the error
// in a very close way to the original in case both sides are actually
// instances of Error.
if (typeof actual === 'object' && actual !== null &&
typeof expected === 'object' && expected !== null &&
'stack' in actual && actual instanceof Error &&
'stack' in expected && expected instanceof Error) {
actual = copyError(actual);
expected = copyError(expected);
}
if (kMethodsWithCustomMessageDiff.includes(operator)) {
super(createErrDiff(actual, expected, operator, message));
} else if (operator === 'notDeepStrictEqual' ||
operator === 'notStrictEqual') {
// In case the objects are equal but the operator requires unequal, show
// the first object and say A equals B
let base = kReadableOperator[operator];
const res = StringPrototypeSplit(inspectValue(actual), '\n');
// In case "actual" is an object or a function, it should not be
// reference equal.
if (operator === 'notStrictEqual' &&
((typeof actual === 'object' && actual !== null) ||
typeof actual === 'function')) {
base = kReadableOperator.notStrictEqualObject;
}
// Only remove lines in case it makes sense to collapse those.
// TODO: Accept env to always show the full error.
if (res.length > 50) {
res[46] = `${colors.blue}...${colors.white}`;
while (res.length > 47) {
ArrayPrototypePop(res);
}
}
// Only print a single input.
if (res.length === 1) {
super(`${base}${res[0].length > 5 ? '\n\n' : ' '}${res[0]}`);
} else {
super(`${base}\n\n${ArrayPrototypeJoin(res, '\n')}\n`);
}
} else {
let res = inspectValue(actual);
let other = inspectValue(expected);
const knownOperator = kReadableOperator[operator];
if (operator === 'notDeepEqual' && res === other) {
res = `${knownOperator}\n\n${res}`;
if (res.length > 1024) {
res = `${StringPrototypeSlice(res, 0, 1021)}...`;
}
super(res);
} else {
if (res.length > kMaxLongStringLength) {
res = `${StringPrototypeSlice(res, 0, 509)}...`;
}
if (other.length > kMaxLongStringLength) {
other = `${StringPrototypeSlice(other, 0, 509)}...`;
}
if (operator === 'deepEqual') {
res = `${knownOperator}\n\n${res}\n\nshould loosely deep-equal\n\n`;
} else {
const newOp = kReadableOperator[`${operator}Unequal`];
if (newOp) {
res = `${newOp}\n\n${res}\n\nshould not loosely deep-equal\n\n`;
} else {
other = ` ${operator} ${other}`;
}
}
super(`${res}${other}`);
}
}
}
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = limit;
this.generatedMessage = !message;
ObjectDefineProperty(this, 'name', {
__proto__: null,
value: 'AssertionError [ERR_ASSERTION]',
enumerable: false,
writable: true,
configurable: true,
});
this.code = 'ERR_ASSERTION';
if (details) {
this.actual = undefined;
this.expected = undefined;
this.operator = undefined;
for (let i = 0; i < details.length; i++) {
this['message ' + i] = details[i].message;
this['actual ' + i] = details[i].actual;
this['expected ' + i] = details[i].expected;
this['operator ' + i] = details[i].operator;
this['stack trace ' + i] = details[i].stack;
}
} else {
this.actual = actual;
this.expected = expected;
this.operator = operator;
}
ErrorCaptureStackTrace(this, stackStartFn || stackStartFunction);
// Create error message including the error code in the name.
this.stack; // eslint-disable-line no-unused-expressions
// Reset the name.
this.name = 'AssertionError';
}
toString() {
return `${this.name} [${this.code}]: ${this.message}`;
}
[inspect.custom](recurseTimes, ctx) {
// Long strings should not be fully inspected.
const tmpActual = this.actual;
const tmpExpected = this.expected;
if (typeof this.actual === 'string') {
this.actual = addEllipsis(this.actual);
}
if (typeof this.expected === 'string') {
this.expected = addEllipsis(this.expected);
}
// This limits the `actual` and `expected` property default inspection to
// the minimum depth. Otherwise those values would be too verbose compared
// to the actual error message which contains a combined view of these two
// input values.
const result = inspect(this, {
...ctx,
customInspect: false,
depth: 0,
});
// Reset the properties after inspection.
this.actual = tmpActual;
this.expected = tmpExpected;
return result;
}
}
module.exports = AssertionError;

View File

@ -0,0 +1,153 @@
'use strict';
const {
ArrayPrototypePush,
ArrayPrototypeSlice,
Error,
FunctionPrototype,
ObjectFreeze,
Proxy,
ReflectApply,
SafeSet,
SafeWeakMap,
} = primordials;
const {
codes: {
ERR_INVALID_ARG_VALUE,
ERR_UNAVAILABLE_DURING_EXIT,
},
} = require('internal/errors');
const AssertionError = require('internal/assert/assertion_error');
const {
validateUint32,
} = require('internal/validators');
const noop = FunctionPrototype;
class CallTrackerContext {
#expected;
#calls;
#name;
#stackTrace;
constructor({ expected, stackTrace, name }) {
this.#calls = [];
this.#expected = expected;
this.#stackTrace = stackTrace;
this.#name = name;
}
track(thisArg, args) {
const argsClone = ObjectFreeze(ArrayPrototypeSlice(args));
ArrayPrototypePush(this.#calls, ObjectFreeze({ thisArg, arguments: argsClone }));
}
get delta() {
return this.#calls.length - this.#expected;
}
reset() {
this.#calls = [];
}
getCalls() {
return ObjectFreeze(ArrayPrototypeSlice(this.#calls));
}
report() {
if (this.delta !== 0) {
const message = `Expected the ${this.#name} function to be ` +
`executed ${this.#expected} time(s) but was ` +
`executed ${this.#calls.length} time(s).`;
return {
message,
actual: this.#calls.length,
expected: this.#expected,
operator: this.#name,
stack: this.#stackTrace,
};
}
}
}
class CallTracker {
#callChecks = new SafeSet();
#trackedFunctions = new SafeWeakMap();
#getTrackedFunction(tracked) {
if (!this.#trackedFunctions.has(tracked)) {
throw new ERR_INVALID_ARG_VALUE('tracked', tracked, 'is not a tracked function');
}
return this.#trackedFunctions.get(tracked);
}
reset(tracked) {
if (tracked === undefined) {
this.#callChecks.forEach((check) => check.reset());
return;
}
this.#getTrackedFunction(tracked).reset();
}
getCalls(tracked) {
return this.#getTrackedFunction(tracked).getCalls();
}
calls(fn, expected = 1) {
if (process._exiting)
throw new ERR_UNAVAILABLE_DURING_EXIT();
if (typeof fn === 'number') {
expected = fn;
fn = noop;
} else if (fn === undefined) {
fn = noop;
}
validateUint32(expected, 'expected', true);
const context = new CallTrackerContext({
expected,
// eslint-disable-next-line no-restricted-syntax
stackTrace: new Error(),
name: fn.name || 'calls',
});
const tracked = new Proxy(fn, {
__proto__: null,
apply(fn, thisArg, argList) {
context.track(thisArg, argList);
return ReflectApply(fn, thisArg, argList);
},
});
this.#callChecks.add(context);
this.#trackedFunctions.set(tracked, context);
return tracked;
}
report() {
const errors = [];
for (const context of this.#callChecks) {
const message = context.report();
if (message !== undefined) {
ArrayPrototypePush(errors, message);
}
}
return errors;
}
verify() {
const errors = this.report();
if (errors.length === 0) {
return;
}
const message = errors.length === 1 ?
errors[0].message :
'Functions were not called the expected number of times';
throw new AssertionError({
message,
details: errors,
});
}
}
module.exports = CallTracker;

View File

@ -0,0 +1,177 @@
'use strict';
const {
ArrayPrototypePush,
Int32Array,
StringPrototypeEndsWith,
} = primordials;
const colors = require('internal/util/colors');
const kNopLinesToCollapse = 5;
const kOperations = {
DELETE: -1,
NOP: 0,
INSERT: 1,
};
function areLinesEqual(actual, expected, checkCommaDisparity) {
if (actual === expected) {
return true;
}
if (checkCommaDisparity) {
return (actual + ',') === expected || actual === (expected + ',');
}
return false;
}
function myersDiff(actual, expected, checkCommaDisparity = false) {
const actualLength = actual.length;
const expectedLength = expected.length;
const max = actualLength + expectedLength;
// TODO(BridgeAR): Cap the input in case the values go beyond the limit of 2^31 - 1.
const v = new Int32Array(2 * max + 1);
const trace = [];
for (let diffLevel = 0; diffLevel <= max; diffLevel++) {
ArrayPrototypePush(trace, new Int32Array(v)); // Clone the current state of `v`
for (let diagonalIndex = -diffLevel; diagonalIndex <= diffLevel; diagonalIndex += 2) {
const offset = diagonalIndex + max;
const previousOffset = v[offset - 1];
const nextOffset = v[offset + 1];
let x = diagonalIndex === -diffLevel || (diagonalIndex !== diffLevel && previousOffset < nextOffset) ?
nextOffset :
previousOffset + 1;
let y = x - diagonalIndex;
while (
x < actualLength &&
y < expectedLength &&
areLinesEqual(actual[x], expected[y], checkCommaDisparity)
) {
x++;
y++;
}
v[offset] = x;
if (x >= actualLength && y >= expectedLength) {
return backtrack(trace, actual, expected, checkCommaDisparity);
}
}
}
}
function backtrack(trace, actual, expected, checkCommaDisparity) {
const actualLength = actual.length;
const expectedLength = expected.length;
const max = actualLength + expectedLength;
let x = actualLength;
let y = expectedLength;
const result = [];
for (let diffLevel = trace.length - 1; diffLevel >= 0; diffLevel--) {
const v = trace[diffLevel];
const diagonalIndex = x - y;
const offset = diagonalIndex + max;
let prevDiagonalIndex;
if (
diagonalIndex === -diffLevel ||
(diagonalIndex !== diffLevel && v[offset - 1] < v[offset + 1])
) {
prevDiagonalIndex = diagonalIndex + 1;
} else {
prevDiagonalIndex = diagonalIndex - 1;
}
const prevX = v[prevDiagonalIndex + max];
const prevY = prevX - prevDiagonalIndex;
while (x > prevX && y > prevY) {
const actualItem = actual[x - 1];
const value = checkCommaDisparity && !StringPrototypeEndsWith(actualItem, ',') ? expected[y - 1] : actualItem;
ArrayPrototypePush(result, [ kOperations.NOP, value ]);
x--;
y--;
}
if (diffLevel > 0) {
if (x > prevX) {
ArrayPrototypePush(result, [ kOperations.INSERT, actual[--x] ]);
} else {
ArrayPrototypePush(result, [ kOperations.DELETE, expected[--y] ]);
}
}
}
return result;
}
function printSimpleMyersDiff(diff) {
let message = '';
for (let diffIdx = diff.length - 1; diffIdx >= 0; diffIdx--) {
const { 0: operation, 1: value } = diff[diffIdx];
let color = colors.white;
if (operation === kOperations.INSERT) {
color = colors.green;
} else if (operation === kOperations.DELETE) {
color = colors.red;
}
message += `${color}${value}${colors.white}`;
}
return `\n${message}`;
}
function printMyersDiff(diff, operator) {
let message = '';
let skipped = false;
let nopCount = 0;
for (let diffIdx = diff.length - 1; diffIdx >= 0; diffIdx--) {
const { 0: operation, 1: value } = diff[diffIdx];
const previousOperation = diffIdx < diff.length - 1 ? diff[diffIdx + 1][0] : null;
// Avoid grouping if only one line would have been grouped otherwise
if (previousOperation === kOperations.NOP && operation !== previousOperation) {
if (nopCount === kNopLinesToCollapse + 1) {
message += `${colors.white} ${diff[diffIdx + 1][1]}\n`;
} else if (nopCount === kNopLinesToCollapse + 2) {
message += `${colors.white} ${diff[diffIdx + 2][1]}\n`;
message += `${colors.white} ${diff[diffIdx + 1][1]}\n`;
} else if (nopCount >= kNopLinesToCollapse + 3) {
message += `${colors.blue}...${colors.white}\n`;
message += `${colors.white} ${diff[diffIdx + 1][1]}\n`;
skipped = true;
}
nopCount = 0;
}
if (operation === kOperations.INSERT) {
if (operator === 'partialDeepStrictEqual') {
message += `${colors.gray}${colors.hasColors ? ' ' : '+'} ${value}${colors.white}\n`;
} else {
message += `${colors.green}+${colors.white} ${value}\n`;
}
} else if (operation === kOperations.DELETE) {
message += `${colors.red}-${colors.white} ${value}\n`;
} else if (operation === kOperations.NOP) {
if (nopCount < kNopLinesToCollapse) {
message += `${colors.white} ${value}\n`;
}
nopCount++;
}
}
message = message.trimEnd();
return { message: `\n${message}`, skipped };
}
module.exports = { myersDiff, printMyersDiff, printSimpleMyersDiff };

View File

@ -0,0 +1,287 @@
'use strict';
const {
ArrayPrototypeShift,
Error,
ErrorCaptureStackTrace,
FunctionPrototypeBind,
RegExpPrototypeSymbolReplace,
SafeMap,
StringPrototypeCharCodeAt,
StringPrototypeIncludes,
StringPrototypeIndexOf,
StringPrototypeReplace,
StringPrototypeSlice,
StringPrototypeSplit,
StringPrototypeStartsWith,
} = primordials;
const { Buffer } = require('buffer');
const {
isErrorStackTraceLimitWritable,
overrideStackTrace,
} = require('internal/errors');
const AssertionError = require('internal/assert/assertion_error');
const { openSync, closeSync, readSync } = require('fs');
const { EOL } = require('internal/constants');
const { BuiltinModule } = require('internal/bootstrap/realm');
const { isError } = require('internal/util');
const errorCache = new SafeMap();
const { fileURLToPath } = require('internal/url');
let parseExpressionAt;
let findNodeAround;
let tokenizer;
let decoder;
// Escape control characters but not \n and \t to keep the line breaks and
// indentation intact.
// eslint-disable-next-line no-control-regex
const escapeSequencesRegExp = /[\x00-\x08\x0b\x0c\x0e-\x1f]/g;
const meta = [
'\\u0000', '\\u0001', '\\u0002', '\\u0003', '\\u0004',
'\\u0005', '\\u0006', '\\u0007', '\\b', '',
'', '\\u000b', '\\f', '', '\\u000e',
'\\u000f', '\\u0010', '\\u0011', '\\u0012', '\\u0013',
'\\u0014', '\\u0015', '\\u0016', '\\u0017', '\\u0018',
'\\u0019', '\\u001a', '\\u001b', '\\u001c', '\\u001d',
'\\u001e', '\\u001f',
];
const escapeFn = (str) => meta[StringPrototypeCharCodeAt(str, 0)];
function findColumn(fd, column, code) {
if (code.length > column + 100) {
try {
return parseCode(code, column);
} catch {
// End recursion in case no code could be parsed. The expression should
// have been found after 2500 characters, so stop trying.
if (code.length - column > 2500) {
// eslint-disable-next-line no-throw-literal
throw null;
}
}
}
// Read up to 2500 bytes more than necessary in columns. That way we address
// multi byte characters and read enough data to parse the code.
const bytesToRead = column - code.length + 2500;
const buffer = Buffer.allocUnsafe(bytesToRead);
const bytesRead = readSync(fd, buffer, 0, bytesToRead);
code += decoder.write(buffer.slice(0, bytesRead));
// EOF: fast path.
if (bytesRead < bytesToRead) {
return parseCode(code, column);
}
// Read potentially missing code.
return findColumn(fd, column, code);
}
function getCode(fd, line, column) {
let bytesRead = 0;
if (line === 0) {
// Special handle line number one. This is more efficient and simplifies the
// rest of the algorithm. Read more than the regular column number in bytes
// to prevent multiple reads in case multi byte characters are used.
return findColumn(fd, column, '');
}
let lines = 0;
// Prevent blocking the event loop by limiting the maximum amount of
// data that may be read.
let maxReads = 32; // bytesPerRead * maxReads = 512 KiB
const bytesPerRead = 16384;
// Use a single buffer up front that is reused until the call site is found.
let buffer = Buffer.allocUnsafe(bytesPerRead);
while (maxReads-- !== 0) {
// Only allocate a new buffer in case the needed line is found. All data
// before that can be discarded.
buffer = lines < line ? buffer : Buffer.allocUnsafe(bytesPerRead);
bytesRead = readSync(fd, buffer, 0, bytesPerRead);
// Read the buffer until the required code line is found.
for (let i = 0; i < bytesRead; i++) {
if (buffer[i] === 10 && ++lines === line) {
// If the end of file is reached, directly parse the code and return.
if (bytesRead < bytesPerRead) {
return parseCode(buffer.toString('utf8', i + 1, bytesRead), column);
}
// Check if the read code is sufficient or read more until the whole
// expression is read. Make sure multi byte characters are preserved
// properly by using the decoder.
const code = decoder.write(buffer.slice(i + 1, bytesRead));
return findColumn(fd, column, code);
}
}
}
}
function parseCode(code, offset) {
// Lazy load acorn.
if (parseExpressionAt === undefined) {
const Parser = require('internal/deps/acorn/acorn/dist/acorn').Parser;
({ findNodeAround } = require('internal/deps/acorn/acorn-walk/dist/walk'));
parseExpressionAt = FunctionPrototypeBind(Parser.parseExpressionAt, Parser);
tokenizer = FunctionPrototypeBind(Parser.tokenizer, Parser);
}
let node;
let start;
// Parse the read code until the correct expression is found.
for (const token of tokenizer(code, { ecmaVersion: 'latest' })) {
start = token.start;
if (start > offset) {
// No matching expression found. This could happen if the assert
// expression is bigger than the provided buffer.
break;
}
try {
node = parseExpressionAt(code, start, { ecmaVersion: 'latest' });
// Find the CallExpression in the tree.
node = findNodeAround(node, offset, 'CallExpression');
if (node?.node.end >= offset) {
return [
node.node.start,
StringPrototypeReplace(StringPrototypeSlice(code,
node.node.start, node.node.end),
escapeSequencesRegExp, escapeFn),
];
}
// eslint-disable-next-line no-unused-vars
} catch (err) {
continue;
}
}
// eslint-disable-next-line no-throw-literal
throw null;
}
function getErrMessage(message, fn) {
const tmpLimit = Error.stackTraceLimit;
const errorStackTraceLimitIsWritable = isErrorStackTraceLimitWritable();
// Make sure the limit is set to 1. Otherwise it could fail (<= 0) or it
// does to much work.
if (errorStackTraceLimitIsWritable) Error.stackTraceLimit = 1;
// We only need the stack trace. To minimize the overhead use an object
// instead of an error.
const err = {};
ErrorCaptureStackTrace(err, fn);
if (errorStackTraceLimitIsWritable) Error.stackTraceLimit = tmpLimit;
overrideStackTrace.set(err, (_, stack) => stack);
const call = err.stack[0];
let filename = call.getFileName();
const line = call.getLineNumber() - 1;
let column = call.getColumnNumber() - 1;
let identifier;
let code;
if (filename) {
identifier = `${filename}${line}${column}`;
// Skip Node.js modules!
if (StringPrototypeStartsWith(filename, 'node:') &&
BuiltinModule.exists(StringPrototypeSlice(filename, 5))) {
errorCache.set(identifier, undefined);
return;
}
} else {
return message;
}
if (errorCache.has(identifier)) {
return errorCache.get(identifier);
}
let fd;
try {
// Set the stack trace limit to zero. This makes sure unexpected token
// errors are handled faster.
if (errorStackTraceLimitIsWritable) Error.stackTraceLimit = 0;
if (filename) {
if (decoder === undefined) {
const { StringDecoder } = require('string_decoder');
decoder = new StringDecoder('utf8');
}
// ESM file prop is a file proto. Convert that to path.
// This ensure opensync will not throw ENOENT for ESM files.
const fileProtoPrefix = 'file://';
if (StringPrototypeStartsWith(filename, fileProtoPrefix)) {
filename = fileURLToPath(filename);
}
fd = openSync(filename, 'r', 0o666);
// Reset column and message.
({ 0: column, 1: message } = getCode(fd, line, column));
// Flush unfinished multi byte characters.
decoder.end();
} else {
for (let i = 0; i < line; i++) {
code = StringPrototypeSlice(code,
StringPrototypeIndexOf(code, '\n') + 1);
}
({ 0: column, 1: message } = parseCode(code, column));
}
// Always normalize indentation, otherwise the message could look weird.
if (StringPrototypeIncludes(message, '\n')) {
if (EOL === '\r\n') {
message = RegExpPrototypeSymbolReplace(/\r\n/g, message, '\n');
}
const frames = StringPrototypeSplit(message, '\n');
message = ArrayPrototypeShift(frames);
for (const frame of frames) {
let pos = 0;
while (pos < column && (frame[pos] === ' ' || frame[pos] === '\t')) {
pos++;
}
message += `\n ${StringPrototypeSlice(frame, pos)}`;
}
}
message = `The expression evaluated to a falsy value:\n\n ${message}\n`;
// Make sure to always set the cache! No matter if the message is
// undefined or not
errorCache.set(identifier, message);
return message;
} catch {
// Invalidate cache to prevent trying to read this part again.
errorCache.set(identifier, undefined);
} finally {
// Reset limit.
if (errorStackTraceLimitIsWritable) Error.stackTraceLimit = tmpLimit;
if (fd !== undefined)
closeSync(fd);
}
}
function innerOk(fn, argLen, value, message) {
if (!value) {
let generatedMessage = false;
if (argLen === 0) {
generatedMessage = true;
message = 'No value argument passed to `assert.ok()`';
} else if (message == null) {
generatedMessage = true;
message = getErrMessage(message, fn);
} else if (isError(message)) {
throw message;
}
const err = new AssertionError({
actual: value,
expected: true,
message,
operator: '==',
stackStartFn: fn,
});
err.generatedMessage = generatedMessage;
throw err;
}
}
module.exports = {
innerOk,
};