diff --git a/napi/parser/generate-visitor-keys.mjs b/napi/parser/generate-visitor-keys.mjs new file mode 100644 index 0000000000000..7c52887e06276 --- /dev/null +++ b/napi/parser/generate-visitor-keys.mjs @@ -0,0 +1,29 @@ +import { visitorKeys as visitorKeysOriginal } from '@typescript-eslint/visitor-keys'; +import { writeFileSync } from 'node:fs'; +import { join as pathJoin } from 'node:path'; + +const PATH_CJS = pathJoin(import.meta.dirname, 'generated/visitor-keys.cjs'); +const PATH_MJS = pathJoin(import.meta.dirname, 'generated/visitor-keys.mjs'); + +// Add keys for `ParenthesizedExpression` and `TSParenthesizedType`, which TS-ESLint doesn't have +const visitorKeys = { + ...visitorKeysOriginal, + ParenthesizedExpression: ['expression'], + TSParenthesizedType: ['typeAnnotation'], +}; + +const keys = Object.entries(visitorKeys) + .filter(([, v]) => v?.length) + .map(([k, v]) => ` ${k}: [${v.map((v) => `'${v}'`).join(', ')}],`) + .join('\n'); + +const code = `// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit \`napi/parser/generate-visitor-keys.mjs\`. + +const visitorKeys = { +${keys} +}; +`; + +writeFileSync(PATH_CJS, `${code}module.exports = visitorKeys;\n`); +writeFileSync(PATH_MJS, `${code}export default visitorKeys;\n`); diff --git a/napi/parser/generated/visitor-keys.cjs b/napi/parser/generated/visitor-keys.cjs new file mode 100644 index 0000000000000..f8eac92f2ebca --- /dev/null +++ b/napi/parser/generated/visitor-keys.cjs @@ -0,0 +1,143 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `napi/parser/generate-visitor-keys.mjs`. + +const visitorKeys = { + ArrayExpression: ['elements'], + ArrayPattern: ['decorators', 'elements', 'typeAnnotation'], + ArrowFunctionExpression: ['typeParameters', 'params', 'returnType', 'body'], + AssignmentExpression: ['left', 'right'], + AssignmentPattern: ['decorators', 'left', 'right', 'typeAnnotation'], + AwaitExpression: ['argument'], + BinaryExpression: ['left', 'right'], + BlockStatement: ['body'], + BreakStatement: ['label'], + CallExpression: ['callee', 'typeArguments', 'arguments'], + CatchClause: ['param', 'body'], + ChainExpression: ['expression'], + ClassBody: ['body'], + ClassDeclaration: ['decorators', 'id', 'typeParameters', 'superClass', 'superTypeArguments', 'implements', 'body'], + ClassExpression: ['decorators', 'id', 'typeParameters', 'superClass', 'superTypeArguments', 'implements', 'body'], + ConditionalExpression: ['test', 'consequent', 'alternate'], + ContinueStatement: ['label'], + DoWhileStatement: ['body', 'test'], + ExperimentalRestProperty: ['argument'], + ExperimentalSpreadProperty: ['argument'], + ExportAllDeclaration: ['exported', 'source', 'attributes'], + ExportDefaultDeclaration: ['declaration'], + ExportNamedDeclaration: ['declaration', 'specifiers', 'source', 'attributes'], + ExportSpecifier: ['exported', 'local'], + ExpressionStatement: ['expression'], + ForInStatement: ['left', 'right', 'body'], + ForOfStatement: ['left', 'right', 'body'], + ForStatement: ['init', 'test', 'update', 'body'], + FunctionDeclaration: ['id', 'typeParameters', 'params', 'returnType', 'body'], + FunctionExpression: ['id', 'typeParameters', 'params', 'returnType', 'body'], + Identifier: ['decorators', 'typeAnnotation'], + IfStatement: ['test', 'consequent', 'alternate'], + ImportAttribute: ['key', 'value'], + ImportDeclaration: ['specifiers', 'source', 'attributes'], + ImportDefaultSpecifier: ['local'], + ImportExpression: ['source', 'options'], + ImportNamespaceSpecifier: ['local'], + ImportSpecifier: ['imported', 'local'], + JSXAttribute: ['name', 'value'], + JSXClosingElement: ['name'], + JSXElement: ['openingElement', 'children', 'closingElement'], + JSXExpressionContainer: ['expression'], + JSXFragment: ['openingFragment', 'children', 'closingFragment'], + JSXMemberExpression: ['object', 'property'], + JSXNamespacedName: ['namespace', 'name'], + JSXOpeningElement: ['name', 'typeArguments', 'attributes'], + JSXSpreadAttribute: ['argument'], + JSXSpreadChild: ['expression'], + LabeledStatement: ['label', 'body'], + LogicalExpression: ['left', 'right'], + MemberExpression: ['object', 'property'], + MetaProperty: ['meta', 'property'], + MethodDefinition: ['decorators', 'key', 'value'], + NewExpression: ['callee', 'typeArguments', 'arguments'], + ObjectExpression: ['properties'], + ObjectPattern: ['decorators', 'properties', 'typeAnnotation'], + Program: ['body'], + Property: ['key', 'value'], + PropertyDefinition: ['decorators', 'key', 'typeAnnotation', 'value'], + RestElement: ['decorators', 'argument', 'typeAnnotation'], + ReturnStatement: ['argument'], + SequenceExpression: ['expressions'], + SpreadElement: ['argument'], + StaticBlock: ['body'], + SwitchCase: ['test', 'consequent'], + SwitchStatement: ['discriminant', 'cases'], + TaggedTemplateExpression: ['tag', 'typeArguments', 'quasi'], + TemplateLiteral: ['quasis', 'expressions'], + ThrowStatement: ['argument'], + TryStatement: ['block', 'handler', 'finalizer'], + UnaryExpression: ['argument'], + UpdateExpression: ['argument'], + VariableDeclaration: ['declarations'], + VariableDeclarator: ['id', 'init'], + WhileStatement: ['test', 'body'], + WithStatement: ['object', 'body'], + YieldExpression: ['argument'], + AccessorProperty: ['decorators', 'key', 'typeAnnotation', 'value'], + Decorator: ['expression'], + TSAbstractAccessorProperty: ['decorators', 'key', 'typeAnnotation'], + TSAbstractMethodDefinition: ['key', 'value'], + TSAbstractPropertyDefinition: ['decorators', 'key', 'typeAnnotation'], + TSArrayType: ['elementType'], + TSAsExpression: ['expression', 'typeAnnotation'], + TSCallSignatureDeclaration: ['typeParameters', 'params', 'returnType'], + TSClassImplements: ['expression', 'typeArguments'], + TSConditionalType: ['checkType', 'extendsType', 'trueType', 'falseType'], + TSConstructorType: ['typeParameters', 'params', 'returnType'], + TSConstructSignatureDeclaration: ['typeParameters', 'params', 'returnType'], + TSDeclareFunction: ['id', 'typeParameters', 'params', 'returnType', 'body'], + TSEmptyBodyFunctionExpression: ['id', 'typeParameters', 'params', 'returnType'], + TSEnumBody: ['members'], + TSEnumDeclaration: ['id', 'body'], + TSEnumMember: ['id', 'initializer'], + TSExportAssignment: ['expression'], + TSExternalModuleReference: ['expression'], + TSFunctionType: ['typeParameters', 'params', 'returnType'], + TSImportEqualsDeclaration: ['id', 'moduleReference'], + TSImportType: ['argument', 'qualifier', 'typeArguments', 'options'], + TSIndexedAccessType: ['indexType', 'objectType'], + TSIndexSignature: ['parameters', 'typeAnnotation'], + TSInferType: ['typeParameter'], + TSInstantiationExpression: ['expression', 'typeArguments'], + TSInterfaceBody: ['body'], + TSInterfaceDeclaration: ['id', 'typeParameters', 'extends', 'body'], + TSInterfaceHeritage: ['expression', 'typeArguments'], + TSIntersectionType: ['types'], + TSLiteralType: ['literal'], + TSMappedType: ['key', 'constraint', 'nameType', 'typeAnnotation'], + TSMethodSignature: ['typeParameters', 'key', 'params', 'returnType'], + TSModuleBlock: ['body'], + TSModuleDeclaration: ['id', 'body'], + TSNamedTupleMember: ['label', 'elementType'], + TSNamespaceExportDeclaration: ['id'], + TSNonNullExpression: ['expression'], + TSOptionalType: ['typeAnnotation'], + TSParameterProperty: ['decorators', 'parameter'], + TSPropertySignature: ['typeAnnotation', 'key'], + TSQualifiedName: ['left', 'right'], + TSRestType: ['typeAnnotation'], + TSSatisfiesExpression: ['expression', 'typeAnnotation'], + TSTemplateLiteralType: ['quasis', 'types'], + TSTupleType: ['elementTypes'], + TSTypeAliasDeclaration: ['id', 'typeParameters', 'typeAnnotation'], + TSTypeAnnotation: ['typeAnnotation'], + TSTypeAssertion: ['typeAnnotation', 'expression'], + TSTypeLiteral: ['members'], + TSTypeOperator: ['typeAnnotation'], + TSTypeParameter: ['name', 'constraint', 'default'], + TSTypeParameterDeclaration: ['params'], + TSTypeParameterInstantiation: ['params'], + TSTypePredicate: ['typeAnnotation', 'parameterName'], + TSTypeQuery: ['exprName', 'typeArguments'], + TSTypeReference: ['typeName', 'typeArguments'], + TSUnionType: ['types'], + ParenthesizedExpression: ['expression'], + TSParenthesizedType: ['typeAnnotation'], +}; +module.exports = visitorKeys; diff --git a/napi/parser/generated/visitor-keys.mjs b/napi/parser/generated/visitor-keys.mjs new file mode 100644 index 0000000000000..bcbf7a9b303c4 --- /dev/null +++ b/napi/parser/generated/visitor-keys.mjs @@ -0,0 +1,143 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `napi/parser/generate-visitor-keys.mjs`. + +const visitorKeys = { + ArrayExpression: ['elements'], + ArrayPattern: ['decorators', 'elements', 'typeAnnotation'], + ArrowFunctionExpression: ['typeParameters', 'params', 'returnType', 'body'], + AssignmentExpression: ['left', 'right'], + AssignmentPattern: ['decorators', 'left', 'right', 'typeAnnotation'], + AwaitExpression: ['argument'], + BinaryExpression: ['left', 'right'], + BlockStatement: ['body'], + BreakStatement: ['label'], + CallExpression: ['callee', 'typeArguments', 'arguments'], + CatchClause: ['param', 'body'], + ChainExpression: ['expression'], + ClassBody: ['body'], + ClassDeclaration: ['decorators', 'id', 'typeParameters', 'superClass', 'superTypeArguments', 'implements', 'body'], + ClassExpression: ['decorators', 'id', 'typeParameters', 'superClass', 'superTypeArguments', 'implements', 'body'], + ConditionalExpression: ['test', 'consequent', 'alternate'], + ContinueStatement: ['label'], + DoWhileStatement: ['body', 'test'], + ExperimentalRestProperty: ['argument'], + ExperimentalSpreadProperty: ['argument'], + ExportAllDeclaration: ['exported', 'source', 'attributes'], + ExportDefaultDeclaration: ['declaration'], + ExportNamedDeclaration: ['declaration', 'specifiers', 'source', 'attributes'], + ExportSpecifier: ['exported', 'local'], + ExpressionStatement: ['expression'], + ForInStatement: ['left', 'right', 'body'], + ForOfStatement: ['left', 'right', 'body'], + ForStatement: ['init', 'test', 'update', 'body'], + FunctionDeclaration: ['id', 'typeParameters', 'params', 'returnType', 'body'], + FunctionExpression: ['id', 'typeParameters', 'params', 'returnType', 'body'], + Identifier: ['decorators', 'typeAnnotation'], + IfStatement: ['test', 'consequent', 'alternate'], + ImportAttribute: ['key', 'value'], + ImportDeclaration: ['specifiers', 'source', 'attributes'], + ImportDefaultSpecifier: ['local'], + ImportExpression: ['source', 'options'], + ImportNamespaceSpecifier: ['local'], + ImportSpecifier: ['imported', 'local'], + JSXAttribute: ['name', 'value'], + JSXClosingElement: ['name'], + JSXElement: ['openingElement', 'children', 'closingElement'], + JSXExpressionContainer: ['expression'], + JSXFragment: ['openingFragment', 'children', 'closingFragment'], + JSXMemberExpression: ['object', 'property'], + JSXNamespacedName: ['namespace', 'name'], + JSXOpeningElement: ['name', 'typeArguments', 'attributes'], + JSXSpreadAttribute: ['argument'], + JSXSpreadChild: ['expression'], + LabeledStatement: ['label', 'body'], + LogicalExpression: ['left', 'right'], + MemberExpression: ['object', 'property'], + MetaProperty: ['meta', 'property'], + MethodDefinition: ['decorators', 'key', 'value'], + NewExpression: ['callee', 'typeArguments', 'arguments'], + ObjectExpression: ['properties'], + ObjectPattern: ['decorators', 'properties', 'typeAnnotation'], + Program: ['body'], + Property: ['key', 'value'], + PropertyDefinition: ['decorators', 'key', 'typeAnnotation', 'value'], + RestElement: ['decorators', 'argument', 'typeAnnotation'], + ReturnStatement: ['argument'], + SequenceExpression: ['expressions'], + SpreadElement: ['argument'], + StaticBlock: ['body'], + SwitchCase: ['test', 'consequent'], + SwitchStatement: ['discriminant', 'cases'], + TaggedTemplateExpression: ['tag', 'typeArguments', 'quasi'], + TemplateLiteral: ['quasis', 'expressions'], + ThrowStatement: ['argument'], + TryStatement: ['block', 'handler', 'finalizer'], + UnaryExpression: ['argument'], + UpdateExpression: ['argument'], + VariableDeclaration: ['declarations'], + VariableDeclarator: ['id', 'init'], + WhileStatement: ['test', 'body'], + WithStatement: ['object', 'body'], + YieldExpression: ['argument'], + AccessorProperty: ['decorators', 'key', 'typeAnnotation', 'value'], + Decorator: ['expression'], + TSAbstractAccessorProperty: ['decorators', 'key', 'typeAnnotation'], + TSAbstractMethodDefinition: ['key', 'value'], + TSAbstractPropertyDefinition: ['decorators', 'key', 'typeAnnotation'], + TSArrayType: ['elementType'], + TSAsExpression: ['expression', 'typeAnnotation'], + TSCallSignatureDeclaration: ['typeParameters', 'params', 'returnType'], + TSClassImplements: ['expression', 'typeArguments'], + TSConditionalType: ['checkType', 'extendsType', 'trueType', 'falseType'], + TSConstructorType: ['typeParameters', 'params', 'returnType'], + TSConstructSignatureDeclaration: ['typeParameters', 'params', 'returnType'], + TSDeclareFunction: ['id', 'typeParameters', 'params', 'returnType', 'body'], + TSEmptyBodyFunctionExpression: ['id', 'typeParameters', 'params', 'returnType'], + TSEnumBody: ['members'], + TSEnumDeclaration: ['id', 'body'], + TSEnumMember: ['id', 'initializer'], + TSExportAssignment: ['expression'], + TSExternalModuleReference: ['expression'], + TSFunctionType: ['typeParameters', 'params', 'returnType'], + TSImportEqualsDeclaration: ['id', 'moduleReference'], + TSImportType: ['argument', 'qualifier', 'typeArguments', 'options'], + TSIndexedAccessType: ['indexType', 'objectType'], + TSIndexSignature: ['parameters', 'typeAnnotation'], + TSInferType: ['typeParameter'], + TSInstantiationExpression: ['expression', 'typeArguments'], + TSInterfaceBody: ['body'], + TSInterfaceDeclaration: ['id', 'typeParameters', 'extends', 'body'], + TSInterfaceHeritage: ['expression', 'typeArguments'], + TSIntersectionType: ['types'], + TSLiteralType: ['literal'], + TSMappedType: ['key', 'constraint', 'nameType', 'typeAnnotation'], + TSMethodSignature: ['typeParameters', 'key', 'params', 'returnType'], + TSModuleBlock: ['body'], + TSModuleDeclaration: ['id', 'body'], + TSNamedTupleMember: ['label', 'elementType'], + TSNamespaceExportDeclaration: ['id'], + TSNonNullExpression: ['expression'], + TSOptionalType: ['typeAnnotation'], + TSParameterProperty: ['decorators', 'parameter'], + TSPropertySignature: ['typeAnnotation', 'key'], + TSQualifiedName: ['left', 'right'], + TSRestType: ['typeAnnotation'], + TSSatisfiesExpression: ['expression', 'typeAnnotation'], + TSTemplateLiteralType: ['quasis', 'types'], + TSTupleType: ['elementTypes'], + TSTypeAliasDeclaration: ['id', 'typeParameters', 'typeAnnotation'], + TSTypeAnnotation: ['typeAnnotation'], + TSTypeAssertion: ['typeAnnotation', 'expression'], + TSTypeLiteral: ['members'], + TSTypeOperator: ['typeAnnotation'], + TSTypeParameter: ['name', 'constraint', 'default'], + TSTypeParameterDeclaration: ['params'], + TSTypeParameterInstantiation: ['params'], + TSTypePredicate: ['typeAnnotation', 'parameterName'], + TSTypeQuery: ['exprName', 'typeArguments'], + TSTypeReference: ['typeName', 'typeArguments'], + TSUnionType: ['types'], + ParenthesizedExpression: ['expression'], + TSParenthesizedType: ['typeAnnotation'], +}; +export default visitorKeys; diff --git a/napi/parser/package.json b/napi/parser/package.json index b31e6e1c2f294..7707a2cdaed91 100644 --- a/napi/parser/package.json +++ b/napi/parser/package.json @@ -4,7 +4,7 @@ "main": "index.js", "browser": "wasm.mjs", "scripts": { - "build-dev": "napi build --no-dts-cache --platform --js bindings.js", + "build-dev": "node generate-visitor-keys.mjs && napi build --no-dts-cache --platform --js bindings.js", "build": "pnpm run build-dev --features allocator --release", "postbuild-dev": "node patch.mjs", "build-wasi": "pnpm run build-dev --release --target wasm32-wasip1-threads", @@ -43,6 +43,7 @@ "wasm.mjs", "bindings.js", "webcontainer-fallback.js", + "generated/visitor-keys.js", "generated/deserialize/js.js", "generated/deserialize/ts.js" ], @@ -56,6 +57,7 @@ "devDependencies": { "@codspeed/vitest-plugin": "^4.0.0", "@napi-rs/wasm-runtime": "^0.2.7", + "@typescript-eslint/visitor-keys": "^8.31.1", "@vitest/browser": "3.1.2", "esbuild": "^0.25.0", "playwright": "^1.51.0", diff --git a/napi/parser/wrap.cjs b/napi/parser/wrap.cjs index 9afac73bcc33d..5249eed50e696 100644 --- a/napi/parser/wrap.cjs +++ b/napi/parser/wrap.cjs @@ -1,6 +1,8 @@ // Note: This code is repeated in `wrap.mjs`. // Any changes should be applied in that file too. +const visitorKeys = require('./generated/visitor-keys.cjs'); + module.exports.wrap = function wrap(result) { let program, module, comments, errors; return { @@ -23,25 +25,43 @@ module.exports.wrap = function wrap(result) { }; }; -function jsonParseAst(program) { - return JSON.parse(program, transform); +function jsonParseAst(programJson) { + const program = JSON.parse(programJson); + visitNode(program, transform); + return program; } -function transform(key, value) { +function transform(node) { // Set `value` field of `Literal`s for `BigInt`s and `RegExp`s. // This is not possible to do on Rust side, as neither can be represented correctly in JSON. - if (value === null && key === 'value' && Object.hasOwn(this, 'type') && this.type === 'Literal') { - if (Object.hasOwn(this, 'bigint')) { - return BigInt(this.bigint); + if (node.type === 'Literal') { + if (node.bigint) { + node.value = BigInt(node.bigint); } - if (Object.hasOwn(this, 'regex')) { - const { regex } = this; + if (node.regex) { try { - return RegExp(regex.pattern, regex.flags); + node.value = RegExp(node.regex.pattern, node.regex.flags); } catch (_err) { // Invalid regexp, or valid regexp using syntax not supported by this version of NodeJS } } } - return value; +} + +function visitNode(node, fn) { + if (!node) return; + if (Array.isArray(node)) { + for (const el of node) { + visitNode(el, fn); + } + return; + } + + fn(node); + + const keys = visitorKeys[node.type]; + if (!keys) return; + for (const key of keys) { + visitNode(node[key], fn); + } } diff --git a/napi/parser/wrap.mjs b/napi/parser/wrap.mjs index 42230d0082dc8..d8d17b9ed1df4 100644 --- a/napi/parser/wrap.mjs +++ b/napi/parser/wrap.mjs @@ -1,6 +1,8 @@ // Note: This code is repeated in `wrap.cjs`. // Any changes should be applied in that file too. +import visitorKeys from './generated/visitor-keys.mjs'; + export function wrap(result) { let program, module, comments, errors; return { @@ -24,25 +26,43 @@ export function wrap(result) { } // Used by napi/playground/patch.mjs -export function jsonParseAst(program) { - return JSON.parse(program, transform); +export function jsonParseAst(programJson) { + const program = JSON.parse(programJson); + visitNode(program, transform); + return program; } -function transform(key, value) { +function transform(node) { // Set `value` field of `Literal`s for `BigInt`s and `RegExp`s. // This is not possible to do on Rust side, as neither can be represented correctly in JSON. - if (value === null && key === 'value' && Object.hasOwn(this, 'type') && this.type === 'Literal') { - if (Object.hasOwn(this, 'bigint')) { - return BigInt(this.bigint); + if (node.type === 'Literal') { + if (node.bigint) { + node.value = BigInt(node.bigint); } - if (Object.hasOwn(this, 'regex')) { - const { regex } = this; + if (node.regex) { try { - return RegExp(regex.pattern, regex.flags); + node.value = RegExp(node.regex.pattern, node.regex.flags); } catch (_err) { // Invalid regexp, or valid regexp using syntax not supported by this version of NodeJS } } } - return value; +} + +function visitNode(node, fn) { + if (!node) return; + if (Array.isArray(node)) { + for (const el of node) { + visitNode(el, fn); + } + return; + } + + fn(node); + + const keys = visitorKeys[node.type]; + if (!keys) return; + for (const key of keys) { + visitNode(node[key], fn); + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 341ce85a50940..652228392af3e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -91,6 +91,9 @@ importers: '@napi-rs/wasm-runtime': specifier: ^0.2.7 version: 0.2.9 + '@typescript-eslint/visitor-keys': + specifier: ^8.31.1 + version: 8.31.1 '@vitest/browser': specifier: 3.1.2 version: 3.1.2(playwright@1.52.0)(vite@6.3.4(@types/node@22.15.3))(vitest@3.1.2) @@ -1307,6 +1310,14 @@ packages: '@types/vscode@1.93.0': resolution: {integrity: sha512-kUK6jAHSR5zY8ps42xuW89NLcBpw1kOabah7yv38J8MyiYuOHxLQBi0e7zeXbQgVefDy/mZZetqEFC+Fl5eIEQ==} + '@typescript-eslint/types@8.31.1': + resolution: {integrity: sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/visitor-keys@8.31.1': + resolution: {integrity: sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typespec/ts-http-runtime@0.2.2': resolution: {integrity: sha512-Gz/Sm64+Sq/vklJu1tt9t+4R2lvnud8NbTD/ZfpZtMiUX7YeVpCA8j6NSW8ptwcoLL+NmYANwqP8DV0q/bwl2w==} engines: {node: '>=18.0.0'} @@ -1829,6 +1840,10 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -4022,6 +4037,13 @@ snapshots: '@types/vscode@1.93.0': {} + '@typescript-eslint/types@8.31.1': {} + + '@typescript-eslint/visitor-keys@8.31.1': + dependencies: + '@typescript-eslint/types': 8.31.1 + eslint-visitor-keys: 4.2.0 + '@typespec/ts-http-runtime@0.2.2': dependencies: http-proxy-agent: 7.0.2 @@ -4606,6 +4628,8 @@ snapshots: escape-string-regexp@4.0.0: {} + eslint-visitor-keys@4.2.0: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.7