UNPKG

@getanthill/datastore

Version:

Event-Sourced Datastore

520 lines (515 loc) 19.5 kB
"use strict"; 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; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.overloadAsString = exports.defaultOperators = exports.overload = void 0; // @ts-nocheck /** * source: https://github.com/codalien/operator-overloading-js/blob/master/lib/overload.js */ const espree = __importStar(require("espree")); const escodegen = require("escodegen"); const FUNC_NAMES = { '+': '__plus', '==': '__doubleEqual', '===': '__tripleEqual', '||': '__logicalOR', '&&': '__logicalAND', '|': '__bitwiseOR', '^': '__bitwiseXOR', '&': '__bitwiseAND', '!=': '__notEqual', '!==': '__notDoubleEqual', '<': '__lessThan', '>': '__greaterThan', '<=': '__lessThanEqual', '>=': '__greaterThanEqual', in: '__in', instanceof: '__instanceOf', '<<': '__bitwiseLSHIFT', '>>': '__bitwiseRSHIFT', '>>>': '__zeroFillRSHIFT', '-': '__minus', '*': '__multiply', '%': '__modulus', '/': '__divide', 'u-': '__unaryNegation', 'u+': '__unaryAddition', '~': '__bitwiseNOT', '++': '__increment', '--': '__decrement', '!': '__unaryNOT', '+=': '__addAssign', '-=': '__minusAssign', '*=': '__multiplyAssign', '/=': '__divideAssign', '%=': '__modulusAssign', '<<=': '__leftShiftAssign', '>>=': '__rightShiftAssign', '>>>=': '__zeroFillRightShiftAssign', '&=': '__andAssign', '|=': '__orAssign', '^=': '__xorAssign', }; //The AST Walker And Transformer function visit(statement, index, program, client) { switch (statement.type) { case 'VariableDeclaration': statement.declarations.forEach(function (declaration, idx) { visit(declaration.init, idx, program, client); }); break; case 'BinaryExpression': case 'LogicalExpression': if (statement.operator && FUNC_NAMES[statement.operator]) { statement.type = 'CallExpression'; statement.callee = { type: 'MemberExpression', computed: false, object: statement.right, property: { type: 'Identifier', name: FUNC_NAMES[statement.operator], }, }; visit(statement.left, index, program, client); visit(statement.right, index, program, client); statement['arguments'] = [statement.left]; } else { visit(statement.left, index, program, client); visit(statement.right, index, program, client); } break; case 'ExpressionStatement': visit(statement.expression, index, program, client); break; case 'CallExpression': statement['arguments'].forEach(function (argument, idx) { visit(argument, idx, program, client); }); visit(statement.callee, index, program, client); if (statement.callee.type === 'Identifier') { statement.callee = { type: 'MemberExpression', computed: false, object: statement.callee, property: { type: 'Identifier', name: 'call' }, }; statement.arguments = [ { type: 'ThisExpression' }, ...statement.arguments, ]; } break; case 'AssignmentExpression': if (statement.operator && FUNC_NAMES[statement.operator]) { statement.right = { type: 'CallExpression', callee: { type: 'MemberExpression', computed: false, object: statement.left, property: { type: 'Identifier', name: FUNC_NAMES[statement.operator], }, }, arguments: [statement.right], }; statement.operator = '='; visit(statement.left, index, program, client); visit(statement.right.arguments[0], index, program, client); } else { visit(statement.right, index, program, client); } break; case 'UnaryExpression': if (statement.operator && FUNC_NAMES[statement.operator]) { statement.type = 'CallExpression'; statement.callee = { type: 'MemberExpression', computed: false, object: statement.argument, property: { type: 'Identifier', name: statement.operator === '+' || statement.operator === '-' ? FUNC_NAMES['u' + statement.operator] : FUNC_NAMES[statement.operator], }, }; visit(statement.argument, index, program, client); statement['arguments'] = []; } else { visit(statement.argument, index, program, client); } break; case 'UpdateExpression': if (statement.operator && FUNC_NAMES[statement.operator]) { statement.type = 'CallExpression'; statement.callee = { type: 'MemberExpression', computed: false, object: statement.argument, property: { type: 'Identifier', name: FUNC_NAMES[statement.operator], }, }; visit(statement.argument, index, program, client); statement['arguments'] = []; } break; case 'FunctionDeclaration': case 'FunctionExpression': visit(statement.body, index, program, client); break; case 'BlockStatement': statement.body.forEach(function (statement) { visit(statement, index, program, client); }); break; case 'ReturnStatement': visit(statement.argument, index, program, client); break; case 'MemberExpression': visit(statement.object, index, program, client); break; case 'SwitchStatement': statement.cases.forEach(function (_case, idx) { visit(_case, idx, program, client); }); break; case 'SwitchCase': statement.consequent.forEach(function (con, idx) { visit(con, idx, program, client); }); break; case 'Literal': break; statement.type = 'NewExpression'; statement.callee = { type: 'MemberExpression', computed: false, object: { type: 'ThisExpression' }, //property: { type: 'Identifier', name: 'HEValue' }, property: { type: 'Identifier', name: 'HEValue' }, }; statement.arguments = [ { type: 'ThisExpression' }, { type: 'CallExpression', callee: { type: 'MemberExpression', computed: false, object: { type: 'ThisExpression' }, property: { type: 'Identifier', name: 'createCypher' }, }, arguments: [ { type: 'Literal', value: statement.value, raw: `${statement.value}`, }, ], }, ]; break; //We don't need to transform following nodes! Phew! case 'Identifier': case 'ThisExpression': case 'NewExpression': case 'AwaitExpression': break; } } //Do the magic function overload(func, client) { //Generate AST const ast = espree.parse('let fn = ' + func, { ecmaVersion: 11 }); //Check for AST if (!ast) throw new Error('Invalid code block! Cannot overload. AST Generation Error.'); //Fetch arguments var args = ast.body[0].declarations[0].init.params.reduce(function (init, val) { init.push(val.name); return init; }, []); //Fetch function body var body = ast.body[0].declarations[0].init.body; //Build the desired program var program = { type: 'Program', body: body.body, }; //Transform program.body.forEach(function (statement, index) { visit(statement, index, program, client); }); //Build new function args args.push(escodegen.generate(program, { comment: true, format: { indent: { style: ' ', }, }, })); const AsyncFunction = Object.getPrototypeOf(async function () { }).constructor; var retFn = AsyncFunction(...args); if (process.env.OVERLOAD_DEBUG) console.log(JSON.stringify(program, null, 4)); if (process.env.OVERLOAD_DEBUG) console.log(retFn.toString()); return retFn; } exports.overload = overload; function defaultOperators(client, constructors = [Object, Number, String, Function, RegExp]) { function defineDefaultProp(constructor, name, val) { Object.defineProperty(constructor.prototype, name, { enumerable: false, writable: true, configurable: false, value: val, }); } const mapValue = (value) => { if (typeof value === 'number' || value instanceof Number) { const cipher = client.createCypher(Array(client.polyModulusDegree).fill(value)); client.addInstance(cipher); return cipher; } if (typeof value === 'string' || value instanceof String) { const cipher = client.seal.CipherText(); cipher.load(client.context, value.toString()); client.addInstance(cipher); return cipher; } return value; }; constructors.forEach(function (constructor) { defineDefaultProp(constructor, FUNC_NAMES['+'], function (left) { // Map entry const _left = mapValue(left); const _right = mapValue(this); // Perform the operation const resultCipher = client.relinearize(client.evaluator.add(_left, _right)); return resultCipher; // Save const result = resultCipher.save(); return result; }); defineDefaultProp(constructor, FUNC_NAMES['=='], function (left) { return left == this; }); defineDefaultProp(constructor, FUNC_NAMES['==='], function (left) { return left === this; }); defineDefaultProp(constructor, FUNC_NAMES['||'], function (left) { return left || this; }); defineDefaultProp(constructor, FUNC_NAMES['&&'], function (left) { return left && this; }); defineDefaultProp(constructor, FUNC_NAMES['&'], function (left) { return left & this; }); defineDefaultProp(constructor, FUNC_NAMES['|'], function (left) { return left | this; }); defineDefaultProp(constructor, FUNC_NAMES['^'], function (left) { return left ^ this; }); defineDefaultProp(constructor, FUNC_NAMES['!='], function (left) { return left != this; }); defineDefaultProp(constructor, FUNC_NAMES['!=='], function (left) { return left !== this; }); defineDefaultProp(constructor, FUNC_NAMES['<'], function (left) { return left < this; }); defineDefaultProp(constructor, FUNC_NAMES['>'], function (left) { return left > this; }); defineDefaultProp(constructor, FUNC_NAMES['>>'], function (left) { return left >> this; }); defineDefaultProp(constructor, FUNC_NAMES['<<'], function (left) { return left << this; }); defineDefaultProp(constructor, FUNC_NAMES['>>>'], function (left) { return left >>> this; }); defineDefaultProp(constructor, FUNC_NAMES['<='], function (left) { return left <= this; }); defineDefaultProp(constructor, FUNC_NAMES['>='], function (left) { return left >= this; }); defineDefaultProp(constructor, FUNC_NAMES['in'], function (left) { return left in this; }); defineDefaultProp(constructor, FUNC_NAMES['instanceof'], function (left) { return left instanceof this; }); defineDefaultProp(constructor, FUNC_NAMES['-'], function (left) { // Map entry const _left = mapValue(left); const _right = mapValue(this); // Perform the operation const resultCipher = client.relinearize(client.evaluator.sub(_left, _right)); return resultCipher; // Save const result = resultCipher.save(); return result; }); defineDefaultProp(constructor, FUNC_NAMES['*'], function (left) { // Map entry const _left = mapValue(left); const _right = mapValue(this); // Perform the operation const resultCipher = client.relinearize(client.evaluator.multiply(_left, _right)); return resultCipher; // Save const result = resultCipher.save(); return result; }); defineDefaultProp(constructor, FUNC_NAMES['%'], function (left) { return left % this; }); defineDefaultProp(constructor, FUNC_NAMES['/'], function (left) { return left / this; }); defineDefaultProp(constructor, FUNC_NAMES['u-'], function () { const _right = mapValue(this); // Perform the operation const resultCipher = client.relinearize(client.evaluator.negate(_right)); return resultCipher; // Save const result = resultCipher.save(); return result; }); defineDefaultProp(constructor, FUNC_NAMES['u+'], function () { return +this; }); defineDefaultProp(constructor, FUNC_NAMES['~'], function () { return ~this; }); defineDefaultProp(constructor, FUNC_NAMES['++'], function () { var val = this; ++val; return val; }); defineDefaultProp(constructor, FUNC_NAMES['--'], function () { var val = this; --val; return val; }); defineDefaultProp(constructor, FUNC_NAMES['!'], function () { return !this; }); defineDefaultProp(constructor, FUNC_NAMES['+='], function (left) { // Map entry const _left = mapValue(left); const _right = mapValue(this); // Perform the operation const resultCipher = client.relinearize(client.evaluator.add(_left, _right)); return resultCipher; // Save const result = resultCipher.save(); return result; return (left += this); }); defineDefaultProp(constructor, FUNC_NAMES['-='], function (left) { // Map entry const _left = mapValue(left); const _right = mapValue(this); // Perform the operation const resultCipher = client.relinearize(client.evaluator.sub(_right, _left)); return resultCipher; // Save const result = resultCipher.save(); return result; return (left -= this); }); defineDefaultProp(constructor, FUNC_NAMES['*='], function (left) { // Map entry const _left = mapValue(left); const _right = mapValue(this); // Perform the operation const resultCipher = client.relinearize(client.evaluator.multiply(_left, _right)); return resultCipher; // Save const result = resultCipher.save(); return result; return (left *= this); }); defineDefaultProp(constructor, FUNC_NAMES['/='], function (left) { return (left /= this); }); defineDefaultProp(constructor, FUNC_NAMES['%='], function (left) { return (left %= this); }); defineDefaultProp(constructor, FUNC_NAMES['<<='], function (left) { return (left <<= this); }); defineDefaultProp(constructor, FUNC_NAMES['>>='], function (left) { return (left >>= this); }); defineDefaultProp(constructor, FUNC_NAMES['>>>='], function (left) { return (left >>>= this); }); defineDefaultProp(constructor, FUNC_NAMES['&='], function (left) { return (left &= this); }); defineDefaultProp(constructor, FUNC_NAMES['|='], function (left) { return (left |= this); }); defineDefaultProp(constructor, FUNC_NAMES['^='], function (left) { return (left ^= this); }); }); } exports.defaultOperators = defaultOperators; function overloadAsString(func, args, client) { const overloadedFunc = overload(func, client); const rawScript = ` const FUNC_NAMES = ${JSON.stringify(FUNC_NAMES)}; ${defaultOperators.toString()}; // Standard constructors overload: defaultOperators(client); // Arguments constructors overload: defaultOperators(client, args.map((arg) => !!arg ? arg.constructor : Object)); ${overloadedFunc.toString()}; anonymous.call(client, ${Array(args.length) .fill(1) .map((v, i) => `args[${i}]`) .join(', ')}).then((res) => resolve(res));`; return rawScript; } exports.overloadAsString = overloadAsString; //# sourceMappingURL=operator-overload.js.map