import { isComputed, isMemberExpression, } from '@/swcx/types.js'; export default function(node, {evaluate, scope}) { const {operator, left} = node; const right = evaluate(node.right, {scope}); if (!isMemberExpression(left)) { const assign = (value) => { switch (operator) { case '=' : return scope.set(left.value, value); case '+=' : return scope.set(left.value, scope.get(left.value) + value); case '-=' : return scope.set(left.value, scope.get(left.value) - value); case '*=' : return scope.set(left.value, scope.get(left.value) * value); case '/=' : return scope.set(left.value, scope.get(left.value) / value); case '%=' : return scope.set(left.value, scope.get(left.value) % value); case '**=' : return scope.set(left.value, scope.get(left.value) ** value); case '<<=' : return scope.set(left.value, scope.get(left.value) << value); case '>>=' : return scope.set(left.value, scope.get(left.value) >> value); case '>>>=': return scope.set(left.value, scope.get(left.value) >>> value); case '|=' : return scope.set(left.value, scope.get(left.value) | value); case '^=' : return scope.set(left.value, scope.get(left.value) ^ value); case '&=' : return scope.set(left.value, scope.get(left.value) & value); case '||=' : return scope.set(left.value, scope.get(left.value) || value); case '&&=' : return scope.set(left.value, scope.get(left.value) && value); case '??=' : { const l = scope.get(left.value); return scope.set(left.value, (l === null || l === undefined) ? value : l); } /* v8 ignore next 2 */ default: throw new Error(`operator not implemented: ${node.operator}`); } }; if (right.async) { return { async: true, value: Promise.resolve(right.value).then(assign), }; } return {value: assign(right.value)}; } const { object, property, } = left; const memberAssign = (O, P, value) => { switch (operator) { 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; 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; case '&&=' : return O[P] &&= value; case '??=' : return O[P] = (O[P] === null || O[P] === undefined) ? value : O[P]; /* v8 ignore next 2 */ default: throw new Error(`operator not implemented: ${node.operator}`); } }; const makeAsync = (O, P, value) => ( Promise.all([O, P, value]).then(([O, P, value]) => memberAssign(O, P, value)) ); const O = evaluate(object, {scope}); const P = isComputed(property) ? evaluate(property, {scope}) : {value: property.value}; if (right.async || O.async || P.async) { return { async: true, value: makeAsync(O.value, P.value, right.value), }; } return {value: memberAssign(O.value, P.value, right.value)}; }