@lcap/nasl
Version:
NetEase Application Specific Language
407 lines • 13.8 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.pickDecoratorObject = exports.checkOQLCalleeNameOrder = exports.fetchFromComments = exports.handleListSort = exports.upgradeListSort = exports.replaceCallFunctionMap = exports.callFunctionMap = exports.tryParseTS = exports.throwWarning = exports.throwError = exports.ParseNaturalTSError = exports.parseNaturalTSErrorMap = exports.DEBUG = exports.generate = exports.naslTypes = exports.babelTypes = void 0;
const babel = __importStar(require("@babel/core"));
const babelTypes = __importStar(require("@babel/types"));
exports.babelTypes = babelTypes;
const naslTypes = __importStar(require("../../concepts"));
exports.naslTypes = naslTypes;
const generator_1 = __importDefault(require("@babel/generator"));
exports.generate = generator_1.default;
// Dynamic DEBUG function to allow runtime environment variable changes
function DEBUG() {
return process.env.NATURAL_TS_THROW_ERROR === 'true';
}
exports.DEBUG = DEBUG;
exports.parseNaturalTSErrorMap = {};
class ParseNaturalTSError extends Error {
constructor(message) {
super(message);
this.name = 'ParseNaturalTSError';
}
}
exports.ParseNaturalTSError = ParseNaturalTSError;
/**
* 抛出错误
* @param message 错误信息
* @param babelNode babel节点,用于便捷生成代码片段信息
* @param babelNode2 babel节点,用于便捷生成代码片段信息
*/
function throwError(state, message, babelNode, babelNode2) {
if (state.nodeNamespace) {
let namespaceAndName = `${state.nodeNamespace}.${state.nodeName ? state.nodeName : '*'}`;
if (state.nodeName && state.appendExtName) {
namespaceAndName += state.nodeNamespace.includes('.views.') ? '.tsx' : '.ts';
}
message += '\n**可能的位置**: ' + namespaceAndName;
}
if (babelNode) {
let code = typeof babelNode === 'string' ? babelNode : (0, generator_1.default)(babelNode).code;
message += '\n**相关代码片段**: ' + code.slice(0, 1000);
}
if (babelNode2) {
let code = typeof babelNode2 === 'string' ? babelNode2 : (0, generator_1.default)(babelNode2).code;
message += '\n**更多代码片段**: ' + code.slice(0, 1000);
}
if (!state.parsingId) {
throw new ParseNaturalTSError(message);
}
else {
const keys = Object.keys(exports.parseNaturalTSErrorMap).map(Number).sort();
keys.forEach((key) => {
if (state.parsingId - key > 1000 * 60 * 60)
delete exports.parseNaturalTSErrorMap[key];
});
const errors = exports.parseNaturalTSErrorMap[state.parsingId] = exports.parseNaturalTSErrorMap[state.parsingId] || [];
errors.push(message);
}
}
exports.throwError = throwError;
/**
* 抛出警告,在 DEBUG 模式下不抛出这类错误
* @param message 错误信息
* @param babelNode babel节点,用于便捷生成代码片段信息
* @param babelNode2 babel节点,用于便捷生成代码片段信息
*/
function throwWarning(message, babelNode, babelNode2) {
if (DEBUG())
return;
if (babelNode) {
let code = typeof babelNode === 'string' ? babelNode : (0, generator_1.default)(babelNode).code;
message += ':' + code.slice(0, 1000);
}
if (babelNode2) {
let code = typeof babelNode2 === 'string' ? babelNode2 : (0, generator_1.default)(babelNode2).code;
message += '\n' + code.slice(0, 1000);
}
throw new Error(message);
}
exports.throwWarning = throwWarning;
function tryParseTS(tsCode) {
try {
const root = babel.parseSync(tsCode, {
filename: 'result.ts',
presets: [require('@babel/preset-typescript')],
});
// console.log((root as any).program.body[0].body.body.map((item) => item.trailingComments));
return root;
}
catch (e) {
return null;
}
}
exports.tryParseTS = tryParseTS;
exports.callFunctionMap = [
'Convert',
'FormatNumber',
'FormatDateTime',
'FormatDate',
'FromString',
'ToString',
'Length',
'IndexOf',
'Join',
'LastIndexOf',
'Replace',
'Split',
'SubString',
'ToLower',
'ToUpper',
'Trim',
'CurrDate',
'CurrDateTime',
'CurrTime',
'DateDiff',
'AlterDateTime',
'GetDateCount',
'GetSpecificDaysOfWeek',
'ListAdd',
'ListAddAll',
'ListContains',
'ListInsert',
'ListDistinct',
'ListDistinctBy',
'ListFilter',
'ListFind',
'ListFindIndex',
'ListFlatten',
'ListGroupBy',
'ListHead',
'ListLast',
'ListMax',
'ListMin',
'ListReverse',
'ListSlice',
'ListSort',
'ListSum',
'ListToMap',
'ListTransform',
'ListGet',
'ListRemove',
'ListRemoveAt',
'ListSet',
'ListRange',
'ListRepeat',
'MapContains',
'MapGet',
'MapPut',
'MapKeys',
'MapRemove',
'MapValues',
'EnumToList',
'EnumItemToText',
'Round',
'Clear',
'Clone',
'HasValue',
'RandomInt',
'NewList',
'NewMap',
'NewEntity',
'NewStructure',
'NewAnonymousStructure',
'jsonSerialize',
'jsonDeserialize',
"Add",
"AddAll",
"Contains",
"Insert",
"Get",
"Remove",
"RemoveAt",
"Set",
"Ceil",
"Floor",
"Trunc",
"TruncDivide",
"Abs",
"Pow",
"Sqrt",
"Cbrt",
"Log",
"PadStart",
"PadEnd",
"TrimStart",
"TrimEnd",
];
exports.replaceCallFunctionMap = {
"ListAdd": "Add",
"ListAddAll": "AddAll",
"ListContains": "Contains",
"ListInsert": "Insert",
"ListGet": "Get",
"ListRemove": "Remove",
"ListRemoveAt": "RemoveAt",
"ListSet": "Set",
"COUNTD": "COUNT",
};
function upgradeListSort(node) {
const asc = node?.arguments?.[2]?.expression;
const by = node?.arguments?.[1]?.expression;
const newArgument = [
{
...node.arguments[0]
},
{
concept: 'Argument',
keyword: 'fn1',
expression: {
concept: 'AnonymousFunction',
body: {
concept: 'NewComposite',
typeAnnotation: {
concept: 'TypeAnnotation',
typeKind: 'anonymousStructure',
properties: [
{
concept: 'StructureProperty',
name: 'asc',
typeAnnotation: {
concept: 'TypeAnnotation',
typeKind: 'primitive',
typeNamespace: 'nasl.core',
typeName: 'Boolean'
}
},
{
concept: 'StructureProperty',
name: 'by',
typeAnnotation: null
}
]
},
properties: [
{
concept: 'Identifier',
name: 'asc',
folded: false,
typeAnnotation: null
},
{
concept: 'Identifier',
name: 'by',
folded: false,
typeAnnotation: null
}
],
rights: [
{
concept: 'SelectMembers',
hideMembers: false,
expression: asc,
members: []
}
],
assignmentLines: [
{
concept: 'AssignmentLine',
leftIndex: [0, 0],
rightIndex: [0]
}
]
},
params: by?.params
}
}
];
if (by?.body) {
newArgument[1].expression.body.rights.push({
concept: 'SelectMembers',
hideMembers: false,
expression: by.body,
members: []
});
newArgument[1].expression.body.assignmentLines.push({
concept: 'AssignmentLine',
leftIndex: [0, 1],
rightIndex: [1]
});
}
node.arguments = newArgument;
return node;
}
exports.upgradeListSort = upgradeListSort;
function handleListSort(node, parseState) {
const args = node?.arguments;
if (args?.[args?.length - 1]?.expression?.concept === 'BooleanLiteral') {
if (DEBUG)
return throwError(parseState, '调用 ListSort 函数需要使用最新的写法');
// 老的 ListSort 结构'nasl.util.ListSort(variable1, (item) => item, true)',要升级成新的
return upgradeListSort(node);
}
else {
args?.forEach((arg, index) => {
// 新的 ListSort: nasl.util.ListSort(list, (item) => ({ asc: true, by: item.name}))
if (index !== 0) {
const argExpression = arg?.expression;
if (argExpression?.concept === 'AnonymousFunction' && argExpression?.body?.concept === 'NewComposite') {
// 做下特殊处理
if (argExpression?.body?.rights[1] && argExpression?.body?.rights[1]?.members[0]) {
argExpression.body.rights[1].expression = argExpression?.body?.rights[1]?.members[0];
argExpression.body.rights[1].members = [];
argExpression.body.assignmentLines[1].rightIndex = [1];
}
if (!argExpression?.params?.length) {
argExpression.params = [
{
concept: 'Param',
name: 'item',
typeAnnotation: null
}
];
}
}
}
});
return node;
}
}
exports.handleListSort = handleListSort;
function fetchFromComments(comments) {
if (!comments || comments.length === 0)
return;
return comments[0].value.trim();
}
exports.fetchFromComments = fetchFromComments;
const expectedOrder = [
"FROM",
"JOIN",
"WHERE",
"GROUP_BY",
"SELECT",
"HAVING",
"ORDER_BY",
];
function checkOQLCalleeNameOrder(calleeNames) {
let currentIndex = -1;
for (const name of calleeNames) {
const expectedIndex = expectedOrder.findIndex((item) => name?.includes(item));
if (expectedIndex === -1) {
// 如果名称不在期望顺序中,返回 false
return false;
}
if (expectedIndex < currentIndex) {
// 如果当前名称的索引小于前一个名称的索引,返回 false
return false;
}
currentIndex = expectedIndex;
}
return true;
}
exports.checkOQLCalleeNameOrder = checkOQLCalleeNameOrder;
function pickDecoratorObject(objectExpression, keys, parseState) {
const result = {};
objectExpression.properties.forEach((item) => {
if (item.type === 'ObjectProperty' && item.key.type === 'Identifier' && keys.has(item.key.name)) {
let value;
if (item.value.type === 'NullLiteral') {
value = null;
}
else if (item.value.type === 'BooleanLiteral') {
value = item.value.value;
}
else if (item.value.type === 'StringLiteral') {
value = item.value.value;
}
else if (item.value.type === 'NumericLiteral') {
value = item.value.value;
}
else {
return throwError(parseState, '不支持的装饰器对象属性值:' + (0, generator_1.default)(item).code);
}
result[item.key.name] = value;
}
else {
return throwError(parseState, '不支持的装饰器对象属性:' + (0, generator_1.default)(item).code);
}
});
return result;
}
exports.pickDecoratorObject = pickDecoratorObject;
//# sourceMappingURL=utils.js.map