UNPKG

@lcap/nasl

Version:

NetEase Application Specific Language

1,113 lines 116 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformCall2CallViewLogic = exports.transformCall2Extension = exports.transformCall2Connector = exports.transformCall2Interface = exports.transformAlert2ShowMessage = exports.transformForEach2ForEachStatement = exports.transformForOf2ForEachStatement = exports.transform2ForEachStatement = exports.transformMap2ListTransform = exports.transform2UIFunction = exports.transformCall2CallFunction = exports.transform2CallFunction = exports.transformCall2JSONFunctions = exports.transformCall2Logging = exports.transformCall2ConsoleLog = exports.transformCall2CallDataSourceLogic = exports.transformCall2CallEntityLogic = exports.transformCall2CallViewElementLogic = exports.transformCallFunctionExpression2Match = exports.transformMemberExpression = exports.transformNewExpression = exports.transform2PartialNewComposite = exports.transform2Comment = exports.transform2StringInterpolation = exports.transformReturnStatement2AssignmentOrEnd = exports.transform2NullLiteral = exports.transform2NumericLiteral = exports.transform2DirectiveLiteral = exports.transform2StringLiteral = exports.transform2BooleanLiteral = exports.transformUpdateExpression2Assignment = exports.transform2Assignment = exports.transform2AnonymousFunction = exports.transformIdentifier = exports.transformSwitchStatement2Match = exports.transform2WhileStatement = exports.transform2Break = exports.transform2Continue = exports.transform2IfStatement = exports.transform2BinaryExpression = exports.transformCallExpressionToBinaryExpression = exports.transform2Param = exports.fixLogicNode = exports.flatIfStatementForMatch = exports.flatMatchPatternsExpression = exports.getSelectMembers = exports.unflatMemberExpression = exports.flatMemberExpression = exports.fixExpression = exports.TransformManager = void 0; exports.transform2LogicItem = exports.transformCall2Paginate = exports.transformCall2LogicWithAuth = exports.transformCall2Logic = void 0; const utils_1 = require("./utils"); const transform2TypeAnnotation_1 = require("./transform2TypeAnnotation"); const utils_2 = require("../../utils"); const server_1 = __importDefault(require("../../server")); ; class TransformManager { constructor() { this.transforms = []; this.transformCallExpressions = []; } register(type, transform) { this.transforms.push([type, transform]); } registerCallExpression(type, transform) { this.transformCallExpressions.push([type, transform]); } apply(node, options) { if (node.type === 'CallExpression') { if (node.callee.type === 'CallExpression') (0, utils_1.throwError)('不支持连续调用!', node.callee); const callee = flatMemberExpression(node.callee); if (callee[0] && callee[0].type === 'CallExpression' && callee[0].callee.type === 'MemberExpression' && callee[0].callee.property.type === 'Identifier' && callee[0].callee.property.name === 'connect') { const headCallee = flatMemberExpression(callee[0].callee); callee.unshift(...headCallee.slice(0, -1)); } else { for (const calleeItem of callee) { if (calleeItem.type !== 'Identifier' && !(calleeItem.type === 'FunctionExpression' && calleeItem.id?.name === 'match')) { (0, utils_1.throwError)('不支持连续调用!', node.callee); } } } const calleeName = (0, utils_1.generate)(node.callee).code; for (const [type, transform] of this.transformCallExpressions) { if (typeof type === 'function' ? type(node, calleeName, callee) : type === calleeName) { return transform(node, calleeName, callee, options); } } (0, utils_1.throwError)(`Unhandled node ${callee.map((item) => item.name).join('.')}`, node.type, node); } else { for (const [type, transform] of this.transforms) { if (typeof type === 'function' ? type(node) : type === node.type) { return transform(node, options); } } (0, utils_1.throwError)('Unhandled node', node.type, node); } } } exports.TransformManager = TransformManager; function transformTSCode2SubLogic(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; const logic = new utils_1.naslTypes.SubLogic(); logic.name = options.transformType === 'logic' && options.logic?.getSubLogicUniqueName ? options.logic.getSubLogicUniqueName() : `subLogic_${(0, utils_2.uuidv4)().slice(0, 2)}`; logic.body = logic.body.slice(0, 1); let parameters = []; let statements = []; if (node.type === 'ArrowFunctionExpression') { parameters = node.params; const body = node.body; statements = [...body?.directives, ...body?.body]; } if (node.type === 'FunctionExpression') { parameters = node.params; statements = [...node?.body?.directives, ...node?.body?.body]; } parameters.forEach((node) => { const param = transform2Param(node); param && logic.addParam(param); }); const newStatements = []; statements.forEach((node, index) => { if (node?.leadingComments?.length) { newStatements.push(...node?.leadingComments); } if (node?.trailingComments?.length && index === statements.length - 1) { newStatements.push(...node?.trailingComments); } newStatements.push(node); }); statements = newStatements; const body = statements.map((node) => transformNodeFunction(node, { ...options, logic, })).filter((item) => !!item); body.forEach((item) => logic.addItemInBody(item.toJSON())); const lastItem = logic.body[logic.body.length - 1]; if (lastItem && lastItem.concept !== 'End') { logic.addItemInBody(new utils_1.naslTypes.End()); } if (logic.returns[0]?.name) { const index = logic.variables.findIndex((variable) => variable.name === logic.returns[0].name); if (index >= 0) logic.variables.splice(index, 1); } if (logic?.variables?.length) { const oldVariables = [...logic.variables]; logic.variables = []; oldVariables.forEach((variable) => { logic.addVariable(variable); }); } if (logic?.returns?.length) { const oldReturns = [...logic.returns]; logic.returns = []; oldReturns.forEach((ret) => { logic.addReturn(ret); }); } return logic; } function assertAssignmentRightIsNotAnonymousFunction(expression) { if (expression?.concept === 'AnonymousFunction') (0, utils_1.throwError)('Anonymous function is not allowed in assignment', expression.toNaturalTS()); return expression; } function fixExpression(arg, options, supportSubLogic = false) { let expression; if (options.transformType === 'logic' && supportSubLogic && (arg?.type === 'FunctionExpression' || (arg?.type === 'ArrowFunctionExpression'))) { if (arg?.body?.type === 'BlockStatement') { expression = transformTSCode2SubLogic(arg, options); } else { const babelReturnStatement = utils_1.babelTypes.returnStatement(arg.body); arg.body = utils_1.babelTypes.blockStatement([babelReturnStatement]); expression = transformTSCode2SubLogic(arg, options); } } else { if (arg?.body?.type === 'ReturnStatement') { arg.body = arg?.body?.argument; } const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; expression = transformNodeFunction(arg, options); if (expression?.concept === 'Identifier' && expression?.name === 'undefined') { expression = undefined; } } return expression; } exports.fixExpression = fixExpression; /** * 铺平点选表达式 */ function flatMemberExpression(node) { if (node.type === 'MemberExpression') return [...flatMemberExpression(node.object), node.property]; return [node]; } exports.flatMemberExpression = flatMemberExpression; /** * 将铺平的点选表达式列表转换回 MemberExpression */ function unflatMemberExpression(nodes, options, memberExpression, namespace) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; // 如果 nodes 为空,直接返回当前的 memberExpression if (nodes.length === 0) { return memberExpression; } let newMemberExpression = null; let remainingNodes = null; // 首次调用时,如果 namespace 存在,构建一个 MemberExpression if (namespace) { const object = nodes[0]; const property = nodes[1]; newMemberExpression = new utils_1.naslTypes.MemberExpression({ object: new utils_1.naslTypes.Identifier({ namespace, // 只有第一个 Identifier 带上 namespace name: object.name, }), property: transformNodeFunction(property, options), }); remainingNodes = nodes.slice(2); // 跳过前两个节点 } else { // 后续递归调用时,逐个添加剩余的节点 const property = nodes[0]; newMemberExpression = new utils_1.naslTypes.MemberExpression({ object: memberExpression, // 使用当前的 memberExpression 作为 object property: transformNodeFunction(property, options), }); remainingNodes = nodes.slice(1); // 跳过当前节点 } // 如果还有剩余的节点,递归处理 if (remainingNodes.length > 0) { return unflatMemberExpression(remainingNodes, options, newMemberExpression); } // 返回最终的 MemberExpression return newMemberExpression; } exports.unflatMemberExpression = unflatMemberExpression; /** * 铺平链式调用表达式 */ function flatChainCallExpression(node) { if (node.callee.type === 'MemberExpression') { if (node.callee.object.type === 'CallExpression' && node.callee.property.type === 'Identifier') return [...flatChainCallExpression(node.callee.object), utils_1.babelTypes.callExpression(node.callee.property, node.arguments)]; else if (node.callee.object.type === 'Identifier' && node.callee.property.type === 'Identifier') return [utils_1.babelTypes.callExpression(node.callee.property, node.arguments)]; } return [node]; } function getSelectMembers(node) { if (node.concept === 'MemberExpression') return [...getSelectMembers(node.object), node]; else return []; } exports.getSelectMembers = getSelectMembers; function flatMatchPatternsExpression(node) { if (node.concept === 'BinaryExpression') { if (node.operator === '||') { return [...flatMatchPatternsExpression(node.left), ...flatMatchPatternsExpression(node.right)]; } if (node.operator === '==') { return [node.right]; } return [node]; } return [node]; } exports.flatMatchPatternsExpression = flatMatchPatternsExpression; function flatIfStatementForMatch(node) { if (node.alternate.type === 'IfStatement') { return [node, ...flatIfStatementForMatch(node.alternate)]; } return [node, { type: 'IfStatement', test: null, consequent: node.alternate, alternate: node.alternate, }]; } exports.flatIfStatementForMatch = flatIfStatementForMatch; /** * 这个函数是修复 AI 翻译出错的情况,与正常的 transform 做个区分 * @param node * @returns */ function fixLogicNode(node) { if (node?.type === 'CallExpression') { const calleeName = (0, utils_1.generate)(node.callee).code; if (calleeName === 'nasl.util.ForEach') { const callee = flatMemberExpression(node.callee); node.callee = callee[2]; } } } exports.fixLogicNode = fixLogicNode; function transform2Param(node) { const exclude = ['event']; if (node.type === 'ObjectProperty') { const typeAnnotation = node?.value?.name ? utils_1.naslTypes.TypeAnnotation.createPrimitive((node?.value).name) : null; const name = node.key.name; if (exclude.includes(name)) return null; let defaultValueExpression = node.key.optional ? { type: 'NullLiteral' } : undefined; return new utils_1.naslTypes.Param({ name, typeAnnotation, defaultValue: defaultValueExpression && new utils_1.naslTypes.DefaultValue({ expression: transform2LogicItem(defaultValueExpression, { transformType: 'attr', isRestricted: true }), }), }); } else if (node.type === 'TSPropertySignature') { const typeAnnotation = node.typeAnnotation?.typeAnnotation; const name = node.key.name; if (exclude.includes(name)) return null; let defaultValueExpression = node.optional ? { type: 'NullLiteral' } : undefined; return new utils_1.naslTypes.Param({ name, typeAnnotation: typeAnnotation ? (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(typeAnnotation) : null, defaultValue: defaultValueExpression && new utils_1.naslTypes.DefaultValue({ expression: transform2LogicItem(defaultValueExpression, { transformType: 'attr', isRestricted: true }), }), }); } else if (node.type === 'Identifier') { const typeAnnotation = node.typeAnnotation?.typeAnnotation; const name = node.name; if (exclude.includes(name)) return null; let defaultValueExpression = node.optional ? { type: 'NullLiteral' } : undefined; return new utils_1.naslTypes.Param({ name, required: !node.optional, typeAnnotation: typeAnnotation ? (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(typeAnnotation) : null, defaultValue: defaultValueExpression && new utils_1.naslTypes.DefaultValue({ expression: transform2LogicItem(defaultValueExpression, { transformType: 'attr', isRestricted: true }), }), }); } else if (node.type === 'AssignmentPattern') { const identifier = node.left; const typeAnnotation = identifier.typeAnnotation?.typeAnnotation; let defaultValueExpression; if (node.type === 'AssignmentPattern') { if (node.right) defaultValueExpression = node.right; else if (identifier.optional) { defaultValueExpression = { type: 'NullLiteral' }; } } const exclude = ['event']; const name = identifier.name; if (exclude.includes(name)) return null; return new utils_1.naslTypes.Param({ name, typeAnnotation: typeAnnotation ? (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(typeAnnotation) : null, defaultValue: defaultValueExpression && new utils_1.naslTypes.DefaultValue({ expression: transform2LogicItem(defaultValueExpression, { transformType: 'attr', isRestricted: true }), }), }); } else { (0, utils_1.throwError)('Unhandled node', node); } } exports.transform2Param = transform2Param; function transformCallExpressionToBinaryExpression(node, calleeName, callee, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; const argument = node?.arguments; const map = { plus: '+', minus: '-', multiply: '*', divide: '/', remainder: '%', STARTS_WITH: 'startwith', ENDS_WITH: 'endwith', LIKE: 'like', IN: 'in', IS_NULL: 'isNull', }; if (calleeName === 'IS_NULL') { return new utils_1.naslTypes.UnaryExpression({ operator: 'isNull', argument: transformNodeFunction(argument?.[0], options), }); } return new utils_1.naslTypes.BinaryExpression({ operator: map[calleeName], left: transformNodeFunction(argument?.[0], options), right: transformNodeFunction(argument?.[1], options), }); } exports.transformCallExpressionToBinaryExpression = transformCallExpressionToBinaryExpression; function transform2BinaryExpression(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; if (node.operator === '===') node.operator = '=='; if (node.operator === '!==') node.operator = '!='; if (node.operator === '==' && node.right?.type === 'NullLiteral' && options?.inCallQueryComponentField) { return new utils_1.naslTypes.UnaryExpression({ operator: 'isNull', argument: transformNodeFunction(node.left, options), }); } if (node.operator === '!=' && node.right?.type === 'NullLiteral' && options?.inCallQueryComponentField) { return new utils_1.naslTypes.UnaryExpression({ operator: '!', argument: new utils_1.naslTypes.UnaryExpression({ operator: 'isNull', argument: transformNodeFunction(node.left, options), }), }); } if (['+', '-', '*', '/', '//', '%', '==', '!=', '>', '<', '>=', '<=', '&&', '||', 'startwith', 'endwith', 'like', 'in', 'isNull'].includes(node.operator)) { if ((node?.left?.name) === '_value' && node?.right?.type === 'BooleanLiteral') { return transformNodeFunction(node.right, options); } return new utils_1.naslTypes.BinaryExpression({ operator: node.operator, left: transformNodeFunction(node.left, options), right: transformNodeFunction(node.right, options), }); } (0, utils_1.throwError)('Unhandled node', node.type, node); } exports.transform2BinaryExpression = transform2BinaryExpression; function transformDefaultExpression(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; return transformNodeFunction(node.left, options); } function transformLogicalExpression(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; const expression = new utils_1.naslTypes.CallFunction({ calleeNamespace: 'nasl.util', calleeName: 'Convert', arguments: [ new utils_1.naslTypes.Argument({ expression: transformNodeFunction(node.left, options), }), ], typeArguments: [utils_1.naslTypes.TypeAnnotation.createPrimitive('Boolean')], }); return new utils_1.naslTypes.Match({ expression, isExpression: true, cases: [ new utils_1.naslTypes.MatchCase({ patterns: [new utils_1.naslTypes.BooleanLiteral({ value: 'true' })], body: [transformNodeFunction(node.left, options)], isMatchedTypeEnumable: true, }), new utils_1.naslTypes.MatchCase({ patterns: [transformNodeFunction(node.right, options)], body: [transformNodeFunction(node.right, options)], }), ], }); } function transformConditionalExpression(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; if (options?.inCallQueryComponentField) { const expr = (0, utils_1.generate)(node.test)?.code; const then_expr = (0, utils_1.generate)(node.consequent)?.code; const else_expr = (0, utils_1.generate)(node.alternate)?.code; (0, utils_1.throwError)(`数据查询中不支持条件表达式!${(0, utils_1.generate)(node)?.code}, 请使用 SQL函数 IF(${expr} == null, ${then_expr}, ${else_expr})`); } const test = transformNodeFunction(node.test, options); const consequent = transformNodeFunction(node.consequent, options); const alternate = transformNodeFunction(node.alternate, options); const variables = options.transformType === 'logic' ? [...options?.logic?.variables, ...options?.logic?.returns, ...options?.logic?.params] : []; const testType = variables?.find((item) => item?.name === test?.name)?.typeAnnotation; const expression = testType?.typeName === 'Boolean' || test?.concept === 'BinaryExpression' ? test : new utils_1.naslTypes.CallFunction({ calleeNamespace: 'nasl.util', calleeName: 'Convert', arguments: [ new utils_1.naslTypes.Argument({ expression: test, }), ], typeArguments: [utils_1.naslTypes.TypeAnnotation.createPrimitive('Boolean')], }); return new utils_1.naslTypes.Match({ expression, isExpression: true, cases: [ new utils_1.naslTypes.MatchCase({ patterns: [new utils_1.naslTypes.BooleanLiteral({ value: 'true' })], body: [consequent], isMatchedTypeEnumable: true, }), new utils_1.naslTypes.MatchCase({ patterns: [alternate], body: [alternate], }), ], }); } function transformArrayExpression(node, options) { let typeAnnotation = options.typeAnnotation; delete options.typeAnnotation; const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; return new utils_1.naslTypes.NewList({ typeAnnotation, items: node?.elements?.map((arg) => transformNodeFunction(arg, { ...options, typeAnnotation: undefined })), }); } function transform2NewAnonymousStructure(node, options) { const newComposite = transform2PartialNewComposite(node, options); const newProperties = node.properties.filter((prop) => prop.type === 'ObjectProperty' && prop.value.type !== 'ConditionalExpression'); const structureProperties = []; newProperties.forEach((arg, index) => { structureProperties.push(new utils_1.naslTypes.StructureProperty({ name: arg.key.name, typeAnnotation: null })); }); newComposite.typeAnnotation = utils_1.naslTypes.TypeAnnotation.createTypeAnonymousStructure(structureProperties); return newComposite; } function transform2NewStructure(namespaceAndName, objectExpression, options) { const newComposite = transform2PartialNewComposite(objectExpression, options); const arr = namespaceAndName.split('.'); newComposite.typeAnnotation = utils_1.naslTypes.TypeAnnotation.createReference(arr[arr.length - 1], { typeNamespace: arr.slice(0, -1).join('.')?.replace(/connectors\./, 'connector.'), }); return newComposite; } function transform2NewExpression(calleeName, node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; if (calleeName === 'NewList') { let typeAnnotation; if (node?.typeParameters?.params?.[0]?.typeName?.name === '__IDENTIFIER__') { typeAnnotation = undefined; } else { typeAnnotation = utils_1.naslTypes.TypeAnnotation.createGeneric('List', { typeArguments: node?.typeParameters?.params.map(transform2TypeAnnotation_1.transform2TypeAnnotation), }); } if (node?.arguments && node?.arguments?.[0]?.type !== 'ArrayExpression') { (0, utils_1.throwError)('Not allowed code in NewList', node); } return new utils_1.naslTypes.NewList({ typeAnnotation: node?.typeParameters ? typeAnnotation : undefined, items: node?.arguments?.[0]?.elements?.map((arg) => transformNodeFunction(arg, options)), }); } if (calleeName === 'NewMap') { const keys = []; const values = []; node?.arguments?.[0]?.properties?.forEach((arg) => { keys.push(transformNodeFunction(arg.key, options)); values.push(transformNodeFunction(arg.value, options)); }); let typeAnnotation; if (node?.typeParameters?.params?.[0]?.typeName?.name === '__IDENTIFIER__') { typeAnnotation = undefined; } else { typeAnnotation = utils_1.naslTypes.TypeAnnotation.createGeneric('Map', { typeArguments: node?.typeParameters?.params.map(transform2TypeAnnotation_1.transform2TypeAnnotation), }); } return new utils_1.naslTypes.NewMap({ typeAnnotation: node?.typeParameters ? typeAnnotation : undefined, keys, values, }); } if (calleeName === 'NewEntity' || calleeName === 'NewStructure') { const typeParam = node.typeParameters?.params[0]; const typeNamespaceAndName = typeParam ? (0, utils_1.generate)(typeParam).code : ''; if (!typeNamespaceAndName) (0, utils_1.throwError)('Not allowed empty namespace in NewEntity', node); return transform2NewStructure(typeNamespaceAndName, node.arguments[0], options); } if (calleeName === 'NewAnonymousStructure') { return transform2NewAnonymousStructure(node.arguments[0], options); } (0, utils_1.throwError)('Unhandled ArrowFunctionExpression node', node.type, node); } function pushElseIf(ifNode, switchStatement, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; const consequent = !ifNode?.consequent ? [] : flatCommentWithNode(ifNode.consequent); switchStatement.cases.push(new utils_1.naslTypes.SwitchCase({ test: transformNodeFunction(ifNode.test, options), consequent: transformBlockBody(consequent, options), })); if (ifNode.alternate && ifNode.alternate.type === 'IfStatement') { pushElseIf(ifNode.alternate, switchStatement, options); } else { const consequent = !ifNode?.alternate ? [] : flatCommentWithNode(ifNode.alternate); switchStatement.cases.push(new utils_1.naslTypes.SwitchCase({ test: undefined, consequent: transformBlockBody(consequent, options), })); } } function transformBlockBody(body, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; if (!body) return undefined; return body.flatMap((item) => { const logicItem = transformNodeFunction(item, options); if (!logicItem) { console.log('item in block:', item); return []; } return item?.type === 'ReturnStatement' && item?.argument && logicItem.concept !== 'End' ? [logicItem, new utils_1.naslTypes.End()] : [logicItem]; }).filter((item) => !!item); } function transform2ArrayPattern(decl, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; let logicItems = []; let getVariableNode; if (decl?.init?.type === 'Identifier') { getVariableNode = transformNodeFunction(decl.init, options); } else { getVariableNode = new utils_1.naslTypes.Identifier({ name: `temp_${(0, utils_2.uuidv4)().slice(0, 4)}`, }); logicItems.push(new utils_1.naslTypes.Assignment({ left: getVariableNode, right: transformNodeFunction(decl.init, options), })); } // 判断一下是否已存在 if (options.transformType === 'logic') { const hasVariable = options?.logic?.variables?.find((item) => item?.name === getVariableNode?.name); if (!hasVariable) { options.logic.variables.push(new utils_1.naslTypes.Variable({ name: getVariableNode.name, typeAnnotation: undefined, })); } } decl?.id?.elements?.map((element, index) => { if (element.type === 'Identifier') { const varTypeAnnotation = element.typeAnnotation?.typeAnnotation; if (options.transformType === 'logic') { options.logic.variables.push(new utils_1.naslTypes.Variable({ name: element.name, typeAnnotation: varTypeAnnotation && (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(varTypeAnnotation), })); } } const logicItem = new utils_1.naslTypes.Assignment({ left: transformNodeFunction(element, options), right: new utils_1.naslTypes.CallFunction({ calleeNamespace: 'nasl.util', calleeName: 'Get', arguments: [ new utils_1.naslTypes.Argument({ expression: getVariableNode, }), new utils_1.naslTypes.Argument({ expression: new utils_1.naslTypes.NumericLiteral({ value: String(index), }), }), ], }), }); logicItems.push(logicItem); }); return new utils_1.naslTypes.Block({ folded: false, logicItems, }); } function transform2VariableAndAddAssignment(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; const declList = node?.declarations || []; let newNode; declList.forEach((decl) => { const variableName = decl.id.name; const isArrayPattern = decl.id?.type === 'ArrayPattern'; if (isArrayPattern && decl.init) { // 取出init中的,get newNode = transform2ArrayPattern(decl, options); return newNode; } let typeAnnotation; if (options.transformType === 'logic' && ![...options.logic.variables, ...options.logic.returns].some((variable) => variable.name === variableName)) { const varTypeAnnotation = decl.id.typeAnnotation?.typeAnnotation; typeAnnotation = varTypeAnnotation && (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(varTypeAnnotation); options.logic.variables.push(new utils_1.naslTypes.Variable({ name: variableName, typeAnnotation, })); } if (decl.init) { const calleeName = (0, utils_1.generate)(decl?.init?.callee).code; const varTypeAnnotation = decl?.id?.typeAnnotation?.typeAnnotation; typeAnnotation = varTypeAnnotation && (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(varTypeAnnotation); if (calleeName === 'nasl.oql.query' && varTypeAnnotation) { decl.init.typeAnnotations = varTypeAnnotation; } options.typeAnnotation = typeAnnotation; newNode = new utils_1.naslTypes.Assignment({ left: transformNodeFunction(decl.id, options), right: assertAssignmentRightIsNotAnonymousFunction(transformNodeFunction(decl.init, { ...options, typeAnnotation })), }); } }); if (newNode) return newNode; } function flatCommentWithNode(node) { let newNodeList = []; if (node?.innerComments?.length) { newNodeList = [...node?.innerComments]; } if (node?.body?.length) { node?.body.forEach((item, index) => { if (item?.leadingComments?.length) { newNodeList.push(...item?.leadingComments); } if (item?.trailingComments?.length && index === node?.body.length - 1) { newNodeList.push(...item?.trailingComments); } newNodeList.push(item); }); } return newNodeList; } function transform2IfStatement(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; if (node.alternate && node.alternate.type === 'IfStatement') { const switchStatement = new utils_1.naslTypes.SwitchStatement({ cases: [], }); pushElseIf(node, switchStatement, options); // 如果 cases 中每一个 case 都有 End,去掉最后一个 case 的 End if (switchStatement.cases.every((caseItem) => caseItem.consequent?.[caseItem.consequent.length - 1]?.concept === 'End')) { switchStatement.cases[switchStatement.cases.length - 1].consequent.pop(); } return switchStatement; } const consequent = !node?.consequent ? [] : flatCommentWithNode(node.consequent); const alternate = !node?.alternate ? [] : flatCommentWithNode(node.alternate); const naslNode = new utils_1.naslTypes.IfStatement({ test: transformNodeFunction(node.test, options), consequent: transformBlockBody(consequent, options), alternate: transformBlockBody(alternate, options), }); // consequent 和 alternate 都有 End 就去掉一个(不然发布时java编译会报错) if (naslNode.consequent?.[naslNode.consequent.length - 1]?.concept === 'End' && naslNode.alternate?.[naslNode.alternate.length - 1]?.concept === 'End') { naslNode.alternate.pop(); } return naslNode; } exports.transform2IfStatement = transform2IfStatement; function transform2Continue() { return new utils_1.naslTypes.Continue(); } exports.transform2Continue = transform2Continue; function transform2Break() { return new utils_1.naslTypes.Break(); } exports.transform2Break = transform2Break; function transform2WhileStatement(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; const body = !node?.body ? [] : flatCommentWithNode(node.body); return new utils_1.naslTypes.WhileStatement({ test: transformNodeFunction(node.test, options), body: transformBlockBody(body, options), }); } exports.transform2WhileStatement = transform2WhileStatement; function transformSwitchStatement2Match(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; const match = new utils_1.naslTypes.Match({ expression: transformNodeFunction(node.discriminant, options), isExpression: options.transformType !== 'logic', cases: node.cases.map((_case) => new utils_1.naslTypes.MatchCase({ patterns: !_case.test ? [] : [transformNodeFunction(_case.test, options)], body: transformBlockBody(_case.consequent.filter((item) => item.type !== 'BreakStatement'), options), })), }); if (!match.cases.length || match.cases[match.cases.length - 1].patterns.length) { match.cases.push(new utils_1.naslTypes.MatchCase({ patterns: [], body: [], })); } match.cases.forEach((case_) => { if (case_.body.length && (case_.body[0].concept === 'BooleanLiteral' || case_.body[0].concept === 'StringLiteral')) { case_.isMatchedTypeEnumable = true; } if (case_.patterns.length && case_.patterns[0].concept === 'MemberExpression') { case_.isMatchedTypeEnumable = true; case_.patterns[0].object.namespace = 'app.enums'; } }); return match; } exports.transformSwitchStatement2Match = transformSwitchStatement2Match; function transformIdentifier(node, options) { if (options.transformType === 'logic' && options.entityAsNames?.includes(node.name)) { return new utils_1.naslTypes.QueryFieldExpression({ isDotStar: false, asName: undefined, entityAsName: node.name, propertyName: '', }); } const placeholderMap = ['__IDENTIFIER__', '__LEFT__', '__RIGHT__', '__RIGHT', '__LEFT', '__IDENTIFIER', 'undefined']; if (placeholderMap.includes(node.name)) { return new utils_1.naslTypes.Identifier({}); } if (node.name === '$self') { return new utils_1.naslTypes.MemberExpression({ object: new utils_1.naslTypes.Identifier({ name: 'elements', }), property: new utils_1.naslTypes.Identifier({ name: '$ce', }), }); } return new utils_1.naslTypes.Identifier({ name: node.name, }); } exports.transformIdentifier = transformIdentifier; function transform2SelectQueryFieldExpression(node, options) { let expression = node.value; let asNameNode = node.key; if (expression.type === 'Identifier') { return new utils_1.naslTypes.QueryFieldExpression({ isDotStar: true, asName: (0, utils_2.firstUpperCase)(asNameNode.name) === expression.name ? undefined : asNameNode.name, entityAsName: expression.name, propertyName: '', }); } else if (expression.type === 'MemberExpression') { return new utils_1.naslTypes.QueryFieldExpression({ isDotStar: false, asName: (0, utils_2.firstUpperCase)(asNameNode.name) === expression.property.name ? undefined : asNameNode.name, entityAsName: expression.object.name, propertyName: expression.property.name, }); } else if (expression.type === 'ObjectExpression') { // @TODO } else { (0, utils_1.throwError)('Unsupported expression type for QueryFieldExpression', expression.type, expression); } } function transform2QueryAggregateExpression(node, options) { const callExpression = node.value; let asNameNode = node.key; const arg = callExpression.arguments[0]; if (arg.type !== 'MemberExpression') { const code = (0, utils_1.generate)(arg).code; (0, utils_1.throwError)(`聚合函数的输入只能是表字段(实体.属性),但AVG(${code})中的${code}不是表字段`); } if (callExpression.arguments?.length > 1) { (0, utils_1.throwError)(`聚合函数${callExpression.callee.name}只支持一个参数`); } return new utils_1.naslTypes.QueryAggregateExpression({ asName: asNameNode.name, aggregateName: callExpression.callee.name, aggregateParam: (arg.type === 'MemberExpression' ? transformMemberExpression(arg, options) : transformIdentifier(arg, options)), }); } function transform2AnonymousFunction(node, options) { if (node.body.type === 'BlockStatement') (0, utils_1.throwError)('Anonymous function with block statement is not supported', node); const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; return new utils_1.naslTypes.AnonymousFunction({ params: node.params.map((param) => transform2Param(param)), body: transformNodeFunction(node.body, options), }); } exports.transform2AnonymousFunction = transform2AnonymousFunction; function transform2Assignment(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; if (node.operator === '+=' || node.operator === '-=') { if (options.transformType === 'logic') { return new utils_1.naslTypes.Assignment({ left: transformNodeFunction(node.left, options), right: new utils_1.naslTypes.BinaryExpression({ operator: node.operator[0], left: transformNodeFunction(node.left, options), right: transformNodeFunction(node.right, options), }), }); } return new utils_1.naslTypes.BinaryExpression({ operator: node.operator[0], left: transformNodeFunction(node.left, options), right: transformNodeFunction(node.right, options), }); } if (options.transformType !== 'logic') { return transformNodeFunction(node.right, options); } return new utils_1.naslTypes.Assignment({ left: transformNodeFunction(node.left, options), right: assertAssignmentRightIsNotAnonymousFunction(transformNodeFunction(node.right, options)), }); } exports.transform2Assignment = transform2Assignment; function transformUpdateExpression2Assignment(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; if (node.operator === '++' || node.operator === '--') { return new utils_1.naslTypes.Assignment({ left: transformNodeFunction(node.argument, options), right: new utils_1.naslTypes.BinaryExpression({ operator: node.operator[0], left: transformNodeFunction(node.argument, options), right: new utils_1.naslTypes.NumericLiteral({ value: '1', typeAnnotation: utils_1.naslTypes.TypeAnnotation.createPrimitive('Long'), }), }), }); } } exports.transformUpdateExpression2Assignment = transformUpdateExpression2Assignment; function transform2BooleanLiteral(node, options) { return new utils_1.naslTypes.BooleanLiteral({ value: String(node.value), }); } exports.transform2BooleanLiteral = transform2BooleanLiteral; function transform2StringLiteral(node, options) { return new utils_1.naslTypes.StringLiteral({ value: node.value, }); } exports.transform2StringLiteral = transform2StringLiteral; function transform2DirectiveLiteral(node, options) { return new utils_1.naslTypes.StringLiteral({ value: node.value?.value, }); } exports.transform2DirectiveLiteral = transform2DirectiveLiteral; function transform2NumericLiteral(node, options) { const value = node.extra?.raw || String(node.value); const literal = new utils_1.naslTypes.NumericLiteral({ value, typeAnnotation: utils_1.naslTypes.TypeAnnotation.createPrimitive('Integer'), }); literal.typeAnnotation.typeName = literal.changeType(value); if (options.typeAnnotation && ['Integer', 'Long', 'Decimal'].includes(options.typeAnnotation.typeName)) { literal.typeAnnotation = options.typeAnnotation; delete options.typeAnnotation; } return literal; } exports.transform2NumericLiteral = transform2NumericLiteral; function transform2NullLiteral(node, options) { return new utils_1.naslTypes.NullLiteral(); } exports.transform2NullLiteral = transform2NullLiteral; function transformReturnStatement2AssignmentOrEnd(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; if (!node.argument) { return new utils_1.naslTypes.End(); } if (options.transformType !== 'logic') return new utils_1.naslTypes.End(); const { logic } = options; const argument = node?.argument?.type === 'TSAsExpression' ? node?.argument?.expression : node?.argument; if (argument?.type === 'Identifier') { if (!logic.returns.length) { const curVariable = logic?.variables?.find((item) => item.name === argument?.name); if (curVariable) { logic.variables = logic?.variables?.filter((item) => item.name !== argument?.name); logic.addReturn(curVariable); return new utils_1.naslTypes.End(); } } } if (!logic.returns.length) { const typeAnnotation = node?.argument?.type === 'TSAsExpression' ? (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(node?.argument?.typeAnnotation) : undefined; logic.returns.push(new utils_1.naslTypes.Return({ name: 'result', typeAnnotation })); } const leftName = logic.returns[0].name; const right = assertAssignmentRightIsNotAnonymousFunction(transformNodeFunction(argument, options)); if (right.concept === 'Identifier' && right.name === leftName) { return new utils_1.naslTypes.End(); } else { return new utils_1.naslTypes.Assignment({ left: new utils_1.naslTypes.Identifier({ name: leftName }), right, }); } } exports.transformReturnStatement2AssignmentOrEnd = transformReturnStatement2AssignmentOrEnd; function transform2StringInterpolation(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; const expressions = [...node.expressions, ...node.quasis.map((element) => ({ type: 'StringLiteral', value: element.value.raw, start: element.start, end: element.end, }))]; expressions.sort((a, b) => a.start - b.start); return new utils_1.naslTypes.StringInterpolation({ expressions: expressions.map((item) => transformNodeFunction(item, options))?.filter(Boolean), }); } exports.transform2StringInterpolation = transform2StringInterpolation; function transform2Comment(node, options) { if (node.type === 'EmptyStatement') { if (node?.leadingComments) { const newValue = node?.leadingComments?.[0]?.value?.replace(/\n/g, '<br>'); return new utils_1.naslTypes.Comment({ value: String(newValue), }); } } const newValue = node?.value?.replace(/\n/g, '<br>'); return new utils_1.naslTypes.Comment({ value: String(newValue || ''), }); } exports.transform2Comment = transform2Comment; function transformBlockStatement(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; return transformNodeFunction(node?.body?.[0], options); } function transform2PartialNewComposite(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; const properties = []; const rights = []; const structureProperties = []; const assignmentLines = []; const newProperties = (node?.properties || node?.arguments?.[0]?.properties); let idx = 0; newProperties?.forEach((arg, index) => { properties.push(transformNodeFunction(arg.key, options)); const calleeName = (0, utils_1.generate)(arg.value).code; let sliceMembers = false; if (arg.value.type === 'MemberExpression') { const expression = flatMemberExpression(arg.value); let members = getSelectMembers(transformNodeFunction(arg.value, options)); if (/app\.enums\./.test(calleeName || '')) { rights.push(new utils_1.naslTypes.SelectMembers({ expression: members[0]?.object, members, })); } else if (/^(app\..+?)\.variables\.(.+)$|nasl\.auth\./.test(calleeName)) { let expression = members[0]?.object; if (!members.length) { sliceMembers = true; expression = transformNodeFunction(arg?.value, options); } rights.push(new utils_1.naslTypes.SelectMembers({ expression, members, })); } else { let expressionNode = expression[0]; if (members[0] && members[0].object.concept !== 'Identifier') { expressionNode = arg.value; members = []; } const newExpression = transformNodeFunction(expressionNode, options); if (!members.length) { sliceMembers = true; } rights.push(new utils_1.naslTypes.SelectMembers({ expression: newExpression, members, })); } if (arg?.value) { let rightIndex = [index - idx, members.length - 1]; if (sliceMembers) { rightIndex = [index - idx]; } assignmentLines.push(new utils_1.naslTypes.AssignmentLine({ leftIndex: [0, index], rightIndex, })); } } else { if (arg.value && arg.value?.name !== 'undefined') { rights.push(new utils_1.naslTypes.SelectMembers({ expression: transformNodeFunction(arg.value, options) })); if (arg?.value) { assignmentLines.push(new utils_1.naslTypes.AssignmentLine({ leftIndex: [0, index], rightIndex: [index - idx], })); } } else { idx += 1; } } structureProperties.push(new utils_1.naslTypes.StructureProperty({ name: arg?.key?.name, typeAnnotation: null })); }); return new utils_1.naslTypes.NewComposite({ typeAnnotation: utils_1.naslTypes.TypeAnnotation.createTypeAnonymousStructure(structureProperties), properties, rights, assignmentLines }); } exports.transform2PartialNewComposite = transform2PartialNewComposite; function transformNewExpression(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; const calleeName = (0, utils_1.generate)(node.callee).code; if (['Boolean', 'Integer', 'Double', 'Decimal', 'Long'].includes(calleeName)) { return transformNodeFunction(node.arguments[0], { ...options, typeAnnotation: utils_1.naslTypes.TypeAnnotation.createPrimitive(calleeName), }); } else if (calleeName.includes('.entities.') || calleeName.includes('.structures.')) { return transform2NewStructure(calleeName, node.arguments[0], options); } (0, utils_1.throwError)('Unhandled node', node.type, node); } exports.transformNewExpression = transformNewExpression; function transformMemberExpression(node, options) { const transformNodeFunction = options?.transformNodeFunction || transform2LogicItem; if (options.transformType === 'logic' && options.entityAsNames?.includes(node.object.name)) { return new utils_1.naslTypes.QueryFi