@jsonjoy.com/json-expression
Version:
High-performance JSON Pointer implementation
279 lines (278 loc) • 9.73 kB
JavaScript
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);
},
],
];
;