UNPKG

@jsonjoy.com/json-expression

Version:

High-performance JSON Pointer implementation

279 lines (278 loc) 9.73 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.arrayOperators = exports.clone = void 0; const tslib_1 = require("tslib"); const util = tslib_1.__importStar(require("../util")); const codegen_steps_1 = require("../codegen-steps"); const deepEqualCodegen_1 = require("@jsonjoy.com/util/lib/json-equal/deepEqualCodegen"); const { isArray } = Array; const objectKeys = Object.keys; /** * Creates a deep clone of any JSON-like object. * * @param obj Any plain POJO object. * @returns A deep copy of the object. */ const clone = (obj) => { if (!obj) return obj; if (isArray(obj)) { const arr = []; const length = obj.length; for (let i = 0; i < length; i++) arr.push((0, exports.clone)(obj[i])); return arr; } else if (typeof obj === 'object') { const keys = objectKeys(obj); const length = keys.length; const newObject = {}; for (let i = 0; i < length; i++) { const key = keys[i]; newObject[key] = (0, exports.clone)(obj[key]); } return newObject; } return obj; }; exports.clone = clone; const createSubExpressionOperator = (name, fn) => { return [ name, [], 3, (expr, ctx) => { const arr = util.asArr(ctx.eval(expr[1], ctx)); const varname = util.asStr(util.asLiteral(expr[2])); const expression = expr[3]; const run = () => ctx.eval(expression, ctx); return fn(arr, varname, ctx.vars, run); }, (ctx) => { ctx.link(util.asArr, 'asArr'); ctx.link(fn, name); const varname = util.asStr(util.asLiteral(ctx.expr[2])); const d = ctx.link(ctx.subExpression(ctx.expr[3])); const operand1 = ctx.operands[0]; const arr = operand1 instanceof codegen_steps_1.Literal && operand1.val instanceof Array ? JSON.stringify(operand1.val) : `asArr(${operand1})`; const js = `${name}(${arr},${JSON.stringify(varname)},vars,function(){return ${d}(vars)})`; return new codegen_steps_1.Expression(js); }, ]; }; exports.arrayOperators = [ [ 'concat', ['++'], -1, (expr, ctx) => { const arrays = expr.slice(1).map((e) => ctx.eval(e, ctx)); return util.concat(arrays); }, (ctx) => { ctx.link(util.concat, 'concat'); const js = `concat([(${ctx.operands.join('),(')})])`; return new codegen_steps_1.Expression(js); }, ], [ 'push', [], -1, (expr, ctx) => { const operand1 = ctx.eval(expr[1], ctx); const arr = (0, exports.clone)(util.asArr(operand1)); for (let i = 2; i < expr.length; i++) arr.push(ctx.eval(expr[i], ctx)); return arr; }, (ctx) => { const arrOperand = ctx.operands[0]; let arr; if (arrOperand instanceof codegen_steps_1.Literal) { arr = new codegen_steps_1.Literal((0, exports.clone)(util.asArr(arrOperand.val))); } else { ctx.link(util.asArr, 'asArr'); arr = new codegen_steps_1.Expression(`asArr(${arrOperand})`); } const rArr = ctx.var('' + arr); const pushes = []; for (let i = 1; i < ctx.operands.length; i++) { const operand = ctx.operands[i]; pushes.push(`(${rArr}.push(${operand}))`); } return new codegen_steps_1.Expression(`(${pushes.join(',')},${rArr})`); }, ], [ 'head', [], 2, (expr, ctx) => { const operand1 = ctx.eval(expr[1], ctx); const operand2 = ctx.eval(expr[2], ctx); return util.head(operand1, operand2); }, (ctx) => { ctx.link(util.head, 'head'); const js = `head((${ctx.operands[0]}),(${ctx.operands[1]}))`; return new codegen_steps_1.Expression(js); }, ], [ 'sort', [], 1, (expr, ctx) => { const operand1 = ctx.eval(expr[1], ctx); const arr = util.asArr(operand1); /** @todo use `.toSorted()`, once it is more common. */ return [...arr].sort(); }, (ctx) => { ctx.link(util.asArr, 'asArr'); const js = `[...asArr(${ctx.operands[0]})].sort()`; return new codegen_steps_1.Expression(js); }, ], [ 'reverse', [], 1, (expr, ctx) => { const operand1 = ctx.eval(expr[1], ctx); const arr = util.asArr(operand1); /** @todo use `.toReversed()`, once it is more common. */ return [...arr].reverse(); }, (ctx) => { ctx.link(util.asArr, 'asArr'); const js = `[...asArr(${ctx.operands[0]})].reverse()`; return new codegen_steps_1.Expression(js); }, ], [ 'in', [], 2, (expr, ctx) => { const arr = ctx.eval(expr[1], ctx); const val = ctx.eval(expr[2], ctx); return util.isInArr(arr, val); }, (ctx) => { const arr = ctx.operands[0]; const val = ctx.operands[1]; if (val instanceof codegen_steps_1.Literal) { const fnJs = (0, deepEqualCodegen_1.deepEqualCodegen)(val.val); const d = ctx.const(fnJs); ctx.link(util.isInArr2, 'isInArr2'); const js = `isInArr2((${ctx.operands[0]}),${d})`; return new codegen_steps_1.Expression(js); } ctx.link(util.isInArr, 'isInArr'); const js = `isInArr((${ctx.operands[0]}),(${ctx.operands[1]}))`; return new codegen_steps_1.Expression(js); }, ], [ 'fromEntries', [], 1, (expr, ctx) => { const operand1 = ctx.eval(expr[1], ctx); return util.fromEntries(operand1); }, (ctx) => { ctx.link(util.fromEntries, 'fromEntries'); const js = `fromEntries(${ctx.operands[0]})`; return new codegen_steps_1.Expression(js); }, ], [ 'indexOf', [], 2, (expr, ctx) => { const operand1 = ctx.eval(expr[1], ctx); const operand2 = ctx.eval(expr[2], ctx); return util.indexOf(operand1, operand2); }, (ctx) => { const val = ctx.operands[1]; if (val instanceof codegen_steps_1.Literal) { const fnJs = (0, deepEqualCodegen_1.deepEqualCodegen)(val.val); const d = ctx.const(fnJs); ctx.link(util.indexOf2, 'indexOf2'); const js = `indexOf2((${ctx.operands[0]}),${d})`; return new codegen_steps_1.Expression(js); } ctx.link(util.indexOf, 'indexOf'); const js = `indexOf((${ctx.operands[0]}),(${ctx.operands[1]}))`; return new codegen_steps_1.Expression(js); }, ], [ 'slice', [], 3, (expr, ctx) => { const operand1 = util.asArr(ctx.eval(expr[1], ctx)); const operand2 = util.int(ctx.eval(expr[2], ctx)); const operand3 = util.int(ctx.eval(expr[3], ctx)); return operand1.slice(operand2, operand3); }, (ctx) => { ctx.link(util.asArr, 'asArr'); const js = `asArr(${ctx.operands[0]}).slice((${ctx.operands[1]}),(${ctx.operands[2]}))`; return new codegen_steps_1.Expression(js); }, ], [ 'zip', [], 2, (expr, ctx) => { const operand1 = ctx.eval(expr[1], ctx); const operand2 = ctx.eval(expr[2], ctx); return util.zip(operand1, operand2); }, (ctx) => { ctx.link(util.zip, 'zip'); const js = `zip((${ctx.operands[0]}),(${ctx.operands[1]}))`; return new codegen_steps_1.Expression(js); }, ], createSubExpressionOperator('filter', util.filter), createSubExpressionOperator('map', util.map), [ 'reduce', [], 5, (expr, ctx) => { const arr = util.asArr(ctx.eval(expr[1], ctx)); const initialValue = ctx.eval(expr[2], ctx); const accname = util.asStr(util.asLiteral(expr[3])); const varname = util.asStr(util.asLiteral(expr[4])); const expression = expr[5]; const run = () => ctx.eval(expression, ctx); return util.reduce(arr, initialValue, accname, varname, ctx.vars, run); }, (ctx) => { ctx.link(util.asArr, 'asArr'); ctx.link(util.reduce, 'reduce'); const accname = util.asStr(util.asLiteral(ctx.expr[3])); const varname = util.asStr(util.asLiteral(ctx.expr[4])); const d = ctx.link(ctx.subExpression(ctx.expr[5])); const operand1 = ctx.operands[0]; const arr = operand1 instanceof codegen_steps_1.Literal && operand1.val instanceof Array ? JSON.stringify(operand1.val) : `asArr(${operand1})`; const js = `reduce((${arr}),(${ctx.operands[1]}),${JSON.stringify(accname)},${JSON.stringify(varname)},vars,function(){return ${d}(vars)})`; return new codegen_steps_1.Expression(js); }, ], ];