diff --git a/packages/sandbox/src/sandbox.js b/packages/sandbox/src/sandbox.js index 2137e6c..daffdee 100644 --- a/packages/sandbox/src/sandbox.js +++ b/packages/sandbox/src/sandbox.js @@ -51,12 +51,53 @@ export default class Sandbox { } evaluateAssignmentExpression(node) { - const {left, right} = node; + const {operator, left, right} = node; const scope = this.nodeScope(node); const {Vasync, value} = this.evaluate(right); if (!types.isMemberExpression(left)) { const assign = (value) => { - scope.set(left.name, value); + switch (operator) { + case '=': + return scope.set(left.name, value); + case '+=': + return scope.set(left.name, scope.get(left.name) + value); + case '-=': + return scope.set(left.name, scope.get(left.name) - value); + case '*=': + return scope.set(left.name, scope.get(left.name) * value); + case '/=': + return scope.set(left.name, scope.get(left.name) / value); + case '%=': + return scope.set(left.name, scope.get(left.name) % value); + case '**=': + return scope.set(left.name, scope.get(left.name) ** value); + /* eslint-disable no-bitwise */ + case '<<=': + return scope.set(left.name, scope.get(left.name) << value); + case '>>=': + return scope.set(left.name, scope.get(left.name) >> value); + case '>>>=': + return scope.set(left.name, scope.get(left.name) >>> value); + case '|=': + return scope.set(left.name, scope.get(left.name) | value); + case '^=': + return scope.set(left.name, scope.get(left.name) ^ value); + case '&=': + return scope.set(left.name, scope.get(left.name) & value); + /* eslint-enable no-bitwise */ + case '||=': + return scope.set(left.name, scope.get(left.name) || value); + case '&&=': + return scope.set(left.name, scope.get(left.name) && value); + case '??=': { + const l = scope.get(left.name); + return scope.set(left.name, (l === null || l === undefined) ? value : l); + } + default: + // eslint-disable-next-line no-console + console.error("evaluateAssignmentExpression(): Can't handle operator", node.operator); + return undefined; + } return value; }; if (Vasync) { @@ -77,8 +118,49 @@ export default class Sandbox { if (optional && !O) { return undefined; } - // eslint-disable-next-line no-param-reassign, no-return-assign - return O[P] = value; + switch (operator) { + /* eslint-disable no-param-reassign, no-return-assign */ + case '=': + return O[P] = value; + case '+=': + return O[P] += value; + case '-=': + return O[P] -= value; + case '*=': + return O[P] *= value; + case '/=': + return O[P] /= value; + case '%=': + return O[P] %= value; + case '**=': + return O[P] **= value; + /* eslint-disable no-bitwise */ + case '<<=': + return O[P] <<= value; + case '>>=': + return O[P] >>= value; + case '>>>=': + return O[P] >>>= value; + case '|=': + return O[P] |= value; + case '^=': + return O[P] ^= value; + case '&=': + return O[P] &= value; + /* eslint-enable no-bitwise */ + case '||=': + return O[P] ||= value; + case '&&=': + return O[P] &&= value; + case '??=': { + return O[P] = (O[P] === null || O[P] === undefined) ? value : O[P]; + /* eslint-enable no-param-reassign, no-return-assign */ + } + default: + // eslint-disable-next-line no-console + console.error("evaluateAssignmentExpression(): Can't handle operator", node.operator); + return undefined; + } }; const makeAsync = (O, P, value) => ( Promise.all([O, P, value]).then(([O, P, value]) => memberAssign(O, P, value))