WIP: bootstrap and partial real Solana watcher implementation

This commit is contained in:
2026-08-16 09:17:45 +00:00
commit dc23412c3f
7232 changed files with 1687637 additions and 0 deletions

View File

@@ -0,0 +1,300 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// lib/npm/node-platform.ts
var fs = require("fs");
var os = require("os");
var path = require("path");
var ESBUILD_BINARY_PATH = process.env.ESBUILD_BINARY_PATH || ESBUILD_BINARY_PATH;
var isValidBinaryPath = (x) => !!x && x !== "/usr/bin/esbuild";
var knownWindowsPackages = {
"win32 arm64 LE": "@esbuild/win32-arm64",
"win32 ia32 LE": "@esbuild/win32-ia32",
"win32 x64 LE": "@esbuild/win32-x64"
};
var knownUnixlikePackages = {
"aix ppc64 BE": "@esbuild/aix-ppc64",
"android arm64 LE": "@esbuild/android-arm64",
"darwin arm64 LE": "@esbuild/darwin-arm64",
"darwin x64 LE": "@esbuild/darwin-x64",
"freebsd arm64 LE": "@esbuild/freebsd-arm64",
"freebsd x64 LE": "@esbuild/freebsd-x64",
"linux arm LE": "@esbuild/linux-arm",
"linux arm64 LE": "@esbuild/linux-arm64",
"linux ia32 LE": "@esbuild/linux-ia32",
"linux mips64el LE": "@esbuild/linux-mips64el",
"linux ppc64 LE": "@esbuild/linux-ppc64",
"linux riscv64 LE": "@esbuild/linux-riscv64",
"linux s390x BE": "@esbuild/linux-s390x",
"linux x64 LE": "@esbuild/linux-x64",
"linux loong64 LE": "@esbuild/linux-loong64",
"netbsd arm64 LE": "@esbuild/netbsd-arm64",
"netbsd x64 LE": "@esbuild/netbsd-x64",
"openbsd arm64 LE": "@esbuild/openbsd-arm64",
"openbsd x64 LE": "@esbuild/openbsd-x64",
"sunos x64 LE": "@esbuild/sunos-x64"
};
var knownWebAssemblyFallbackPackages = {
"android arm LE": "@esbuild/android-arm",
"android x64 LE": "@esbuild/android-x64",
"openharmony arm64 LE": "@esbuild/openharmony-arm64"
};
function pkgAndSubpathForCurrentPlatform() {
let pkg;
let subpath;
let isWASM = false;
let platformKey = `${process.platform} ${os.arch()} ${os.endianness()}`;
if (platformKey in knownWindowsPackages) {
pkg = knownWindowsPackages[platformKey];
subpath = "esbuild.exe";
} else if (platformKey in knownUnixlikePackages) {
pkg = knownUnixlikePackages[platformKey];
subpath = "bin/esbuild";
} else if (platformKey in knownWebAssemblyFallbackPackages) {
pkg = knownWebAssemblyFallbackPackages[platformKey];
subpath = "bin/esbuild";
isWASM = true;
} else {
throw new Error(`Unsupported platform: ${platformKey}`);
}
return { pkg, subpath, isWASM };
}
function downloadedBinPath(pkg, subpath) {
const esbuildLibDir = path.dirname(require.resolve("esbuild"));
return path.join(esbuildLibDir, `downloaded-${pkg.replace("/", "-")}-${path.basename(subpath)}`);
}
// lib/npm/node-install.ts
var fs2 = require("fs");
var os2 = require("os");
var path2 = require("path");
var zlib = require("zlib");
var https = require("https");
var crypto = require("crypto");
var child_process = require("child_process");
var packageJSON = require(path2.join(__dirname, "package.json"));
var toPath = path2.join(__dirname, "bin", "esbuild");
var isToPathJS = true;
function validateBinaryVersion(...command) {
command.push("--version");
let stdout;
try {
stdout = child_process.execFileSync(command.shift(), command, {
// Without this, this install script strangely crashes with the error
// "EACCES: permission denied, write" but only on Ubuntu Linux when node is
// installed from the Snap Store. This is not a problem when you download
// the official version of node. The problem appears to be that stderr
// (i.e. file descriptor 2) isn't writable?
//
// More info:
// - https://snapcraft.io/ (what the Snap Store is)
// - https://nodejs.org/dist/ (download the official version of node)
// - https://github.com/evanw/esbuild/issues/1711#issuecomment-1027554035
//
stdio: "pipe"
}).toString().trim();
} catch (err) {
if (os2.platform() === "darwin" && /_SecTrustEvaluateWithError/.test(err + "")) {
let os3 = "this version of macOS";
try {
os3 = "macOS " + child_process.execFileSync("sw_vers", ["-productVersion"]).toString().trim();
} catch {
}
throw new Error(`The "esbuild" package cannot be installed because ${os3} is too outdated.
The Go compiler (which esbuild relies on) no longer supports ${os3},
which means the "esbuild" binary executable can't be run. You can either:
* Update your version of macOS to one that the Go compiler supports
* Use the "esbuild-wasm" package instead of the "esbuild" package
* Build esbuild yourself using an older version of the Go compiler
`);
}
throw err;
}
if (stdout !== packageJSON.version) {
throw new Error(`Expected ${JSON.stringify(packageJSON.version)} but got ${JSON.stringify(stdout)}`);
}
}
function isYarn() {
const { npm_config_user_agent } = process.env;
if (npm_config_user_agent) {
return /\byarn\//.test(npm_config_user_agent);
}
return false;
}
function fetch(url) {
return new Promise((resolve, reject) => {
https.get(url, (res) => {
if ((res.statusCode === 301 || res.statusCode === 302) && res.headers.location)
return fetch(res.headers.location).then(resolve, reject);
if (res.statusCode !== 200)
return reject(new Error(`Server responded with ${res.statusCode}`));
let chunks = [];
res.on("data", (chunk) => chunks.push(chunk));
res.on("end", () => resolve(Buffer.concat(chunks)));
}).on("error", reject);
});
}
function extractFileFromTarGzip(buffer, subpath) {
try {
buffer = zlib.unzipSync(buffer);
} catch (err) {
throw new Error(`Invalid gzip data in archive: ${err && err.message || err}`);
}
let str = (i, n) => String.fromCharCode(...buffer.subarray(i, i + n)).replace(/\0.*$/, "");
let offset = 0;
subpath = `package/${subpath}`;
while (offset < buffer.length) {
let name = str(offset, 100);
let size = parseInt(str(offset + 124, 12), 8);
offset += 512;
if (!isNaN(size) && size >= 0) {
if (name === subpath) return buffer.subarray(offset, offset + size);
offset += size + 511 & ~511;
}
}
throw new Error(`Could not find ${JSON.stringify(subpath)} in archive`);
}
function installUsingNPM(pkg, subpath, binPath) {
const env = { ...process.env, npm_config_global: void 0 };
const esbuildLibDir = path2.dirname(require.resolve("esbuild"));
const installDir = path2.join(esbuildLibDir, "npm-install");
fs2.mkdirSync(installDir);
try {
fs2.writeFileSync(path2.join(installDir, "package.json"), "{}");
child_process.execSync(
`npm install --loglevel=error --prefer-offline --no-audit --progress=false ${pkg}@${packageJSON.version}`,
{ cwd: installDir, stdio: "pipe", env }
);
const installedBinPath = path2.join(installDir, "node_modules", pkg, subpath);
binaryIntegrityCheck(pkg, subpath, fs2.readFileSync(installedBinPath));
fs2.renameSync(installedBinPath, binPath);
} finally {
try {
removeRecursive(installDir);
} catch {
}
}
}
function removeRecursive(dir) {
for (const entry of fs2.readdirSync(dir)) {
const entryPath = path2.join(dir, entry);
let stats;
try {
stats = fs2.lstatSync(entryPath);
} catch {
continue;
}
if (stats.isDirectory()) removeRecursive(entryPath);
else fs2.unlinkSync(entryPath);
}
fs2.rmdirSync(dir);
}
function applyManualBinaryPathOverride(overridePath) {
const pathString = JSON.stringify(overridePath);
fs2.writeFileSync(toPath, `#!/usr/bin/env node
require('child_process').execFileSync(${pathString}, process.argv.slice(2), { stdio: 'inherit' });
`);
const libMain = path2.join(__dirname, "lib", "main.js");
const code = fs2.readFileSync(libMain, "utf8");
fs2.writeFileSync(libMain, `var ESBUILD_BINARY_PATH = ${pathString};
${code}`);
}
function maybeOptimizePackage(binPath, isWASM) {
if (os2.platform() !== "win32" && !isYarn() && !isWASM) {
const tempPath = path2.join(__dirname, "bin-esbuild");
try {
fs2.linkSync(binPath, tempPath);
fs2.renameSync(tempPath, toPath);
isToPathJS = false;
fs2.unlinkSync(tempPath);
} catch {
}
}
}
function binaryIntegrityCheck(pkg, subpath, bytes) {
const hash = crypto.createHash("sha256").update(bytes).digest("hex");
const key = `${pkg}/${subpath}`;
const expected = packageJSON["esbuild.binaryHashes"][key];
if (!expected) throw new Error(`Missing hash for "${key}"`);
if (hash !== expected) throw new Error(`"${hash.slice(0, 8)}..." doesn't match "${expected.slice(0, 8)}..." for "${pkg}"`);
}
async function downloadDirectlyFromNPM(pkg, subpath, binPath) {
const url = `https://registry.npmjs.org/${pkg}/-/${pkg.replace("@esbuild/", "")}-${packageJSON.version}.tgz`;
console.error(`[esbuild] Trying to download ${JSON.stringify(url)}`);
try {
const bytes = extractFileFromTarGzip(await fetch(url), subpath);
binaryIntegrityCheck(pkg, subpath, bytes);
fs2.writeFileSync(binPath, bytes);
fs2.chmodSync(binPath, 493);
} catch (e) {
console.error(`[esbuild] Failed to download ${JSON.stringify(url)}: ${e && e.message || e}`);
throw e;
}
}
async function checkAndPreparePackage() {
if (isValidBinaryPath(ESBUILD_BINARY_PATH)) {
if (!fs2.existsSync(ESBUILD_BINARY_PATH)) {
console.warn(`[esbuild] Ignoring bad configuration: ESBUILD_BINARY_PATH=${ESBUILD_BINARY_PATH}`);
} else {
applyManualBinaryPathOverride(ESBUILD_BINARY_PATH);
return;
}
}
const { pkg, subpath, isWASM } = pkgAndSubpathForCurrentPlatform();
let binPath;
try {
binPath = require.resolve(`${pkg}/${subpath}`);
} catch (e) {
console.error(`[esbuild] Failed to find package "${pkg}" on the file system
This can happen if you use the "--no-optional" flag. The "optionalDependencies"
package.json feature is used by esbuild to install the correct binary executable
for your current platform. This install script will now attempt to work around
this. If that fails, you need to remove the "--no-optional" flag to use esbuild.
`);
if (isWASM) throw new Error(`Failed to install package "${pkg}"`);
binPath = downloadedBinPath(pkg, subpath);
try {
console.error(`[esbuild] Trying to install package "${pkg}" using npm`);
installUsingNPM(pkg, subpath, binPath);
} catch (e2) {
console.error(`[esbuild] Failed to install package "${pkg}" using npm: ${e2 && e2.message || e2}`);
try {
await downloadDirectlyFromNPM(pkg, subpath, binPath);
} catch (e3) {
throw new Error(`Failed to install package "${pkg}"`);
}
}
}
maybeOptimizePackage(binPath, isWASM);
}
checkAndPreparePackage().then(() => {
if (isToPathJS) {
validateBinaryVersion(process.execPath, toPath);
} else {
validateBinaryVersion(toPath);
}
});

View File

@@ -0,0 +1,7 @@
export * from './ast-converter';
export * from './create-program/getScriptKind';
export type { ParseSettings } from './parseSettings';
export { SUPPORTED_TYPESCRIPT_VERSIONS } from './parseSettings/warnAboutTSVersion';
export * from './getModifiers';
export { typescriptVersionIsAtLeast } from './version-check';
export { getCanonicalFileName } from './create-program/shared';

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAO,MAAM,QAAQ,GAAG,CACtB,CAAkB,EAClB,CAAkB,EAClB,GAAW,EACX,EAAE;IACF,MAAM,EAAE,GAAG,CAAC,YAAY,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACvD,MAAM,EAAE,GAAG,CAAC,YAAY,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAEvD,MAAM,CAAC,GAAG,EAAE,KAAK,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,IAAA,aAAK,EAAC,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAA;IAEzD,OAAO,CACL,CAAC,IAAI;QACH,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QACX,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACT,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC;KAClC,CACF,CAAA;AACH,CAAC,CAAA;AAnBY,QAAA,QAAQ,YAmBpB;AAED,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,GAAW,EAAE,EAAE;IAC9C,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACxB,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACxB,CAAC,CAAA;AAEM,MAAM,KAAK,GAAG,CACnB,CAAS,EACT,CAAS,EACT,GAAW,EACmB,EAAE;IAChC,IAAI,IAAc,EAChB,GAAuB,EACvB,IAAY,EACZ,KAAK,GAAuB,SAAS,EACrC,MAAoC,CAAA;IACtC,IAAI,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IACvB,IAAI,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAA;IAC/B,IAAI,CAAC,GAAG,EAAE,CAAA;IAEV,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACZ,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QACjB,CAAC;QACD,IAAI,GAAG,EAAE,CAAA;QACT,IAAI,GAAG,GAAG,CAAC,MAAM,CAAA;QAEjB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;gBACb,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBACZ,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;YAC5B,CAAC;iBAAM,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;gBACpB,IAAI,CAAC,KAAK,SAAS;oBAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YACvC,CAAC;iBAAM,CAAC;gBACN,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;gBAChB,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,GAAG,IAAI,EAAE,CAAC;oBACpC,IAAI,GAAG,GAAG,CAAA;oBACV,KAAK,GAAG,EAAE,CAAA;gBACZ,CAAC;gBAED,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;YAC5B,CAAC;YAED,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QAClC,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACvC,MAAM,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACxB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AA/CY,QAAA,KAAK,SA+CjB","sourcesContent":["export const balanced = (\n a: string | RegExp,\n b: string | RegExp,\n str: string,\n) => {\n const ma = a instanceof RegExp ? maybeMatch(a, str) : a\n const mb = b instanceof RegExp ? maybeMatch(b, str) : b\n\n const r = ma !== null && mb != null && range(ma, mb, str)\n\n return (\n r && {\n start: r[0],\n end: r[1],\n pre: str.slice(0, r[0]),\n body: str.slice(r[0] + ma.length, r[1]),\n post: str.slice(r[1] + mb.length),\n }\n )\n}\n\nconst maybeMatch = (reg: RegExp, str: string) => {\n const m = str.match(reg)\n return m ? m[0] : null\n}\n\nexport const range = (\n a: string,\n b: string,\n str: string,\n): undefined | [number, number] => {\n let begs: number[],\n beg: number | undefined,\n left: number,\n right: number | undefined = undefined,\n result: undefined | [number, number]\n let ai = str.indexOf(a)\n let bi = str.indexOf(b, ai + 1)\n let i = ai\n\n if (ai >= 0 && bi > 0) {\n if (a === b) {\n return [ai, bi]\n }\n begs = []\n left = str.length\n\n while (i >= 0 && !result) {\n if (i === ai) {\n begs.push(i)\n ai = str.indexOf(a, i + 1)\n } else if (begs.length === 1) {\n const r = begs.pop()\n if (r !== undefined) result = [r, bi]\n } else {\n beg = begs.pop()\n if (beg !== undefined && beg < left) {\n left = beg\n right = bi\n }\n\n bi = str.indexOf(b, i + 1)\n }\n\n i = ai < bi && ai >= 0 ? ai : bi\n }\n\n if (begs.length && right !== undefined) {\n result = [left, right]\n }\n }\n\n return result\n}\n"]}

View File

@@ -0,0 +1,10 @@
export { c as createManualModuleSource } from './chunk-utils.js';
export { a as automockModule, c as collectModuleExports, i as initSyntaxLexers } from './chunk-automock.js';
export { h as hoistMocks } from './chunk-hoistMocks.js';
import 'node:fs';
import 'node:url';
import 'magic-string';
import 'estree-walker';
import 'node:module';
import 'node:path';
import './chunk-helpers.js';

View File

@@ -0,0 +1 @@
{"version":3,"file":"moduleDetectionKind.js","sourceRoot":"","sources":["../../src/enums/moduleDetectionKind.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,MAAM,CAAC,IAAI,mBAAwB,CAAC;AACpC,CAAC,UAAU,mBAAmB;IAC1B,mBAAmB,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;IAC9D,mBAAmB,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;IAC9D,mBAAmB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IAClE,mBAAmB,CAAC,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC;AACpE,CAAC,CAAC,CAAC,mBAAmB,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC,CAAC"}

View File

@@ -0,0 +1,49 @@
'use strict'
const Benchmark = require('benchmark')
const sjson = require('..')
const internals = {
text: '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }',
invalid: '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } } }'
}
const suite = new Benchmark.Suite()
suite
.add('JSON.parse valid', () => {
JSON.parse(internals.text)
})
.add('JSON.parse error', () => {
try {
JSON.parse(internals.invalid)
} catch { }
})
.add('secure-json-parse parse', () => {
try {
sjson.parse(internals.invalid)
} catch { }
})
.add('secure-json-parse safeParse', () => {
sjson.safeParse(internals.invalid)
})
.add('reviver', () => {
try {
JSON.parse(internals.invalid, internals.reviver)
} catch { }
})
.on('cycle', (event) => {
console.log(String(event.target))
})
.on('complete', function () {
console.log('Fastest is ' + this.filter('fastest').map('name'))
})
.run({ async: true })
internals.reviver = function (key, value) {
if (key === '__proto__') {
throw new Error('kaboom')
}
return value
}

View File

@@ -0,0 +1,185 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getWrappingFixer = getWrappingFixer;
exports.getMovedNodeCode = getMovedNodeCode;
exports.isStrongPrecedenceNode = isStrongPrecedenceNode;
exports.isWeakPrecedenceParent = isWeakPrecedenceParent;
const utils_1 = require("@typescript-eslint/utils");
/**
* Wraps node with some code. Adds parentheses as necessary.
* @returns Fixer which adds the specified code and parens if necessary.
*/
function getWrappingFixer(params) {
const { node, innerNode = node, sourceCode, wrap } = params;
const innerNodes = Array.isArray(innerNode) ? innerNode : [innerNode];
return (fixer) => {
const innerCodes = innerNodes.map(innerNode => {
let code = sourceCode.getText(innerNode);
/**
* Wrap our node in parens to prevent the following cases:
* - It has a weaker precedence than the code we are wrapping it in
* - It's gotten mistaken as block statement instead of object expression
*/
if (!isStrongPrecedenceNode(innerNode) ||
isObjectExpressionInOneLineReturn(node, innerNode)) {
code = `(${code})`;
}
return code;
});
if (!wrap) {
return fixer.replaceText(node, innerCodes.join(''));
}
// do the wrapping
let code = wrap(...innerCodes);
// check the outer expression's precedence
if (isWeakPrecedenceParent(node) &&
// we wrapped the node in some expression which very likely has a different precedence than original wrapped node
// let's wrap the whole expression in parens just in case
!utils_1.ASTUtils.isParenthesized(node, sourceCode)) {
code = `(${code})`;
}
// check if we need to insert semicolon
if (/^[`([]/.test(code) && isMissingSemicolonBefore(node, sourceCode)) {
code = `;${code}`;
}
return fixer.replaceText(node, code);
};
}
/**
* If the node to be moved and the destination node require parentheses, include parentheses in the node to be moved.
* @param sourceCode Source code of current file
* @param nodeToMove Nodes that need to be moved
* @param destinationNode Final destination node with nodeToMove
* @returns If parentheses are required, code for the nodeToMove node is returned with parentheses at both ends of the code.
*/
function getMovedNodeCode(params) {
const { destinationNode, nodeToMove: existingNode, sourceCode } = params;
const code = sourceCode.getText(existingNode);
if (isStrongPrecedenceNode(existingNode)) {
// Moved node never needs parens
return code;
}
if (!isWeakPrecedenceParent(destinationNode)) {
// Destination would never needs parens, regardless what node moves there
return code;
}
// Parens may be necessary
return `(${code})`;
}
/**
* Check if a node will always have the same precedence if its parent changes.
*/
function isStrongPrecedenceNode(innerNode) {
return (innerNode.type === utils_1.AST_NODE_TYPES.Literal ||
innerNode.type === utils_1.AST_NODE_TYPES.Identifier ||
innerNode.type === utils_1.AST_NODE_TYPES.TSTypeReference ||
innerNode.type === utils_1.AST_NODE_TYPES.TSTypeOperator ||
innerNode.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
innerNode.type === utils_1.AST_NODE_TYPES.ObjectExpression ||
innerNode.type === utils_1.AST_NODE_TYPES.MemberExpression ||
innerNode.type === utils_1.AST_NODE_TYPES.CallExpression ||
innerNode.type === utils_1.AST_NODE_TYPES.NewExpression ||
innerNode.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression ||
innerNode.type === utils_1.AST_NODE_TYPES.TSInstantiationExpression);
}
/**
* Check if a node's parent could have different precedence if the node changes.
*/
function isWeakPrecedenceParent(node) {
const parent = node.parent;
if (!parent) {
return false;
}
if (parent.type === utils_1.AST_NODE_TYPES.UpdateExpression ||
parent.type === utils_1.AST_NODE_TYPES.UnaryExpression ||
parent.type === utils_1.AST_NODE_TYPES.BinaryExpression ||
parent.type === utils_1.AST_NODE_TYPES.LogicalExpression ||
parent.type === utils_1.AST_NODE_TYPES.ConditionalExpression ||
parent.type === utils_1.AST_NODE_TYPES.AwaitExpression) {
return true;
}
if (parent.type === utils_1.AST_NODE_TYPES.MemberExpression &&
parent.object === node) {
return true;
}
if ((parent.type === utils_1.AST_NODE_TYPES.CallExpression ||
parent.type === utils_1.AST_NODE_TYPES.NewExpression) &&
parent.callee === node) {
return true;
}
if (parent.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression &&
parent.tag === node) {
return true;
}
return false;
}
/**
* Returns true if a node is at the beginning of expression statement and the statement above doesn't end with semicolon.
* Doesn't check if the node begins with `(`, `[` or `` ` ``.
*/
function isMissingSemicolonBefore(node, sourceCode) {
for (;;) {
// https://github.com/typescript-eslint/typescript-eslint/issues/6225
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const parent = node.parent;
if (parent.type === utils_1.AST_NODE_TYPES.ExpressionStatement) {
const block = parent.parent;
if (block.type === utils_1.AST_NODE_TYPES.Program ||
block.type === utils_1.AST_NODE_TYPES.BlockStatement) {
// parent is an expression statement in a block
const statementIndex = block.body.indexOf(parent);
const previousStatement = block.body[statementIndex - 1];
if (statementIndex > 0 &&
utils_1.ESLintUtils.nullThrows(sourceCode.getLastToken(previousStatement), 'Mismatched semicolon and block').value !== ';') {
return true;
}
}
}
if (!isLeftHandSide(node)) {
return false;
}
node = parent;
}
}
/**
* Checks if a node is LHS of an operator.
*/
function isLeftHandSide(node) {
// https://github.com/typescript-eslint/typescript-eslint/issues/6225
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const parent = node.parent;
// a++
if (parent.type === utils_1.AST_NODE_TYPES.UpdateExpression) {
return true;
}
// a + b
if ((parent.type === utils_1.AST_NODE_TYPES.BinaryExpression ||
parent.type === utils_1.AST_NODE_TYPES.LogicalExpression ||
parent.type === utils_1.AST_NODE_TYPES.AssignmentExpression) &&
node === parent.left) {
return true;
}
// a ? b : c
if (parent.type === utils_1.AST_NODE_TYPES.ConditionalExpression &&
node === parent.test) {
return true;
}
// a(b)
if (parent.type === utils_1.AST_NODE_TYPES.CallExpression && node === parent.callee) {
return true;
}
// a`b`
if (parent.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression &&
node === parent.tag) {
return true;
}
return false;
}
/**
* Checks if a node's parent is arrow function expression and a inner node is object expression
*/
function isObjectExpressionInOneLineReturn(node, innerNode) {
return (node.parent?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression &&
node.parent.body === node &&
innerNode.type === utils_1.AST_NODE_TYPES.ObjectExpression);
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"languageVariant.enum.js","sourceRoot":"","sources":["../../src/enums/languageVariant.enum.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,eAGX;AAHD,WAAY,eAAe;IACvB,6DAAY,CAAA;IACZ,mDAAO,CAAA;AACX,CAAC,EAHW,eAAe,KAAf,eAAe,QAG1B"}

View File

@@ -0,0 +1,105 @@
import * as util from "../core/util.js";
const error = () => {
const Sizable = {
string: { unit: "simvol", verb: "olmalıdır" },
file: { unit: "bayt", verb: "olmalıdır" },
array: { unit: "element", verb: "olmalıdır" },
set: { unit: "element", verb: "olmalıdır" },
};
function getSizing(origin) {
return Sizable[origin] ?? null;
}
const FormatDictionary = {
regex: "input",
email: "email address",
url: "URL",
emoji: "emoji",
uuid: "UUID",
uuidv4: "UUIDv4",
uuidv6: "UUIDv6",
nanoid: "nanoid",
guid: "GUID",
cuid: "cuid",
cuid2: "cuid2",
ulid: "ULID",
xid: "XID",
ksuid: "KSUID",
datetime: "ISO datetime",
date: "ISO date",
time: "ISO time",
duration: "ISO duration",
ipv4: "IPv4 address",
ipv6: "IPv6 address",
cidrv4: "IPv4 range",
cidrv6: "IPv6 range",
base64: "base64-encoded string",
base64url: "base64url-encoded string",
json_string: "JSON string",
e164: "E.164 number",
jwt: "JWT",
template_literal: "input",
};
const TypeDictionary = {
nan: "NaN",
};
return (issue) => {
switch (issue.code) {
case "invalid_type": {
const expected = TypeDictionary[issue.expected] ?? issue.expected;
const receivedType = util.parsedType(issue.input);
const received = TypeDictionary[receivedType] ?? receivedType;
if (/^[A-Z]/.test(issue.expected)) {
return `Yanlış dəyər: gözlənilən instanceof ${issue.expected}, daxil olan ${received}`;
}
return `Yanlış dəyər: gözlənilən ${expected}, daxil olan ${received}`;
}
case "invalid_value":
if (issue.values.length === 1)
return `Yanlış dəyər: gözlənilən ${util.stringifyPrimitive(issue.values[0])}`;
return `Yanlış seçim: aşağıdakılardan biri olmalıdır: ${util.joinValues(issue.values, "|")}`;
case "too_big": {
const adj = issue.inclusive ? "<=" : "<";
const sizing = getSizing(issue.origin);
if (sizing)
return `Çox böyük: gözlənilən ${issue.origin ?? "dəyər"} ${adj}${issue.maximum.toString()} ${sizing.unit ?? "element"}`;
return `Çox böyük: gözlənilən ${issue.origin ?? "dəyər"} ${adj}${issue.maximum.toString()}`;
}
case "too_small": {
const adj = issue.inclusive ? ">=" : ">";
const sizing = getSizing(issue.origin);
if (sizing)
return `Çox kiçik: gözlənilən ${issue.origin} ${adj}${issue.minimum.toString()} ${sizing.unit}`;
return `Çox kiçik: gözlənilən ${issue.origin} ${adj}${issue.minimum.toString()}`;
}
case "invalid_format": {
const _issue = issue;
if (_issue.format === "starts_with")
return `Yanlış mətn: "${_issue.prefix}" ilə başlamalıdır`;
if (_issue.format === "ends_with")
return `Yanlış mətn: "${_issue.suffix}" ilə bitməlidir`;
if (_issue.format === "includes")
return `Yanlış mətn: "${_issue.includes}" daxil olmalıdır`;
if (_issue.format === "regex")
return `Yanlış mətn: ${_issue.pattern} şablonuna uyğun olmalıdır`;
return `Yanlış ${FormatDictionary[_issue.format] ?? issue.format}`;
}
case "not_multiple_of":
return `Yanlış ədəd: ${issue.divisor} ilə bölünə bilən olmalıdır`;
case "unrecognized_keys":
return `Tanınmayan açar${issue.keys.length > 1 ? "lar" : ""}: ${util.joinValues(issue.keys, ", ")}`;
case "invalid_key":
return `${issue.origin} daxilində yanlış açar`;
case "invalid_union":
return "Yanlış dəyər";
case "invalid_element":
return `${issue.origin} daxilində yanlış dəyər`;
default:
return `Yanlış dəyər`;
}
};
};
export default function () {
return {
localeError: error(),
};
}

View File

@@ -0,0 +1,31 @@
import build, { OnUnknown } from "../../index";
import { expectType } from "tsd";
import { Transform } from "stream";
/**
* If enablePipelining is set to true, the function passed as an argument
* must return a transform. The unknown event should be listened to on the
* stream passed in the first argument.
*/
expectType<Transform>(build((source) => source, { enablePipelining: true }));
/**
* If expectPinoConfig is set with enablePipelining, build returns a promise
*/
expectType<(Promise<Transform>)>(build((source) => source, { enablePipelining: true, expectPinoConfig: true }));
/**
* If enablePipelining is not set the unknown event can be listened to on
* the returned stream.
*/
expectType<Transform & OnUnknown>(build((source) => {}));
/**
* If expectPinoConfig is set, build returns a promise
*/
expectType<(Promise<Transform & OnUnknown>)>(build((source) => {}, { expectPinoConfig: true }));
/**
* build also accepts an async function
*/
expectType<Transform & OnUnknown>(build(async (source) => {}));

View File

@@ -0,0 +1,673 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.TSError = void 0;
exports.isLogicalOperator = isLogicalOperator;
exports.isESTreeBinaryOperator = isESTreeBinaryOperator;
exports.getTextForTokenKind = getTextForTokenKind;
exports.isESTreeClassMember = isESTreeClassMember;
exports.hasModifier = hasModifier;
exports.getLastModifier = getLastModifier;
exports.isComma = isComma;
exports.isComment = isComment;
exports.getBinaryExpressionType = getBinaryExpressionType;
exports.getLineAndCharacterFor = getLineAndCharacterFor;
exports.getLocFor = getLocFor;
exports.canContainDirective = canContainDirective;
exports.getRange = getRange;
exports.isJSXToken = isJSXToken;
exports.getDeclarationKind = getDeclarationKind;
exports.getTSNodeAccessibility = getTSNodeAccessibility;
exports.findNextToken = findNextToken;
exports.findFirstMatchingAncestor = findFirstMatchingAncestor;
exports.hasJSXAncestor = hasJSXAncestor;
exports.unescapeStringLiteralText = unescapeStringLiteralText;
exports.isComputedProperty = isComputedProperty;
exports.isOptional = isOptional;
exports.isChainExpression = isChainExpression;
exports.isChildUnwrappableOptionalChain = isChildUnwrappableOptionalChain;
exports.getTokenType = getTokenType;
exports.convertToken = convertToken;
exports.convertTokens = convertTokens;
exports.createError = createError;
exports.nodeHasTokens = nodeHasTokens;
exports.firstDefined = firstDefined;
exports.identifierIsThisKeyword = identifierIsThisKeyword;
exports.isThisIdentifier = isThisIdentifier;
exports.isThisInTypeQuery = isThisInTypeQuery;
exports.isValidAssignmentTarget = isValidAssignmentTarget;
exports.getNamespaceModifiers = getNamespaceModifiers;
exports.declarationNameToString = declarationNameToString;
exports.isEntityNameExpression = isEntityNameExpression;
const ts = __importStar(require("typescript"));
const getModifiers_1 = require("./getModifiers");
const xhtml_entities_1 = require("./jsx/xhtml-entities");
const ts_estree_1 = require("./ts-estree");
const version_check_1 = require("./version-check");
const isAtLeast50 = version_check_1.typescriptVersionIsAtLeast['5.0'];
const SyntaxKind = ts.SyntaxKind;
const LOGICAL_OPERATORS = new Set([
SyntaxKind.AmpersandAmpersandToken,
SyntaxKind.BarBarToken,
SyntaxKind.QuestionQuestionToken,
]);
const ASSIGNMENT_OPERATORS = new Set([
ts.SyntaxKind.AmpersandAmpersandEqualsToken,
ts.SyntaxKind.AmpersandEqualsToken,
ts.SyntaxKind.AsteriskAsteriskEqualsToken,
ts.SyntaxKind.AsteriskEqualsToken,
ts.SyntaxKind.BarBarEqualsToken,
ts.SyntaxKind.BarEqualsToken,
ts.SyntaxKind.CaretEqualsToken,
ts.SyntaxKind.EqualsToken,
ts.SyntaxKind.GreaterThanGreaterThanEqualsToken,
ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken,
ts.SyntaxKind.LessThanLessThanEqualsToken,
ts.SyntaxKind.MinusEqualsToken,
ts.SyntaxKind.PercentEqualsToken,
ts.SyntaxKind.PlusEqualsToken,
ts.SyntaxKind.QuestionQuestionEqualsToken,
ts.SyntaxKind.SlashEqualsToken,
]);
const BINARY_OPERATORS = new Set([
SyntaxKind.AmpersandAmpersandToken,
SyntaxKind.AmpersandToken,
SyntaxKind.AsteriskAsteriskToken,
SyntaxKind.AsteriskToken,
SyntaxKind.BarBarToken,
SyntaxKind.BarToken,
SyntaxKind.CaretToken,
SyntaxKind.EqualsEqualsEqualsToken,
SyntaxKind.EqualsEqualsToken,
SyntaxKind.ExclamationEqualsEqualsToken,
SyntaxKind.ExclamationEqualsToken,
SyntaxKind.GreaterThanEqualsToken,
SyntaxKind.GreaterThanGreaterThanGreaterThanToken,
SyntaxKind.GreaterThanGreaterThanToken,
SyntaxKind.GreaterThanToken,
SyntaxKind.InKeyword,
SyntaxKind.InstanceOfKeyword,
SyntaxKind.LessThanEqualsToken,
SyntaxKind.LessThanLessThanToken,
SyntaxKind.LessThanToken,
SyntaxKind.MinusToken,
SyntaxKind.PercentToken,
SyntaxKind.PlusToken,
SyntaxKind.SlashToken,
]);
/**
* Returns true if the given ts.Token is the assignment operator
*/
function isAssignmentOperator(operator) {
return ASSIGNMENT_OPERATORS.has(operator.kind);
}
/**
* Returns true if the given ts.Token is a logical operator
*/
function isLogicalOperator(operator) {
return LOGICAL_OPERATORS.has(operator.kind);
}
function isESTreeBinaryOperator(operator) {
return BINARY_OPERATORS.has(operator.kind);
}
/**
* Returns the string form of the given TSToken SyntaxKind
*/
function getTextForTokenKind(kind) {
return ts.tokenToString(kind);
}
/**
* Returns true if the given ts.Node is a valid ESTree class member
*/
function isESTreeClassMember(node) {
return node.kind !== SyntaxKind.SemicolonClassElement;
}
/**
* Checks if a ts.Node has a modifier
*/
function hasModifier(modifierKind, node) {
const modifiers = (0, getModifiers_1.getModifiers)(node);
return modifiers?.some(modifier => modifier.kind === modifierKind) === true;
}
/**
* Get last last modifier in ast
* @returns returns last modifier if present or null
*/
function getLastModifier(node) {
const modifiers = (0, getModifiers_1.getModifiers)(node);
if (modifiers == null) {
return null;
}
return modifiers[modifiers.length - 1] ?? null;
}
/**
* Returns true if the given ts.Token is a comma
*/
function isComma(token) {
return token.kind === SyntaxKind.CommaToken;
}
/**
* Returns true if the given ts.Node is a comment
*/
function isComment(node) {
return (node.kind === SyntaxKind.SingleLineCommentTrivia ||
node.kind === SyntaxKind.MultiLineCommentTrivia);
}
/**
* Returns true if the given ts.Node is a JSDoc comment
*/
function isJSDocComment(node) {
// eslint-disable-next-line @typescript-eslint/no-deprecated -- SyntaxKind.JSDoc was only added in TS4.7 so we can't use it yet
return node.kind === SyntaxKind.JSDocComment;
}
/**
* Returns the binary expression type of the given ts.Token
*/
function getBinaryExpressionType(operator) {
if (isAssignmentOperator(operator)) {
return {
type: ts_estree_1.AST_NODE_TYPES.AssignmentExpression,
operator: getTextForTokenKind(operator.kind),
};
}
if (isLogicalOperator(operator)) {
return {
type: ts_estree_1.AST_NODE_TYPES.LogicalExpression,
operator: getTextForTokenKind(operator.kind),
};
}
if (isESTreeBinaryOperator(operator)) {
return {
type: ts_estree_1.AST_NODE_TYPES.BinaryExpression,
operator: getTextForTokenKind(operator.kind),
};
}
throw new Error(`Unexpected binary operator ${ts.tokenToString(operator.kind)}`);
}
/**
* Returns line and column data for the given positions
*/
function getLineAndCharacterFor(pos, ast) {
const loc = ast.getLineAndCharacterOfPosition(pos);
return {
column: loc.character,
line: loc.line + 1,
};
}
/**
* Returns line and column data for the given start and end positions,
* for the given AST
*/
function getLocFor(range, ast) {
const [start, end] = range.map(pos => getLineAndCharacterFor(pos, ast));
return { end, start };
}
/**
* Check whatever node can contain directive
*/
function canContainDirective(node) {
if (node.kind === ts.SyntaxKind.Block) {
switch (node.parent.kind) {
case ts.SyntaxKind.Constructor:
case ts.SyntaxKind.GetAccessor:
case ts.SyntaxKind.SetAccessor:
case ts.SyntaxKind.ArrowFunction:
case ts.SyntaxKind.FunctionExpression:
case ts.SyntaxKind.FunctionDeclaration:
case ts.SyntaxKind.MethodDeclaration:
return true;
default:
return false;
}
}
return true;
}
/**
* Returns range for the given ts.Node
*/
function getRange(node, ast) {
return [node.getStart(ast), node.getEnd()];
}
/**
* Returns true if a given ts.Node is a token
*/
function isToken(node) {
return (node.kind >= SyntaxKind.FirstToken && node.kind <= SyntaxKind.LastToken);
}
/**
* Returns true if a given ts.Node is a JSX token
*/
function isJSXToken(node) {
return (node.kind >= SyntaxKind.JsxElement && node.kind <= SyntaxKind.JsxAttribute);
}
/**
* Returns the declaration kind of the given ts.Node
*/
function getDeclarationKind(node) {
if (node.flags & ts.NodeFlags.Let) {
return 'let';
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
if ((node.flags & ts.NodeFlags.AwaitUsing) === ts.NodeFlags.AwaitUsing) {
return 'await using';
}
if (node.flags & ts.NodeFlags.Const) {
return 'const';
}
if (node.flags & ts.NodeFlags.Using) {
return 'using';
}
return 'var';
}
/**
* Gets a ts.Node's accessibility level
*/
function getTSNodeAccessibility(node) {
const modifiers = (0, getModifiers_1.getModifiers)(node);
if (modifiers == null) {
return undefined;
}
for (const modifier of modifiers) {
switch (modifier.kind) {
case SyntaxKind.PublicKeyword:
return 'public';
case SyntaxKind.ProtectedKeyword:
return 'protected';
case SyntaxKind.PrivateKeyword:
return 'private';
default:
break;
}
}
return undefined;
}
/**
* Finds the next token based on the previous one and its parent
* Had to copy this from TS instead of using TS's version because theirs doesn't pass the ast to getChildren
*/
function findNextToken(previousToken, parent, ast) {
return find(parent);
function find(n) {
if (ts.isToken(n) && n.pos === previousToken.end) {
// this is token that starts at the end of previous token - return it
return n;
}
return firstDefined(n.getChildren(ast), (child) => {
const shouldDiveInChildNode =
// previous token is enclosed somewhere in the child
(child.pos <= previousToken.pos && child.end > previousToken.end) ||
// previous token ends exactly at the beginning of child
child.pos === previousToken.end;
return shouldDiveInChildNode && nodeHasTokens(child, ast)
? find(child)
: undefined;
});
}
}
/**
* Find the first matching ancestor based on the given predicate function.
* @param node The current ts.Node
* @param predicate The predicate function to apply to each checked ancestor
* @returns a matching parent ts.Node
*/
function findFirstMatchingAncestor(node, predicate) {
let current = node;
while (current) {
if (predicate(current)) {
return current;
}
current = current.parent;
}
return undefined;
}
/**
* Returns true if a given ts.Node has a JSX token within its hierarchy
*/
function hasJSXAncestor(node) {
return !!findFirstMatchingAncestor(node, isJSXToken);
}
/**
* Unescape the text content of string literals, e.g. &amp; -> &
* @param text The escaped string literal text.
* @returns The unescaped string literal text.
*/
function unescapeStringLiteralText(text) {
return text.replaceAll(/&(?:#\d+|#x[\da-fA-F]+|[0-9a-zA-Z]+);/g, entity => {
const item = entity.slice(1, -1);
if (item[0] === '#') {
const codePoint = item[1] === 'x'
? parseInt(item.slice(2), 16)
: parseInt(item.slice(1), 10);
return codePoint > 0x10ffff // RangeError: Invalid code point
? entity
: String.fromCodePoint(codePoint);
}
return xhtml_entities_1.xhtmlEntities[item] || entity;
});
}
/**
* Returns true if a given ts.Node is a computed property
*/
function isComputedProperty(node) {
return node.kind === SyntaxKind.ComputedPropertyName;
}
/**
* Returns true if a given ts.Node is optional (has QuestionToken)
* @param node ts.Node to be checked
*/
function isOptional(node) {
return !!node.questionToken;
}
/**
* Returns true if the node is an optional chain node
*/
function isChainExpression(node) {
return node.type === ts_estree_1.AST_NODE_TYPES.ChainExpression;
}
/**
* Returns true of the child of property access expression is an optional chain
*/
function isChildUnwrappableOptionalChain(node, child) {
return (isChainExpression(child) &&
// (x?.y).z is semantically different, and as such .z is no longer optional
node.expression.kind !== ts.SyntaxKind.ParenthesizedExpression);
}
/**
* Returns the type of a given ts.Token
*/
function getTokenType(token) {
if (token.kind === SyntaxKind.NullKeyword) {
return ts_estree_1.AST_TOKEN_TYPES.Null;
}
if (token.kind >= SyntaxKind.FirstKeyword &&
token.kind <= SyntaxKind.LastFutureReservedWord) {
if (token.kind === SyntaxKind.FalseKeyword ||
token.kind === SyntaxKind.TrueKeyword) {
return ts_estree_1.AST_TOKEN_TYPES.Boolean;
}
return ts_estree_1.AST_TOKEN_TYPES.Keyword;
}
if (token.kind >= SyntaxKind.FirstPunctuation &&
token.kind <= SyntaxKind.LastPunctuation) {
return ts_estree_1.AST_TOKEN_TYPES.Punctuator;
}
if (token.kind >= SyntaxKind.NoSubstitutionTemplateLiteral &&
token.kind <= SyntaxKind.TemplateTail) {
return ts_estree_1.AST_TOKEN_TYPES.Template;
}
switch (token.kind) {
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
return ts_estree_1.AST_TOKEN_TYPES.Numeric;
case SyntaxKind.PrivateIdentifier:
return ts_estree_1.AST_TOKEN_TYPES.PrivateIdentifier;
case SyntaxKind.JsxText:
return ts_estree_1.AST_TOKEN_TYPES.JSXText;
case SyntaxKind.StringLiteral:
// A TypeScript-StringLiteral token with a TypeScript-JsxAttribute or TypeScript-JsxElement parent,
// must actually be an ESTree-JSXText token
if (token.parent.kind === SyntaxKind.JsxAttribute ||
token.parent.kind === SyntaxKind.JsxElement) {
return ts_estree_1.AST_TOKEN_TYPES.JSXText;
}
return ts_estree_1.AST_TOKEN_TYPES.String;
case SyntaxKind.RegularExpressionLiteral:
return ts_estree_1.AST_TOKEN_TYPES.RegularExpression;
case SyntaxKind.Identifier:
case SyntaxKind.ConstructorKeyword:
case SyntaxKind.GetKeyword:
case SyntaxKind.SetKeyword:
// intentional fallthrough
default:
}
// Some JSX tokens have to be determined based on their parent
if (token.kind === SyntaxKind.Identifier) {
if (isJSXToken(token.parent)) {
return ts_estree_1.AST_TOKEN_TYPES.JSXIdentifier;
}
if (token.parent.kind === SyntaxKind.PropertyAccessExpression &&
hasJSXAncestor(token)) {
return ts_estree_1.AST_TOKEN_TYPES.JSXIdentifier;
}
}
return ts_estree_1.AST_TOKEN_TYPES.Identifier;
}
/**
* Extends and formats a given ts.Token, for a given AST
*/
function convertToken(token, ast) {
const start = token.kind === SyntaxKind.JsxText
? token.getFullStart()
: token.getStart(ast);
const end = token.getEnd();
const value = ast.text.slice(start, end);
const tokenType = getTokenType(token);
const range = [start, end];
const loc = getLocFor(range, ast);
if (tokenType === ts_estree_1.AST_TOKEN_TYPES.RegularExpression) {
return {
type: tokenType,
loc,
range,
regex: {
flags: value.slice(value.lastIndexOf('/') + 1),
pattern: value.slice(1, value.lastIndexOf('/')),
},
value,
};
}
if (tokenType === ts_estree_1.AST_TOKEN_TYPES.PrivateIdentifier) {
return {
type: tokenType,
loc,
range,
value: value.slice(1),
};
}
// @ts-expect-error TS is complaining about `value` not being the correct
// type but it is
return {
type: tokenType,
loc,
range,
value,
};
}
/**
* Converts all tokens for the given AST
* @param ast the AST object
* @returns the converted Tokens
*/
function convertTokens(ast) {
const result = [];
/**
* @param node the ts.Node
*/
function walk(node) {
// TypeScript generates tokens for types in JSDoc blocks. Comment tokens
// and their children should not be walked or added to the resulting tokens list.
if (isComment(node) || isJSDocComment(node)) {
return;
}
if (isToken(node) && node.kind !== SyntaxKind.EndOfFileToken) {
result.push(convertToken(node, ast));
}
else {
node.getChildren(ast).forEach(walk);
}
}
walk(ast);
return result;
}
class TSError extends Error {
fileName;
location;
name = 'TSError';
constructor(message, fileName, location) {
super(message);
this.fileName = fileName;
this.location = location;
}
// For old version of ESLint https://github.com/typescript-eslint/typescript-eslint/pull/6556#discussion_r1123237311
get index() {
return this.location.start.offset;
}
// https://github.com/eslint/eslint/blob/b09a512107249a4eb19ef5a37b0bd672266eafdb/lib/linter/linter.js#L853
get lineNumber() {
return this.location.start.line;
}
// https://github.com/eslint/eslint/blob/b09a512107249a4eb19ef5a37b0bd672266eafdb/lib/linter/linter.js#L854
get column() {
return this.location.start.column;
}
}
exports.TSError = TSError;
function createError(node, message, sourceFile) {
let startIndex;
let endIndex;
if (Array.isArray(node)) {
[startIndex, endIndex] = node;
}
else if (typeof node === 'number') {
startIndex = endIndex = node;
}
else {
sourceFile ??= node.getSourceFile();
startIndex = node.getStart(sourceFile);
endIndex = node.getEnd();
}
if (!sourceFile) {
throw new Error('`sourceFile` is required.');
}
const [start, end] = [startIndex, endIndex].map(offset => {
const { character: column, line } = sourceFile.getLineAndCharacterOfPosition(offset);
return { column, line: line + 1, offset };
});
return new TSError(message, sourceFile.fileName, { end, start });
}
function nodeHasTokens(n, ast) {
// If we have a token or node that has a non-zero width, it must have tokens.
// Note: getWidth() does not take trivia into account.
return n.kind === SyntaxKind.EndOfFileToken
? !!n.jsDoc
: n.getWidth(ast) !== 0;
}
/**
* Like `forEach`, but suitable for use with numbers and strings (which may be falsy).
*/
function firstDefined(array, callback) {
// eslint-disable-next-line @typescript-eslint/internal/eqeq-nullish
if (array === undefined) {
return undefined;
}
for (let i = 0; i < array.length; i++) {
const result = callback(array[i], i);
// eslint-disable-next-line @typescript-eslint/internal/eqeq-nullish
if (result !== undefined) {
return result;
}
}
return undefined;
}
function identifierIsThisKeyword(id) {
return ((isAtLeast50
? ts.identifierToKeywordKind(id)
: // @ts-expect-error -- intentional fallback for older TS versions <=4.9
id.originalKeywordKind) === SyntaxKind.ThisKeyword);
}
function isThisIdentifier(node) {
return (!!node &&
node.kind === SyntaxKind.Identifier &&
identifierIsThisKeyword(node));
}
function isThisInTypeQuery(node) {
if (!isThisIdentifier(node)) {
return false;
}
while (ts.isQualifiedName(node.parent) && node.parent.left === node) {
node = node.parent;
}
return node.parent.kind === SyntaxKind.TypeQuery;
}
function isValidAssignmentTarget(node) {
switch (node.kind) {
case SyntaxKind.Identifier:
return true;
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
if (node.flags & ts.NodeFlags.OptionalChain) {
return false;
}
return true;
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.AsExpression:
case SyntaxKind.SatisfiesExpression:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.NonNullExpression:
return isValidAssignmentTarget(node.expression);
default:
return false;
}
}
function getNamespaceModifiers(node) {
// For following nested namespaces, use modifiers given to the topmost namespace
// export declare namespace foo.bar.baz {}
let modifiers = (0, getModifiers_1.getModifiers)(node);
let moduleDeclaration = node;
while ((!modifiers || modifiers.length === 0) &&
ts.isModuleDeclaration(moduleDeclaration.parent)) {
const parentModifiers = (0, getModifiers_1.getModifiers)(moduleDeclaration.parent);
if (parentModifiers?.length) {
modifiers = parentModifiers;
}
moduleDeclaration = moduleDeclaration.parent;
}
return modifiers;
}
// `ts.declarationNameToString`
function declarationNameToString(node) {
const text = node.getSourceFile().text.slice(node.pos, node.end).trimStart();
return text || '(Missing)';
}
function isPropertyAccessEntityNameExpression(node) {
return (ts.isPropertyAccessExpression(node) &&
ts.isIdentifier(node.name) &&
isEntityNameExpression(node.expression));
}
function isEntityNameExpression(node) {
return (node.kind === SyntaxKind.Identifier ||
isPropertyAccessEntityNameExpression(node));
}

View File

@@ -0,0 +1,115 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const util_1 = require("../util");
exports.default = (0, util_1.createRule)({
name: 'prefer-for-of',
meta: {
type: 'suggestion',
docs: {
description: 'Enforce the use of `for-of` loop over the standard `for` loop where possible',
recommended: 'stylistic',
},
messages: {
preferForOf: 'Expected a `for-of` loop instead of a `for` loop with this simple iteration.',
},
schema: [],
},
defaultOptions: [],
create(context) {
function isSingleVariableDeclaration(node) {
return (node?.type === utils_1.AST_NODE_TYPES.VariableDeclaration &&
node.kind !== 'const' &&
node.declarations.length === 1);
}
function isLiteral(node, value) {
return node.type === utils_1.AST_NODE_TYPES.Literal && node.value === value;
}
function isZeroInitialized(node) {
return node.init != null && isLiteral(node.init, 0);
}
function isMatchingIdentifier(node, name) {
return node.type === utils_1.AST_NODE_TYPES.Identifier && node.name === name;
}
function isLessThanLengthExpression(node, name) {
if (node?.type === utils_1.AST_NODE_TYPES.BinaryExpression &&
node.operator === '<' &&
isMatchingIdentifier(node.left, name) &&
node.right.type === utils_1.AST_NODE_TYPES.MemberExpression &&
isMatchingIdentifier(node.right.property, 'length')) {
return node.right.object;
}
return null;
}
function isIncrement(node, name) {
if (!node) {
return false;
}
switch (node.type) {
case utils_1.AST_NODE_TYPES.UpdateExpression:
// x++ or ++x
return (node.operator === '++' && isMatchingIdentifier(node.argument, name));
case utils_1.AST_NODE_TYPES.AssignmentExpression:
if (isMatchingIdentifier(node.left, name)) {
if (node.operator === '+=') {
// x += 1
return isLiteral(node.right, 1);
}
if (node.operator === '=') {
// x = x + 1 or x = 1 + x
const expr = node.right;
return (expr.type === utils_1.AST_NODE_TYPES.BinaryExpression &&
expr.operator === '+' &&
((isMatchingIdentifier(expr.left, name) &&
isLiteral(expr.right, 1)) ||
(isLiteral(expr.left, 1) &&
isMatchingIdentifier(expr.right, name))));
}
}
}
return false;
}
function contains(outer, inner) {
return (outer.range[0] <= inner.range[0] && outer.range[1] >= inner.range[1]);
}
function isIndexOnlyUsedWithArray(body, indexVar, arrayExpression) {
const arrayText = context.sourceCode.getText(arrayExpression);
return indexVar.references.every(reference => {
const id = reference.identifier;
const node = id.parent;
return (!contains(body, id) ||
(node.type === utils_1.AST_NODE_TYPES.MemberExpression &&
node.object.type !== utils_1.AST_NODE_TYPES.ThisExpression &&
node.property === id &&
context.sourceCode.getText(node.object) === arrayText &&
!(0, util_1.isAssignee)(node)));
});
}
return {
'ForStatement:exit'(node) {
if (!isSingleVariableDeclaration(node.init)) {
return;
}
const declarator = node.init.declarations[0];
if (!declarator ||
!isZeroInitialized(declarator) ||
declarator.id.type !== utils_1.AST_NODE_TYPES.Identifier) {
return;
}
const indexName = declarator.id.name;
const arrayExpression = isLessThanLengthExpression(node.test, indexName);
if (!arrayExpression) {
return;
}
const [indexVar] = context.sourceCode.getDeclaredVariables(node.init);
if (isIncrement(node.update, indexName) &&
isIndexOnlyUsedWithArray(node.body, indexVar, arrayExpression)) {
context.report({
node,
messageId: 'preferForOf',
});
}
},
};
},
});

View File

@@ -0,0 +1,109 @@
/**
* @fileoverview Common helpers for naming of plugins, formatters and configs
*/
"use strict";
const NAMESPACE_REGEX = /^@.*\//u;
/**
* Brings package name to correct format based on prefix
* @param {string} name The name of the package.
* @param {string} prefix Can be either "eslint-plugin", "eslint-config" or "eslint-formatter"
* @returns {string} Normalized name of the package
* @private
*/
function normalizePackageName(name, prefix) {
let normalizedName = name;
/**
* On Windows, name can come in with Windows slashes instead of Unix slashes.
* Normalize to Unix first to avoid errors later on.
* https://github.com/eslint/eslint/issues/5644
*/
if (normalizedName.includes("\\")) {
normalizedName = normalizedName.replace(/\\/gu, "/");
}
if (normalizedName.charAt(0) === "@") {
/**
* it's a scoped package
* package name is the prefix, or just a username
*/
const scopedPackageShortcutRegex = new RegExp(
`^(@[^/]+)(?:/(?:${prefix})?)?$`,
"u",
),
scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, "u");
if (scopedPackageShortcutRegex.test(normalizedName)) {
normalizedName = normalizedName.replace(
scopedPackageShortcutRegex,
`$1/${prefix}`,
);
} else if (!scopedPackageNameRegex.test(normalizedName.split("/")[1])) {
/*
* for scoped packages, insert the prefix after the first / unless
* the path is already @scope/eslint or @scope/eslint-xxx-yyy
*/
normalizedName = normalizedName.replace(
/^@([^/]+)\/(.*)$/u,
`@$1/${prefix}-$2`,
);
}
} else if (!normalizedName.startsWith(`${prefix}-`)) {
normalizedName = `${prefix}-${normalizedName}`;
}
return normalizedName;
}
/**
* Removes the prefix from a fullname.
* @param {string} fullname The term which may have the prefix.
* @param {string} prefix The prefix to remove.
* @returns {string} The term without prefix.
*/
function getShorthandName(fullname, prefix) {
if (fullname[0] === "@") {
let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, "u").exec(
fullname,
);
if (matchResult) {
return matchResult[1];
}
matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, "u").exec(
fullname,
);
if (matchResult) {
return `${matchResult[1]}/${matchResult[2]}`;
}
} else if (fullname.startsWith(`${prefix}-`)) {
return fullname.slice(prefix.length + 1);
}
return fullname;
}
/**
* Gets the scope (namespace) of a term.
* @param {string} term The term which may have the namespace.
* @returns {string} The namespace of the term if it has one.
*/
function getNamespaceFromTerm(term) {
const match = term.match(NAMESPACE_REGEX);
return match ? match[0] : "";
}
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
module.exports = {
normalizePackageName,
getShorthandName,
getNamespaceFromTerm,
};

View File

@@ -0,0 +1,9 @@
export { default as v1 } from './v1.js';
export { default as v3 } from './v3.js';
export { default as v4 } from './v4.js';
export { default as v5 } from './v5.js';
export { default as NIL } from './nil.js';
export { default as version } from './version.js';
export { default as validate } from './validate.js';
export { default as stringify } from './stringify.js';
export { default as parse } from './parse.js';

View File

@@ -0,0 +1,419 @@
'use strict'
const fs = require('fs')
const path = require('path')
const SonicBoom = require('../')
const { file, runTests } = require('./helper')
const proxyquire = require('proxyquire')
runTests(buildTests)
function buildTests (test, sync) {
// Reset the unmask for testing
process.umask(0o000)
test('append', (t) => {
t.plan(4)
const dest = file()
fs.writeFileSync(dest, 'hello world\n')
const stream = new SonicBoom({ dest, append: false, sync })
stream.on('ready', () => {
t.pass('ready emitted')
})
t.ok(stream.write('something else\n'))
stream.flush()
stream.on('drain', () => {
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'something else\n')
stream.end()
})
})
})
test('mkdir', (t) => {
t.plan(4)
const dest = path.join(file(), 'out.log')
const stream = new SonicBoom({ dest, mkdir: true, sync })
stream.on('ready', () => {
t.pass('ready emitted')
})
t.ok(stream.write('hello world\n'))
stream.flush()
stream.on('drain', () => {
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'hello world\n')
stream.end()
})
})
})
test('flush', (t) => {
t.plan(5)
const dest = file()
const fd = fs.openSync(dest, 'w')
const stream = new SonicBoom({ fd, minLength: 4096, sync })
stream.on('ready', () => {
t.pass('ready emitted')
})
t.ok(stream.write('hello world\n'))
t.ok(stream.write('something else\n'))
stream.flush()
stream.on('drain', () => {
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'hello world\nsomething else\n')
stream.end()
})
})
})
test('flush with no data', (t) => {
t.plan(2)
const dest = file()
const fd = fs.openSync(dest, 'w')
const stream = new SonicBoom({ fd, minLength: 4096, sync })
stream.on('ready', () => {
t.pass('ready emitted')
})
stream.flush()
stream.on('drain', () => {
t.pass('drain emitted')
})
})
test('call flush cb after flushed', (t) => {
t.plan(4)
const dest = file()
const fd = fs.openSync(dest, 'w')
const stream = new SonicBoom({ fd, minLength: 4096, sync })
stream.on('ready', () => {
t.pass('ready emitted')
})
t.ok(stream.write('hello world\n'))
t.ok(stream.write('something else\n'))
stream.flush((err) => {
if (err) t.fail(err)
else t.pass('flush cb called')
})
})
test('only call fsyncSync and not fsync when fsync: true', (t) => {
t.plan(6)
const fakeFs = Object.create(fs)
const SonicBoom = proxyquire('../', {
fs: fakeFs
})
const dest = file()
const fd = fs.openSync(dest, 'w')
const stream = new SonicBoom({
fd,
sync,
fsync: true,
minLength: 4096
})
stream.on('ready', () => {
t.pass('ready emitted')
})
fakeFs.fsync = function (fd, cb) {
t.fail('fake fs.fsync called while should not')
cb()
}
fakeFs.fsyncSync = function (fd) {
t.pass('fake fsyncSync called')
}
function successOnAsyncOrSyncFn (isSync, originalFn) {
return function (...args) {
t.pass(`fake fs.${originalFn.name} called`)
fakeFs[originalFn.name] = originalFn
return fakeFs[originalFn.name](...args)
}
}
if (sync) {
fakeFs.writeSync = successOnAsyncOrSyncFn(true, fs.writeSync)
} else {
fakeFs.write = successOnAsyncOrSyncFn(false, fs.write)
}
t.ok(stream.write('hello world\n'))
stream.flush((err) => {
if (err) t.fail(err)
else t.pass('flush cb called')
process.nextTick(() => {
// to make sure fsync is not called as well
t.pass('nextTick after flush called')
})
})
})
test('call flush cb with error when fsync failed', (t) => {
t.plan(5)
const fakeFs = Object.create(fs)
const SonicBoom = proxyquire('../', {
fs: fakeFs
})
const dest = file()
const fd = fs.openSync(dest, 'w')
const stream = new SonicBoom({
fd,
sync,
minLength: 4096
})
stream.on('ready', () => {
t.pass('ready emitted')
})
const err = new Error('other')
err.code = 'other'
function onFsyncOnFsyncSync (isSync, originalFn) {
return function (...args) {
Error.captureStackTrace(err)
t.pass(`fake fs.${originalFn.name} called`)
fakeFs[originalFn.name] = originalFn
const cb = args[args.length - 1]
cb(err)
}
}
// only one is called depends on sync
fakeFs.fsync = onFsyncOnFsyncSync(false, fs.fsync)
function successOnAsyncOrSyncFn (isSync, originalFn) {
return function (...args) {
t.pass(`fake fs.${originalFn.name} called`)
fakeFs[originalFn.name] = originalFn
return fakeFs[originalFn.name](...args)
}
}
if (sync) {
fakeFs.writeSync = successOnAsyncOrSyncFn(true, fs.writeSync)
} else {
fakeFs.write = successOnAsyncOrSyncFn(false, fs.write)
}
t.ok(stream.write('hello world\n'))
stream.flush((err) => {
if (err) t.equal(err.code, 'other')
else t.fail('flush cb called without an error')
})
})
test('call flush cb even when have no data', (t) => {
t.plan(2)
const dest = file()
const fd = fs.openSync(dest, 'w')
const stream = new SonicBoom({ fd, minLength: 4096, sync })
stream.on('ready', () => {
t.pass('ready emitted')
stream.flush((err) => {
if (err) t.fail(err)
else t.pass('flush cb called')
})
})
})
test('call flush cb even when minLength is 0', (t) => {
t.plan(1)
const dest = file()
const fd = fs.openSync(dest, 'w')
const stream = new SonicBoom({ fd, minLength: 0, sync })
stream.flush((err) => {
if (err) t.fail(err)
else t.pass('flush cb called')
})
})
test('call flush cb with an error when trying to flush destroyed stream', (t) => {
t.plan(1)
const dest = file()
const fd = fs.openSync(dest, 'w')
const stream = new SonicBoom({ fd, minLength: 4096, sync })
stream.destroy()
stream.flush((err) => {
if (err) t.pass(err)
else t.fail('flush cb called without an error')
})
})
test('call flush cb with an error when failed to flush', (t) => {
t.plan(5)
const fakeFs = Object.create(fs)
const SonicBoom = proxyquire('../', {
fs: fakeFs
})
const dest = file()
const fd = fs.openSync(dest, 'w')
const stream = new SonicBoom({
fd,
sync,
minLength: 4096
})
stream.on('ready', () => {
t.pass('ready emitted')
})
const err = new Error('other')
err.code = 'other'
function onWriteOrWriteSync (isSync, originalFn) {
return function (...args) {
Error.captureStackTrace(err)
t.pass(`fake fs.${originalFn.name} called`)
fakeFs[originalFn.name] = originalFn
if (isSync) throw err
const cb = args[args.length - 1]
cb(err)
}
}
// only one is called depends on sync
fakeFs.write = onWriteOrWriteSync(false, fs.write)
fakeFs.writeSync = onWriteOrWriteSync(true, fs.writeSync)
t.ok(stream.write('hello world\n'))
stream.flush((err) => {
if (err) t.equal(err.code, 'other')
else t.fail('flush cb called without an error')
})
stream.end()
stream.on('close', () => {
t.pass('close emitted')
})
})
test('call flush cb when finish writing when currently in the middle', (t) => {
t.plan(4)
const fakeFs = Object.create(fs)
const SonicBoom = proxyquire('../', {
fs: fakeFs
})
const dest = file()
const fd = fs.openSync(dest, 'w')
const stream = new SonicBoom({
fd,
sync,
// to trigger write without calling flush
minLength: 1
})
stream.on('ready', () => {
t.pass('ready emitted')
})
function onWriteOrWriteSync (originalFn) {
return function (...args) {
stream.flush((err) => {
if (err) t.fail(err)
else t.pass('flush cb called')
})
t.pass(`fake fs.${originalFn.name} called`)
fakeFs[originalFn.name] = originalFn
return originalFn(...args)
}
}
// only one is called depends on sync
fakeFs.write = onWriteOrWriteSync(fs.write)
fakeFs.writeSync = onWriteOrWriteSync(fs.writeSync)
t.ok(stream.write('hello world\n'))
})
test('call flush cb when writing and trying to flush before ready (on async)', (t) => {
t.plan(4)
const fakeFs = Object.create(fs)
const SonicBoom = proxyquire('../', {
fs: fakeFs
})
fakeFs.open = fsOpen
const dest = file()
const stream = new SonicBoom({
fd: dest,
// only async as sync is part of the constructor so the user will not be able to call write/flush
// before ready
sync: false,
// to not trigger write without calling flush
minLength: 4096
})
stream.on('ready', () => {
t.pass('ready emitted')
})
function fsOpen (...args) {
process.nextTick(() => {
// try writing and flushing before ready and in the middle of opening
t.pass('fake fs.open called')
t.ok(stream.write('hello world\n'))
// calling flush
stream.flush((err) => {
if (err) t.fail(err)
else t.pass('flush cb called')
})
fakeFs.open = fs.open
fs.open(...args)
})
}
})
}

View File

@@ -0,0 +1,95 @@
import { HotPayload } from "#types/hmrPayload";
//#region src/shared/invokeMethods.d.ts
interface FetchFunctionOptions {
cached?: boolean;
startOffset?: number;
}
type FetchResult = CachedFetchResult | ExternalFetchResult | ViteFetchResult;
interface CachedFetchResult {
/**
* If the module is cached in the runner, this confirms
* it was not invalidated on the server side.
*/
cache: true;
}
interface ExternalFetchResult {
/**
* The path to the externalized module starting with file://.
* By default this will be imported via a dynamic "import"
* instead of being transformed by Vite and loaded with the Vite runner.
*/
externalize: string;
/**
* Type of the module. Used to determine if the import statement is correct.
* For example, if Vite needs to throw an error if a variable is not actually exported.
*/
type: "module" | "commonjs" | "builtin" | "network";
}
interface ViteFetchResult {
/**
* Code that will be evaluated by the Vite runner.
* By default this will be wrapped in an async function.
*/
code: string;
/**
* File path of the module on disk.
* This will be resolved as import.meta.url/filename.
* Will be `null` for virtual modules.
*/
file: string | null;
/**
* Module ID in the server module graph.
*/
id: string;
/**
* Module URL used in the import.
*/
url: string;
/**
* Invalidate module on the client side.
*/
invalidate: boolean;
}
type InvokeMethods = {
fetchModule: (id: string, importer?: string, options?: FetchFunctionOptions) => Promise<FetchResult>;
getBuiltins: () => Promise<Array<{
type: "string";
value: string;
} | {
type: "RegExp";
source: string;
flags: string;
}>>;
};
//#endregion
//#region src/shared/moduleRunnerTransport.d.ts
type ModuleRunnerTransportHandlers = {
onMessage: (data: HotPayload) => void;
onDisconnection: () => void;
};
/**
* "send and connect" or "invoke" must be implemented
*/
interface ModuleRunnerTransport {
connect?(handlers: ModuleRunnerTransportHandlers): Promise<void> | void;
disconnect?(): Promise<void> | void;
send?(data: HotPayload): Promise<void> | void;
invoke?(data: HotPayload): Promise<{
result: any;
} | {
error: any;
}>;
timeout?: number;
}
interface NormalizedModuleRunnerTransport {
connect?(onMessage?: (data: HotPayload) => void): Promise<void> | void;
disconnect?(): Promise<void> | void;
send(data: HotPayload): Promise<void>;
invoke<T extends keyof InvokeMethods>(name: T, data: Parameters<InvokeMethods[T]>): Promise<ReturnType<Awaited<InvokeMethods[T]>>>;
}
declare const createWebSocketModuleRunnerTransport: (options: {
createConnection: () => WebSocket;
pingInterval?: number;
}) => Required<Pick<ModuleRunnerTransport, "connect" | "disconnect" | "send">>;
//#endregion
export { ExternalFetchResult as a, ViteFetchResult as c, createWebSocketModuleRunnerTransport as i, ModuleRunnerTransportHandlers as n, FetchFunctionOptions as o, NormalizedModuleRunnerTransport as r, FetchResult as s, ModuleRunnerTransport as t };

View File

@@ -0,0 +1,4 @@
function _classPrivateMethodSet() {
throw new TypeError("attempted to reassign private method");
}
module.exports = _classPrivateMethodSet, module.exports.__esModule = true, module.exports["default"] = module.exports;

View File

@@ -0,0 +1,46 @@
/**
* A class that manages a queue of retry jobs.
*/
export class Retrier {
/**
* Creates a new instance.
* @param {Function} check The function to call.
* @param {object} [options] The options for the instance.
* @param {number} [options.timeout] The timeout for the queue.
* @param {number} [options.maxDelay] The maximum delay for the queue.
* @param {number} [options.concurrency] The maximum number of concurrent tasks.
*/
constructor(check: Function, { timeout, maxDelay, concurrency }?: {
timeout?: number | undefined;
maxDelay?: number | undefined;
concurrency?: number | undefined;
} | undefined);
/**
* Gets the number of tasks waiting to be retried.
* @returns {number} The number of tasks in the retry queue.
*/
get retrying(): number;
/**
* Gets the number of tasks waiting to be processed in the pending queue.
* @returns {number} The number of tasks in the pending queue.
*/
get pending(): number;
/**
* Gets the number of tasks currently being processed.
* @returns {number} The number of tasks currently being processed.
*/
get working(): number;
/**
* Adds a new retry job to the queue.
* @template {(...args: unknown[]) => Promise<unknown>} Func
* @template {Awaited<ReturnType<Func>>} RetVal
* @param {Func} fn The function to call.
* @param {object} [options] The options for the job.
* @param {AbortSignal} [options.signal] The AbortSignal to monitor for cancellation.
* @returns {Promise<RetVal>} A promise that resolves when the queue is processed.
*/
retry<Func extends (...args: unknown[]) => Promise<unknown>, RetVal extends Awaited<ReturnType<Func>>>(fn: Func, { signal }?: {
signal?: AbortSignal | undefined;
} | undefined): Promise<RetVal>;
#private;
}

View File

@@ -0,0 +1,31 @@
'use strict'
const { test } = require('node:test')
const { createCopier } = require('fast-copy')
const fastCopy = createCopier({})
const deleteLogProperty = require('./delete-log-property')
const logData = {
level: 30,
data1: {
data2: { 'data-3': 'bar' }
}
}
test('deleteLogProperty deletes property of depth 1', t => {
const log = fastCopy(logData)
deleteLogProperty(log, 'data1')
t.assert.deepStrictEqual(log, { level: 30 })
})
test('deleteLogProperty deletes property of depth 2', t => {
const log = fastCopy(logData)
deleteLogProperty(log, 'data1.data2')
t.assert.deepStrictEqual(log, { level: 30, data1: { } })
})
test('deleteLogProperty deletes property of depth 3', t => {
const log = fastCopy(logData)
deleteLogProperty(log, 'data1.data2.data-3')
t.assert.deepStrictEqual(log, { level: 30, data1: { data2: { } } })
})

View File

@@ -0,0 +1,67 @@
# whatwg-url
whatwg-url is a full implementation of the WHATWG [URL Standard](https://url.spec.whatwg.org/). It can be used standalone, but it also exposes a lot of the internal algorithms that are useful for integrating a URL parser into a project like [jsdom](https://github.com/tmpvar/jsdom).
## Current Status
whatwg-url is currently up to date with the URL spec up to commit [a62223](https://github.com/whatwg/url/commit/a622235308342c9adc7fc2fd1659ff059f7d5e2a).
## API
### The `URL` Constructor
The main API is the [`URL`](https://url.spec.whatwg.org/#url) export, which follows the spec's behavior in all ways (including e.g. `USVString` conversion). Most consumers of this library will want to use this.
### Low-level URL Standard API
The following methods are exported for use by places like jsdom that need to implement things like [`HTMLHyperlinkElementUtils`](https://html.spec.whatwg.org/#htmlhyperlinkelementutils). They operate on or return an "internal URL" or ["URL record"](https://url.spec.whatwg.org/#concept-url) type.
- [URL parser](https://url.spec.whatwg.org/#concept-url-parser): `parseURL(input, { baseURL, encodingOverride })`
- [Basic URL parser](https://url.spec.whatwg.org/#concept-basic-url-parser): `basicURLParse(input, { baseURL, encodingOverride, url, stateOverride })`
- [URL serializer](https://url.spec.whatwg.org/#concept-url-serializer): `serializeURL(urlRecord, excludeFragment)`
- [Host serializer](https://url.spec.whatwg.org/#concept-host-serializer): `serializeHost(hostFromURLRecord)`
- [Serialize an integer](https://url.spec.whatwg.org/#serialize-an-integer): `serializeInteger(number)`
- [Origin](https://url.spec.whatwg.org/#concept-url-origin) [serializer](https://html.spec.whatwg.org/multipage/browsers.html#serialization-of-an-origin): `serializeURLOrigin(urlRecord)`
- [Set the username](https://url.spec.whatwg.org/#set-the-username): `setTheUsername(urlRecord, usernameString)`
- [Set the password](https://url.spec.whatwg.org/#set-the-password): `setThePassword(urlRecord, passwordString)`
- [Cannot have a username/password/port](https://url.spec.whatwg.org/#cannot-have-a-username-password-port): `cannotHaveAUsernamePasswordPort(urlRecord)`
The `stateOverride` parameter is one of the following strings:
- [`"scheme start"`](https://url.spec.whatwg.org/#scheme-start-state)
- [`"scheme"`](https://url.spec.whatwg.org/#scheme-state)
- [`"no scheme"`](https://url.spec.whatwg.org/#no-scheme-state)
- [`"special relative or authority"`](https://url.spec.whatwg.org/#special-relative-or-authority-state)
- [`"path or authority"`](https://url.spec.whatwg.org/#path-or-authority-state)
- [`"relative"`](https://url.spec.whatwg.org/#relative-state)
- [`"relative slash"`](https://url.spec.whatwg.org/#relative-slash-state)
- [`"special authority slashes"`](https://url.spec.whatwg.org/#special-authority-slashes-state)
- [`"special authority ignore slashes"`](https://url.spec.whatwg.org/#special-authority-ignore-slashes-state)
- [`"authority"`](https://url.spec.whatwg.org/#authority-state)
- [`"host"`](https://url.spec.whatwg.org/#host-state)
- [`"hostname"`](https://url.spec.whatwg.org/#hostname-state)
- [`"port"`](https://url.spec.whatwg.org/#port-state)
- [`"file"`](https://url.spec.whatwg.org/#file-state)
- [`"file slash"`](https://url.spec.whatwg.org/#file-slash-state)
- [`"file host"`](https://url.spec.whatwg.org/#file-host-state)
- [`"path start"`](https://url.spec.whatwg.org/#path-start-state)
- [`"path"`](https://url.spec.whatwg.org/#path-state)
- [`"cannot-be-a-base-URL path"`](https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state)
- [`"query"`](https://url.spec.whatwg.org/#query-state)
- [`"fragment"`](https://url.spec.whatwg.org/#fragment-state)
The URL record type has the following API:
- [`scheme`](https://url.spec.whatwg.org/#concept-url-scheme)
- [`username`](https://url.spec.whatwg.org/#concept-url-username)
- [`password`](https://url.spec.whatwg.org/#concept-url-password)
- [`host`](https://url.spec.whatwg.org/#concept-url-host)
- [`port`](https://url.spec.whatwg.org/#concept-url-port)
- [`path`](https://url.spec.whatwg.org/#concept-url-path) (as an array)
- [`query`](https://url.spec.whatwg.org/#concept-url-query)
- [`fragment`](https://url.spec.whatwg.org/#concept-url-fragment)
- [`cannotBeABaseURL`](https://url.spec.whatwg.org/#url-cannot-be-a-base-url-flag) (as a boolean)
These properties should be treated with care, as in general changing them will cause the URL record to be in an inconsistent state until the appropriate invocation of `basicURLParse` is used to fix it up. You can see examples of this in the URL Standard, where there are many step sequences like "4. Set context objects urls fragment to the empty string. 5. Basic URL parse _input_ with context objects url as _url_ and fragment state as _state override_." In between those two steps, a URL record is in an unusable state.
The return value of "failure" in the spec is represented by the string `"failure"`. That is, functions like `parseURL` and `basicURLParse` can return _either_ a URL record _or_ the string `"failure"`.

View File

@@ -0,0 +1,164 @@
import type { $ZodStringFormats } from "../core/checks.js";
import type * as errors from "../core/errors.js";
import * as util from "../core/util.js";
function getArmenianPlural(count: number, one: string, many: string): string {
return Math.abs(count) === 1 ? one : many;
}
function withDefiniteArticle(word: string | undefined): string {
if (!word) return "";
const vowels = ["ա", "ե", "ը", "ի", "ո", "ու", "օ"];
const lastChar = word[word.length - 1];
return word + (vowels.includes(lastChar) ? "ն" : "ը");
}
interface ArmenianSizable {
unit: {
one: string;
many: string;
};
verb: string;
}
const error: () => errors.$ZodErrorMap = () => {
const Sizable: Record<string, ArmenianSizable> = {
string: {
unit: {
one: "նշան",
many: "նշաններ",
},
verb: "ունենալ",
},
file: {
unit: {
one: "բայթ",
many: "բայթեր",
},
verb: "ունենալ",
},
array: {
unit: {
one: "տարր",
many: "տարրեր",
},
verb: "ունենալ",
},
set: {
unit: {
one: "տարր",
many: "տարրեր",
},
verb: "ունենալ",
},
};
function getSizing(origin: string): ArmenianSizable | null {
return Sizable[origin] ?? null;
}
const FormatDictionary: {
[k in $ZodStringFormats | (string & {})]?: string;
} = {
regex: "մուտք",
email: "էլ. հասցե",
url: "URL",
emoji: "էմոջի",
uuid: "UUID",
uuidv4: "UUIDv4",
uuidv6: "UUIDv6",
nanoid: "nanoid",
guid: "GUID",
cuid: "cuid",
cuid2: "cuid2",
ulid: "ULID",
xid: "XID",
ksuid: "KSUID",
datetime: "ISO ամսաթիվ և ժամ",
date: "ISO ամսաթիվ",
time: "ISO ժամ",
duration: "ISO տևողություն",
ipv4: "IPv4 հասցե",
ipv6: "IPv6 հասցե",
cidrv4: "IPv4 միջակայք",
cidrv6: "IPv6 միջակայք",
base64: "base64 ձևաչափով տող",
base64url: "base64url ձևաչափով տող",
json_string: "JSON տող",
e164: "E.164 համար",
jwt: "JWT",
template_literal: "մուտք",
};
const TypeDictionary: {
[k in errors.$ZodInvalidTypeExpected | (string & {})]?: string;
} = {
nan: "NaN",
number: "թիվ",
array: "զանգված",
};
return (issue) => {
switch (issue.code) {
case "invalid_type": {
const expected = TypeDictionary[issue.expected] ?? issue.expected;
const receivedType = util.parsedType(issue.input);
const received = TypeDictionary[receivedType] ?? receivedType;
if (/^[A-Z]/.test(issue.expected)) {
return `Սխալ մուտքագրում․ սպասվում էր instanceof ${issue.expected}, ստացվել է ${received}`;
}
return `Սխալ մուտքագրում․ սպասվում էր ${expected}, ստացվել է ${received}`;
}
case "invalid_value":
if (issue.values.length === 1)
return `Սխալ մուտքագրում․ սպասվում էր ${util.stringifyPrimitive(issue.values[1])}`;
return `Սխալ տարբերակ․ սպասվում էր հետևյալներից մեկը՝ ${util.joinValues(issue.values, "|")}`;
case "too_big": {
const adj = issue.inclusive ? "<=" : "<";
const sizing = getSizing(issue.origin);
if (sizing) {
const maxValue = Number(issue.maximum);
const unit = getArmenianPlural(maxValue, sizing.unit.one, sizing.unit.many);
return `Չափազանց մեծ արժեք․ սպասվում է, որ ${withDefiniteArticle(issue.origin ?? "արժեք")} կունենա ${adj}${issue.maximum.toString()} ${unit}`;
}
return `Չափազանց մեծ արժեք․ սպասվում է, որ ${withDefiniteArticle(issue.origin ?? "արժեք")} լինի ${adj}${issue.maximum.toString()}`;
}
case "too_small": {
const adj = issue.inclusive ? ">=" : ">";
const sizing = getSizing(issue.origin);
if (sizing) {
const minValue = Number(issue.minimum);
const unit = getArmenianPlural(minValue, sizing.unit.one, sizing.unit.many);
return `Չափազանց փոքր արժեք․ սպասվում է, որ ${withDefiniteArticle(issue.origin)} կունենա ${adj}${issue.minimum.toString()} ${unit}`;
}
return `Չափազանց փոքր արժեք․ սպասվում է, որ ${withDefiniteArticle(issue.origin)} լինի ${adj}${issue.minimum.toString()}`;
}
case "invalid_format": {
const _issue = issue as errors.$ZodStringFormatIssues;
if (_issue.format === "starts_with") return `Սխալ տող․ պետք է սկսվի "${_issue.prefix}"-ով`;
if (_issue.format === "ends_with") return `Սխալ տող․ պետք է ավարտվի "${_issue.suffix}"-ով`;
if (_issue.format === "includes") return `Սխալ տող․ պետք է պարունակի "${_issue.includes}"`;
if (_issue.format === "regex") return `Սխալ տող․ պետք է համապատասխանի ${_issue.pattern} ձևաչափին`;
return `Սխալ ${FormatDictionary[_issue.format] ?? issue.format}`;
}
case "not_multiple_of":
return `Սխալ թիվ․ պետք է բազմապատիկ լինի ${issue.divisor}-ի`;
case "unrecognized_keys":
return `Չճանաչված բանալի${issue.keys.length > 1 ? "ներ" : ""}. ${util.joinValues(issue.keys, ", ")}`;
case "invalid_key":
return `Սխալ բանալի ${withDefiniteArticle(issue.origin)}-ում`;
case "invalid_union":
return "Սխալ մուտքագրում";
case "invalid_element":
return `Սխալ արժեք ${withDefiniteArticle(issue.origin)}-ում`;
default:
return `Սխալ մուտքագրում`;
}
};
};
export default function (): { localeError: errors.$ZodErrorMap } {
return {
localeError: error(),
};
}

View File

@@ -0,0 +1,2 @@
export declare var InternalSymbolName: any;
//# sourceMappingURL=internalSymbolName.d.ts.map

View File

@@ -0,0 +1,260 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const tsutils = __importStar(require("ts-api-utils"));
const ts = __importStar(require("typescript"));
const util_1 = require("../util");
exports.default = (0, util_1.createRule)({
name: 'no-misused-spread',
meta: {
type: 'problem',
docs: {
description: 'Disallow using the spread operator when it might cause unexpected behavior',
recommended: 'strict',
requiresTypeChecking: true,
},
hasSuggestions: true,
messages: {
addAwait: 'Add await operator.',
noArraySpreadInObject: 'Using the spread operator on an array in an object will result in a list of indices.',
noClassDeclarationSpreadInObject: 'Using the spread operator on class declarations will spread only their static properties, and will lose their class prototype.',
noClassInstanceSpreadInObject: 'Using the spread operator on class instances will lose their class prototype.',
noFunctionSpreadInObject: 'Using the spread operator on a function without additional properties can cause unexpected behavior. Did you forget to call the function?',
noIterableSpreadInObject: 'Using the spread operator on an Iterable in an object can cause unexpected behavior.',
noMapSpreadInObject: 'Using the spread operator on a Map in an object will result in an empty object. Did you mean to use `Object.fromEntries(map)` instead?',
noPromiseSpreadInObject: 'Using the spread operator on Promise in an object can cause unexpected behavior. Did you forget to await the promise?',
noStringSpread: [
'Using the spread operator on a string can mishandle special characters, as can `.split("")`.',
'- `...` produces Unicode code points, which will decompose complex emojis into individual emojis',
'- .split("") produces UTF-16 code units, which breaks rich characters in many languages',
'Consider using `Intl.Segmenter` for locale-aware string decomposition.',
"Otherwise, if you don't need to preserve emojis or other non-Ascii characters, disable this lint rule on this line or configure the 'allow' rule option.",
].join('\n'),
replaceMapSpreadInObject: 'Replace map spread in object with `Object.fromEntries()`',
},
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
allow: {
...util_1.readonlynessOptionsSchema.properties.allow,
description: 'An array of type specifiers that are known to be safe to spread.',
},
},
},
],
},
defaultOptions: [
{
allow: [],
},
],
create(context, [options]) {
const services = (0, util_1.getParserServices)(context);
const checker = services.program.getTypeChecker();
function checkArrayOrCallSpread(node) {
const type = (0, util_1.getConstrainedTypeAtLocation)(services, node.argument);
if (!(0, util_1.typeMatchesSomeSpecifier)(type, options.allow, services.program) &&
isString(type)) {
context.report({
node,
messageId: 'noStringSpread',
});
}
}
function getMapSpreadSuggestions(node, type) {
const types = tsutils.unionConstituents(type);
if (types.some(t => !isMap(services.program, t))) {
return null;
}
if (node.parent.type === utils_1.AST_NODE_TYPES.ObjectExpression &&
node.parent.properties.length === 1) {
return [
{
messageId: 'replaceMapSpreadInObject',
fix: (0, util_1.getWrappingFixer)({
node: node.parent,
innerNode: node.argument,
sourceCode: context.sourceCode,
wrap: code => `Object.fromEntries(${code})`,
}),
},
];
}
return [
{
messageId: 'replaceMapSpreadInObject',
fix: (0, util_1.getWrappingFixer)({
node: node.argument,
sourceCode: context.sourceCode,
wrap: code => `Object.fromEntries(${code})`,
}),
},
];
}
function getPromiseSpreadSuggestions(node) {
const isHighPrecedence = (0, util_1.isHigherPrecedenceThanAwait)(services.esTreeNodeToTSNodeMap.get(node));
return [
{
messageId: 'addAwait',
fix: fixer => isHighPrecedence
? fixer.insertTextBefore(node, 'await ')
: [
fixer.insertTextBefore(node, 'await ('),
fixer.insertTextAfter(node, ')'),
],
},
];
}
function checkObjectSpread(node) {
const type = (0, util_1.getConstrainedTypeAtLocation)(services, node.argument);
if ((0, util_1.typeMatchesSomeSpecifier)(type, options.allow, services.program)) {
return;
}
if (isPromise(services.program, type)) {
context.report({
node,
messageId: 'noPromiseSpreadInObject',
suggest: getPromiseSpreadSuggestions(node.argument),
});
return;
}
if (isFunctionWithoutProps(type)) {
context.report({
node,
messageId: 'noFunctionSpreadInObject',
});
return;
}
if (isMap(services.program, type)) {
context.report({
node,
messageId: 'noMapSpreadInObject',
suggest: getMapSpreadSuggestions(node, type),
});
return;
}
if (isArray(checker, type)) {
context.report({
node,
messageId: 'noArraySpreadInObject',
});
return;
}
if (isIterable(type, checker) &&
// Don't report when the type is string, since TS will flag it already
!isString(type)) {
context.report({
node,
messageId: 'noIterableSpreadInObject',
});
return;
}
if (isClassInstance(checker, type)) {
context.report({
node,
messageId: 'noClassInstanceSpreadInObject',
});
return;
}
if (isClassDeclaration(type)) {
context.report({
node,
messageId: 'noClassDeclarationSpreadInObject',
});
}
}
return {
'ArrayExpression > SpreadElement': checkArrayOrCallSpread,
'CallExpression > SpreadElement': checkArrayOrCallSpread,
JSXSpreadAttribute: checkObjectSpread,
'ObjectExpression > SpreadElement': checkObjectSpread,
};
},
});
function isIterable(type, checker) {
return tsutils
.typeConstituents(type)
.some(t => !!tsutils.getWellKnownSymbolPropertyOfType(t, 'iterator', checker));
}
function isArray(checker, type) {
return isTypeRecurser(type, t => checker.isArrayType(t) || checker.isTupleType(t));
}
function isString(type) {
return isTypeRecurser(type, t => (0, util_1.isTypeFlagSet)(t, ts.TypeFlags.StringLike));
}
function isFunctionWithoutProps(type) {
return isTypeRecurser(type, t => t.getCallSignatures().length > 0 && t.getProperties().length === 0);
}
function isPromise(program, type) {
return isTypeRecurser(type, t => (0, util_1.isPromiseLike)(program, t));
}
function isClassInstance(checker, type) {
return isTypeRecurser(type, t => {
// If the type itself has a construct signature, it's a class(-like)
if (t.getConstructSignatures().length) {
return false;
}
const symbol = t.getSymbol();
// If the type's symbol has a construct signature, the type is an instance
return !!symbol
?.getDeclarations()
?.some(declaration => checker
.getTypeOfSymbolAtLocation(symbol, declaration)
.getConstructSignatures().length);
});
}
function isClassDeclaration(type) {
return isTypeRecurser(type, t => {
if (tsutils.isObjectType(t) &&
tsutils.isObjectFlagSet(t, ts.ObjectFlags.InstantiationExpressionType)) {
return true;
}
const kind = t.getSymbol()?.valueDeclaration?.kind;
return (kind === ts.SyntaxKind.ClassDeclaration ||
kind === ts.SyntaxKind.ClassExpression);
});
}
function isMap(program, type) {
return isTypeRecurser(type, t => (0, util_1.isBuiltinSymbolLike)(program, t, ['Map', 'ReadonlyMap', 'WeakMap']));
}
function isTypeRecurser(type, predicate) {
if (type.isUnionOrIntersection()) {
return type.types.some(t => isTypeRecurser(t, predicate));
}
return predicate(type);
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"regularExpressionFlags.js","sourceRoot":"","sources":["../../src/enums/regularExpressionFlags.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAI,sBAA2B,CAAC;AACvC,CAAC,UAAU,sBAAsB;IAC7B,sBAAsB,CAAC,sBAAsB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;IACpE,sBAAsB,CAAC,sBAAsB,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC;IAChF,sBAAsB,CAAC,sBAAsB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IACxE,sBAAsB,CAAC,sBAAsB,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC;IAChF,sBAAsB,CAAC,sBAAsB,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC;IAC9E,sBAAsB,CAAC,sBAAsB,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,QAAQ,CAAC;IACzE,sBAAsB,CAAC,sBAAsB,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC;IAC3E,sBAAsB,CAAC,sBAAsB,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,GAAG,aAAa,CAAC;IACnF,sBAAsB,CAAC,sBAAsB,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;IAC1E,sBAAsB,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,GAAG,gBAAgB,CAAC;AAC7F,CAAC,CAAC,CAAC,sBAAsB,IAAI,CAAC,sBAAsB,GAAG,EAAE,CAAC,CAAC,CAAC"}

View File

@@ -0,0 +1,196 @@
import { F as withFilter } from "./shared/define-config-Dsp5YQR4.mjs";
//#region ../../node_modules/.pnpm/@rolldown+pluginutils@1.0.1/node_modules/@rolldown/pluginutils/dist/filter/index.d.mts
//#region src/filter/composable-filters.d.ts
type StringOrRegExp = string | RegExp;
type PluginModuleType = 'js' | 'jsx' | 'ts' | 'tsx' | 'json' | 'text' | 'base64' | 'dataurl' | 'binary' | 'empty' | (string & {});
type FilterExpressionKind = FilterExpression['kind'];
type FilterExpression = And | Or | Not | Id | ImporterId | ModuleType | Code | Query;
type TopLevelFilterExpression = Include | Exclude;
declare class And {
kind: 'and';
args: FilterExpression[];
constructor(...args: FilterExpression[]);
}
declare class Or {
kind: 'or';
args: FilterExpression[];
constructor(...args: FilterExpression[]);
}
declare class Not {
kind: 'not';
expr: FilterExpression;
constructor(expr: FilterExpression);
}
interface QueryFilterObject {
[key: string]: StringOrRegExp | boolean;
}
interface IdParams {
cleanUrl?: boolean;
}
declare class Id {
kind: 'id';
pattern: StringOrRegExp;
params: IdParams;
constructor(pattern: StringOrRegExp, params?: IdParams);
}
declare class ImporterId {
kind: 'importerId';
pattern: StringOrRegExp;
params: IdParams;
constructor(pattern: StringOrRegExp, params?: IdParams);
}
declare class ModuleType {
kind: 'moduleType';
pattern: PluginModuleType;
constructor(pattern: PluginModuleType);
}
declare class Code {
kind: 'code';
pattern: StringOrRegExp;
constructor(expr: StringOrRegExp);
}
declare class Query {
kind: 'query';
key: string;
pattern: StringOrRegExp | boolean;
constructor(key: string, pattern: StringOrRegExp | boolean);
}
declare class Include {
kind: 'include';
expr: FilterExpression;
constructor(expr: FilterExpression);
}
declare class Exclude {
kind: 'exclude';
expr: FilterExpression;
constructor(expr: FilterExpression);
}
declare function and(...args: FilterExpression[]): And;
declare function or(...args: FilterExpression[]): Or;
declare function not(expr: FilterExpression): Not;
declare function id(pattern: StringOrRegExp, params?: IdParams): Id;
declare function importerId(pattern: StringOrRegExp, params?: IdParams): ImporterId;
declare function moduleType(pattern: PluginModuleType): ModuleType;
declare function code(pattern: StringOrRegExp): Code;
declare function query(key: string, pattern: StringOrRegExp | boolean): Query;
declare function include(expr: FilterExpression): Include;
declare function exclude(expr: FilterExpression): Exclude;
/**
* convert a queryObject to FilterExpression like
* ```js
* and(query(k1, v1), query(k2, v2))
* ```
* @param queryFilterObject The query filter object needs to be matched.
* @returns a `And` FilterExpression
*/
declare function queries(queryFilter: QueryFilterObject): And;
declare function interpreter(exprs: TopLevelFilterExpression | TopLevelFilterExpression[], code?: string, id?: string, moduleType?: PluginModuleType, importerId?: string): boolean;
interface InterpreterCtx {
urlSearchParamsCache?: URLSearchParams;
}
declare function interpreterImpl(expr: TopLevelFilterExpression[], code?: string, id?: string, moduleType?: PluginModuleType, importerId?: string, ctx?: InterpreterCtx): boolean;
declare function exprInterpreter(expr: FilterExpression, code?: string, id?: string, moduleType?: PluginModuleType, importerId?: string, ctx?: InterpreterCtx): boolean;
//#endregion
//#region src/filter/filter-vite-plugins.d.ts
/**
* Filters out Vite plugins that have `apply: 'serve'` set.
*
* Since Rolldown operates in build mode, plugins marked with `apply: 'serve'`
* are intended only for Vite's dev server and should be excluded from the build process.
*
* @param plugins - Array of plugins (can include nested arrays)
* @returns Filtered array with serve-only plugins removed
*
* @example
* ```ts
* import { defineConfig } from 'rolldown';
* import { filterVitePlugins } from '@rolldown/pluginutils';
* import viteReact from '@vitejs/plugin-react';
*
* export default defineConfig({
* plugins: filterVitePlugins([
* viteReact(),
* {
* name: 'dev-only',
* apply: 'serve', // This will be filtered out
* // ...
* }
* ])
* });
* ```
*/
declare function filterVitePlugins<T = any>(plugins: T | T[] | null | undefined | false): T[];
//#endregion
//#region src/filter/simple-filters.d.ts
/**
* Constructs a RegExp that matches the exact string specified.
*
* This is useful for plugin hook filters.
*
* @param str the string to match.
* @param flags flags for the RegExp.
*
* @example
* ```ts
* import { exactRegex } from '@rolldown/pluginutils';
* const plugin = {
* name: 'plugin',
* resolveId: {
* filter: { id: exactRegex('foo') },
* handler(id) {} // will only be called for `foo`
* }
* }
* ```
*/
declare function exactRegex(str: string, flags?: string): RegExp;
/**
* Constructs a RegExp that matches a value that has the specified prefix.
*
* This is useful for plugin hook filters.
*
* @param str the string to match.
* @param flags flags for the RegExp.
*
* @example
* ```ts
* import { prefixRegex } from '@rolldown/pluginutils';
* const plugin = {
* name: 'plugin',
* resolveId: {
* filter: { id: prefixRegex('foo') },
* handler(id) {} // will only be called for IDs starting with `foo`
* }
* }
* ```
*/
declare function prefixRegex(str: string, flags?: string): RegExp;
type WidenString<T> = T extends string ? string : T;
/**
* Converts a id filter to match with an id with a query.
*
* @param input the id filters to convert.
*
* @example
* ```ts
* import { makeIdFiltersToMatchWithQuery } from '@rolldown/pluginutils';
* const plugin = {
* name: 'plugin',
* transform: {
* filter: { id: makeIdFiltersToMatchWithQuery(['**' + '/*.js', /\.ts$/]) },
* // The handler will be called for IDs like:
* // - foo.js
* // - foo.js?foo
* // - foo.txt?foo.js
* // - foo.ts
* // - foo.ts?foo
* // - foo.txt?foo.ts
* handler(code, id) {}
* }
* }
* ```
*/
declare function makeIdFiltersToMatchWithQuery<T extends string | RegExp>(input: T): WidenString<T>;
declare function makeIdFiltersToMatchWithQuery<T extends string | RegExp>(input: readonly T[]): WidenString<T>[];
declare function makeIdFiltersToMatchWithQuery(input: string | RegExp | readonly (string | RegExp)[]): string | RegExp | (string | RegExp)[];
//#endregion
export { FilterExpression, FilterExpressionKind, QueryFilterObject, TopLevelFilterExpression, and, code, exactRegex, exclude, exprInterpreter, filterVitePlugins, id, importerId, include, interpreter, interpreterImpl, makeIdFiltersToMatchWithQuery, moduleType, not, or, prefixRegex, queries, query, withFilter };

View File

@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2024_full: LibDefinition;

View File

@@ -0,0 +1,83 @@
export {};
type _DOMException = typeof globalThis extends { onmessage: any } ? {} : DOMException;
interface DOMException extends Error {
readonly code: number;
readonly message: string;
readonly name: string;
readonly INDEX_SIZE_ERR: 1;
readonly DOMSTRING_SIZE_ERR: 2;
readonly HIERARCHY_REQUEST_ERR: 3;
readonly WRONG_DOCUMENT_ERR: 4;
readonly INVALID_CHARACTER_ERR: 5;
readonly NO_DATA_ALLOWED_ERR: 6;
readonly NO_MODIFICATION_ALLOWED_ERR: 7;
readonly NOT_FOUND_ERR: 8;
readonly NOT_SUPPORTED_ERR: 9;
readonly INUSE_ATTRIBUTE_ERR: 10;
readonly INVALID_STATE_ERR: 11;
readonly SYNTAX_ERR: 12;
readonly INVALID_MODIFICATION_ERR: 13;
readonly NAMESPACE_ERR: 14;
readonly INVALID_ACCESS_ERR: 15;
readonly VALIDATION_ERR: 16;
readonly TYPE_MISMATCH_ERR: 17;
readonly SECURITY_ERR: 18;
readonly NETWORK_ERR: 19;
readonly ABORT_ERR: 20;
readonly URL_MISMATCH_ERR: 21;
readonly QUOTA_EXCEEDED_ERR: 22;
readonly TIMEOUT_ERR: 23;
readonly INVALID_NODE_TYPE_ERR: 24;
readonly DATA_CLONE_ERR: 25;
}
declare global {
interface DOMException extends _DOMException {}
var DOMException: typeof globalThis extends { onmessage: any; DOMException: infer T } ? T
: {
prototype: DOMException;
new(message?: string, name?: string): DOMException;
new(message?: string, options?: { name?: string; cause?: unknown }): DOMException;
readonly INDEX_SIZE_ERR: 1;
readonly DOMSTRING_SIZE_ERR: 2;
readonly HIERARCHY_REQUEST_ERR: 3;
readonly WRONG_DOCUMENT_ERR: 4;
readonly INVALID_CHARACTER_ERR: 5;
readonly NO_DATA_ALLOWED_ERR: 6;
readonly NO_MODIFICATION_ALLOWED_ERR: 7;
readonly NOT_FOUND_ERR: 8;
readonly NOT_SUPPORTED_ERR: 9;
readonly INUSE_ATTRIBUTE_ERR: 10;
readonly INVALID_STATE_ERR: 11;
readonly SYNTAX_ERR: 12;
readonly INVALID_MODIFICATION_ERR: 13;
readonly NAMESPACE_ERR: 14;
readonly INVALID_ACCESS_ERR: 15;
readonly VALIDATION_ERR: 16;
readonly TYPE_MISMATCH_ERR: 17;
readonly SECURITY_ERR: 18;
readonly NETWORK_ERR: 19;
readonly ABORT_ERR: 20;
readonly URL_MISMATCH_ERR: 21;
readonly QUOTA_EXCEEDED_ERR: 22;
readonly TIMEOUT_ERR: 23;
readonly INVALID_NODE_TYPE_ERR: 24;
readonly DATA_CLONE_ERR: 25;
};
// Not conditional, as this is not yet exposed by the DOM lib generator.
interface QuotaExceededError extends DOMException {
readonly quota: number | null;
readonly requested: number | null;
}
var QuotaExceededError: {
prototype: QuotaExceededError;
new(message?: string, options?: QuotaExceededErrorOptions): QuotaExceededError;
};
interface QuotaExceededErrorOptions {
quota?: number;
requested?: number;
}
}