WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"name": "typescript",
|
||||
"version": "7.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"author": "Microsoft Corp.",
|
||||
"homepage": "https://www.typescriptlang.org/",
|
||||
"description": "TypeScript is a language for application scale JavaScript development",
|
||||
"keywords": [
|
||||
"TypeScript",
|
||||
"Microsoft",
|
||||
"compiler",
|
||||
"language",
|
||||
"javascript"
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/microsoft/TypeScript/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/microsoft/TypeScript.git"
|
||||
},
|
||||
"type": "module",
|
||||
"preferUnplugged": true,
|
||||
"engines": {
|
||||
"node": ">=16.20.0"
|
||||
},
|
||||
"files": [
|
||||
"bin",
|
||||
"lib",
|
||||
"dist",
|
||||
"vendor",
|
||||
"NOTICE.txt"
|
||||
],
|
||||
"bin": {
|
||||
"tsc": "./bin/tsc"
|
||||
},
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": "./lib/version.cjs",
|
||||
"./unstable/sync": "./dist/api/sync/api.js",
|
||||
"./unstable/async": "./dist/api/async/api.js",
|
||||
"./unstable/fs": "./dist/api/fs.js",
|
||||
"./unstable/proto": "./dist/api/proto.js",
|
||||
"./unstable/ast": "./dist/ast/index.js",
|
||||
"./unstable/ast/is": "./dist/ast/is.js",
|
||||
"./unstable/ast/factory": "./dist/ast/factory.generated.js",
|
||||
"./unstable/ast/utils": "./dist/ast/utils.js",
|
||||
"./unstable/ast/scanner": "./dist/ast/scanner.js",
|
||||
"./unstable/ast/visitor": "./dist/ast/visitor.js",
|
||||
"./unstable/ast/clone": "./dist/ast/clone.js"
|
||||
},
|
||||
"imports": {
|
||||
"#getExePath": "./lib/getExePath.js",
|
||||
"#enums/*": {
|
||||
"types": "./dist/enums/*.enum.d.ts",
|
||||
"default": "./dist/enums/*.js"
|
||||
},
|
||||
"#vscode-jsonrpc/node": "./vendor/vscode-jsonrpc/lib/node/main.js"
|
||||
},
|
||||
"gitHead": "2bd066d87f5bafd315be9f40889d0a60b9e58e0b",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"tag": "latest"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@typescript/typescript-win32-x64": "7.0.2",
|
||||
"@typescript/typescript-win32-arm64": "7.0.2",
|
||||
"@typescript/typescript-linux-x64": "7.0.2",
|
||||
"@typescript/typescript-linux-arm": "7.0.2",
|
||||
"@typescript/typescript-linux-arm64": "7.0.2",
|
||||
"@typescript/typescript-darwin-x64": "7.0.2",
|
||||
"@typescript/typescript-darwin-arm64": "7.0.2",
|
||||
"@typescript/typescript-aix-ppc64": "7.0.2",
|
||||
"@typescript/typescript-freebsd-arm64": "7.0.2",
|
||||
"@typescript/typescript-freebsd-x64": "7.0.2",
|
||||
"@typescript/typescript-linux-loong64": "7.0.2",
|
||||
"@typescript/typescript-linux-mips64el": "7.0.2",
|
||||
"@typescript/typescript-linux-ppc64": "7.0.2",
|
||||
"@typescript/typescript-linux-riscv64": "7.0.2",
|
||||
"@typescript/typescript-linux-s390x": "7.0.2",
|
||||
"@typescript/typescript-netbsd-arm64": "7.0.2",
|
||||
"@typescript/typescript-netbsd-x64": "7.0.2",
|
||||
"@typescript/typescript-openbsd-arm64": "7.0.2",
|
||||
"@typescript/typescript-openbsd-x64": "7.0.2",
|
||||
"@typescript/typescript-sunos-x64": "7.0.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// SEE https://typescript-eslint.io/users/configs
|
||||
//
|
||||
// For developers working in the typescript-eslint monorepo:
|
||||
// You can regenerate it using `pnpm run generate-configs`
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const base_1 = __importDefault(require("./base"));
|
||||
const eslint_recommended_1 = __importDefault(require("./eslint-recommended"));
|
||||
/**
|
||||
* Contains all of `recommended` along with additional recommended rules that require type information.
|
||||
* @see {@link https://typescript-eslint.io/users/configs#recommended-type-checked}
|
||||
*/
|
||||
exports.default = (plugin, parser) => [
|
||||
(0, base_1.default)(plugin, parser),
|
||||
(0, eslint_recommended_1.default)(plugin, parser),
|
||||
{
|
||||
name: 'typescript-eslint/recommended-type-checked',
|
||||
rules: {
|
||||
'@typescript-eslint/await-thenable': 'error',
|
||||
'@typescript-eslint/ban-ts-comment': 'error',
|
||||
'no-array-constructor': 'off',
|
||||
'@typescript-eslint/no-array-constructor': 'error',
|
||||
'@typescript-eslint/no-array-delete': 'error',
|
||||
'@typescript-eslint/no-base-to-string': 'error',
|
||||
'@typescript-eslint/no-duplicate-enum-values': 'error',
|
||||
'@typescript-eslint/no-duplicate-type-constituents': 'error',
|
||||
'@typescript-eslint/no-empty-object-type': 'error',
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/no-extra-non-null-assertion': 'error',
|
||||
'@typescript-eslint/no-floating-promises': 'error',
|
||||
'@typescript-eslint/no-for-in-array': 'error',
|
||||
'no-implied-eval': 'off',
|
||||
'@typescript-eslint/no-implied-eval': 'error',
|
||||
'@typescript-eslint/no-misused-new': 'error',
|
||||
'@typescript-eslint/no-misused-promises': 'error',
|
||||
'@typescript-eslint/no-namespace': 'error',
|
||||
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
|
||||
'@typescript-eslint/no-redundant-type-constituents': 'error',
|
||||
'@typescript-eslint/no-require-imports': 'error',
|
||||
'@typescript-eslint/no-this-alias': 'error',
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
|
||||
'@typescript-eslint/no-unnecessary-type-constraint': 'error',
|
||||
'@typescript-eslint/no-unsafe-argument': 'error',
|
||||
'@typescript-eslint/no-unsafe-assignment': 'error',
|
||||
'@typescript-eslint/no-unsafe-call': 'error',
|
||||
'@typescript-eslint/no-unsafe-declaration-merging': 'error',
|
||||
'@typescript-eslint/no-unsafe-enum-comparison': 'error',
|
||||
'@typescript-eslint/no-unsafe-function-type': 'error',
|
||||
'@typescript-eslint/no-unsafe-member-access': 'error',
|
||||
'@typescript-eslint/no-unsafe-return': 'error',
|
||||
'@typescript-eslint/no-unsafe-unary-minus': 'error',
|
||||
'no-unused-expressions': 'off',
|
||||
'@typescript-eslint/no-unused-expressions': 'error',
|
||||
'no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'error',
|
||||
'@typescript-eslint/no-wrapper-object-types': 'error',
|
||||
'no-throw-literal': 'off',
|
||||
'@typescript-eslint/only-throw-error': 'error',
|
||||
'@typescript-eslint/prefer-as-const': 'error',
|
||||
'@typescript-eslint/prefer-namespace-keyword': 'error',
|
||||
'prefer-promise-reject-errors': 'off',
|
||||
'@typescript-eslint/prefer-promise-reject-errors': 'error',
|
||||
'require-await': 'off',
|
||||
'@typescript-eslint/require-await': 'error',
|
||||
'@typescript-eslint/restrict-plus-operands': 'error',
|
||||
'@typescript-eslint/restrict-template-expressions': 'error',
|
||||
'@typescript-eslint/triple-slash-reference': 'error',
|
||||
'@typescript-eslint/unbound-method': 'error',
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
'variables': {
|
||||
'openssl_fips': ''
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'bufferutil',
|
||||
'sources': ['src/bufferutil.c'],
|
||||
'cflags': ['-std=c99'],
|
||||
'conditions': [
|
||||
["OS=='mac'", {
|
||||
'xcode_settings': {
|
||||
'MACOSX_DEPLOYMENT_TARGET': '10.7'
|
||||
}
|
||||
}]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { TSESLint } from '@typescript-eslint/utils';
|
||||
import type { TypeOrValueSpecifier } from '../util';
|
||||
export type Options = [
|
||||
{
|
||||
allowForKnownSafeCalls?: TypeOrValueSpecifier[];
|
||||
allowForKnownSafePromises?: TypeOrValueSpecifier[];
|
||||
checkThenables?: boolean;
|
||||
ignoreIIFE?: boolean;
|
||||
ignoreVoid?: boolean;
|
||||
}
|
||||
];
|
||||
export type MessageId = 'floating' | 'floatingFixAwait' | 'floatingFixVoid' | 'floatingPromiseArray' | 'floatingPromiseArrayVoid' | 'floatingUselessRejectionHandler' | 'floatingUselessRejectionHandlerVoid' | 'floatingVoid';
|
||||
declare const _default: TSESLint.RuleModule<MessageId, Options, import("../../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
|
||||
// npx nx generate-lib repo
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.es2021_intl = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
exports.es2021_intl = {
|
||||
libs: [],
|
||||
variables: [['Intl', base_config_1.TYPE_VALUE]],
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
"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-as-const',
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
docs: {
|
||||
description: 'Enforce the use of `as const` over literal type',
|
||||
recommended: 'recommended',
|
||||
},
|
||||
fixable: 'code',
|
||||
hasSuggestions: true,
|
||||
messages: {
|
||||
preferConstAssertion: 'Expected a `const` instead of a literal type assertion.',
|
||||
variableConstAssertion: 'Expected a `const` assertion instead of a literal type annotation.',
|
||||
variableSuggest: 'You should use `as const` instead of type annotation.',
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
defaultOptions: [],
|
||||
create(context) {
|
||||
function compareTypes(valueNode, typeNode, canFix) {
|
||||
if (valueNode.type === utils_1.AST_NODE_TYPES.Literal &&
|
||||
typeNode.type === utils_1.AST_NODE_TYPES.TSLiteralType &&
|
||||
typeNode.literal.type === utils_1.AST_NODE_TYPES.Literal &&
|
||||
valueNode.raw === typeNode.literal.raw) {
|
||||
if (canFix) {
|
||||
context.report({
|
||||
node: typeNode,
|
||||
messageId: 'preferConstAssertion',
|
||||
fix: fixer => fixer.replaceText(typeNode, 'const'),
|
||||
});
|
||||
}
|
||||
else {
|
||||
context.report({
|
||||
node: typeNode,
|
||||
messageId: 'variableConstAssertion',
|
||||
suggest: [
|
||||
{
|
||||
messageId: 'variableSuggest',
|
||||
fix: (fixer) => [
|
||||
fixer.remove(typeNode.parent),
|
||||
fixer.insertTextAfter(valueNode, ' as const'),
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
PropertyDefinition(node) {
|
||||
if (node.value && node.typeAnnotation) {
|
||||
compareTypes(node.value, node.typeAnnotation.typeAnnotation, false);
|
||||
}
|
||||
},
|
||||
TSAsExpression(node) {
|
||||
compareTypes(node.expression, node.typeAnnotation, true);
|
||||
},
|
||||
TSTypeAssertion(node) {
|
||||
compareTypes(node.expression, node.typeAnnotation, true);
|
||||
},
|
||||
VariableDeclarator(node) {
|
||||
if (node.init && node.id.typeAnnotation) {
|
||||
compareTypes(node.init, node.id.typeAnnotation.typeAnnotation, false);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* @fileoverview Disallow use of multiple spaces.
|
||||
* @author Nicholas C. Zakas
|
||||
* @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: "no-multi-spaces",
|
||||
url: "https://eslint.style/rules/no-multi-spaces",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "Disallow multiple spaces",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-multi-spaces",
|
||||
},
|
||||
|
||||
fixable: "whitespace",
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
exceptions: {
|
||||
type: "object",
|
||||
patternProperties: {
|
||||
"^([A-Z][a-z]*)+$": {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
ignoreEOLComments: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
messages: {
|
||||
multipleSpaces: "Multiple spaces found before '{{displayValue}}'.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
const options = context.options[0] || {};
|
||||
const ignoreEOLComments = options.ignoreEOLComments;
|
||||
const exceptions = Object.assign(
|
||||
{ Property: true },
|
||||
options.exceptions,
|
||||
);
|
||||
const hasExceptions = Object.keys(exceptions).some(
|
||||
key => exceptions[key],
|
||||
);
|
||||
|
||||
/**
|
||||
* Formats value of given comment token for error message by truncating its length.
|
||||
* @param {Token} token comment token
|
||||
* @returns {string} formatted value
|
||||
* @private
|
||||
*/
|
||||
function formatReportedCommentValue(token) {
|
||||
const valueLines = token.value.split("\n");
|
||||
const value = valueLines[0];
|
||||
const formattedValue = `${value.slice(0, 12)}...`;
|
||||
|
||||
return valueLines.length === 1 && value.length <= 12
|
||||
? value
|
||||
: formattedValue;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
return {
|
||||
Program() {
|
||||
sourceCode.tokensAndComments.forEach(
|
||||
(leftToken, leftIndex, tokensAndComments) => {
|
||||
if (leftIndex === tokensAndComments.length - 1) {
|
||||
return;
|
||||
}
|
||||
const rightToken = tokensAndComments[leftIndex + 1];
|
||||
|
||||
// Ignore tokens that don't have 2 spaces between them or are on different lines
|
||||
if (
|
||||
!sourceCode.text
|
||||
.slice(leftToken.range[1], rightToken.range[0])
|
||||
.includes(" ") ||
|
||||
leftToken.loc.end.line < rightToken.loc.start.line
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore comments that are the last token on their line if `ignoreEOLComments` is active.
|
||||
if (
|
||||
ignoreEOLComments &&
|
||||
astUtils.isCommentToken(rightToken) &&
|
||||
(leftIndex === tokensAndComments.length - 2 ||
|
||||
rightToken.loc.end.line <
|
||||
tokensAndComments[leftIndex + 2].loc.start
|
||||
.line)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore tokens that are in a node in the "exceptions" object
|
||||
if (hasExceptions) {
|
||||
const parentNode = sourceCode.getNodeByRangeIndex(
|
||||
rightToken.range[0] - 1,
|
||||
);
|
||||
|
||||
if (parentNode && exceptions[parentNode.type]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let displayValue;
|
||||
|
||||
if (rightToken.type === "Block") {
|
||||
displayValue = `/*${formatReportedCommentValue(rightToken)}*/`;
|
||||
} else if (rightToken.type === "Line") {
|
||||
displayValue = `//${formatReportedCommentValue(rightToken)}`;
|
||||
} else {
|
||||
displayValue = rightToken.value;
|
||||
}
|
||||
|
||||
context.report({
|
||||
node: rightToken,
|
||||
loc: {
|
||||
start: leftToken.loc.end,
|
||||
end: rightToken.loc.start,
|
||||
},
|
||||
messageId: "multipleSpaces",
|
||||
data: { displayValue },
|
||||
fix: fixer =>
|
||||
fixer.replaceTextRange(
|
||||
[leftToken.range[1], rightToken.range[0]],
|
||||
" ",
|
||||
),
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { Node } from "../../ast/index.ts";
|
||||
import { SyntaxKind } from "../../ast/index.ts";
|
||||
export declare function getNodeDataType(kind: SyntaxKind): number;
|
||||
export declare function getNodeCommonData(node: Node): number;
|
||||
//# sourceMappingURL=encoder.generated.d.ts.map
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @fileoverview Rule to flag when deleting variables
|
||||
* @author Ilya Volodin
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "Disallow deleting variables",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/latest/rules/no-delete-var",
|
||||
},
|
||||
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
unexpected: "Variables should not be deleted.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
return {
|
||||
UnaryExpression(node) {
|
||||
if (
|
||||
node.operator === "delete" &&
|
||||
node.argument.type === "Identifier"
|
||||
) {
|
||||
context.report({ node, messageId: "unexpected" });
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
const handler = {
|
||||
scheme: "http",
|
||||
domainHost: true,
|
||||
parse: function (components, options) {
|
||||
//report missing host
|
||||
if (!components.host) {
|
||||
components.error = components.error || "HTTP URIs must have a host.";
|
||||
}
|
||||
return components;
|
||||
},
|
||||
serialize: function (components, options) {
|
||||
const secure = String(components.scheme).toLowerCase() === "https";
|
||||
//normalize the default port
|
||||
if (components.port === (secure ? 443 : 80) || components.port === "") {
|
||||
components.port = undefined;
|
||||
}
|
||||
//normalize the empty path
|
||||
if (!components.path) {
|
||||
components.path = "/";
|
||||
}
|
||||
//NOTE: We do not parse query strings for HTTP URIs
|
||||
//as WWW Form Url Encoded query strings are part of the HTML4+ spec,
|
||||
//and not the HTTP spec.
|
||||
return components;
|
||||
}
|
||||
};
|
||||
export default handler;
|
||||
//# sourceMappingURL=http.js.map
|
||||
@@ -0,0 +1,7 @@
|
||||
import * as ts from 'typescript';
|
||||
/**
|
||||
* Returns the contextual type of a given node.
|
||||
* Contextual type is the type of the target the node is going into.
|
||||
* i.e. the type of a called function's parameter, or the defined type of a variable declaration
|
||||
*/
|
||||
export declare function getContextualType(checker: ts.TypeChecker, node: ts.Expression): ts.Type | undefined;
|
||||
@@ -0,0 +1,197 @@
|
||||
// @ts-ignore TS6133
|
||||
import { test } from "vitest";
|
||||
|
||||
import { z } from "zod/v3";
|
||||
|
||||
interface Category {
|
||||
name: string;
|
||||
subcategories: Category[];
|
||||
}
|
||||
|
||||
const testCategory: Category = {
|
||||
name: "I",
|
||||
subcategories: [
|
||||
{
|
||||
name: "A",
|
||||
subcategories: [
|
||||
{
|
||||
name: "1",
|
||||
subcategories: [
|
||||
{
|
||||
name: "a",
|
||||
subcategories: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
test("recursion with z.late.object", () => {
|
||||
const Category: z.ZodType<Category> = z.late.object(() => ({
|
||||
name: z.string(),
|
||||
subcategories: z.array(Category),
|
||||
}));
|
||||
Category.parse(testCategory);
|
||||
});
|
||||
|
||||
test("recursion with z.lazy", () => {
|
||||
const Category: z.ZodType<Category> = z.lazy(() =>
|
||||
z.object({
|
||||
name: z.string(),
|
||||
subcategories: z.array(Category),
|
||||
})
|
||||
);
|
||||
Category.parse(testCategory);
|
||||
});
|
||||
|
||||
test("schema getter", () => {
|
||||
z.lazy(() => z.string()).schema.parse("asdf");
|
||||
});
|
||||
|
||||
type LinkedList = null | { value: number; next: LinkedList };
|
||||
|
||||
const linkedListExample = {
|
||||
value: 1,
|
||||
next: {
|
||||
value: 2,
|
||||
next: {
|
||||
value: 3,
|
||||
next: {
|
||||
value: 4,
|
||||
next: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
test("recursion involving union type", () => {
|
||||
const LinkedListSchema: z.ZodType<LinkedList> = z.lazy(() =>
|
||||
z.union([
|
||||
z.null(),
|
||||
z.object({
|
||||
value: z.number(),
|
||||
next: LinkedListSchema,
|
||||
}),
|
||||
])
|
||||
);
|
||||
LinkedListSchema.parse(linkedListExample);
|
||||
});
|
||||
|
||||
// interface A {
|
||||
// val: number;
|
||||
// b: B;
|
||||
// }
|
||||
|
||||
// interface B {
|
||||
// val: number;
|
||||
// a: A;
|
||||
// }
|
||||
|
||||
// const A: z.ZodType<A> = z.late.object(() => ({
|
||||
// val: z.number(),
|
||||
// b: B,
|
||||
// }));
|
||||
|
||||
// const B: z.ZodType<B> = z.late.object(() => ({
|
||||
// val: z.number(),
|
||||
// a: A,
|
||||
// }));
|
||||
|
||||
// const Alazy: z.ZodType<A> = z.lazy(() => z.object({
|
||||
// val: z.number(),
|
||||
// b: B,
|
||||
// }));
|
||||
|
||||
// const Blazy: z.ZodType<B> = z.lazy(() => z.object({
|
||||
// val: z.number(),
|
||||
// a: A,
|
||||
// }));
|
||||
|
||||
// const a: any = { val: 1 };
|
||||
// const b: any = { val: 2 };
|
||||
// a.b = b;
|
||||
// b.a = a;
|
||||
|
||||
// test('valid check', () => {
|
||||
// A.parse(a);
|
||||
// B.parse(b);
|
||||
// });
|
||||
|
||||
// test("valid check lazy", () => {
|
||||
// A.parse({val:1, b:});
|
||||
// B.parse(b);
|
||||
// });
|
||||
|
||||
// test('masking check', () => {
|
||||
// const FragmentOnA = z
|
||||
// .object({
|
||||
// val: z.number(),
|
||||
// b: z
|
||||
// .object({
|
||||
// val: z.number(),
|
||||
// a: z
|
||||
// .object({
|
||||
// val: z.number(),
|
||||
// })
|
||||
// .nonstrict(),
|
||||
// })
|
||||
// .nonstrict(),
|
||||
// })
|
||||
// .nonstrict();
|
||||
|
||||
// const fragment = FragmentOnA.parse(a);
|
||||
// fragment;
|
||||
// });
|
||||
|
||||
// test('invalid check', () => {
|
||||
// expect(() => A.parse({} as any)).toThrow();
|
||||
// });
|
||||
|
||||
// test('schema getter', () => {
|
||||
// (A as z.ZodLazy<any>).schema;
|
||||
// });
|
||||
|
||||
// test("self recursion with cyclical data", () => {
|
||||
// interface Category {
|
||||
// name: string;
|
||||
// subcategories: Category[];
|
||||
// }
|
||||
|
||||
// const Category: z.ZodType<Category> = z.late.object(() => ({
|
||||
// name: z.string(),
|
||||
// subcategories: z.array(Category),
|
||||
// }));
|
||||
|
||||
// const untypedCategory: any = {
|
||||
// name: "Category A",
|
||||
// };
|
||||
// // creating a cycle
|
||||
// untypedCategory.subcategories = [untypedCategory];
|
||||
// Category.parse(untypedCategory);
|
||||
// });
|
||||
|
||||
// test("self recursion with base type", () => {
|
||||
// const BaseCategory = z.object({
|
||||
// name: z.string(),
|
||||
// });
|
||||
// type BaseCategory = z.infer<typeof BaseCategory>;
|
||||
|
||||
// type Category = BaseCategory & { subcategories: Category[] };
|
||||
|
||||
// const Category: z.ZodType<Category> = z.late
|
||||
// .object(() => ({
|
||||
// subcategories: z.array(Category),
|
||||
// }))
|
||||
// .extend({
|
||||
// name: z.string(),
|
||||
// });
|
||||
|
||||
// const untypedCategory: any = {
|
||||
// name: "Category A",
|
||||
// };
|
||||
// // creating a cycle
|
||||
// untypedCategory.subcategories = [untypedCategory];
|
||||
// Category.parse(untypedCategory); // parses successfully
|
||||
// });
|
||||
@@ -0,0 +1,119 @@
|
||||
import { StructSchema } from './utils.js';
|
||||
import { StructError, Failure } from './error.js';
|
||||
/**
|
||||
* `Struct` objects encapsulate the validation logic for a specific type of
|
||||
* values. Once constructed, you use the `assert`, `is` or `validate` helpers to
|
||||
* validate unknown input data against the struct.
|
||||
*/
|
||||
export declare class Struct<T = unknown, S = unknown> {
|
||||
readonly TYPE: T;
|
||||
type: string;
|
||||
schema: S;
|
||||
coercer: (value: unknown, context: Context) => unknown;
|
||||
validator: (value: unknown, context: Context) => Iterable<Failure>;
|
||||
refiner: (value: T, context: Context) => Iterable<Failure>;
|
||||
entries: (value: unknown, context: Context) => Iterable<[string | number, unknown, Struct<any> | Struct<never>]>;
|
||||
constructor(props: {
|
||||
type: string;
|
||||
schema: S;
|
||||
coercer?: Coercer;
|
||||
validator?: Validator;
|
||||
refiner?: Refiner<T>;
|
||||
entries?: Struct<T, S>['entries'];
|
||||
});
|
||||
/**
|
||||
* Assert that a value passes the struct's validation, throwing if it doesn't.
|
||||
*/
|
||||
assert(value: unknown, message?: string): asserts value is T;
|
||||
/**
|
||||
* Create a value with the struct's coercion logic, then validate it.
|
||||
*/
|
||||
create(value: unknown, message?: string): T;
|
||||
/**
|
||||
* Check if a value passes the struct's validation.
|
||||
*/
|
||||
is(value: unknown): value is T;
|
||||
/**
|
||||
* Mask a value, coercing and validating it, but returning only the subset of
|
||||
* properties defined by the struct's schema. Masking applies recursively to
|
||||
* props of `object` structs only.
|
||||
*/
|
||||
mask(value: unknown, message?: string): T;
|
||||
/**
|
||||
* Validate a value with the struct's validation logic, returning a tuple
|
||||
* representing the result.
|
||||
*
|
||||
* You may optionally pass `true` for the `coerce` argument to coerce
|
||||
* the value before attempting to validate it. If you do, the result will
|
||||
* contain the coerced result when successful. Also, `mask` will turn on
|
||||
* masking of the unknown `object` props recursively if passed.
|
||||
*/
|
||||
validate(value: unknown, options?: {
|
||||
coerce?: boolean;
|
||||
mask?: boolean;
|
||||
message?: string;
|
||||
}): [StructError, undefined] | [undefined, T];
|
||||
}
|
||||
/**
|
||||
* Assert that a value passes a struct, throwing if it doesn't.
|
||||
*/
|
||||
export declare function assert<T, S>(value: unknown, struct: Struct<T, S>, message?: string): asserts value is T;
|
||||
/**
|
||||
* Create a value with the coercion logic of struct and validate it.
|
||||
*/
|
||||
export declare function create<T, S>(value: unknown, struct: Struct<T, S>, message?: string): T;
|
||||
/**
|
||||
* Mask a value, returning only the subset of properties defined by a struct.
|
||||
*/
|
||||
export declare function mask<T, S>(value: unknown, struct: Struct<T, S>, message?: string): T;
|
||||
/**
|
||||
* Check if a value passes a struct.
|
||||
*/
|
||||
export declare function is<T, S>(value: unknown, struct: Struct<T, S>): value is T;
|
||||
/**
|
||||
* Validate a value against a struct, returning an error if invalid, or the
|
||||
* value (with potential coercion) if valid.
|
||||
*/
|
||||
export declare function validate<T, S>(value: unknown, struct: Struct<T, S>, options?: {
|
||||
coerce?: boolean;
|
||||
mask?: boolean;
|
||||
message?: string;
|
||||
}): [StructError, undefined] | [undefined, T];
|
||||
/**
|
||||
* A `Context` contains information about the current location of the
|
||||
* validation inside the initial input value. It also carries `mask`
|
||||
* since it's a run-time flag determining how the validation was invoked
|
||||
* (via `mask()` or via `validate()`), plus it applies recursively
|
||||
* to all of the nested structs.
|
||||
*/
|
||||
export type Context = {
|
||||
branch: Array<any>;
|
||||
path: Array<any>;
|
||||
mask?: boolean;
|
||||
};
|
||||
/**
|
||||
* A type utility to extract the type from a `Struct` class.
|
||||
*/
|
||||
export type Infer<T extends Struct<any, any>> = T['TYPE'];
|
||||
/**
|
||||
* A type utility to describe that a struct represents a TypeScript type.
|
||||
*/
|
||||
export type Describe<T> = Struct<T, StructSchema<T>>;
|
||||
/**
|
||||
* A `Result` is returned from validation functions.
|
||||
*/
|
||||
export type Result = boolean | string | Partial<Failure> | Iterable<boolean | string | Partial<Failure>>;
|
||||
/**
|
||||
* A `Coercer` takes an unknown value and optionally coerces it.
|
||||
*/
|
||||
export type Coercer<T = unknown> = (value: T, context: Context) => unknown;
|
||||
/**
|
||||
* A `Validator` takes an unknown value and validates it.
|
||||
*/
|
||||
export type Validator = (value: unknown, context: Context) => Result;
|
||||
/**
|
||||
* A `Refiner` takes a value of a known type and validates it against a further
|
||||
* constraint.
|
||||
*/
|
||||
export type Refiner<T> = (value: T, context: Context) => Result;
|
||||
//# sourceMappingURL=struct.d.ts.map
|
||||
@@ -0,0 +1,109 @@
|
||||
import { getPathComponents } from "./path.js";
|
||||
/** The callback names supported by the Go server for virtual FS delegation. */
|
||||
export const fsCallbackNames = ["readFile", "fileExists", "directoryExists", "getAccessibleEntries", "realpath"];
|
||||
export function createVirtualFileSystem(files) {
|
||||
const root = {
|
||||
type: "directory",
|
||||
children: {},
|
||||
};
|
||||
const content = {};
|
||||
for (const filePath of Object.keys(files)) {
|
||||
content[filePath] = files[filePath];
|
||||
addToTree(filePath);
|
||||
}
|
||||
return {
|
||||
directoryExists,
|
||||
fileExists,
|
||||
getAccessibleEntries,
|
||||
readFile,
|
||||
realpath: path => path,
|
||||
writeFile,
|
||||
removeFile,
|
||||
};
|
||||
function getNodeFromPath(path) {
|
||||
if (!path || path === "/") {
|
||||
return root;
|
||||
}
|
||||
const segments = getPathComponents(path).slice(1);
|
||||
let current = root;
|
||||
for (const segment of segments) {
|
||||
if (current.type !== "directory") {
|
||||
return undefined;
|
||||
}
|
||||
const child = current.children[segment];
|
||||
if (!child) {
|
||||
return undefined;
|
||||
}
|
||||
current = child;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
function ensureDirectory(segments) {
|
||||
let current = root;
|
||||
for (const segment of segments) {
|
||||
if (!current.children[segment]) {
|
||||
current.children[segment] = { type: "directory", children: {} };
|
||||
}
|
||||
else if (current.children[segment].type !== "directory") {
|
||||
throw new Error(`Cannot create directory: a file already exists at "/${segments.join("/")}"`);
|
||||
}
|
||||
current = current.children[segment];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
function addToTree(path) {
|
||||
const segments = getPathComponents(path).slice(1);
|
||||
if (segments.length === 0) {
|
||||
throw new Error(`Invalid file path: "${path}"`);
|
||||
}
|
||||
const filename = segments.pop();
|
||||
const dirNode = ensureDirectory(segments);
|
||||
dirNode.children[filename] = { type: "file" };
|
||||
}
|
||||
function writeFile(path, data) {
|
||||
content[path] = data;
|
||||
addToTree(path);
|
||||
}
|
||||
function removeFile(path) {
|
||||
delete content[path];
|
||||
const segments = getPathComponents(path).slice(1);
|
||||
if (segments.length === 0)
|
||||
return;
|
||||
const filename = segments.pop();
|
||||
const dirNode = getNodeFromPath("/" + segments.join("/"));
|
||||
if (dirNode && dirNode.type === "directory") {
|
||||
delete dirNode.children[filename];
|
||||
}
|
||||
}
|
||||
function directoryExists(directoryName) {
|
||||
const node = getNodeFromPath(directoryName);
|
||||
return !!node && node.type === "directory";
|
||||
}
|
||||
function fileExists(fileName) {
|
||||
return fileName in content;
|
||||
}
|
||||
function getAccessibleEntries(directoryName) {
|
||||
const node = getNodeFromPath(directoryName);
|
||||
if (!node || node.type !== "directory") {
|
||||
return undefined;
|
||||
}
|
||||
const fileEntries = [];
|
||||
const directories = [];
|
||||
for (const [name, child] of Object.entries(node.children)) {
|
||||
if (child.type === "file") {
|
||||
fileEntries.push(name);
|
||||
}
|
||||
else {
|
||||
directories.push(name);
|
||||
}
|
||||
}
|
||||
return { files: fileEntries, directories };
|
||||
}
|
||||
function readFile(fileName) {
|
||||
if (fileName in content) {
|
||||
return content[fileName];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=fs.js.map
|
||||
@@ -0,0 +1,298 @@
|
||||
import { computeLineStarts, NodeFlags, SyntaxKind, TokenFlags, } from "../../ast/index.js";
|
||||
import { MsgpackReader } from "./msgpack.js";
|
||||
import { RemoteNode, RemoteNodeList, } from "./node.generated.js";
|
||||
import { NODE_EXTENDED_DATA_MASK, } from "./node.infrastructure.js";
|
||||
import { HEADER_OFFSET_EXTENDED_DATA, HEADER_OFFSET_NODES, HEADER_OFFSET_STRING_TABLE, HEADER_OFFSET_STRING_TABLE_OFFSETS, HEADER_OFFSET_STRUCTURED_DATA, KIND_NODE_LIST, NODE_LEN, NODE_OFFSET_KIND, NODE_OFFSET_PARENT, } from "./protocol.js";
|
||||
import { Wtf8Decoder } from "./wtf8.js";
|
||||
// Re-export everything consumers need from the other two files.
|
||||
export { RemoteNode, RemoteNodeList } from "./node.generated.js";
|
||||
export { readParseOptionsKey, readSourceFileHash, RemoteNodeBase } from "./node.infrastructure.js";
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// RemoteSourceFile
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
const NO_STRUCTURED_DATA = 0xFFFFFFFF;
|
||||
export class RemoteSourceFile extends RemoteNode {
|
||||
nodes;
|
||||
_offsetNodes;
|
||||
_offsetStringTableOffsets;
|
||||
_offsetStringTable;
|
||||
_offsetExtendedData;
|
||||
_offsetStructuredData;
|
||||
_decoder;
|
||||
_timing;
|
||||
_lineStarts;
|
||||
_cachedText;
|
||||
_cachedReferencedFiles;
|
||||
_cachedTypeReferenceDirectives;
|
||||
_cachedLibReferenceDirectives;
|
||||
_cachedImports;
|
||||
_cachedModuleAugmentations;
|
||||
_cachedAmbientModuleNames;
|
||||
constructor(data, decoder, timing) {
|
||||
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
||||
const offsetNodes = view.getUint32(HEADER_OFFSET_NODES, true);
|
||||
super(view, 1, undefined, undefined, offsetNodes);
|
||||
this._sourceFile = this;
|
||||
this._offsetNodes = offsetNodes;
|
||||
this._offsetStringTableOffsets = view.getUint32(HEADER_OFFSET_STRING_TABLE_OFFSETS, true);
|
||||
this._offsetStringTable = view.getUint32(HEADER_OFFSET_STRING_TABLE, true);
|
||||
this._offsetExtendedData = view.getUint32(HEADER_OFFSET_EXTENDED_DATA, true);
|
||||
this._offsetStructuredData = view.getUint32(HEADER_OFFSET_STRUCTURED_DATA, true);
|
||||
this._decoder = decoder;
|
||||
this._timing = timing;
|
||||
this.nodes = Array((view.byteLength - offsetNodes) / NODE_LEN);
|
||||
this.nodes[1] = this;
|
||||
// Every node slot is materializable on demand except the nil sentinel at
|
||||
// index 0 and the source-file node at index 1, which is pre-materialized.
|
||||
timing?.recordSourceFileFetched(Math.max(0, this.nodes.length - 2));
|
||||
}
|
||||
readFileReferences(structuredDataOffset) {
|
||||
if (structuredDataOffset === NO_STRUCTURED_DATA) {
|
||||
return [];
|
||||
}
|
||||
const buf = new Uint8Array(this.view.buffer, this.view.byteOffset, this.view.byteLength);
|
||||
const reader = new MsgpackReader(buf, this._offsetStructuredData + structuredDataOffset);
|
||||
const count = reader.readArrayHeader();
|
||||
const result = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
reader.readArrayHeader(); // 5-element tuple
|
||||
const pos = reader.readUint();
|
||||
const end = reader.readUint();
|
||||
const fileName = reader.readString();
|
||||
const resolutionMode = reader.readUint();
|
||||
const preserve = reader.readBool();
|
||||
result.push({ pos, end, fileName, resolutionMode, preserve });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
readNodeIndexArray(structuredDataOffset) {
|
||||
if (structuredDataOffset === NO_STRUCTURED_DATA) {
|
||||
return [];
|
||||
}
|
||||
const buf = new Uint8Array(this.view.buffer, this.view.byteOffset, this.view.byteLength);
|
||||
const reader = new MsgpackReader(buf, this._offsetStructuredData + structuredDataOffset);
|
||||
const count = reader.readArrayHeader();
|
||||
const result = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
const nodeIndex = reader.readUint();
|
||||
result.push(this.getOrCreateNodeAtIndex(nodeIndex));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
readStringArray(structuredDataOffset) {
|
||||
if (structuredDataOffset === NO_STRUCTURED_DATA) {
|
||||
return [];
|
||||
}
|
||||
const buf = new Uint8Array(this.view.buffer, this.view.byteOffset, this.view.byteLength);
|
||||
const reader = new MsgpackReader(buf, this._offsetStructuredData + structuredDataOffset);
|
||||
const count = reader.readArrayHeader();
|
||||
const result = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
result.push(reader.readString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/** @internal */
|
||||
getOrCreateNodeAtIndex(index) {
|
||||
let node = this.nodes[index];
|
||||
if (!node) {
|
||||
// Resolve the real parent so that nodes looked up directly by index (e.g. via
|
||||
// NodeHandle.resolve) report the correct `parent`, rather than always pointing at
|
||||
// the source file. The stored parent index can refer to a synthetic NodeList
|
||||
// container; skip those to mirror normal traversal, where list elements take the
|
||||
// list's parent. The walk terminates at the source file, which occupies index 1
|
||||
// and is already cached.
|
||||
let parentIndex = this.view.getUint32(this._offsetNodes + index * NODE_LEN + NODE_OFFSET_PARENT, true);
|
||||
while (parentIndex !== index &&
|
||||
this.view.getUint32(this._offsetNodes + parentIndex * NODE_LEN + NODE_OFFSET_KIND, true) === KIND_NODE_LIST) {
|
||||
parentIndex = this.view.getUint32(this._offsetNodes + parentIndex * NODE_LEN + NODE_OFFSET_PARENT, true);
|
||||
}
|
||||
const parent = parentIndex === index ? this : this.getOrCreateNodeAtIndex(parentIndex);
|
||||
node = new RemoteNode(this.view, index, parent, this, this._offsetNodes);
|
||||
this.nodes[index] = node;
|
||||
this._timing?.recordMaterialization();
|
||||
}
|
||||
return node;
|
||||
}
|
||||
// ═══ SourceFile-specific extended data getters ═══
|
||||
get extendedDataOffset() {
|
||||
return this._offsetExtendedData + (this.data & NODE_EXTENDED_DATA_MASK);
|
||||
}
|
||||
get fileName() {
|
||||
const stringIndex = this.view.getUint32(this.extendedDataOffset + 4, true);
|
||||
return this.getString(stringIndex);
|
||||
}
|
||||
get path() {
|
||||
const stringIndex = this.view.getUint32(this.extendedDataOffset + 8, true);
|
||||
return this.getString(stringIndex);
|
||||
}
|
||||
get languageVariant() {
|
||||
return this.view.getUint32(this.extendedDataOffset + 12, true);
|
||||
}
|
||||
get scriptKind() {
|
||||
return this.view.getUint32(this.extendedDataOffset + 16, true);
|
||||
}
|
||||
get referencedFiles() {
|
||||
if (this._cachedReferencedFiles !== undefined)
|
||||
return this._cachedReferencedFiles;
|
||||
const offset = this.view.getUint32(this.extendedDataOffset + 20, true);
|
||||
const files = this.readFileReferences(offset);
|
||||
this._cachedReferencedFiles = files;
|
||||
return files;
|
||||
}
|
||||
get typeReferenceDirectives() {
|
||||
if (this._cachedTypeReferenceDirectives !== undefined)
|
||||
return this._cachedTypeReferenceDirectives;
|
||||
const offset = this.view.getUint32(this.extendedDataOffset + 24, true);
|
||||
const directives = this.readFileReferences(offset);
|
||||
this._cachedTypeReferenceDirectives = directives;
|
||||
return directives;
|
||||
}
|
||||
get libReferenceDirectives() {
|
||||
if (this._cachedLibReferenceDirectives !== undefined)
|
||||
return this._cachedLibReferenceDirectives;
|
||||
const offset = this.view.getUint32(this.extendedDataOffset + 28, true);
|
||||
const directives = this.readFileReferences(offset);
|
||||
this._cachedLibReferenceDirectives = directives;
|
||||
return directives;
|
||||
}
|
||||
get imports() {
|
||||
if (this._cachedImports !== undefined)
|
||||
return this._cachedImports;
|
||||
const offset = this.view.getUint32(this.extendedDataOffset + 32, true);
|
||||
const imports = this.readNodeIndexArray(offset);
|
||||
this._cachedImports = imports;
|
||||
return imports;
|
||||
}
|
||||
get moduleAugmentations() {
|
||||
if (this._cachedModuleAugmentations !== undefined)
|
||||
return this._cachedModuleAugmentations;
|
||||
const offset = this.view.getUint32(this.extendedDataOffset + 36, true);
|
||||
const moduleAugmentations = this.readNodeIndexArray(offset);
|
||||
this._cachedModuleAugmentations = moduleAugmentations;
|
||||
return moduleAugmentations;
|
||||
}
|
||||
get ambientModuleNames() {
|
||||
if (this._cachedAmbientModuleNames !== undefined)
|
||||
return this._cachedAmbientModuleNames;
|
||||
const offset = this.view.getUint32(this.extendedDataOffset + 40, true);
|
||||
const names = this.readStringArray(offset);
|
||||
this._cachedAmbientModuleNames = names;
|
||||
return names;
|
||||
}
|
||||
get externalModuleIndicator() {
|
||||
const nodeIndex = this.view.getUint32(this.extendedDataOffset + 44, true);
|
||||
if (nodeIndex === 0)
|
||||
return undefined;
|
||||
if (nodeIndex === this.index)
|
||||
return true;
|
||||
return this.getOrCreateNodeAtIndex(nodeIndex);
|
||||
}
|
||||
get isDeclarationFile() {
|
||||
return (this.flags & NodeFlags.Ambient) !== 0;
|
||||
}
|
||||
get text() {
|
||||
if (this._cachedText !== undefined)
|
||||
return this._cachedText;
|
||||
const text = super.text;
|
||||
this._cachedText = text;
|
||||
return text;
|
||||
}
|
||||
// ═══ Line/character position mapping ═══
|
||||
getLineStarts() {
|
||||
return this._lineStarts ??= computeLineStarts(this.text ?? "");
|
||||
}
|
||||
getLineAndCharacterOfPosition(position) {
|
||||
const lineStarts = this.getLineStarts();
|
||||
const line = computeLineOfPosition(lineStarts, position);
|
||||
return { line, character: position - lineStarts[line] };
|
||||
}
|
||||
getPositionOfLineAndCharacter(line, character) {
|
||||
const lineStarts = this.getLineStarts();
|
||||
if (line < 0 || line >= lineStarts.length) {
|
||||
throw new Error(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length}`);
|
||||
}
|
||||
return lineStarts[line] + character;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Find the 0-based line number containing the given position via binary search.
|
||||
* Assumes the first line starts at position 0 and `position` is non-negative.
|
||||
*/
|
||||
function computeLineOfPosition(lineStarts, position) {
|
||||
let low = 0;
|
||||
let high = lineStarts.length - 1;
|
||||
while (low <= high) {
|
||||
const middle = low + ((high - low) >> 1);
|
||||
const value = lineStarts[middle];
|
||||
if (value < position) {
|
||||
low = middle + 1;
|
||||
}
|
||||
else if (value > position) {
|
||||
high = middle - 1;
|
||||
}
|
||||
else {
|
||||
return middle;
|
||||
}
|
||||
}
|
||||
return low - 1;
|
||||
}
|
||||
/**
|
||||
* Find a descendant node at a specific position with matching kind and end position.
|
||||
*/
|
||||
export function findDescendant(root, pos, end, kind) {
|
||||
if (root.pos === pos && root.end === end && root.kind === kind) {
|
||||
return root;
|
||||
}
|
||||
// Search children
|
||||
let result;
|
||||
root.forEachChild(child => {
|
||||
if (result)
|
||||
return result; // Already found
|
||||
// Only search in children that could contain our target
|
||||
if (child.pos <= pos && child.end >= end) {
|
||||
result = findDescendant(child, pos, end, kind);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Parse a node handle string into its components.
|
||||
* Handle format: "index.kind.path" where path may contain dots.
|
||||
*/
|
||||
export function parseNodeHandle(handle) {
|
||||
const firstDot = handle.indexOf(".");
|
||||
if (firstDot === -1) {
|
||||
throw new Error(`Invalid node handle: ${handle}`);
|
||||
}
|
||||
const secondDot = handle.indexOf(".", firstDot + 1);
|
||||
if (secondDot === -1) {
|
||||
throw new Error(`Invalid node handle: ${handle}`);
|
||||
}
|
||||
return {
|
||||
index: parseInt(handle.slice(0, firstDot), 10),
|
||||
kind: parseInt(handle.slice(firstDot + 1, secondDot), 10),
|
||||
path: handle.slice(secondDot + 1),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Decode binary-encoded AST data into a Node.
|
||||
* Works for any binary-encoded node, including synthetic nodes
|
||||
* (e.g. from typeToTypeNode) that don't have a source file.
|
||||
*/
|
||||
export function decodeNode(data) {
|
||||
const sf = new RemoteSourceFile(data, new Wtf8Decoder());
|
||||
return sf;
|
||||
}
|
||||
/**
|
||||
* Get the unique ID string for a remote node.
|
||||
* Throws if the node is not a RemoteNode (i.e. not decoded from binary data).
|
||||
*/
|
||||
export function getNodeId(node) {
|
||||
if (!(node instanceof RemoteNode)) {
|
||||
throw new Error("getNodeId requires a RemoteNode");
|
||||
}
|
||||
return node.id;
|
||||
}
|
||||
//# sourceMappingURL=node.js.map
|
||||
@@ -0,0 +1,14 @@
|
||||
import defineProperty from "./defineProperty.js";
|
||||
function _objectSpread(e) {
|
||||
for (var r = 1; r < arguments.length; r++) {
|
||||
var t = null != arguments[r] ? Object(arguments[r]) : {},
|
||||
o = Object.keys(t);
|
||||
"function" == typeof Object.getOwnPropertySymbols && o.push.apply(o, Object.getOwnPropertySymbols(t).filter(function (e) {
|
||||
return Object.getOwnPropertyDescriptor(t, e).enumerable;
|
||||
})), o.forEach(function (r) {
|
||||
defineProperty(e, r, t[r]);
|
||||
});
|
||||
}
|
||||
return e;
|
||||
}
|
||||
export { _objectSpread as default };
|
||||
@@ -0,0 +1,116 @@
|
||||
import type { $ZodStringFormats } from "../core/checks.js";
|
||||
import type * as errors from "../core/errors.js";
|
||||
import * as util from "../core/util.js";
|
||||
|
||||
const error: () => errors.$ZodErrorMap = () => {
|
||||
const Sizable: Record<string, { unit: string; verb: string }> = {
|
||||
string: { unit: "tegn", verb: "å ha" },
|
||||
file: { unit: "bytes", verb: "å ha" },
|
||||
array: { unit: "elementer", verb: "å inneholde" },
|
||||
set: { unit: "elementer", verb: "å inneholde" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
const FormatDictionary: {
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: "input",
|
||||
email: "e-postadresse",
|
||||
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 dato- og klokkeslett",
|
||||
date: "ISO-dato",
|
||||
time: "ISO-klokkeslett",
|
||||
duration: "ISO-varighet",
|
||||
ipv4: "IPv4-område",
|
||||
ipv6: "IPv6-område",
|
||||
cidrv4: "IPv4-spekter",
|
||||
cidrv6: "IPv6-spekter",
|
||||
base64: "base64-enkodet streng",
|
||||
base64url: "base64url-enkodet streng",
|
||||
json_string: "JSON-streng",
|
||||
e164: "E.164-nummer",
|
||||
jwt: "JWT",
|
||||
template_literal: "input",
|
||||
};
|
||||
|
||||
const TypeDictionary: {
|
||||
[k in errors.$ZodInvalidTypeExpected | (string & {})]?: string;
|
||||
} = {
|
||||
nan: "NaN",
|
||||
number: "tall",
|
||||
array: "liste",
|
||||
};
|
||||
|
||||
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 `Ugyldig input: forventet instanceof ${issue.expected}, fikk ${received}`;
|
||||
}
|
||||
return `Ugyldig input: forventet ${expected}, fikk ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1) return `Ugyldig verdi: forventet ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Ugyldig valg: forventet en av ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `For stor(t): forventet ${issue.origin ?? "value"} til å ha ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elementer"}`;
|
||||
return `For stor(t): forventet ${issue.origin ?? "value"} til å ha ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `For lite(n): forventet ${issue.origin} til å ha ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
|
||||
return `For lite(n): forventet ${issue.origin} til å ha ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
if (_issue.format === "starts_with") return `Ugyldig streng: må starte med "${_issue.prefix}"`;
|
||||
if (_issue.format === "ends_with") return `Ugyldig streng: må ende med "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes") return `Ugyldig streng: må inneholde "${_issue.includes}"`;
|
||||
if (_issue.format === "regex") return `Ugyldig streng: må matche mønsteret ${_issue.pattern}`;
|
||||
return `Ugyldig ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Ugyldig tall: må være et multiplum av ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `${issue.keys.length > 1 ? "Ukjente nøkler" : "Ukjent nøkkel"}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Ugyldig nøkkel i ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Ugyldig input";
|
||||
case "invalid_element":
|
||||
return `Ugyldig verdi i ${issue.origin}`;
|
||||
default:
|
||||
return `Ugyldig input`;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "text-encoding-utf-8",
|
||||
"author": "Erik Arvidsson <erik.arvidsson@gmail.com>",
|
||||
"contributors": ["Rick Eyre <rick.eyre@outlook.com>", "Joshua Bell <inexorabletash@gmail.com>"],
|
||||
"version": "1.0.2",
|
||||
"description": "UTF-8 only polyfill for the Encoding Living Standard's API.",
|
||||
"main": "lib/encoding.lib",
|
||||
"jsnext:main": "src/encoding.js",
|
||||
"files": ["src", "lib"],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/arv/text-encoding-utf-8.git"
|
||||
},
|
||||
"keywords": ["encoding", "decoding", "living standard"],
|
||||
"bugs": {
|
||||
"url": "https://github.com/arv/text-encoding-utf-8/issues"
|
||||
},
|
||||
"homepage": "https://github.com/arv/text-encoding-utf-8",
|
||||
"scripts": {
|
||||
"prepublish":
|
||||
"rollup -f iife -o lib/encoding.js -- src/polyfill.js && rollup -f cjs -o lib/encoding.lib.js -- src/encoding.js && cp src/encoding.js lib/encoding.lib.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rollup": "^0.21.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
'use strict'
|
||||
|
||||
const { type, platform, arch, release, cpus } = require('node:os')
|
||||
const { resolve, join } = require('node:path')
|
||||
const spawn = require('node:child_process').spawn
|
||||
const pump = require('pump')
|
||||
const split = require('split2')
|
||||
const through = require('through2')
|
||||
const steed = require('steed')
|
||||
|
||||
function usage () {
|
||||
console.log(`
|
||||
Pino Benchmarks
|
||||
|
||||
To run a benchmark, specify which to run:
|
||||
|
||||
・all ⁃ run all benchmarks (takes a while)
|
||||
・basic ⁃ log a simple string
|
||||
・object ⁃ logging a basic object
|
||||
・deep-object ⁃ logging a large object
|
||||
・multi-arg ⁃ multiple log method arguments
|
||||
・child ⁃ child from a parent
|
||||
・child-child ⁃ child from a child
|
||||
・child-creation ⁃ child constructor
|
||||
・formatters ⁃ difference between with or without formatters
|
||||
|
||||
Example:
|
||||
|
||||
node runbench basic
|
||||
`)
|
||||
}
|
||||
|
||||
if (!process.argv[2]) {
|
||||
usage()
|
||||
process.exit()
|
||||
}
|
||||
|
||||
const quiet = process.argv[3] === '-q'
|
||||
|
||||
const selectedBenchmark = process.argv[2].toLowerCase()
|
||||
const benchmarkDir = resolve(__dirname, '..')
|
||||
const benchmarks = {
|
||||
basic: 'basic.bench.js',
|
||||
object: 'object.bench.js',
|
||||
'deep-object': 'deep-object.bench.js',
|
||||
'multi-arg': 'multi-arg.bench.js',
|
||||
'long-string': 'long-string.bench.js',
|
||||
child: 'child.bench.js',
|
||||
'child-child': 'child-child.bench.js',
|
||||
'child-creation': 'child-creation.bench.js',
|
||||
formatters: 'formatters.bench.js'
|
||||
}
|
||||
|
||||
function runBenchmark (name, done) {
|
||||
const benchmarkResults = {}
|
||||
benchmarkResults[name] = {}
|
||||
|
||||
const processor = through(function (line, enc, cb) {
|
||||
const [label, time] = ('' + line).split(': ')
|
||||
const [target, iterations] = label.split('*')
|
||||
const logger = target.replace('bench', '')
|
||||
|
||||
if (!benchmarkResults[name][logger]) benchmarkResults[name][logger] = []
|
||||
|
||||
benchmarkResults[name][logger].push({
|
||||
time: time.replace('ms', ''),
|
||||
iterations: iterations.replace(':', '')
|
||||
})
|
||||
|
||||
cb()
|
||||
})
|
||||
|
||||
if (quiet === false) console.log(`Running ${name.toUpperCase()} benchmark\n`)
|
||||
|
||||
const benchmark = spawn(
|
||||
process.argv[0],
|
||||
[join(benchmarkDir, benchmarks[name])]
|
||||
)
|
||||
|
||||
if (quiet === false) {
|
||||
benchmark.stdout.pipe(process.stdout)
|
||||
}
|
||||
|
||||
pump(benchmark.stdout, split(), processor)
|
||||
|
||||
benchmark.on('exit', () => {
|
||||
console.log()
|
||||
if (done && typeof done === 'function') done(null, benchmarkResults)
|
||||
})
|
||||
}
|
||||
|
||||
function sum (arr) {
|
||||
let result = 0
|
||||
for (var i = 0; i < arr.length; i += 1) {
|
||||
result += Number.parseFloat(arr[i].time)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function displayResults (results) {
|
||||
if (quiet === false) console.log('==========')
|
||||
const benchNames = Object.keys(results)
|
||||
for (var i = 0; i < benchNames.length; i += 1) {
|
||||
console.log(`${benchNames[i].toUpperCase()} benchmark averages`)
|
||||
const benchmark = results[benchNames[i]]
|
||||
const loggers = Object.keys(benchmark)
|
||||
for (var j = 0; j < loggers.length; j += 1) {
|
||||
const logger = benchmark[loggers[j]]
|
||||
const average = sum(logger) / logger.length
|
||||
console.log(`${loggers[j]} average: ${average.toFixed(3)}ms`)
|
||||
}
|
||||
}
|
||||
if (quiet === false) {
|
||||
console.log('==========')
|
||||
console.log(
|
||||
`System: ${type()}/${platform()} ${arch()} ${release()}`,
|
||||
`~ ${cpus()[0].model} (cores/threads: ${cpus().length})`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function toBench (done) {
|
||||
runBenchmark(this.name, done)
|
||||
}
|
||||
|
||||
const benchQueue = []
|
||||
if (selectedBenchmark !== 'all') {
|
||||
benchQueue.push(toBench.bind({ name: selectedBenchmark }))
|
||||
} else {
|
||||
const keys = Object.keys(benchmarks)
|
||||
for (var i = 0; i < keys.length; i += 1) {
|
||||
benchQueue.push(toBench.bind({ name: keys[i] }))
|
||||
}
|
||||
}
|
||||
steed.series(benchQueue, function (err, results) {
|
||||
if (err) return console.error(err.message)
|
||||
results.forEach(displayResults)
|
||||
})
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "../../cjs/_decorate.cjs",
|
||||
"module": "../../esm/_decorate.js"
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "brace-expansion",
|
||||
"description": "Brace expansion as known from sh/bash",
|
||||
"version": "5.0.9",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"import": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"default": "./dist/commonjs/index.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"preversion": "npm test",
|
||||
"postversion": "npm publish",
|
||||
"prepublishOnly": "git push origin --follow-tags",
|
||||
"prepare": "tshy",
|
||||
"pretest": "npm run prepare",
|
||||
"presnap": "npm run prepare",
|
||||
"test": "tap",
|
||||
"snap": "tap",
|
||||
"format": "prettier --write .",
|
||||
"benchmark": "node benchmark/index.js",
|
||||
"typedoc": "typedoc --tsconfig .tshy/esm.json ./src/*.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/brace-expansion": "^1.1.2",
|
||||
"@types/node": "^25.2.1",
|
||||
"mkdirp": "^3.0.1",
|
||||
"prettier": "^3.3.2",
|
||||
"tap": "^21.6.2",
|
||||
"tshy": "^3.0.2",
|
||||
"typedoc": "^0.28.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"balanced-match": "^4.0.2"
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"tshy": {
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": "./src/index.ts"
|
||||
}
|
||||
},
|
||||
"main": "./dist/commonjs/index.js",
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"module": "./dist/esm/index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/juliangruber/brace-expansion.git"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
const ClientBrowser = require('../../../../lib/client/browser/index');
|
||||
const promiseUtils = require('../../utils');
|
||||
|
||||
/**
|
||||
* Constructor for a Jayson Promise Browser Client that does not depend any node.js core libraries
|
||||
* @class PromiseClientBrowser
|
||||
* @extends ClientBrowser
|
||||
* @return {PromiseClientBrowser}
|
||||
*/
|
||||
const PromiseClientBrowser = function(callServerPromise, options) {
|
||||
if(!(this instanceof PromiseClientBrowser)) {
|
||||
return new PromiseClientBrowser(callServerPromise, options);
|
||||
}
|
||||
|
||||
const callServer = function (request, callback) {
|
||||
callServerPromise(request).then(res => callback(null, res), err => callback(err));
|
||||
};
|
||||
|
||||
ClientBrowser.call(this, callServer, options);
|
||||
this.request = promiseUtils.wrapClientRequestMethod(this.request.bind(this));
|
||||
};
|
||||
|
||||
// let's hope this ancient method of inheriting works the way I remember it.
|
||||
PromiseClientBrowser.prototype = ClientBrowser.prototype;
|
||||
|
||||
module.exports = PromiseClientBrowser;
|
||||
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
// See http://www.robvanderwoude.com/escapechars.php
|
||||
const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
|
||||
|
||||
function escapeCommand(arg) {
|
||||
// Escape meta chars
|
||||
arg = arg.replace(metaCharsRegExp, '^$1');
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
function escapeArgument(arg, doubleEscapeMetaChars) {
|
||||
// Convert to string
|
||||
arg = `${arg}`;
|
||||
|
||||
// Algorithm below is based on https://qntm.org/cmd
|
||||
// It's slightly altered to disable JS backtracking to avoid hanging on specially crafted input
|
||||
// Please see https://github.com/moxystudio/node-cross-spawn/pull/160 for more information
|
||||
|
||||
// Sequence of backslashes followed by a double quote:
|
||||
// double up all the backslashes and escape the double quote
|
||||
arg = arg.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
|
||||
|
||||
// Sequence of backslashes followed by the end of the string
|
||||
// (which will become a double quote later):
|
||||
// double up all the backslashes
|
||||
arg = arg.replace(/(?=(\\+?)?)\1$/, '$1$1');
|
||||
|
||||
// All other backslashes occur literally
|
||||
|
||||
// Quote the whole thing:
|
||||
arg = `"${arg}"`;
|
||||
|
||||
// Escape meta chars
|
||||
arg = arg.replace(metaCharsRegExp, '^$1');
|
||||
|
||||
// Double escape meta chars if necessary
|
||||
if (doubleEscapeMetaChars) {
|
||||
arg = arg.replace(metaCharsRegExp, '^$1');
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
module.exports.command = escapeCommand;
|
||||
module.exports.argument = escapeArgument;
|
||||
@@ -0,0 +1,33 @@
|
||||
import type { NodeWithParent, TSESTree } from '@typescript-eslint/types';
|
||||
import type { DefinitionType } from './DefinitionType';
|
||||
export declare abstract class DefinitionBase<Type extends DefinitionType, Node extends NodeWithParent, Parent extends TSESTree.Node | null, Name extends TSESTree.Node> {
|
||||
/**
|
||||
* A unique ID for this instance - primarily used to help debugging and testing
|
||||
*/
|
||||
readonly $id: number;
|
||||
readonly type: Type;
|
||||
/**
|
||||
* The `Identifier` node of this definition
|
||||
* @public
|
||||
*/
|
||||
readonly name: Name;
|
||||
/**
|
||||
* The enclosing node of the name.
|
||||
* @public
|
||||
*/
|
||||
readonly node: Node;
|
||||
/**
|
||||
* the enclosing statement node of the identifier.
|
||||
* @public
|
||||
*/
|
||||
readonly parent: Parent;
|
||||
constructor(type: Type, name: Name, node: Node, parent: Parent);
|
||||
/**
|
||||
* `true` if the variable is valid in a type context, false otherwise
|
||||
*/
|
||||
abstract readonly isTypeDefinition: boolean;
|
||||
/**
|
||||
* `true` if the variable is valid in a value context, false otherwise
|
||||
*/
|
||||
abstract readonly isVariableDefinition: boolean;
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
'use strict'
|
||||
|
||||
exports.byteLength = byteLength
|
||||
exports.toByteArray = toByteArray
|
||||
exports.fromByteArray = fromByteArray
|
||||
|
||||
var lookup = []
|
||||
var revLookup = []
|
||||
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
|
||||
|
||||
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||
for (var i = 0, len = code.length; i < len; ++i) {
|
||||
lookup[i] = code[i]
|
||||
revLookup[code.charCodeAt(i)] = i
|
||||
}
|
||||
|
||||
// Support decoding URL-safe base64 strings, as Node.js does.
|
||||
// See: https://en.wikipedia.org/wiki/Base64#URL_applications
|
||||
revLookup['-'.charCodeAt(0)] = 62
|
||||
revLookup['_'.charCodeAt(0)] = 63
|
||||
|
||||
function getLens (b64) {
|
||||
var len = b64.length
|
||||
|
||||
if (len % 4 > 0) {
|
||||
throw new Error('Invalid string. Length must be a multiple of 4')
|
||||
}
|
||||
|
||||
// Trim off extra bytes after placeholder bytes are found
|
||||
// See: https://github.com/beatgammit/base64-js/issues/42
|
||||
var validLen = b64.indexOf('=')
|
||||
if (validLen === -1) validLen = len
|
||||
|
||||
var placeHoldersLen = validLen === len
|
||||
? 0
|
||||
: 4 - (validLen % 4)
|
||||
|
||||
return [validLen, placeHoldersLen]
|
||||
}
|
||||
|
||||
// base64 is 4/3 + up to two characters of the original data
|
||||
function byteLength (b64) {
|
||||
var lens = getLens(b64)
|
||||
var validLen = lens[0]
|
||||
var placeHoldersLen = lens[1]
|
||||
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
|
||||
}
|
||||
|
||||
function _byteLength (b64, validLen, placeHoldersLen) {
|
||||
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
|
||||
}
|
||||
|
||||
function toByteArray (b64) {
|
||||
var tmp
|
||||
var lens = getLens(b64)
|
||||
var validLen = lens[0]
|
||||
var placeHoldersLen = lens[1]
|
||||
|
||||
var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
|
||||
|
||||
var curByte = 0
|
||||
|
||||
// if there are placeholders, only get up to the last complete 4 chars
|
||||
var len = placeHoldersLen > 0
|
||||
? validLen - 4
|
||||
: validLen
|
||||
|
||||
var i
|
||||
for (i = 0; i < len; i += 4) {
|
||||
tmp =
|
||||
(revLookup[b64.charCodeAt(i)] << 18) |
|
||||
(revLookup[b64.charCodeAt(i + 1)] << 12) |
|
||||
(revLookup[b64.charCodeAt(i + 2)] << 6) |
|
||||
revLookup[b64.charCodeAt(i + 3)]
|
||||
arr[curByte++] = (tmp >> 16) & 0xFF
|
||||
arr[curByte++] = (tmp >> 8) & 0xFF
|
||||
arr[curByte++] = tmp & 0xFF
|
||||
}
|
||||
|
||||
if (placeHoldersLen === 2) {
|
||||
tmp =
|
||||
(revLookup[b64.charCodeAt(i)] << 2) |
|
||||
(revLookup[b64.charCodeAt(i + 1)] >> 4)
|
||||
arr[curByte++] = tmp & 0xFF
|
||||
}
|
||||
|
||||
if (placeHoldersLen === 1) {
|
||||
tmp =
|
||||
(revLookup[b64.charCodeAt(i)] << 10) |
|
||||
(revLookup[b64.charCodeAt(i + 1)] << 4) |
|
||||
(revLookup[b64.charCodeAt(i + 2)] >> 2)
|
||||
arr[curByte++] = (tmp >> 8) & 0xFF
|
||||
arr[curByte++] = tmp & 0xFF
|
||||
}
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
function tripletToBase64 (num) {
|
||||
return lookup[num >> 18 & 0x3F] +
|
||||
lookup[num >> 12 & 0x3F] +
|
||||
lookup[num >> 6 & 0x3F] +
|
||||
lookup[num & 0x3F]
|
||||
}
|
||||
|
||||
function encodeChunk (uint8, start, end) {
|
||||
var tmp
|
||||
var output = []
|
||||
for (var i = start; i < end; i += 3) {
|
||||
tmp =
|
||||
((uint8[i] << 16) & 0xFF0000) +
|
||||
((uint8[i + 1] << 8) & 0xFF00) +
|
||||
(uint8[i + 2] & 0xFF)
|
||||
output.push(tripletToBase64(tmp))
|
||||
}
|
||||
return output.join('')
|
||||
}
|
||||
|
||||
function fromByteArray (uint8) {
|
||||
var tmp
|
||||
var len = uint8.length
|
||||
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
|
||||
var parts = []
|
||||
var maxChunkLength = 16383 // must be multiple of 3
|
||||
|
||||
// go through the array every three bytes, we'll deal with trailing stuff later
|
||||
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
|
||||
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
|
||||
}
|
||||
|
||||
// pad the end with zeros, but make sure to not forget the extra bytes
|
||||
if (extraBytes === 1) {
|
||||
tmp = uint8[len - 1]
|
||||
parts.push(
|
||||
lookup[tmp >> 2] +
|
||||
lookup[(tmp << 4) & 0x3F] +
|
||||
'=='
|
||||
)
|
||||
} else if (extraBytes === 2) {
|
||||
tmp = (uint8[len - 2] << 8) + uint8[len - 1]
|
||||
parts.push(
|
||||
lookup[tmp >> 10] +
|
||||
lookup[(tmp >> 4) & 0x3F] +
|
||||
lookup[(tmp << 2) & 0x3F] +
|
||||
'='
|
||||
)
|
||||
}
|
||||
|
||||
return parts.join('')
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// @ts-ignore TS6133
|
||||
import { test } from "vitest";
|
||||
|
||||
import * as z from "zod/v3";
|
||||
import { util } from "../helpers/util.js";
|
||||
|
||||
test("branded types", () => {
|
||||
const mySchema = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
})
|
||||
.brand<"superschema">();
|
||||
|
||||
// simple branding
|
||||
type MySchema = z.infer<typeof mySchema>;
|
||||
util.assertEqual<MySchema, { name: string } & { [z.BRAND]: { superschema: true } }>(true);
|
||||
|
||||
const doStuff = (arg: MySchema) => arg;
|
||||
doStuff(mySchema.parse({ name: "hello there" }));
|
||||
|
||||
// inheritance
|
||||
const extendedSchema = mySchema.brand<"subschema">();
|
||||
type ExtendedSchema = z.infer<typeof extendedSchema>;
|
||||
util.assertEqual<ExtendedSchema, { name: string } & z.BRAND<"superschema"> & z.BRAND<"subschema">>(true);
|
||||
|
||||
doStuff(extendedSchema.parse({ name: "hello again" }));
|
||||
|
||||
// number branding
|
||||
const numberSchema = z.number().brand<42>();
|
||||
type NumberSchema = z.infer<typeof numberSchema>;
|
||||
util.assertEqual<NumberSchema, number & { [z.BRAND]: { 42: true } }>(true);
|
||||
|
||||
// symbol branding
|
||||
const MyBrand: unique symbol = Symbol("hello");
|
||||
type MyBrand = typeof MyBrand;
|
||||
const symbolBrand = z.number().brand<"sup">().brand<typeof MyBrand>();
|
||||
type SymbolBrand = z.infer<typeof symbolBrand>;
|
||||
// number & { [z.BRAND]: { sup: true, [MyBrand]: true } }
|
||||
util.assertEqual<SymbolBrand, number & z.BRAND<"sup"> & z.BRAND<MyBrand>>(true);
|
||||
|
||||
// keeping brands out of input types
|
||||
const age = z.number().brand<"age">();
|
||||
|
||||
type Age = z.infer<typeof age>;
|
||||
type AgeInput = z.input<typeof age>;
|
||||
|
||||
util.assertEqual<AgeInput, Age>(false);
|
||||
util.assertEqual<number, AgeInput>(true);
|
||||
util.assertEqual<number & z.BRAND<"age">, Age>(true);
|
||||
|
||||
// @ts-expect-error
|
||||
doStuff({ name: "hello there!" });
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 Zejin Zhuang <heineiuo@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,117 @@
|
||||
import type { $ZodStringFormats } from "../core/checks.js";
|
||||
import type * as errors from "../core/errors.js";
|
||||
import * as util from "../core/util.js";
|
||||
|
||||
const error: () => errors.$ZodErrorMap = () => {
|
||||
const Sizable: Record<string, { unit: string; verb: string }> = {
|
||||
string: { unit: "символів", verb: "матиме" },
|
||||
file: { unit: "байтів", verb: "матиме" },
|
||||
array: { unit: "елементів", verb: "матиме" },
|
||||
set: { unit: "елементів", verb: "матиме" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | 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[0])}`;
|
||||
return `Неправильна опція: очікується одне з ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Занадто велике: очікується, що ${issue.origin ?? "значення"} ${sizing.verb} ${adj}${issue.maximum.toString()} ${sizing.unit ?? "елементів"}`;
|
||||
return `Занадто велике: очікується, що ${issue.origin ?? "значення"} буде ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `Занадто мале: очікується, що ${issue.origin} ${sizing.verb} ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
|
||||
return `Занадто мале: очікується, що ${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 `Неправильний ключ у ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Неправильні вхідні дані";
|
||||
case "invalid_element":
|
||||
return `Неправильне значення у ${issue.origin}`;
|
||||
default:
|
||||
return `Неправильні вхідні дані`;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,596 @@
|
||||
import { NodeFlags } from "#enums/nodeFlags";
|
||||
import { SyntaxKind } from "#enums/syntaxKind";
|
||||
import { createToken } from "./factory.generated.js";
|
||||
import { isJSDocNodeKind, isKeywordKind, isPrivateIdentifier, isPropertyNameLiteral, isTokenKind, } from "./is.js";
|
||||
import { createScanner, skipTrivia, } from "./scanner.js";
|
||||
export function getTokenAtPosition(sourceFile, position) {
|
||||
return getTokenAtPositionImpl(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includePrecedingTokenAtEndPosition*/ undefined);
|
||||
}
|
||||
export function getTouchingPropertyName(sourceFile, position) {
|
||||
return getTokenAtPositionImpl(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, node => isPropertyNameLiteral(node) || isKeywordKind(node.kind) || isPrivateIdentifier(node));
|
||||
}
|
||||
export function getTouchingToken(sourceFile, position) {
|
||||
return getTokenAtPositionImpl(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, /*includePrecedingTokenAtEndPosition*/ undefined);
|
||||
}
|
||||
/**
|
||||
* Finds the token that starts immediately after `previousToken` ends, searching
|
||||
* within `parent`. Returns `undefined` if no such token exists.
|
||||
*/
|
||||
export function findNextToken(previousToken, parent, sourceFile) {
|
||||
return find(parent);
|
||||
function find(n) {
|
||||
if (isTokenKind(n.kind) && n.pos === previousToken.end) {
|
||||
// This is the token that starts at the end of previousToken – return it.
|
||||
return n;
|
||||
}
|
||||
// Find the child node that contains `previousToken` or starts immediately after it.
|
||||
let foundNode;
|
||||
const visitChild = (node) => {
|
||||
if (node.flags & NodeFlags.Reparsed) {
|
||||
return undefined;
|
||||
}
|
||||
if (node.pos <= previousToken.end && node.end > previousToken.end) {
|
||||
foundNode = node;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
// Visit JSDoc children first (mirrors Go's VisitEachChildAndJSDoc).
|
||||
if (n.jsDoc) {
|
||||
for (const jsdoc of n.jsDoc) {
|
||||
visitChild(jsdoc);
|
||||
}
|
||||
}
|
||||
n.forEachChild(visitChild, nodes => {
|
||||
if (nodes.length > 0 && foundNode === undefined) {
|
||||
for (const node of nodes) {
|
||||
if (node.flags & NodeFlags.Reparsed)
|
||||
continue;
|
||||
if (node.pos > previousToken.end)
|
||||
break;
|
||||
if (node.end > previousToken.end) {
|
||||
foundNode = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
// Recurse into the found child.
|
||||
if (foundNode !== undefined) {
|
||||
return find(foundNode);
|
||||
}
|
||||
// No AST child covers the position; use the scanner to find the syntactic token.
|
||||
// The scanner is initialized at `previousToken.end`, so tokenFullStart === previousToken.end.
|
||||
const startPos = previousToken.end;
|
||||
if (startPos >= n.pos && startPos < n.end) {
|
||||
const scanner = getScannerForSourceFile(sourceFile, startPos);
|
||||
const token = scanner.getToken();
|
||||
const tokenFullStart = scanner.getTokenFullStart();
|
||||
const tokenEnd = scanner.getTokenEnd();
|
||||
const flags = scanner.getTokenFlags();
|
||||
return getOrCreateToken(sourceFile, token, tokenFullStart, tokenEnd, n, flags);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Finds the leftmost token satisfying `position < token.end`.
|
||||
* If the position is in the trivia of that leftmost token, or the token is invalid,
|
||||
* returns the rightmost valid token with `token.end <= position`.
|
||||
* Excludes `JsxText` tokens containing only whitespace.
|
||||
*/
|
||||
export function findPrecedingToken(sourceFile, position) {
|
||||
return findPrecedingTokenImpl(sourceFile, position, sourceFile);
|
||||
}
|
||||
function getTokenAtPositionImpl(sourceFile, position, allowPositionInLeadingTrivia, includePrecedingTokenAtEndPosition) {
|
||||
let current = sourceFile;
|
||||
let nodeAfterLeft;
|
||||
const state = {
|
||||
next: undefined,
|
||||
prevSubtree: undefined,
|
||||
left: 0,
|
||||
};
|
||||
const testNode = (node) => {
|
||||
if (node.kind !== SyntaxKind.EndOfFile && node.end === position && includePrecedingTokenAtEndPosition !== undefined) {
|
||||
state.prevSubtree = node;
|
||||
}
|
||||
// A node "contains" the position if position < end, except nodes at the file end
|
||||
// treat end as inclusive (there's nowhere else to look). This applies to the EOF
|
||||
// token itself, and to JSDoc nodes reaching EOF (e.g. unterminated JSDoc comments).
|
||||
if (node.end < position || node.end === position &&
|
||||
node.kind !== SyntaxKind.EndOfFile &&
|
||||
(!isJSDocNodeKind(node.kind) || node.end !== sourceFile.endOfFileToken.end)) {
|
||||
return -1;
|
||||
}
|
||||
const nodePos = getPosition(node, sourceFile, allowPositionInLeadingTrivia);
|
||||
if (nodePos > position) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
while (true) {
|
||||
// Visit each child of current to find the one containing the position.
|
||||
state.next = undefined;
|
||||
nodeAfterLeft = undefined;
|
||||
// In Strada, JSDoc nodes with a single comment represent that comment as a string
|
||||
// property (not a child node), so forEachChild does not visit it. We replicate this
|
||||
// by detecting single-comment NodeLists in visitList and skipping their elements in visitNode.
|
||||
let skipSingleCommentChildren = false;
|
||||
const visitNode = (node) => {
|
||||
if (node.flags & NodeFlags.Reparsed) {
|
||||
return undefined;
|
||||
}
|
||||
if (skipSingleCommentChildren && isJSDocCommentChildKind(node.kind)) {
|
||||
return undefined;
|
||||
}
|
||||
if (nodeAfterLeft === undefined) {
|
||||
nodeAfterLeft = node;
|
||||
}
|
||||
if (state.next === undefined) {
|
||||
const result = testNode(node);
|
||||
switch (result) {
|
||||
case -1:
|
||||
if (!isJSDocNodeKind(node.kind)) {
|
||||
state.left = node.end;
|
||||
}
|
||||
nodeAfterLeft = undefined;
|
||||
break;
|
||||
case 0:
|
||||
state.next = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
// Visit JSDoc children first, then regular children (mirrors Go's VisitEachChildAndJSDoc).
|
||||
if (current.jsDoc) {
|
||||
for (const jsdoc of current.jsDoc) {
|
||||
visitNode(jsdoc);
|
||||
}
|
||||
}
|
||||
current.forEachChild(visitNode, nodes => {
|
||||
// Track whether this NodeList is a single-comment list that should be skipped.
|
||||
// The flag affects the subsequent forEachNode(visitNode) calls for this NodeList.
|
||||
skipSingleCommentChildren = isJSDocSingleCommentNodeList(nodes);
|
||||
if (nodes.length === 0 || skipSingleCommentChildren) {
|
||||
return undefined;
|
||||
}
|
||||
if (nodeAfterLeft === undefined) {
|
||||
for (const node of nodes) {
|
||||
if (!(node.flags & NodeFlags.Reparsed)) {
|
||||
nodeAfterLeft = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state.next === undefined) {
|
||||
if (nodes.end === position && includePrecedingTokenAtEndPosition !== undefined) {
|
||||
state.left = nodes.end;
|
||||
nodeAfterLeft = undefined;
|
||||
state.prevSubtree = nodes[nodes.length - 1];
|
||||
}
|
||||
else if (nodes.end <= position) {
|
||||
state.left = nodes.end;
|
||||
nodeAfterLeft = undefined;
|
||||
}
|
||||
else if (nodes.pos <= position) {
|
||||
binarySearchNodeList(nodes, testNode, (node, middle, arr) => {
|
||||
state.left = node.end;
|
||||
nodeAfterLeft = undefined;
|
||||
for (let i = middle + 1; i < arr.length; i++) {
|
||||
if (!(arr[i].flags & NodeFlags.Reparsed)) {
|
||||
nodeAfterLeft = arr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, found => {
|
||||
state.next = found;
|
||||
});
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
// If prevSubtree was set, check if the rightmost token of prevSubtree should be returned.
|
||||
if (state.prevSubtree !== undefined) {
|
||||
const child = findPrecedingTokenImpl(sourceFile, position, state.prevSubtree);
|
||||
if (child !== undefined && child.end === position && includePrecedingTokenAtEndPosition(child)) {
|
||||
return child;
|
||||
}
|
||||
state.prevSubtree = undefined;
|
||||
}
|
||||
if (state.next === undefined) {
|
||||
if (isTokenKind(current.kind) || shouldSkipChild(current)) {
|
||||
return current;
|
||||
}
|
||||
// Use the scanner to find a token not stored in the AST.
|
||||
const scanner = getScannerForSourceFile(sourceFile, state.left);
|
||||
let end = current.end;
|
||||
const afterLeft = nodeAfterLeft;
|
||||
if (afterLeft !== undefined) {
|
||||
end = afterLeft.pos;
|
||||
}
|
||||
while (state.left < end) {
|
||||
const token = scanner.getToken();
|
||||
const tokenFullStart = scanner.getTokenFullStart();
|
||||
const tokenStart = allowPositionInLeadingTrivia ? tokenFullStart : scanner.getTokenStart();
|
||||
const tokenEnd = scanner.getTokenEnd();
|
||||
const flags = scanner.getTokenFlags();
|
||||
if (tokenEnd > end) {
|
||||
break;
|
||||
}
|
||||
if (tokenStart <= position && position < tokenEnd) {
|
||||
if (token === SyntaxKind.Identifier || !isTokenKind(token)) {
|
||||
if (isJSDocNodeKind(current.kind)) {
|
||||
return current;
|
||||
}
|
||||
throw new Error(`did not expect ${SyntaxKind[current.kind]} to have ${SyntaxKind[token]} in its trivia`);
|
||||
}
|
||||
return getOrCreateToken(sourceFile, token, tokenFullStart, tokenEnd, current, flags);
|
||||
}
|
||||
if (includePrecedingTokenAtEndPosition !== undefined && tokenEnd === position) {
|
||||
const prevToken = getOrCreateToken(sourceFile, token, tokenFullStart, tokenEnd, current, flags);
|
||||
if (includePrecedingTokenAtEndPosition(prevToken)) {
|
||||
return prevToken;
|
||||
}
|
||||
}
|
||||
state.left = tokenEnd;
|
||||
scanner.scan();
|
||||
}
|
||||
return current;
|
||||
}
|
||||
current = state.next;
|
||||
state.left = current.pos;
|
||||
nodeAfterLeft = undefined;
|
||||
}
|
||||
}
|
||||
function getPosition(node, sourceFile, allowPositionInLeadingTrivia) {
|
||||
if (allowPositionInLeadingTrivia) {
|
||||
return node.pos;
|
||||
}
|
||||
return getTokenPosOfNode(node, sourceFile, /*includeJSDoc*/ true);
|
||||
}
|
||||
/** @internal */
|
||||
export function getTokenPosOfNode(node, sourceFile, includeJSDoc) {
|
||||
// With nodes that have no width (i.e. 'Missing' nodes), we actually *don't*
|
||||
// want to skip trivia because this will launch us forward to the next token.
|
||||
if (nodeIsMissing(node)) {
|
||||
return node.pos;
|
||||
}
|
||||
if (isJSDocNodeKind(node.kind) || node.kind === SyntaxKind.JsxText) {
|
||||
return skipTrivia(sourceFile.text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
|
||||
}
|
||||
if (includeJSDoc && node.jsDoc && node.jsDoc.length > 0) {
|
||||
return getTokenPosOfNode(node.jsDoc[0], sourceFile, /*includeJSDoc*/ false);
|
||||
}
|
||||
return skipTrivia(sourceFile.text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ false, /*inJSDoc*/ !!(node.flags & NodeFlags.JSDoc));
|
||||
}
|
||||
function nodeIsMissing(node) {
|
||||
return node.pos === node.end && node.pos >= 0 && node.kind !== SyntaxKind.EndOfFile;
|
||||
}
|
||||
function findPrecedingTokenImpl(sourceFile, position, startNode) {
|
||||
const find = (n) => {
|
||||
if (isTokenKind(n.kind) && n.kind !== SyntaxKind.EndOfFile) {
|
||||
return n;
|
||||
}
|
||||
let foundChild;
|
||||
let prevChild;
|
||||
// Visit JSDoc nodes first (mirrors Go's VisitEachChildAndJSDoc).
|
||||
if (n.jsDoc) {
|
||||
for (const jsdoc of n.jsDoc) {
|
||||
if (jsdoc.flags & NodeFlags.Reparsed)
|
||||
continue;
|
||||
if (foundChild !== undefined)
|
||||
break;
|
||||
if (position < jsdoc.end && (prevChild === undefined || prevChild.end <= position)) {
|
||||
foundChild = jsdoc;
|
||||
}
|
||||
else {
|
||||
prevChild = jsdoc;
|
||||
}
|
||||
}
|
||||
}
|
||||
let skipSingleCommentChildrenImpl = false;
|
||||
n.forEachChild(node => {
|
||||
if (node.flags & NodeFlags.Reparsed) {
|
||||
return undefined;
|
||||
}
|
||||
if (skipSingleCommentChildrenImpl && isJSDocCommentChildKind(node.kind)) {
|
||||
return undefined;
|
||||
}
|
||||
if (foundChild !== undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (position < node.end && (prevChild === undefined || prevChild.end <= position)) {
|
||||
foundChild = node;
|
||||
}
|
||||
else {
|
||||
prevChild = node;
|
||||
}
|
||||
return undefined;
|
||||
}, nodes => {
|
||||
skipSingleCommentChildrenImpl = isJSDocSingleCommentNodeList(nodes);
|
||||
if (foundChild !== undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (nodes.length > 0 && !skipSingleCommentChildrenImpl) {
|
||||
const index = binarySearchForPrecedingToken(nodes, position);
|
||||
if (index >= 0 && !(nodes[index].flags & NodeFlags.Reparsed)) {
|
||||
foundChild = nodes[index];
|
||||
}
|
||||
const lookupIndex = index >= 0 ? index - 1 : nodes.length - 1;
|
||||
for (let i = lookupIndex; i >= 0; i--) {
|
||||
if (!(nodes[i].flags & NodeFlags.Reparsed)) {
|
||||
if (prevChild === undefined) {
|
||||
prevChild = nodes[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
if (foundChild !== undefined) {
|
||||
const start = getTokenPosOfNode(foundChild, sourceFile, /*includeJSDoc*/ true);
|
||||
if (start >= position) {
|
||||
if (position >= foundChild.pos) {
|
||||
// We are in the leading trivia of foundChild. Check for JSDoc nodes of n
|
||||
// preceding foundChild, mirroring Go's findPrecedingToken logic.
|
||||
let jsDoc;
|
||||
if (n.jsDoc) {
|
||||
for (let i = n.jsDoc.length - 1; i >= 0; i--) {
|
||||
if (n.jsDoc[i].pos >= foundChild.pos) {
|
||||
jsDoc = n.jsDoc[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jsDoc !== undefined) {
|
||||
if (position < jsDoc.end) {
|
||||
return find(jsDoc);
|
||||
}
|
||||
return findRightmostValidToken(sourceFile, jsDoc.end, n, position);
|
||||
}
|
||||
return findRightmostValidToken(sourceFile, foundChild.pos, n, -1);
|
||||
}
|
||||
// Answer is in tokens between two visited children.
|
||||
return findRightmostValidToken(sourceFile, foundChild.pos, n, position);
|
||||
}
|
||||
return find(foundChild);
|
||||
}
|
||||
if (position >= n.end) {
|
||||
return findRightmostValidToken(sourceFile, n.end, n, -1);
|
||||
}
|
||||
return findRightmostValidToken(sourceFile, n.end, n, position);
|
||||
};
|
||||
return find(startNode);
|
||||
}
|
||||
function findRightmostValidToken(sourceFile, endPos, containingNode, position) {
|
||||
if (position === -1) {
|
||||
position = containingNode.end;
|
||||
}
|
||||
const find = (n, endPos) => {
|
||||
if (isTokenKind(n.kind) && n.kind !== SyntaxKind.EndOfFile) {
|
||||
return n;
|
||||
}
|
||||
let rightmostValidNode;
|
||||
let hasChildren = false;
|
||||
// Visit JSDoc nodes first (mirrors Go's VisitEachChildAndJSDoc).
|
||||
if (n.jsDoc) {
|
||||
hasChildren = true;
|
||||
for (const jsdoc of n.jsDoc) {
|
||||
if (jsdoc.flags & NodeFlags.Reparsed)
|
||||
continue;
|
||||
if (jsdoc.end > endPos || getTokenPosOfNode(jsdoc, sourceFile) >= position)
|
||||
continue;
|
||||
if (isValidPrecedingNode(jsdoc, sourceFile)) {
|
||||
rightmostValidNode = jsdoc;
|
||||
}
|
||||
}
|
||||
}
|
||||
let skipSingleCommentChildren = false;
|
||||
n.forEachChild(node => {
|
||||
if (node.flags & NodeFlags.Reparsed) {
|
||||
return undefined;
|
||||
}
|
||||
if (skipSingleCommentChildren && isJSDocCommentChildKind(node.kind)) {
|
||||
return undefined;
|
||||
}
|
||||
hasChildren = true;
|
||||
if (node.end > endPos || getTokenPosOfNode(node, sourceFile) >= position) {
|
||||
return undefined;
|
||||
}
|
||||
if (isValidPrecedingNode(node, sourceFile)) {
|
||||
rightmostValidNode = node;
|
||||
}
|
||||
return undefined;
|
||||
}, nodes => {
|
||||
// Skip single-comment JSDoc NodeLists (e.g. JSDocText children of a JSDoc node):
|
||||
// In Go, these are stored as string properties and are never visited as children.
|
||||
skipSingleCommentChildren = isJSDocSingleCommentNodeList(nodes);
|
||||
if (nodes.length > 0 && !skipSingleCommentChildren) {
|
||||
hasChildren = true;
|
||||
for (let i = nodes.length - 1; i >= 0; i--) {
|
||||
const node = nodes[i];
|
||||
if (node.flags & NodeFlags.Reparsed)
|
||||
continue;
|
||||
if (node.end > endPos || getTokenPosOfNode(node, sourceFile) >= position)
|
||||
continue;
|
||||
if (isValidPrecedingNode(node, sourceFile)) {
|
||||
rightmostValidNode = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
// Scan for syntactic tokens (e.g. `{`, `,`) between AST nodes, matching Go's
|
||||
// findRightmostValidToken scanner step.
|
||||
if (!shouldSkipChild(n)) {
|
||||
const startPos = rightmostValidNode !== undefined ? rightmostValidNode.end : n.pos;
|
||||
const targetEnd = Math.min(endPos, position);
|
||||
if (startPos < targetEnd) {
|
||||
const scanner = getScannerForSourceFile(sourceFile, startPos);
|
||||
let pos = startPos;
|
||||
let lastScannedToken;
|
||||
while (pos < targetEnd) {
|
||||
const tokenStart = scanner.getTokenStart();
|
||||
if (tokenStart >= position)
|
||||
break;
|
||||
const tokenFullStart = scanner.getTokenFullStart();
|
||||
const tokenEnd = scanner.getTokenEnd();
|
||||
const token = scanner.getToken();
|
||||
const flags = scanner.getTokenFlags();
|
||||
lastScannedToken = getOrCreateToken(sourceFile, token, tokenFullStart, tokenEnd, n, flags);
|
||||
pos = tokenEnd;
|
||||
scanner.scan();
|
||||
}
|
||||
if (lastScannedToken !== undefined) {
|
||||
return lastScannedToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasChildren) {
|
||||
if (n !== containingNode) {
|
||||
return n;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
if (rightmostValidNode !== undefined) {
|
||||
return find(rightmostValidNode, rightmostValidNode.end);
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
return find(containingNode, endPos);
|
||||
}
|
||||
function isValidPrecedingNode(node, sourceFile) {
|
||||
if (node.kind === SyntaxKind.EndOfFile) {
|
||||
return false;
|
||||
}
|
||||
const start = getTokenPosOfNode(node, sourceFile);
|
||||
const width = node.end - start;
|
||||
return width > 0;
|
||||
}
|
||||
function shouldSkipChild(node) {
|
||||
return node.kind === SyntaxKind.JSDoc ||
|
||||
node.kind === SyntaxKind.JSDocText ||
|
||||
node.kind === SyntaxKind.JSDocTypeLiteral ||
|
||||
node.kind === SyntaxKind.JSDocSignature ||
|
||||
node.kind === SyntaxKind.JSDocLink ||
|
||||
node.kind === SyntaxKind.JSDocLinkCode ||
|
||||
node.kind === SyntaxKind.JSDocLinkPlain ||
|
||||
isJSDocTag(node);
|
||||
}
|
||||
function isJSDocTag(node) {
|
||||
return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode;
|
||||
}
|
||||
// In Strada, if a JSDoc node has a single comment, that comment is represented as a string
|
||||
// property as a simplification, and therefore that comment is not visited by forEachChild.
|
||||
// To match, we skip single-element comment NodeLists within JSDoc/JSDocTag nodes.
|
||||
function isJSDocCommentChildKind(kind) {
|
||||
switch (kind) {
|
||||
case SyntaxKind.JSDocText:
|
||||
case SyntaxKind.JSDocLink:
|
||||
case SyntaxKind.JSDocLinkCode:
|
||||
case SyntaxKind.JSDocLinkPlain:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function isJSDocSingleCommentNodeList(nodes) {
|
||||
return nodes.length === 1 && isJSDocCommentChildKind(nodes[0].kind);
|
||||
}
|
||||
function getScannerForSourceFile(sourceFile, pos) {
|
||||
const scanner = createScanner(/*skipTrivia*/ true, sourceFile.languageVariant, sourceFile.text);
|
||||
scanner.resetTokenState(pos);
|
||||
scanner.scan();
|
||||
return scanner;
|
||||
}
|
||||
function getOrCreateToken(sourceFile, kind, pos, end, parent, _flags) {
|
||||
const key = `${pos}_${end}`;
|
||||
if (!sourceFile.tokenCache) {
|
||||
sourceFile.tokenCache = new Map();
|
||||
}
|
||||
const existing = sourceFile.tokenCache.get(key);
|
||||
if (existing !== undefined) {
|
||||
return existing;
|
||||
}
|
||||
const token = createToken(kind);
|
||||
token.pos = pos;
|
||||
token.end = end;
|
||||
token.parent = parent;
|
||||
sourceFile.tokenCache.set(key, token);
|
||||
return token;
|
||||
}
|
||||
/** Binary search a node list for the node containing position. */
|
||||
function binarySearchNodeList(nodes, testNode, onLeft, onMatch) {
|
||||
let lo = 0;
|
||||
let hi = nodes.length - 1;
|
||||
while (lo <= hi) {
|
||||
const mid = (lo + hi) >>> 1;
|
||||
const node = nodes[mid];
|
||||
if (node.flags & NodeFlags.Reparsed) {
|
||||
// Skip reparsed nodes: try to find a non-reparsed node nearby
|
||||
let found = false;
|
||||
for (let i = mid + 1; i <= hi; i++) {
|
||||
if (!(nodes[i].flags & NodeFlags.Reparsed)) {
|
||||
const cmp = testNode(nodes[i]);
|
||||
if (cmp < 0) {
|
||||
onLeft(nodes[i], i, nodes);
|
||||
lo = i + 1;
|
||||
}
|
||||
else if (cmp > 0) {
|
||||
hi = i - 1;
|
||||
}
|
||||
else {
|
||||
onMatch(nodes[i]);
|
||||
return;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
hi = mid - 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const cmp = testNode(node);
|
||||
if (cmp < 0) {
|
||||
onLeft(node, mid, nodes);
|
||||
lo = mid + 1;
|
||||
}
|
||||
else if (cmp > 0) {
|
||||
hi = mid - 1;
|
||||
}
|
||||
else {
|
||||
onMatch(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
function binarySearchForPrecedingToken(nodes, position) {
|
||||
let lo = 0;
|
||||
let hi = nodes.length - 1;
|
||||
let result = -1;
|
||||
while (lo <= hi) {
|
||||
const mid = (lo + hi) >>> 1;
|
||||
const node = nodes[mid];
|
||||
if (node.flags & NodeFlags.Reparsed) {
|
||||
lo = mid + 1;
|
||||
continue;
|
||||
}
|
||||
if (position < node.end) {
|
||||
if (mid === 0 || position >= nodes[mid - 1].end) {
|
||||
result = mid;
|
||||
break;
|
||||
}
|
||||
hi = mid - 1;
|
||||
}
|
||||
else {
|
||||
lo = mid + 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//# sourceMappingURL=astnav.js.map
|
||||
@@ -0,0 +1,21 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="es2020" />
|
||||
/// <reference lib="es2021.promise" />
|
||||
/// <reference lib="es2021.string" />
|
||||
/// <reference lib="es2021.weakref" />
|
||||
/// <reference lib="es2021.intl" />
|
||||
@@ -0,0 +1,16 @@
|
||||
var getPrototypeOf = require("./getPrototypeOf.js");
|
||||
var isNativeReflectConstruct = require("./isNativeReflectConstruct.js");
|
||||
var possibleConstructorReturn = require("./possibleConstructorReturn.js");
|
||||
function _createSuper(t) {
|
||||
var r = isNativeReflectConstruct();
|
||||
return function () {
|
||||
var e,
|
||||
o = getPrototypeOf(t);
|
||||
if (r) {
|
||||
var s = getPrototypeOf(this).constructor;
|
||||
e = Reflect.construct(o, arguments, s);
|
||||
} else e = o.apply(this, arguments);
|
||||
return possibleConstructorReturn(this, e);
|
||||
};
|
||||
}
|
||||
module.exports = _createSuper, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
Reference in New Issue
Block a user