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,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _crypto = _interopRequireDefault(require("crypto"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function md5(bytes) {
if (Array.isArray(bytes)) {
bytes = Buffer.from(bytes);
} else if (typeof bytes === 'string') {
bytes = Buffer.from(bytes, 'utf8');
}
return _crypto.default.createHash('md5').update(bytes).digest();
}
var _default = md5;
exports.default = _default;

View File

@@ -0,0 +1 @@
export { _ as default } from "../esm/_non_iterable_spread.js";

View File

@@ -0,0 +1,99 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.JSONSchemaGenerator = void 0;
const json_schema_processors_js_1 = require("./json-schema-processors.cjs");
const to_json_schema_js_1 = require("./to-json-schema.cjs");
/**
* Legacy class-based interface for JSON Schema generation.
* This class wraps the new functional implementation to provide backward compatibility.
*
* @deprecated Use the `toJSONSchema` function instead for new code.
*
* @example
* ```typescript
* // Legacy usage (still supported)
* const gen = new JSONSchemaGenerator({ target: "draft-07" });
* gen.process(schema);
* const result = gen.emit(schema);
*
* // Preferred modern usage
* const result = toJSONSchema(schema, { target: "draft-07" });
* ```
*/
class JSONSchemaGenerator {
/** @deprecated Access via ctx instead */
get metadataRegistry() {
return this.ctx.metadataRegistry;
}
/** @deprecated Access via ctx instead */
get target() {
return this.ctx.target;
}
/** @deprecated Access via ctx instead */
get unrepresentable() {
return this.ctx.unrepresentable;
}
/** @deprecated Access via ctx instead */
get override() {
return this.ctx.override;
}
/** @deprecated Access via ctx instead */
get io() {
return this.ctx.io;
}
/** @deprecated Access via ctx instead */
get counter() {
return this.ctx.counter;
}
set counter(value) {
this.ctx.counter = value;
}
/** @deprecated Access via ctx instead */
get seen() {
return this.ctx.seen;
}
constructor(params) {
// Normalize target for internal context
let normalizedTarget = params?.target ?? "draft-2020-12";
if (normalizedTarget === "draft-4")
normalizedTarget = "draft-04";
if (normalizedTarget === "draft-7")
normalizedTarget = "draft-07";
this.ctx = (0, to_json_schema_js_1.initializeContext)({
processors: json_schema_processors_js_1.allProcessors,
target: normalizedTarget,
...(params?.metadata && { metadata: params.metadata }),
...(params?.unrepresentable && { unrepresentable: params.unrepresentable }),
...(params?.override && { override: params.override }),
...(params?.io && { io: params.io }),
});
}
/**
* Process a schema to prepare it for JSON Schema generation.
* This must be called before emit().
*/
process(schema, _params = { path: [], schemaPath: [] }) {
return (0, to_json_schema_js_1.process)(schema, this.ctx, _params);
}
/**
* Emit the final JSON Schema after processing.
* Must call process() first.
*/
emit(schema, _params) {
// Apply emit params to the context
if (_params) {
if (_params.cycles)
this.ctx.cycles = _params.cycles;
if (_params.reused)
this.ctx.reused = _params.reused;
if (_params.external)
this.ctx.external = _params.external;
}
(0, to_json_schema_js_1.extractDefs)(this.ctx, schema);
const result = (0, to_json_schema_js_1.finalize)(this.ctx, schema);
// Strip ~standard property to match old implementation's return type
const { "~standard": _, ...plainResult } = result;
return plainResult;
}
}
exports.JSONSchemaGenerator = JSONSchemaGenerator;

View File

@@ -0,0 +1,740 @@
import fs from 'node:fs';
import { splitFileAndPostfix as splitFileAndPostfix$1, isBareImport } from '@vitest/utils/helpers';
import { i as isBuiltin, a as isBrowserExternal, t as toBuiltin } from './modules.BJuCwlRJ.js';
import { E as EnvironmentTeardownError, a as getSafeWorkerState } from './utils.BX5Fg8C4.js';
import { pathToFileURL } from 'node:url';
import { normalize, join } from 'pathe';
import { distDir } from '../path.js';
import { VitestModuleEvaluator, unwrapId } from '../module-evaluator.js';
import { isAbsolute, resolve } from 'node:path';
import vm from 'node:vm';
import { MockerRegistry, mockObject, RedirectedModule, AutomockedModule } from '@vitest/mocker';
import { findMockRedirect } from '@vitest/mocker/redirect';
import * as viteModuleRunner from 'vite/module-runner';
import { T as Traces } from './traces.DT5aQ62U.js';
class BareModuleMocker {
static pendingIds = [];
spyModule;
primitives;
registries = /* @__PURE__ */ new Map();
mockContext = { callstack: null };
_otel;
constructor(options) {
this.options = options;
this._otel = options.traces;
this.primitives = {
Object,
Error,
Function,
RegExp,
Symbol: globalThis.Symbol,
Array,
Map
};
if (options.spyModule) this.spyModule = options.spyModule;
}
get root() {
return this.options.root;
}
get moduleDirectories() {
return this.options.moduleDirectories || [];
}
getMockerRegistry() {
const suite = this.getSuiteFilepath();
if (!this.registries.has(suite)) this.registries.set(suite, new MockerRegistry());
return this.registries.get(suite);
}
reset() {
this.registries.clear();
}
invalidateModuleById(_id) {
// implemented by mockers that control the module runner
}
isModuleDirectory(path) {
return this.moduleDirectories.some((dir) => path.includes(dir));
}
getSuiteFilepath() {
return this.options.getCurrentTestFilepath() || "global";
}
createError(message, codeFrame) {
const Error = this.primitives.Error;
const error = new Error(message);
Object.assign(error, { codeFrame });
return error;
}
async resolveId(rawId, importer) {
return this._otel.$("vitest.mocker.resolve_id", { attributes: {
"vitest.module.raw_id": rawId,
"vitest.module.importer": rawId
} }, async (span) => {
const result = await this.options.resolveId(rawId, importer);
if (!result) {
span.addEvent("could not resolve id, fallback to unresolved values");
const id = normalizeModuleId(rawId);
span.setAttributes({
"vitest.module.id": id,
"vitest.module.url": rawId,
"vitest.module.external": id,
"vitest.module.fallback": true
});
return {
id,
url: rawId,
external: id
};
}
// external is node_module or unresolved module
// for example, some people mock "vscode" and don't have it installed
const external = !isAbsolute(result.file) || this.isModuleDirectory(result.file) ? normalizeModuleId(rawId) : null;
const id = normalizeModuleId(result.id);
span.setAttributes({
"vitest.module.id": id,
"vitest.module.url": result.url,
"vitest.module.external": external ?? false
});
return {
...result,
id,
external
};
});
}
async resolveMocks() {
if (!BareModuleMocker.pendingIds.length) return;
const resolveMock = async (mock) => {
const { id, url, external } = await this.resolveId(mock.id, mock.importer);
if (mock.action === "unmock") this.unmockPath(id);
if (mock.action === "mock") this.mockPath(mock.id, id, url, external, mock.type, mock.factory);
};
// group consecutive mocks of the same action type together,
// resolve in parallel inside each group, but run groups sequentially
// to preserve mock/unmock ordering
const groups = groupByConsecutiveAction(BareModuleMocker.pendingIds);
for (const group of groups) await Promise.all(group.map(resolveMock));
BareModuleMocker.pendingIds = [];
}
// public method to avoid circular dependency
getMockContext() {
return this.mockContext;
}
// path used to store mocked dependencies
getMockPath(dep) {
return `mock:${dep}`;
}
getDependencyMock(id) {
return this.getMockerRegistry().getById(fixLeadingSlashes(id));
}
getDependencyMockByUrl(url) {
return this.getMockerRegistry().get(url);
}
findMockRedirect(mockPath, external) {
return findMockRedirect(this.root, mockPath, external);
}
mockObject(object, mockExportsOrModuleType, moduleType) {
let mockExports;
if (mockExportsOrModuleType === "automock" || mockExportsOrModuleType === "autospy") {
moduleType = mockExportsOrModuleType;
mockExports = void 0;
} else mockExports = mockExportsOrModuleType;
moduleType ??= "automock";
const createMockInstance = this.spyModule?.createMockInstance;
if (!createMockInstance) throw this.createError("[vitest] `spyModule` is not defined. This is a Vitest error. Please open a new issue with reproduction.");
return mockObject({
globalConstructors: this.primitives,
createMockInstance,
type: moduleType
}, object, mockExports);
}
unmockPath(id) {
this.getMockerRegistry().deleteById(id);
this.invalidateModuleById(id);
}
mockPath(originalId, id, url, external, mockType, factory) {
const registry = this.getMockerRegistry();
if (mockType === "manual") registry.register("manual", originalId, id, url, factory);
else if (mockType === "autospy") registry.register("autospy", originalId, id, url);
else {
const redirect = this.findMockRedirect(id, external);
if (redirect) registry.register("redirect", originalId, id, url, redirect);
else registry.register("automock", originalId, id, url);
}
// every time the mock is registered, we remove the previous one from the cache
this.invalidateModuleById(id);
}
async importActual(_rawId, _importer, _callstack) {
throw new Error(`importActual is not implemented`);
}
async importMock(_rawId, _importer, _callstack) {
throw new Error(`importMock is not implemented`);
}
queueMock(id, importer, factoryOrOptions) {
const mockType = getMockType(factoryOrOptions);
BareModuleMocker.pendingIds.push({
action: "mock",
id,
importer,
factory: typeof factoryOrOptions === "function" ? factoryOrOptions : void 0,
type: mockType
});
}
queueUnmock(id, importer) {
BareModuleMocker.pendingIds.push({
action: "unmock",
id,
importer
});
}
}
function getMockType(factoryOrOptions) {
if (!factoryOrOptions) return "automock";
if (typeof factoryOrOptions === "function") return "manual";
return factoryOrOptions.spy ? "autospy" : "automock";
}
// unique id that is not available as "$bare_import" like "test"
// https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix
const prefixedBuiltins = new Set([
"node:sea",
"node:sqlite",
"node:test",
"node:test/reporters"
]);
const isWindows$1 = process.platform === "win32";
// transform file url to id
// virtual:custom -> virtual:custom
// \0custom -> \0custom
// /root/id -> /id
// /root/id.js -> /id.js
// C:/root/id.js -> /id.js
// C:\root\id.js -> /id.js
// TODO: expose this in vite/module-runner
function normalizeModuleId(file) {
if (prefixedBuiltins.has(file)) return file;
// if it's not in the root, keep it as a path, not a URL
return slash(file).replace(/^\/@fs\//, isWindows$1 ? "" : "/").replace(/^node:/, "").replace(/^\/+/, "/").replace(/^file:\//, "/");
}
const windowsSlashRE = /\\/g;
function slash(p) {
return p.replace(windowsSlashRE, "/");
}
function groupByConsecutiveAction(mocks) {
const groups = [];
for (const mock of mocks) {
const last = groups.at(-1);
if (last?.[0].action === mock.action) last.push(mock);
else groups.push([mock]);
}
return groups;
}
const multipleSlashRe = /^\/+/;
// module-runner incorrectly replaces file:///path with `///path`
function fixLeadingSlashes(id) {
if (id.startsWith("//")) return id.replace(multipleSlashRe, "/");
return id;
}
// copied from vite
// https://github.com/vitejs/vite/blob/4417b4f305623b2850bd6ae6553834c017694672/packages/vite/src/shared/utils.ts
// https://github.com/vitejs/vite/blob/4417b4f305623b2850bd6ae6553834c017694672/packages/vite/src/node/utils.ts
const postfixRE = /[?#].*$/;
const trailingSeparatorRE = /[?&]$/;
function cleanUrl(url) {
return url.replace(postfixRE, "");
}
function splitFileAndPostfix(path) {
const file = cleanUrl(path);
return {
file,
postfix: path.slice(file.length)
};
}
function injectQuery(url, queryToInject) {
const { file, postfix } = splitFileAndPostfix(url);
return `${file}?${queryToInject}${postfix[0] === "?" ? `&${postfix.slice(1)}` : postfix}`;
}
function removeQuery(url, queryToRemove) {
return url.replace(new RegExp(`([?&])${queryToRemove}(?:&|$)`), "$1").replace(trailingSeparatorRE, "");
}
const spyModulePath = resolve(distDir, "spy.js");
class VitestMocker extends BareModuleMocker {
filterPublicKeys;
constructor(moduleRunner, options) {
super(options);
this.moduleRunner = moduleRunner;
this.options = options;
const context = this.options.context;
if (context) this.primitives = vm.runInContext("({ Object, Error, Function, RegExp, Symbol, Array, Map })", context);
const Symbol = this.primitives.Symbol;
this.filterPublicKeys = [
"__esModule",
Symbol.asyncIterator,
Symbol.hasInstance,
Symbol.isConcatSpreadable,
Symbol.iterator,
Symbol.match,
Symbol.matchAll,
Symbol.replace,
Symbol.search,
Symbol.split,
Symbol.species,
Symbol.toPrimitive,
Symbol.toStringTag,
Symbol.unscopables
];
}
get evaluatedModules() {
return this.moduleRunner.evaluatedModules;
}
async initializeSpyModule() {
if (this.spyModule) return;
this.spyModule = await this.moduleRunner.import(spyModulePath);
}
reset() {
this.registries.clear();
}
invalidateModuleById(id) {
const mockId = this.getMockPath(id);
const node = this.evaluatedModules.getModuleById(mockId);
if (node) {
this.evaluatedModules.invalidateModule(node);
node.mockedExports = void 0;
}
}
ensureModule(id, url) {
const node = this.evaluatedModules.ensureModule(id, url);
// TODO
node.meta = {
id,
url,
code: "",
file: null,
invalidate: false
};
return node;
}
async callFunctionMock(id, url, mock) {
const node = this.ensureModule(id, url);
if (node.exports) return node.exports;
const exports$1 = await mock.resolve();
const moduleExports = new Proxy(exports$1, { get: (target, prop) => {
const val = target[prop];
// 'then' can exist on non-Promise objects, need nested instanceof check for logic to work
if (prop === "then") {
if (target instanceof Promise) return target.then.bind(target);
} else if (!(prop in target)) {
if (this.filterPublicKeys.includes(prop)) return;
throw this.createError(`[vitest] No "${String(prop)}" export is defined on the "${mock.raw}" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:
`, `vi.mock(import("${mock.raw}"), async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})`);
}
return val;
} });
node.exports = moduleExports;
return moduleExports;
}
async importActual(rawId, importer, callstack) {
const { url } = await this.resolveId(rawId, importer);
const actualUrl = injectQuery(url, "_vitest_original");
const node = await this.moduleRunner.fetchModule(actualUrl, importer);
return await this.moduleRunner.cachedRequest(node.url, node, callstack || [importer], void 0, true);
}
async importMock(rawId, importer) {
const { id, url, external } = await this.resolveId(rawId, importer);
let mock = this.getDependencyMock(id);
if (!mock) {
const redirect = this.findMockRedirect(id, external);
if (redirect) mock = new RedirectedModule(rawId, id, rawId, redirect);
else mock = new AutomockedModule(rawId, id, rawId);
}
if (mock.type === "automock" || mock.type === "autospy") {
const node = await this.moduleRunner.fetchModule(url, importer);
const mod = await this.moduleRunner.cachedRequest(url, node, [importer], void 0, true);
const Object = this.primitives.Object;
return this.mockObject(mod, Object.create(Object.prototype), mock.type);
}
if (mock.type === "manual") return this.callFunctionMock(id, url, mock);
const node = await this.moduleRunner.fetchModule(mock.redirect);
return this.moduleRunner.cachedRequest(mock.redirect, node, [importer], void 0, true);
}
async requestWithMockedModule(url, evaluatedNode, callstack, mock) {
return this._otel.$("vitest.mocker.evaluate", async (span) => {
const mockId = this.getMockPath(evaluatedNode.id);
span.setAttributes({
"vitest.module.id": mockId,
"vitest.mock.type": mock.type,
"vitest.mock.id": mock.id,
"vitest.mock.url": mock.url,
"vitest.mock.raw": mock.raw
});
if (mock.type === "automock" || mock.type === "autospy") {
const cache = this.evaluatedModules.getModuleById(mockId);
if (cache && cache.mockedExports) return cache.mockedExports;
const Object = this.primitives.Object;
// we have to define a separate object that will copy all properties into itself
// and can't just use the same `exports` define automatically by Vite before the evaluator
const exports$1 = Object.create(null);
Object.defineProperty(exports$1, Symbol.toStringTag, {
value: "Module",
configurable: true,
writable: true
});
const node = this.ensureModule(mockId, this.getMockPath(evaluatedNode.url));
node.meta = evaluatedNode.meta;
node.file = evaluatedNode.file;
node.mockedExports = exports$1;
const mod = await this.moduleRunner.cachedRequest(url, node, callstack, void 0, true);
this.mockObject(mod, exports$1, mock.type);
return exports$1;
}
if (mock.type === "manual" && !callstack.includes(mockId) && !callstack.includes(url)) try {
callstack.push(mockId);
// this will not work if user does Promise.all(import(), import())
// we can also use AsyncLocalStorage to store callstack, but this won't work in the browser
// maybe we should improve mock API in the future?
this.mockContext.callstack = callstack;
return await this.callFunctionMock(mockId, this.getMockPath(url), mock);
} finally {
this.mockContext.callstack = null;
const indexMock = callstack.indexOf(mockId);
callstack.splice(indexMock, 1);
}
else if (mock.type === "redirect" && !callstack.includes(mock.redirect)) {
span.setAttribute("vitest.mock.redirect", mock.redirect);
return mock.redirect;
}
});
}
async mockedRequest(url, evaluatedNode, callstack) {
const mock = this.getDependencyMock(evaluatedNode.id);
if (!mock) return;
return this.requestWithMockedModule(url, evaluatedNode, callstack, mock);
}
}
class VitestTransport {
constructor(options, evaluatedModules, callstacks) {
this.options = options;
this.evaluatedModules = evaluatedModules;
this.callstacks = callstacks;
}
async invoke(event) {
if (event.type !== "custom") return { error: /* @__PURE__ */ new Error(`Vitest Module Runner doesn't support Vite HMR events.`) };
if (event.event !== "vite:invoke") return { error: /* @__PURE__ */ new Error(`Vitest Module Runner doesn't support ${event.event} event.`) };
const { name, data } = event.data;
if (name === "getBuiltins")
// we return an empty array here to avoid client-side builtin check,
// as we need builtins to go through `fetchModule`
return { result: [] };
if (name !== "fetchModule") return { error: /* @__PURE__ */ new Error(`Unknown method: ${name}. Expected "fetchModule".`) };
try {
return { result: await this.options.fetchModule(...data) };
} catch (cause) {
if (cause instanceof EnvironmentTeardownError) {
const [id, importer] = data;
let message = `Cannot load '${id}'${importer ? ` imported from ${importer}` : ""} after the environment was torn down. This is not a bug in Vitest.`;
const moduleNode = importer ? this.evaluatedModules.getModuleById(importer) : void 0;
const callstack = moduleNode ? this.callstacks.get(moduleNode) : void 0;
if (callstack) message += ` The last recorded callstack:\n- ${[
...callstack,
importer,
id
].reverse().join("\n- ")}`;
const error = new EnvironmentTeardownError(message);
if (cause.stack) error.stack = cause.stack.replace(cause.message, error.message);
return { error };
}
return { error: cause };
}
}
}
const createNodeImportMeta = (modulePath) => {
if (!viteModuleRunner.createDefaultImportMeta) throw new Error(`createNodeImportMeta is not supported in this version of Vite.`);
const defaultMeta = viteModuleRunner.createDefaultImportMeta(modulePath);
const href = defaultMeta.url;
const importMetaResolver = createImportMetaResolver();
return {
...defaultMeta,
main: false,
resolve(id, parent) {
return (importMetaResolver ?? defaultMeta.resolve)(id, parent ?? href);
}
};
};
function createImportMetaResolver() {
if (!import.meta.resolve) return;
return (specifier, importer) => import.meta.resolve(specifier, importer);
}
// @ts-expect-error overriding private method
class VitestModuleRunner extends viteModuleRunner.ModuleRunner {
mocker;
moduleExecutionInfo;
_otel;
_callstacks;
constructor(vitestOptions) {
const options = vitestOptions;
const evaluatedModules = options.evaluatedModules;
const callstacks = /* @__PURE__ */ new WeakMap();
const transport = new VitestTransport(options.transport, evaluatedModules, callstacks);
super({
transport,
hmr: false,
evaluatedModules,
sourcemapInterceptor: "prepareStackTrace",
createImportMeta: vitestOptions.createImportMeta
}, options.evaluator);
this.vitestOptions = vitestOptions;
this._callstacks = callstacks;
this._otel = vitestOptions.traces || new Traces({ enabled: false });
this.moduleExecutionInfo = options.getWorkerState().moduleExecutionInfo;
this.mocker = options.mocker || new VitestMocker(this, {
spyModule: options.spyModule,
context: options.vm?.context,
traces: this._otel,
resolveId: options.transport.resolveId,
get root() {
return options.getWorkerState().config.root;
},
get moduleDirectories() {
return options.getWorkerState().config.deps.moduleDirectories || [];
},
getCurrentTestFilepath() {
return options.getWorkerState().filepath;
}
});
if (options.vm) options.vm.context.__vitest_mocker__ = this.mocker;
else Object.defineProperty(globalThis, "__vitest_mocker__", {
configurable: true,
writable: true,
value: this.mocker
});
}
/**
* Vite checks that the module has exports emulating the Node.js behaviour,
* but Vitest is more relaxed.
*
* We should keep the Vite behavior when there is a `strict` flag.
* @internal
*/
processImport(exports$1) {
return exports$1;
}
async import(rawId) {
const resolved = await this._otel.$("vitest.module.resolve_id", { attributes: { "vitest.module.raw_id": rawId } }, async (span) => {
const result = await this.vitestOptions.transport.resolveId(rawId);
if (result) span.setAttributes({
"vitest.module.url": result.url,
"vitest.module.file": result.file,
"vitest.module.id": result.id
});
return result;
});
return super.import(resolved ? resolved.url : rawId);
}
async fetchModule(url, importer) {
return await this.cachedModule(url, importer);
}
_cachedRequest(url, module, callstack = [], metadata) {
// @ts-expect-error "cachedRequest" is private
return super.cachedRequest(url, module, callstack, metadata);
}
/**
* @internal
*/
async cachedRequest(url, mod, callstack = [], metadata, ignoreMock = false) {
// Track for a better error message if dynamic import is not resolved properly
this._callstacks.set(mod, callstack);
if (ignoreMock) return this._cachedRequest(url, mod, callstack, metadata);
let mocked;
if (mod.meta && "mockedModule" in mod.meta) {
const mockedModule = mod.meta.mockedModule;
const mockId = this.mocker.getMockPath(mod.id);
// bypass mock and force "importActual" behavior when:
// - mock was removed by doUnmock (stale mockedModule in meta)
// - self-import: mock factory/file is importing the module it's mocking
const isStale = !this.mocker.getDependencyMock(mod.id);
const isSelfImport = callstack.includes(mockId) || callstack.includes(url) || "redirect" in mockedModule && callstack.includes(mockedModule.redirect);
if (isStale || isSelfImport) {
const node = await this.fetchModule(injectQuery(url, "_vitest_original"));
return this._cachedRequest(node.url, node, callstack, metadata);
}
mocked = await this.mocker.requestWithMockedModule(url, mod, callstack, mockedModule);
} else mocked = await this.mocker.mockedRequest(url, mod, callstack);
if (typeof mocked === "string") {
const node = await this.fetchModule(mocked);
return this._cachedRequest(mocked, node, callstack, metadata);
}
if (mocked != null && typeof mocked === "object") return mocked;
return this._cachedRequest(url, mod, callstack, metadata);
}
/** @internal */
_invalidateSubTreeById(ids, invalidated = /* @__PURE__ */ new Set()) {
for (const id of ids) {
if (invalidated.has(id)) continue;
const node = this.evaluatedModules.getModuleById(id);
if (!node) continue;
invalidated.add(id);
const subIds = Array.from(this.evaluatedModules.idToModuleMap).filter(([, mod]) => mod.importers.has(id)).map(([key]) => key);
if (subIds.length) this._invalidateSubTreeById(subIds, invalidated);
this.evaluatedModules.invalidateModule(node);
}
}
}
const bareVitestRegexp = /^@?vitest(?:\/|$)/;
const normalizedDistDir = normalize(distDir);
const relativeIds = {};
const externalizeMap = /* @__PURE__ */ new Map();
// all Vitest imports always need to be externalized
function getCachedVitestImport(id, state) {
if (id.startsWith("/@fs/") || id.startsWith("\\@fs\\")) id = id.slice(process.platform === "win32" ? 5 : 4);
if (externalizeMap.has(id)) return {
externalize: externalizeMap.get(id),
type: "module"
};
// always externalize Vitest because we import from there before running tests
// so we already have it cached by Node.js
const root = state().config.root;
const relativeRoot = relativeIds[root] ?? (relativeIds[root] = normalizedDistDir.slice(root.length));
if (id.includes(distDir) || id.includes(normalizedDistDir)) {
const { file, postfix } = splitFileAndPostfix$1(id);
const externalize = id.startsWith("file://") ? id : `${pathToFileURL(file)}${postfix}`;
externalizeMap.set(id, externalize);
return {
externalize,
type: "module"
};
}
if (relativeRoot && relativeRoot !== "/" && id.startsWith(relativeRoot)) {
const { file, postfix } = splitFileAndPostfix$1(id);
const externalize = `${pathToFileURL(join(root, file))}${postfix}`;
externalizeMap.set(id, externalize);
return {
externalize,
type: "module"
};
}
if (bareVitestRegexp.test(id)) {
externalizeMap.set(id, id);
return {
externalize: id,
type: "module"
};
}
return null;
}
const { readFileSync } = fs;
const VITEST_VM_CONTEXT_SYMBOL = "__vitest_vm_context__";
const cwd = process.cwd();
const isWindows = process.platform === "win32";
function startVitestModuleRunner(options) {
const traces = options.traces;
const state = () => getSafeWorkerState() || options.state;
const rpc = () => state().rpc;
const environment = () => {
const environment = state().environment;
return environment.viteEnvironment || environment.name;
};
const vm = options.context && options.externalModulesExecutor ? {
context: options.context,
externalModulesExecutor: options.externalModulesExecutor
} : void 0;
const evaluator = options.evaluator || new VitestModuleEvaluator(vm, {
traces,
evaluatedModules: options.evaluatedModules,
get moduleExecutionInfo() {
return state().moduleExecutionInfo;
},
get interopDefault() {
return state().config.deps.interopDefault;
},
getCurrentTestFilepath: () => state().filepath
});
const moduleRunner = new VitestModuleRunner({
spyModule: options.spyModule,
evaluatedModules: options.evaluatedModules,
evaluator,
traces,
mocker: options.mocker,
transport: {
async fetchModule(id, importer, options) {
const resolvingModules = state().resolvingModules;
if (isWindows) {
if (id[1] === ":") {
// The drive letter is different for whatever reason, we need to normalize it to CWD
if (id[0] !== cwd[0] && id[0].toUpperCase() === cwd[0].toUpperCase()) id = (cwd[0].toUpperCase() === cwd[0] ? id[0].toUpperCase() : id[0].toLowerCase()) + id.slice(1);
// always mark absolute windows paths, otherwise Vite will externalize it
id = `/@id/${id}`;
}
}
const vitest = getCachedVitestImport(id, state);
if (vitest) return vitest;
// strip _vitest_original query added by importActual so that
// the plugin pipeline sees the original import id (e.g. virtual modules's load hook)
const isImportActual = id.includes("_vitest_original");
if (isImportActual) id = removeQuery(id, "_vitest_original");
const rawId = unwrapId(id);
resolvingModules.add(rawId);
try {
if (VitestMocker.pendingIds.length) await moduleRunner.mocker.resolveMocks();
if (!isImportActual) {
const resolvedMock = moduleRunner.mocker.getDependencyMockByUrl(id);
if (resolvedMock?.type === "manual" || resolvedMock?.type === "redirect") return {
code: "",
file: null,
id: resolvedMock.id,
url: resolvedMock.url,
invalidate: false,
mockedModule: resolvedMock
};
}
if (isBuiltin(rawId)) return {
externalize: rawId,
type: "builtin"
};
if (isBrowserExternal(rawId)) return {
externalize: toBuiltin(rawId),
type: "builtin"
};
// if module is invalidated, the worker will be recreated,
// so cached is always true in a single worker
if (!isImportActual && options?.cached) return { cache: true };
const otelCarrier = traces?.getContextCarrier();
const result = await rpc().fetch(id, importer, environment(), options, otelCarrier);
if ("cached" in result) return {
code: readFileSync(result.tmp, "utf-8"),
...result
};
return result;
} catch (cause) {
// rethrow vite error if it cannot load the module because it's not resolved
if (typeof cause === "object" && cause != null && cause.code === "ERR_LOAD_URL" || typeof cause?.message === "string" && cause.message.includes("Failed to load url") || typeof cause?.message === "string" && cause.message.startsWith("Cannot find module '")) {
const error = new Error(`Cannot find ${isBareImport(id) ? "package" : "module"} '${id}'${importer ? ` imported from ${importer}` : ""}`, { cause });
error.code = "ERR_MODULE_NOT_FOUND";
throw error;
}
throw cause;
} finally {
resolvingModules.delete(rawId);
}
},
resolveId(id, importer) {
return rpc().resolve(id, importer, environment());
}
},
getWorkerState: state,
vm,
createImportMeta: options.createImportMeta
});
return moduleRunner;
}
export { BareModuleMocker as B, VITEST_VM_CONTEXT_SYMBOL as V, VitestModuleRunner as a, VitestTransport as b, createNodeImportMeta as c, normalizeModuleId as n, startVitestModuleRunner as s };

View File

@@ -0,0 +1,8 @@
"use strict";
function _assert_this_initialized(self) {
if (self === void 0) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
return self;
}
exports._ = _assert_this_initialized;

View File

@@ -0,0 +1,75 @@
'use strict'
const bench = require('fastbench')
const pino = require('../../')
const base = pino(pino.destination('/dev/null'))
const child = base.child({})
const childChild = child.child({})
const childChildChild = childChild.child({})
const childChildChildChild = childChildChild.child({})
const child2 = base.child({})
const baseSerializers = pino(pino.destination('/dev/null'))
const baseSerializersChild = baseSerializers.child({})
const baseSerializersChildSerializers = baseSerializers.child({})
const max = 100
const run = bench([
function benchPinoBase (cb) {
for (var i = 0; i < max; i++) {
base.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchPinoChild (cb) {
for (var i = 0; i < max; i++) {
child.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchPinoChildChild (cb) {
for (var i = 0; i < max; i++) {
childChild.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchPinoChildChildChild (cb) {
for (var i = 0; i < max; i++) {
childChildChild.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchPinoChildChildChildChild (cb) {
for (var i = 0; i < max; i++) {
childChildChildChild.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchPinoChild2 (cb) {
for (var i = 0; i < max; i++) {
child2.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchPinoBaseSerializers (cb) {
for (var i = 0; i < max; i++) {
baseSerializers.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchPinoBaseSerializersChild (cb) {
for (var i = 0; i < max; i++) {
baseSerializersChild.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchPinoBaseSerializersChildSerializers (cb) {
for (var i = 0; i < max; i++) {
baseSerializersChildSerializers.info({ hello: 'world' })
}
setImmediate(cb)
}
], 10000)
run(run)

View File

@@ -0,0 +1,14 @@
import type { TSESLint } from '@typescript-eslint/utils';
export type MessageIds = 'angle-bracket' | 'as' | 'never' | 'replaceArrayTypeAssertionWithAnnotation' | 'replaceArrayTypeAssertionWithSatisfies' | 'replaceObjectTypeAssertionWithAnnotation' | 'replaceObjectTypeAssertionWithSatisfies' | 'unexpectedArrayTypeAssertion' | 'unexpectedObjectTypeAssertion';
type OptUnion = {
assertionStyle: 'angle-bracket' | 'as';
objectLiteralTypeAssertions?: 'allow' | 'allow-as-parameter' | 'never';
arrayLiteralTypeAssertions?: 'allow' | 'allow-as-parameter' | 'never';
} | {
assertionStyle: 'never';
};
export type Options = readonly [OptUnion];
declare const _default: TSESLint.RuleModule<MessageIds, Options, import("../../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
name: string;
};
export default _default;

View File

@@ -0,0 +1,36 @@
'use strict'
const { join } = require('node:path')
const { execSync } = require('node:child_process')
const run = (type) => {
process.stderr.write(`benchmarking ${type}\n`)
return execSync(`node ${join(__dirname, 'runbench')} ${type} -q`)
}
console.log(`
# Benchmarks
\`pino.info('hello world')\`:
\`\`\`
${run('basic')}
\`\`\`
\`pino.info({'hello': 'world'})\`:
\`\`\`
${run('object')}
\`\`\`
\`pino.info(aBigDeeplyNestedObject)\`:
\`\`\`
${run('deep-object')}
\`\`\`
\`pino.info('hello %s %j %d', 'world', {obj: true}, 4, {another: 'obj'})\`:
For a fair comparison, [LogLevel](http://npm.im/loglevel) was extended
to include a timestamp and [bole](http://npm.im/bole) had
\`fastTime\` mode switched on.
`)

View File

@@ -0,0 +1,64 @@
{
"name": "debug",
"version": "4.4.3",
"repository": {
"type": "git",
"url": "git://github.com/debug-js/debug.git"
},
"description": "Lightweight debugging utility for Node.js and the browser",
"keywords": [
"debug",
"log",
"debugger"
],
"files": [
"src",
"LICENSE",
"README.md"
],
"author": "Josh Junon (https://github.com/qix-)",
"contributors": [
"TJ Holowaychuk <tj@vision-media.ca>",
"Nathan Rajlich <nathan@tootallnate.net> (http://n8.io)",
"Andrew Rhyne <rhyneandrew@gmail.com>"
],
"license": "MIT",
"scripts": {
"lint": "xo",
"test": "npm run test:node && npm run test:browser && npm run lint",
"test:node": "mocha test.js test.node.js",
"test:browser": "karma start --single-run",
"test:coverage": "cat ./coverage/lcov.info | coveralls"
},
"dependencies": {
"ms": "^2.1.3"
},
"devDependencies": {
"brfs": "^2.0.1",
"browserify": "^16.2.3",
"coveralls": "^3.0.2",
"karma": "^3.1.4",
"karma-browserify": "^6.0.0",
"karma-chrome-launcher": "^2.2.0",
"karma-mocha": "^1.3.0",
"mocha": "^5.2.0",
"mocha-lcov-reporter": "^1.2.0",
"sinon": "^14.0.0",
"xo": "^0.23.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
},
"main": "./src/index.js",
"browser": "./src/browser.js",
"engines": {
"node": ">=6.0"
},
"xo": {
"rules": {
"import/extensions": "off"
}
}
}

View File

@@ -0,0 +1,4 @@
{
"main": "../../cjs/_ts_generator.cjs",
"module": "../../esm/_ts_generator.js"
}

View File

@@ -0,0 +1,26 @@
{
"rules": {
"generator-star": ["generator-star-spacing"],
"global-strict": ["strict"],
"no-arrow-condition": ["no-confusing-arrow", "no-constant-condition"],
"no-comma-dangle": ["comma-dangle"],
"no-empty-class": ["no-empty-character-class"],
"no-empty-label": ["no-labels"],
"no-extra-strict": ["strict"],
"no-reserved-keys": ["quote-props"],
"no-space-before-semi": ["semi-spacing"],
"no-wrap-func": ["no-extra-parens"],
"space-after-function-name": ["space-before-function-paren"],
"space-after-keywords": ["keyword-spacing"],
"space-before-function-parentheses": ["space-before-function-paren"],
"space-before-keywords": ["keyword-spacing"],
"space-in-brackets": [
"object-curly-spacing",
"array-bracket-spacing",
"computed-property-spacing"
],
"space-return-throw-case": ["keyword-spacing"],
"space-unary-word-ops": ["space-unary-ops"],
"spaced-line-comment": ["spaced-comment"]
}
}

View File

@@ -0,0 +1,22 @@
import { expect, test } from "vitest";
import { parsedType } from "../../util.js";
test("parsedType", () => {
expect(parsedType("string")).toBe("string");
expect(parsedType(1)).toBe("number");
expect(parsedType(true)).toBe("boolean");
expect(parsedType(null)).toBe("null");
expect(parsedType(undefined)).toBe("undefined");
expect(parsedType([])).toBe("array");
expect(parsedType({})).toBe("object");
expect(parsedType(new Date())).toBe("Date");
expect(parsedType(new Map())).toBe("Map");
expect(parsedType(new Set())).toBe("Set");
expect(parsedType(new Error())).toBe("Error");
const nullPrototype = Object.create(null);
expect(parsedType(nullPrototype)).toBe("object");
const doubleNullPrototype = Object.create(Object.create(null));
expect(parsedType(doubleNullPrototype)).toBe("object");
});

View File

@@ -0,0 +1,2 @@
export const crypto = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;
//# sourceMappingURL=crypto.js.map

View File

@@ -0,0 +1,29 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
test("string to number pipeline", () => {
const schema = z.string().transform(Number).pipe(z.number());
expect(schema.parse("1234")).toEqual(1234);
});
test("string to number pipeline async", async () => {
const schema = z
.string()
.transform(async (val) => Number(val))
.pipe(z.number());
expect(await schema.parseAsync("1234")).toEqual(1234);
});
test("break if dirty", () => {
const schema = z
.string()
.refine((c) => c === "1234")
.transform(async (val) => Number(val))
.pipe(z.number().refine((v) => v < 100));
const r1: any = schema.safeParse("12345");
expect(r1.error.issues.length).toBe(1);
const r2: any = schema.safeParse("3");
expect(r2.error.issues.length).toBe(1);
});

View File

@@ -0,0 +1 @@
{"version":3,"file":"struct.d.ts","sourceRoot":"","sources":["../src/struct.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,239 @@
'use strict'
const fs = require('fs')
const proxyquire = require('proxyquire')
const SonicBoom = require('../')
const { file, runTests } = require('./helper')
runTests(buildTests)
function buildTests (test, sync) {
// Reset the umask for testing
process.umask(0o000)
test('reopen', (t) => {
t.plan(9)
const dest = file()
const stream = new SonicBoom({ dest, sync })
t.ok(stream.write('hello world\n'))
t.ok(stream.write('something else\n'))
const after = dest + '-moved'
stream.once('drain', () => {
t.pass('drain emitted')
fs.renameSync(dest, after)
stream.reopen()
stream.once('ready', () => {
t.pass('ready emitted')
t.ok(stream.write('after reopen\n'))
stream.once('drain', () => {
fs.readFile(after, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'hello world\nsomething else\n')
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'after reopen\n')
stream.end()
})
})
})
})
})
})
test('reopen with buffer', (t) => {
t.plan(9)
const dest = file()
const stream = new SonicBoom({ dest, minLength: 4096, sync })
t.ok(stream.write('hello world\n'))
t.ok(stream.write('something else\n'))
const after = dest + '-moved'
stream.once('ready', () => {
t.pass('drain emitted')
stream.flush()
fs.renameSync(dest, after)
stream.reopen()
stream.once('ready', () => {
t.pass('ready emitted')
t.ok(stream.write('after reopen\n'))
stream.flush()
stream.once('drain', () => {
fs.readFile(after, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'hello world\nsomething else\n')
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'after reopen\n')
stream.end()
})
})
})
})
})
})
test('reopen if not open', (t) => {
t.plan(3)
const dest = file()
const stream = new SonicBoom({ dest, sync })
t.ok(stream.write('hello world\n'))
t.ok(stream.write('something else\n'))
stream.reopen()
stream.end()
stream.on('close', function () {
t.pass('ended')
})
})
test('reopen with file', (t) => {
t.plan(10)
const dest = file()
const stream = new SonicBoom({ dest, minLength: 0, sync })
t.ok(stream.write('hello world\n'))
t.ok(stream.write('something else\n'))
const after = dest + '-new'
stream.once('drain', () => {
t.pass('drain emitted')
stream.reopen(after)
t.equal(stream.file, after)
stream.once('ready', () => {
t.pass('ready emitted')
t.ok(stream.write('after reopen\n'))
stream.once('drain', () => {
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'hello world\nsomething else\n')
fs.readFile(after, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'after reopen\n')
stream.end()
})
})
})
})
})
})
test('reopen throws an error', (t) => {
t.plan(sync ? 10 : 9)
const fakeFs = Object.create(fs)
const SonicBoom = proxyquire('../', {
fs: fakeFs
})
const dest = file()
const stream = new SonicBoom({ dest, sync })
t.ok(stream.write('hello world\n'))
t.ok(stream.write('something else\n'))
const after = dest + '-moved'
stream.on('error', () => {
t.pass('error emitted')
})
stream.once('drain', () => {
t.pass('drain emitted')
fs.renameSync(dest, after)
if (sync) {
fakeFs.openSync = function (file, flags) {
t.pass('fake fs.openSync called')
throw new Error('open error')
}
} else {
fakeFs.open = function (file, flags, mode, cb) {
t.pass('fake fs.open called')
setTimeout(() => cb(new Error('open error')), 0)
}
}
if (sync) {
try {
stream.reopen()
} catch (err) {
t.pass('reopen throwed')
}
} else {
stream.reopen()
}
setTimeout(() => {
t.ok(stream.write('after reopen\n'))
stream.end()
stream.on('finish', () => {
fs.readFile(after, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'hello world\nsomething else\nafter reopen\n')
})
})
stream.on('close', () => {
t.pass('close emitted')
})
}, 0)
})
})
test('reopen emits drain', (t) => {
t.plan(9)
const dest = file()
const stream = new SonicBoom({ dest, sync })
t.ok(stream.write('hello world\n'))
t.ok(stream.write('something else\n'))
const after = dest + '-moved'
stream.once('drain', () => {
t.pass('drain emitted')
fs.renameSync(dest, after)
stream.reopen()
stream.once('drain', () => {
t.pass('drain emitted')
t.ok(stream.write('after reopen\n'))
stream.once('drain', () => {
fs.readFile(after, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'hello world\nsomething else\n')
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'after reopen\n')
stream.end()
})
})
})
})
})
})
}

View File

@@ -0,0 +1,581 @@
/**
* @fileoverview Enforces empty lines around comments.
* @author Jamund Ferguson
* @deprecated in ESLint v8.53.0
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Return an array with any line numbers that are empty.
* @param {Array} lines An array of each line of the file.
* @returns {Array} An array of line numbers.
*/
function getEmptyLineNums(lines) {
const emptyLines = lines
.map((line, i) => ({
code: line.trim(),
num: i + 1,
}))
.filter(line => !line.code)
.map(line => line.num);
return emptyLines;
}
/**
* Return an array with any line numbers that contain comments.
* @param {Array} comments An array of comment tokens.
* @returns {Array} An array of line numbers.
*/
function getCommentLineNums(comments) {
const lines = [];
comments.forEach(token => {
const start = token.loc.start.line;
const end = token.loc.end.line;
lines.push(start, end);
});
return lines;
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
deprecated: {
message: "Formatting rules are being moved out of ESLint core.",
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
deprecatedSince: "8.53.0",
availableUntil: "11.0.0",
replacedBy: [
{
message:
"ESLint Stylistic now maintains deprecated stylistic core rules.",
url: "https://eslint.style/guide/migration",
plugin: {
name: "@stylistic/eslint-plugin",
url: "https://eslint.style",
},
rule: {
name: "lines-around-comment",
url: "https://eslint.style/rules/lines-around-comment",
},
},
],
},
type: "layout",
docs: {
description: "Require empty lines around comments",
recommended: false,
url: "https://eslint.org/docs/latest/rules/lines-around-comment",
},
fixable: "whitespace",
schema: [
{
type: "object",
properties: {
beforeBlockComment: {
type: "boolean",
default: true,
},
afterBlockComment: {
type: "boolean",
default: false,
},
beforeLineComment: {
type: "boolean",
default: false,
},
afterLineComment: {
type: "boolean",
default: false,
},
allowBlockStart: {
type: "boolean",
default: false,
},
allowBlockEnd: {
type: "boolean",
default: false,
},
allowClassStart: {
type: "boolean",
},
allowClassEnd: {
type: "boolean",
},
allowObjectStart: {
type: "boolean",
},
allowObjectEnd: {
type: "boolean",
},
allowArrayStart: {
type: "boolean",
},
allowArrayEnd: {
type: "boolean",
},
ignorePattern: {
type: "string",
},
applyDefaultIgnorePatterns: {
type: "boolean",
},
afterHashbangComment: {
type: "boolean",
default: false,
},
},
additionalProperties: false,
},
],
messages: {
after: "Expected line after comment.",
before: "Expected line before comment.",
},
},
create(context) {
const options = Object.assign({}, context.options[0]);
const ignorePattern = options.ignorePattern;
const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN;
const customIgnoreRegExp = new RegExp(ignorePattern, "u");
const applyDefaultIgnorePatterns =
options.applyDefaultIgnorePatterns !== false;
options.beforeBlockComment =
typeof options.beforeBlockComment !== "undefined"
? options.beforeBlockComment
: true;
const sourceCode = context.sourceCode;
const lines = sourceCode.lines,
numLines = lines.length + 1,
comments = sourceCode.getAllComments(),
commentLines = getCommentLineNums(comments),
emptyLines = getEmptyLineNums(lines),
commentAndEmptyLines = new Set(commentLines.concat(emptyLines));
/**
* Returns whether or not comments are on lines starting with or ending with code
* @param {token} token The comment token to check.
* @returns {boolean} True if the comment is not alone.
*/
function codeAroundComment(token) {
let currentToken = token;
do {
currentToken = sourceCode.getTokenBefore(currentToken, {
includeComments: true,
});
} while (currentToken && astUtils.isCommentToken(currentToken));
if (
currentToken &&
astUtils.isTokenOnSameLine(currentToken, token)
) {
return true;
}
currentToken = token;
do {
currentToken = sourceCode.getTokenAfter(currentToken, {
includeComments: true,
});
} while (currentToken && astUtils.isCommentToken(currentToken));
if (
currentToken &&
astUtils.isTokenOnSameLine(token, currentToken)
) {
return true;
}
return false;
}
/**
* Returns whether or not comments are inside a node type or not.
* @param {ASTNode} parent The Comment parent node.
* @param {string} nodeType The parent type to check against.
* @returns {boolean} True if the comment is inside nodeType.
*/
function isParentNodeType(parent, nodeType) {
return (
parent.type === nodeType ||
(parent.body && parent.body.type === nodeType) ||
(parent.consequent && parent.consequent.type === nodeType)
);
}
/**
* Returns the parent node that contains the given token.
* @param {token} token The token to check.
* @returns {ASTNode|null} The parent node that contains the given token.
*/
function getParentNodeOfToken(token) {
const node = sourceCode.getNodeByRangeIndex(token.range[0]);
/*
* For the purpose of this rule, the comment token is in a `StaticBlock` node only
* if it's inside the braces of that `StaticBlock` node.
*
* Example where this function returns `null`:
*
* static
* // comment
* {
* }
*
* Example where this function returns `StaticBlock` node:
*
* static
* {
* // comment
* }
*
*/
if (node && node.type === "StaticBlock") {
const openingBrace = sourceCode.getFirstToken(node, {
skip: 1,
}); // skip the `static` token
return token.range[0] >= openingBrace.range[0] ? node : null;
}
return node;
}
/**
* Returns whether or not comments are at the parent start or not.
* @param {token} token The Comment token.
* @param {string} nodeType The parent type to check against.
* @returns {boolean} True if the comment is at parent start.
*/
function isCommentAtParentStart(token, nodeType) {
const parent = getParentNodeOfToken(token);
if (parent && isParentNodeType(parent, nodeType)) {
let parentStartNodeOrToken = parent;
if (parent.type === "StaticBlock") {
parentStartNodeOrToken = sourceCode.getFirstToken(parent, {
skip: 1,
}); // opening brace of the static block
} else if (parent.type === "SwitchStatement") {
parentStartNodeOrToken = sourceCode.getTokenAfter(
parent.discriminant,
{
filter: astUtils.isOpeningBraceToken,
},
); // opening brace of the switch statement
}
return (
token.loc.start.line -
parentStartNodeOrToken.loc.start.line ===
1
);
}
return false;
}
/**
* Returns whether or not comments are at the parent end or not.
* @param {token} token The Comment token.
* @param {string} nodeType The parent type to check against.
* @returns {boolean} True if the comment is at parent end.
*/
function isCommentAtParentEnd(token, nodeType) {
const parent = getParentNodeOfToken(token);
return (
!!parent &&
isParentNodeType(parent, nodeType) &&
parent.loc.end.line - token.loc.end.line === 1
);
}
/**
* Returns whether or not comments are at the block start or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at block start.
*/
function isCommentAtBlockStart(token) {
return (
isCommentAtParentStart(token, "ClassBody") ||
isCommentAtParentStart(token, "BlockStatement") ||
isCommentAtParentStart(token, "StaticBlock") ||
isCommentAtParentStart(token, "SwitchCase") ||
isCommentAtParentStart(token, "SwitchStatement")
);
}
/**
* Returns whether or not comments are at the block end or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at block end.
*/
function isCommentAtBlockEnd(token) {
return (
isCommentAtParentEnd(token, "ClassBody") ||
isCommentAtParentEnd(token, "BlockStatement") ||
isCommentAtParentEnd(token, "StaticBlock") ||
isCommentAtParentEnd(token, "SwitchCase") ||
isCommentAtParentEnd(token, "SwitchStatement")
);
}
/**
* Returns whether or not comments are at the class start or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at class start.
*/
function isCommentAtClassStart(token) {
return isCommentAtParentStart(token, "ClassBody");
}
/**
* Returns whether or not comments are at the class end or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at class end.
*/
function isCommentAtClassEnd(token) {
return isCommentAtParentEnd(token, "ClassBody");
}
/**
* Returns whether or not comments are at the object start or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at object start.
*/
function isCommentAtObjectStart(token) {
return (
isCommentAtParentStart(token, "ObjectExpression") ||
isCommentAtParentStart(token, "ObjectPattern")
);
}
/**
* Returns whether or not comments are at the object end or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at object end.
*/
function isCommentAtObjectEnd(token) {
return (
isCommentAtParentEnd(token, "ObjectExpression") ||
isCommentAtParentEnd(token, "ObjectPattern")
);
}
/**
* Returns whether or not comments are at the array start or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at array start.
*/
function isCommentAtArrayStart(token) {
return (
isCommentAtParentStart(token, "ArrayExpression") ||
isCommentAtParentStart(token, "ArrayPattern")
);
}
/**
* Returns whether or not comments are at the array end or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at array end.
*/
function isCommentAtArrayEnd(token) {
return (
isCommentAtParentEnd(token, "ArrayExpression") ||
isCommentAtParentEnd(token, "ArrayPattern")
);
}
/**
* Checks if a comment token has lines around it (ignores inline comments)
* @param {token} token The Comment token.
* @param {Object} opts Options to determine the newline.
* @param {boolean} opts.after Should have a newline after this line.
* @param {boolean} opts.before Should have a newline before this line.
* @returns {void}
*/
function checkForEmptyLine(token, opts) {
if (
applyDefaultIgnorePatterns &&
defaultIgnoreRegExp.test(token.value)
) {
return;
}
if (ignorePattern && customIgnoreRegExp.test(token.value)) {
return;
}
let after = opts.after,
before = opts.before;
const prevLineNum = token.loc.start.line - 1,
nextLineNum = token.loc.end.line + 1,
commentIsNotAlone = codeAroundComment(token);
const blockStartAllowed =
options.allowBlockStart &&
isCommentAtBlockStart(token) &&
!(
options.allowClassStart === false &&
isCommentAtClassStart(token)
),
blockEndAllowed =
options.allowBlockEnd &&
isCommentAtBlockEnd(token) &&
!(
options.allowClassEnd === false &&
isCommentAtClassEnd(token)
),
classStartAllowed =
options.allowClassStart && isCommentAtClassStart(token),
classEndAllowed =
options.allowClassEnd && isCommentAtClassEnd(token),
objectStartAllowed =
options.allowObjectStart && isCommentAtObjectStart(token),
objectEndAllowed =
options.allowObjectEnd && isCommentAtObjectEnd(token),
arrayStartAllowed =
options.allowArrayStart && isCommentAtArrayStart(token),
arrayEndAllowed =
options.allowArrayEnd && isCommentAtArrayEnd(token);
const exceptionStartAllowed =
blockStartAllowed ||
classStartAllowed ||
objectStartAllowed ||
arrayStartAllowed;
const exceptionEndAllowed =
blockEndAllowed ||
classEndAllowed ||
objectEndAllowed ||
arrayEndAllowed;
// ignore top of the file and bottom of the file
if (prevLineNum < 1) {
before = false;
}
if (nextLineNum >= numLines) {
after = false;
}
// we ignore all inline comments
if (commentIsNotAlone) {
return;
}
const previousTokenOrComment = sourceCode.getTokenBefore(token, {
includeComments: true,
});
const nextTokenOrComment = sourceCode.getTokenAfter(token, {
includeComments: true,
});
// check for newline before
if (
!exceptionStartAllowed &&
before &&
!commentAndEmptyLines.has(prevLineNum) &&
!(
astUtils.isCommentToken(previousTokenOrComment) &&
astUtils.isTokenOnSameLine(previousTokenOrComment, token)
)
) {
const lineStart = token.range[0] - token.loc.start.column;
const range = [lineStart, lineStart];
context.report({
node: token,
messageId: "before",
fix(fixer) {
return fixer.insertTextBeforeRange(range, "\n");
},
});
}
// check for newline after
if (
!exceptionEndAllowed &&
after &&
!commentAndEmptyLines.has(nextLineNum) &&
!(
astUtils.isCommentToken(nextTokenOrComment) &&
astUtils.isTokenOnSameLine(token, nextTokenOrComment)
)
) {
context.report({
node: token,
messageId: "after",
fix(fixer) {
return fixer.insertTextAfter(token, "\n");
},
});
}
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
Program() {
comments.forEach(token => {
if (token.type === "Line") {
if (
options.beforeLineComment ||
options.afterLineComment
) {
checkForEmptyLine(token, {
after: options.afterLineComment,
before: options.beforeLineComment,
});
}
} else if (token.type === "Block") {
if (
options.beforeBlockComment ||
options.afterBlockComment
) {
checkForEmptyLine(token, {
after: options.afterBlockComment,
before: options.beforeBlockComment,
});
}
} else if (token.type === "Shebang") {
if (options.afterHashbangComment) {
checkForEmptyLine(token, {
after: options.afterHashbangComment,
before: false,
});
}
}
});
},
};
},
};

View File

@@ -0,0 +1,291 @@
/**
* @fileoverview Rule to enforce linebreaks after open and before close array brackets
* @author Jan Peer Stöcklmair <https://github.com/JPeer264>
* @deprecated in ESLint v8.53.0
*/
"use strict";
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
deprecated: {
message: "Formatting rules are being moved out of ESLint core.",
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
deprecatedSince: "8.53.0",
availableUntil: "11.0.0",
replacedBy: [
{
message:
"ESLint Stylistic now maintains deprecated stylistic core rules.",
url: "https://eslint.style/guide/migration",
plugin: {
name: "@stylistic/eslint-plugin",
url: "https://eslint.style",
},
rule: {
name: "array-bracket-newline",
url: "https://eslint.style/rules/array-bracket-newline",
},
},
],
},
type: "layout",
docs: {
description:
"Enforce linebreaks after opening and before closing array brackets",
recommended: false,
url: "https://eslint.org/docs/latest/rules/array-bracket-newline",
},
fixable: "whitespace",
schema: [
{
oneOf: [
{
enum: ["always", "never", "consistent"],
},
{
type: "object",
properties: {
multiline: {
type: "boolean",
},
minItems: {
type: ["integer", "null"],
minimum: 0,
},
},
additionalProperties: false,
},
],
},
],
messages: {
unexpectedOpeningLinebreak:
"There should be no linebreak after '['.",
unexpectedClosingLinebreak:
"There should be no linebreak before ']'.",
missingOpeningLinebreak: "A linebreak is required after '['.",
missingClosingLinebreak: "A linebreak is required before ']'.",
},
},
create(context) {
const sourceCode = context.sourceCode;
//----------------------------------------------------------------------
// Helpers
//----------------------------------------------------------------------
/**
* Normalizes a given option value.
* @param {string|Object|undefined} option An option value to parse.
* @returns {{multiline: boolean, minItems: number}} Normalized option object.
*/
function normalizeOptionValue(option) {
let consistent = false;
let multiline = false;
let minItems;
if (option) {
if (option === "consistent") {
consistent = true;
minItems = Number.POSITIVE_INFINITY;
} else if (option === "always" || option.minItems === 0) {
minItems = 0;
} else if (option === "never") {
minItems = Number.POSITIVE_INFINITY;
} else {
multiline = Boolean(option.multiline);
minItems = option.minItems || Number.POSITIVE_INFINITY;
}
} else {
consistent = false;
multiline = true;
minItems = Number.POSITIVE_INFINITY;
}
return { consistent, multiline, minItems };
}
/**
* Normalizes a given option value.
* @param {string|Object|undefined} options An option value to parse.
* @returns {{ArrayExpression: {multiline: boolean, minItems: number}, ArrayPattern: {multiline: boolean, minItems: number}}} Normalized option object.
*/
function normalizeOptions(options) {
const value = normalizeOptionValue(options);
return { ArrayExpression: value, ArrayPattern: value };
}
/**
* Reports that there shouldn't be a linebreak after the first token
* @param {ASTNode} node The node to report in the event of an error.
* @param {Token} token The token to use for the report.
* @returns {void}
*/
function reportNoBeginningLinebreak(node, token) {
context.report({
node,
loc: token.loc,
messageId: "unexpectedOpeningLinebreak",
fix(fixer) {
const nextToken = sourceCode.getTokenAfter(token, {
includeComments: true,
});
if (astUtils.isCommentToken(nextToken)) {
return null;
}
return fixer.removeRange([
token.range[1],
nextToken.range[0],
]);
},
});
}
/**
* Reports that there shouldn't be a linebreak before the last token
* @param {ASTNode} node The node to report in the event of an error.
* @param {Token} token The token to use for the report.
* @returns {void}
*/
function reportNoEndingLinebreak(node, token) {
context.report({
node,
loc: token.loc,
messageId: "unexpectedClosingLinebreak",
fix(fixer) {
const previousToken = sourceCode.getTokenBefore(token, {
includeComments: true,
});
if (astUtils.isCommentToken(previousToken)) {
return null;
}
return fixer.removeRange([
previousToken.range[1],
token.range[0],
]);
},
});
}
/**
* Reports that there should be a linebreak after the first token
* @param {ASTNode} node The node to report in the event of an error.
* @param {Token} token The token to use for the report.
* @returns {void}
*/
function reportRequiredBeginningLinebreak(node, token) {
context.report({
node,
loc: token.loc,
messageId: "missingOpeningLinebreak",
fix(fixer) {
return fixer.insertTextAfter(token, "\n");
},
});
}
/**
* Reports that there should be a linebreak before the last token
* @param {ASTNode} node The node to report in the event of an error.
* @param {Token} token The token to use for the report.
* @returns {void}
*/
function reportRequiredEndingLinebreak(node, token) {
context.report({
node,
loc: token.loc,
messageId: "missingClosingLinebreak",
fix(fixer) {
return fixer.insertTextBefore(token, "\n");
},
});
}
/**
* Reports a given node if it violated this rule.
* @param {ASTNode} node A node to check. This is an ArrayExpression node or an ArrayPattern node.
* @returns {void}
*/
function check(node) {
const elements = node.elements;
const normalizedOptions = normalizeOptions(context.options[0]);
const options = normalizedOptions[node.type];
const openBracket = sourceCode.getFirstToken(node);
const closeBracket = sourceCode.getLastToken(node);
const firstIncComment = sourceCode.getTokenAfter(openBracket, {
includeComments: true,
});
const lastIncComment = sourceCode.getTokenBefore(closeBracket, {
includeComments: true,
});
const first = sourceCode.getTokenAfter(openBracket);
const last = sourceCode.getTokenBefore(closeBracket);
const needsLinebreaks =
elements.length >= options.minItems ||
(options.multiline &&
elements.length > 0 &&
firstIncComment.loc.start.line !==
lastIncComment.loc.end.line) ||
(elements.length === 0 &&
firstIncComment.type === "Block" &&
firstIncComment.loc.start.line !==
lastIncComment.loc.end.line &&
firstIncComment === lastIncComment) ||
(options.consistent &&
openBracket.loc.end.line !== first.loc.start.line);
/*
* Use tokens or comments to check multiline or not.
* But use only tokens to check whether linebreaks are needed.
* This allows:
* var arr = [ // eslint-disable-line foo
* 'a'
* ]
*/
if (needsLinebreaks) {
if (astUtils.isTokenOnSameLine(openBracket, first)) {
reportRequiredBeginningLinebreak(node, openBracket);
}
if (astUtils.isTokenOnSameLine(last, closeBracket)) {
reportRequiredEndingLinebreak(node, closeBracket);
}
} else {
if (!astUtils.isTokenOnSameLine(openBracket, first)) {
reportNoBeginningLinebreak(node, openBracket);
}
if (!astUtils.isTokenOnSameLine(last, closeBracket)) {
reportNoEndingLinebreak(node, closeBracket);
}
}
}
//----------------------------------------------------------------------
// Public
//----------------------------------------------------------------------
return {
ArrayPattern: check,
ArrayExpression: check,
};
},
};

View File

@@ -0,0 +1,70 @@
deep-is
==========
Node's `assert.deepEqual() algorithm` as a standalone module. Exactly like
[deep-equal](https://github.com/substack/node-deep-equal) except for the fact that `deepEqual(NaN, NaN) === true`.
This module is around [5 times faster](https://gist.github.com/2790507)
than wrapping `assert.deepEqual()` in a `try/catch`.
[![browser support](http://ci.testling.com/thlorenz/deep-is.png)](http://ci.testling.com/thlorenz/deep-is)
[![build status](https://secure.travis-ci.org/thlorenz/deep-is.png)](http://travis-ci.org/thlorenz/deep-is)
example
=======
``` js
var equal = require('deep-is');
console.dir([
equal(
{ a : [ 2, 3 ], b : [ 4 ] },
{ a : [ 2, 3 ], b : [ 4 ] }
),
equal(
{ x : 5, y : [6] },
{ x : 5, y : 6 }
)
]);
```
methods
=======
var deepIs = require('deep-is')
deepIs(a, b)
---------------
Compare objects `a` and `b`, returning whether they are equal according to a
recursive equality algorithm.
install
=======
With [npm](http://npmjs.org) do:
```
npm install deep-is
```
test
====
With [npm](http://npmjs.org) do:
```
npm test
```
license
=======
Copyright (c) 2012, 2013 Thorsten Lorenz <thlorenz@gmx.de>
Copyright (c) 2012 James Halliday <mail@substack.net>
Derived largely from node's assert module, which has the copyright statement:
Copyright (c) 2009 Thomas Robinson <280north.com>
Released under the MIT license, see LICENSE for details.

View File

@@ -0,0 +1,37 @@
import { documentURIToFileName, fileNameToDocumentURI, } from "./path.js";
/**
* Resolves a DocumentIdentifier to a file name.
* If the identifier contains a URI, it is converted to a file name.
*/
export function resolveFileName(identifier) {
if (typeof identifier === "string") {
return identifier;
}
return documentURIToFileName(identifier.uri);
}
/**
* Resolves a DocumentIdentifier to a document URI.
* If the identifier contains a file name, it is converted to a URI.
*/
export function resolveDocumentURI(identifier) {
if (typeof identifier === "string") {
return fileNameToDocumentURI(identifier);
}
return identifier.uri;
}
/**
* Builds the wire request for updateSnapshot, applying the deprecated `openProject`
* compatibility shim: a single `openProject` is folded into `openProjects` and is
* never sent on the wire.
*/
export function toUpdateSnapshotRequest(params) {
const { openProject, openProjects, ...rest } = params ?? {};
const mergedOpenProjects = openProject !== undefined
? [resolveFileName(openProject), ...(openProjects ?? [])]
: openProjects;
return {
...rest,
...(mergedOpenProjects !== undefined ? { openProjects: mergedOpenProjects } : {}),
};
}
//# sourceMappingURL=proto.js.map

View File

@@ -0,0 +1,36 @@
'use strict'
const errSerializer = require('./lib/err')
const errWithCauseSerializer = require('./lib/err-with-cause')
const reqSerializers = require('./lib/req')
const resSerializers = require('./lib/res')
module.exports = {
err: errSerializer,
errWithCause: errWithCauseSerializer,
mapHttpRequest: reqSerializers.mapHttpRequest,
mapHttpResponse: resSerializers.mapHttpResponse,
req: reqSerializers.reqSerializer,
res: resSerializers.resSerializer,
wrapErrorSerializer: function wrapErrorSerializer (customSerializer) {
if (customSerializer === errSerializer) return customSerializer
return function wrapErrSerializer (err) {
return customSerializer(errSerializer(err))
}
},
wrapRequestSerializer: function wrapRequestSerializer (customSerializer) {
if (customSerializer === reqSerializers.reqSerializer) return customSerializer
return function wrappedReqSerializer (req) {
return customSerializer(reqSerializers.reqSerializer(req))
}
},
wrapResponseSerializer: function wrapResponseSerializer (customSerializer) {
if (customSerializer === resSerializers.resSerializer) return customSerializer
return function wrappedResSerializer (res) {
return customSerializer(resSerializers.resSerializer(res))
}
}
}

View File

@@ -0,0 +1,2 @@
export * from "./node-hfs.js";
export { Hfs } from "@humanfs/core";

View File

@@ -0,0 +1,40 @@
# Acorn-JSX
[![Build Status](https://travis-ci.org/acornjs/acorn-jsx.svg?branch=master)](https://travis-ci.org/acornjs/acorn-jsx)
[![NPM version](https://img.shields.io/npm/v/acorn-jsx.svg)](https://www.npmjs.org/package/acorn-jsx)
This is plugin for [Acorn](http://marijnhaverbeke.nl/acorn/) - a tiny, fast JavaScript parser, written completely in JavaScript.
It was created as an experimental alternative, faster [React.js JSX](http://facebook.github.io/react/docs/jsx-in-depth.html) parser. Later, it replaced the [official parser](https://github.com/facebookarchive/esprima) and these days is used by many prominent development tools.
## Transpiler
Please note that this tool only parses source code to JSX AST, which is useful for various language tools and services. If you want to transpile your code to regular ES5-compliant JavaScript with source map, check out [Babel](https://babeljs.io/) and [Buble](https://buble.surge.sh/) transpilers which use `acorn-jsx` under the hood.
## Usage
Requiring this module provides you with an Acorn plugin that you can use like this:
```javascript
var acorn = require("acorn");
var jsx = require("acorn-jsx");
acorn.Parser.extend(jsx()).parse("my(<jsx/>, 'code');");
```
Note that official spec doesn't support mix of XML namespaces and object-style access in tag names (#27) like in `<namespace:Object.Property />`, so it was deprecated in `acorn-jsx@3.0`. If you still want to opt-in to support of such constructions, you can pass the following option:
```javascript
acorn.Parser.extend(jsx({ allowNamespacedObjects: true }))
```
Also, since most apps use pure React transformer, a new option was introduced that allows to prohibit namespaces completely:
```javascript
acorn.Parser.extend(jsx({ allowNamespaces: false }))
```
Note that by default `allowNamespaces` is enabled for spec compliancy.
## License
This plugin is issued under the [MIT license](./LICENSE).