import {expect, test} from 'vitest'; import evaluate from '@/astride/evaluate.js'; import expression from '@/astride/test/expression.js'; const scopeTest = test.extend({ scope: async ({}, use) => { await use({ S: {O: {}}, get(k) { return this.S[k]; }, set(k, v) { return this.S[k] = v; } }); }, }); scopeTest('evaluates =', async ({scope}) => { expect(evaluate(await expression('x = 4'), {scope})) .to.deep.include({value: 4}); expect(scope.get('x')) .to.equal(4); expect(evaluate(await expression('O.x = 4'), {scope})) .to.deep.include({value: 4}); expect(scope.get('O').x) .to.equal(4); }); scopeTest('evaluates +=', async ({scope}) => { scope.set('x', 1); expect(evaluate(await expression('x += 4'), {scope})) .to.deep.include({value: 5}); expect(scope.get('x')) .to.equal(5); scope.set('O', {x: 1}); expect(evaluate(await expression('O.x += 4'), {scope})) .to.deep.include({value: 5}); expect(scope.get('O').x) .to.equal(5); }); scopeTest('evaluates -=', async ({scope}) => { scope.set('x', 5); expect(evaluate(await expression('x -= 4'), {scope})) .to.deep.include({value: 1}); expect(scope.get('x')) .to.equal(1); scope.set('O', {x: 5}); expect(evaluate(await expression('O.x -= 4'), {scope})) .to.deep.include({value: 1}); expect(scope.get('O').x) .to.equal(1); }); scopeTest('evaluates *=', async ({scope}) => { scope.set('x', 5); expect(evaluate(await expression('x *= 4'), {scope})) .to.deep.include({value: 20}); expect(scope.get('x')) .to.equal(20); scope.set('O', {x: 5}); expect(evaluate(await expression('O.x *= 4'), {scope})) .to.deep.include({value: 20}); expect(scope.get('O').x) .to.equal(20); }); scopeTest('evaluates /=', async ({scope}) => { scope.set('x', 25); expect(evaluate(await expression('x /= 5'), {scope})) .to.deep.include({value: 5}); expect(scope.get('x')) .to.equal(5); scope.set('O', {x: 25}); expect(evaluate(await expression('O.x /= 5'), {scope})) .to.deep.include({value: 5}); expect(scope.get('O').x) .to.equal(5); }); scopeTest('evaluates %=', async ({scope}) => { scope.set('x', 5); expect(evaluate(await expression('x %= 2'), {scope})) .to.deep.include({value: 1}); expect(scope.get('x')) .to.equal(1); scope.set('O', {x: 5}); expect(evaluate(await expression('O.x %= 2'), {scope})) .to.deep.include({value: 1}); expect(scope.get('O').x) .to.equal(1); }); scopeTest('evaluates **=', async ({scope}) => { scope.set('x', 5); expect(evaluate(await expression('x **= 3'), {scope})) .to.deep.include({value: 125}); expect(scope.get('x')) .to.equal(125); scope.set('O', {x: 5}); expect(evaluate(await expression('O.x **= 3'), {scope})) .to.deep.include({value: 125}); expect(scope.get('O').x) .to.equal(125); }); scopeTest('evaluates <<=', async ({scope}) => { scope.set('x', 2); expect(evaluate(await expression('x <<= 1'), {scope})) .to.deep.include({value: 4}); expect(scope.get('x')) .to.equal(4); scope.set('O', {x: 2}); expect(evaluate(await expression('O.x <<= 1'), {scope})) .to.deep.include({value: 4}); expect(scope.get('O').x) .to.equal(4); }); scopeTest('evaluates >>=', async ({scope}) => { scope.set('x', 8); expect(evaluate(await expression('x >>= 2'), {scope})) .to.deep.include({value: 2}); expect(scope.get('x')) .to.equal(2); scope.set('O', {x: 8}); expect(evaluate(await expression('O.x >>= 2'), {scope})) .to.deep.include({value: 2}); expect(scope.get('O').x) .to.equal(2); }); scopeTest('evaluates >>>=', async ({scope}) => { scope.set('x', -1); expect(evaluate(await expression('x >>>= 1'), {scope})) .to.deep.include({value: 2147483647}); expect(scope.get('x')) .to.equal(2147483647); scope.set('O', {x: -1}); expect(evaluate(await expression('O.x >>>= 1'), {scope})) .to.deep.include({value: 2147483647}); expect(scope.get('O').x) .to.equal(2147483647); }); scopeTest('evaluates |=', async ({scope}) => { scope.set('x', 3); expect(evaluate(await expression('x |= 5'), {scope})) .to.deep.include({value: 7}); expect(scope.get('x')) .to.equal(7); scope.set('O', {x: 3}); expect(evaluate(await expression('O.x |= 5'), {scope})) .to.deep.include({value: 7}); expect(scope.get('O').x) .to.equal(7); }); scopeTest('evaluates ^=', async ({scope}) => { scope.set('x', 7); expect(evaluate(await expression('x ^= 2'), {scope})) .to.deep.include({value: 5}); expect(scope.get('x')) .to.equal(5); scope.set('O', {x: 7}); expect(evaluate(await expression('O.x ^= 2'), {scope})) .to.deep.include({value: 5}); expect(scope.get('O').x) .to.equal(5); }); scopeTest('evaluates &=', async ({scope}) => { scope.set('x', 5); expect(evaluate(await expression('x &= 3'), {scope})) .to.deep.include({value: 1}); expect(scope.get('x')) .to.equal(1); scope.set('O', {x: 5}); expect(evaluate(await expression('O.x &= 3'), {scope})) .to.deep.include({value: 1}); expect(scope.get('O').x) .to.equal(1); }); scopeTest('evaluates ||=', async ({scope}) => { scope.set('x', false); expect(evaluate(await expression('x ||= true'), {scope})) .to.deep.include({value: true}); expect(scope.get('x')) .to.equal(true); scope.set('O', {x: false}); expect(evaluate(await expression('O.x ||= true'), {scope})) .to.deep.include({value: true}); expect(scope.get('O').x) .to.equal(true); }); scopeTest('evaluates &&=', async ({scope}) => { scope.set('x', true); expect(evaluate(await expression('x &&= true'), {scope})) .to.deep.include({value: true}); expect(scope.get('x')) .to.equal(true); expect(evaluate(await expression('x &&= false'), {scope})) .to.deep.include({value: false}); expect(scope.get('x')) .to.equal(false); scope.set('O', {x: true}); expect(evaluate(await expression('O.x &&= true'), {scope})) .to.deep.include({value: true}); expect(scope.get('O').x) .to.equal(true); expect(evaluate(await expression('O.x &&= false'), {scope})) .to.deep.include({value: false}); expect(scope.get('O').x) .to.equal(false); }); scopeTest('evaluates ??=', async ({scope}) => { scope.set('x', null); expect(evaluate(await expression('x ??= 2'), {scope})) .to.deep.include({value: 2}); expect(scope.get('x')) .to.equal(2); expect(evaluate(await expression('x ??= 4'), {scope})) .to.deep.include({value: 2}); expect(scope.get('x')) .to.equal(2); scope.set('O', {x: null}); expect(evaluate(await expression('O.x ??= 2'), {scope})) .to.deep.include({value: 2}); expect(scope.get('O').x) .to.equal(2); expect(evaluate(await expression('O.x ??= 4'), {scope})) .to.deep.include({value: 2}); expect(scope.get('O').x) .to.equal(2); }); scopeTest('evaluates promised assignment', async ({scope}) => { const evaluated = evaluate(await expression('x = await 4'), {scope}); expect(evaluated.async) .to.equal(true); expect(await evaluated.value) .to.equal(4); expect(await scope.get('x')) .to.equal(4); const evaluatedComputedObject = evaluate(await expression('O["x"] = await 4'), {scope}); expect(evaluatedComputedObject.async) .to.equal(true); expect(await evaluatedComputedObject.value) .to.equal(4); expect(await scope.get('O').x) .to.equal(4); const evaluatedObject = evaluate(await expression('O.x = await 4'), {scope}); expect(evaluatedObject.async) .to.equal(true); expect(await evaluatedObject.value) .to.equal(4); expect(await scope.get('O').x) .to.equal(4); const evaluatedPromisedObject = evaluate(await expression('(await O).x = await 4'), {scope}); expect(evaluatedPromisedObject.async) .to.equal(true); expect(await evaluatedPromisedObject.value) .to.equal(4); expect(await scope.get('O').x) .to.equal(4); });