import {expect, test} from 'vitest'; import {parse} from '@swc/core'; import Sandbox from '@/swcx/sandbox.js'; test('declares variables', async () => { const sandbox = new Sandbox( await parse(` const scalar = 1; const asyncScalar = await 2; const array = [3, 4, 5]; const asyncArray = await [6, 7, 8]; const object = {9: '10'}; const asyncObject = await {11: '12'}; `), ); let result; do { result = sandbox.step(); if (result.value?.async) { await result.value.async; } } while (!result.done); expect(sandbox.context) .to.deep.equal({ scalar: 1, asyncScalar: 2, array: [3, 4, 5], asyncArray: [6, 7, 8], object: {9: '10'}, asyncObject: {11: '12'}, }); }); test('destructures variables', async () => { const sandbox = new Sandbox( await parse(` const [a, , c] = [1, 2, 3]; const {x: x1, y, z: {zz}} = {x: 4, y: 5, z: {zz: 6}}; const [d, e] = await [7, 8]; const {t, u: {uu}} = {t: 9, u: {uu: await 10}}; `), ); let result; do { result = sandbox.step(); if (result.value?.async) { await result.value.value; } } while (!result.done); expect(sandbox.context) .to.deep.equal({ a: 1, c: 3, x1: 4, y: 5, zz: 6, d: 7, e: 8, t: 9, uu: 10, }); }); test('runs arbitrary number of ops', async () => { const sandbox = new Sandbox( await parse(` const foo = []; for (let i = 0; i < 1500; ++i) { foo.push(i); } `), ); sandbox.run(1000); expect(sandbox.context.foo.length) .to.equal(1000); sandbox.run(1000); expect(sandbox.context.foo.length) .to.equal(1500); expect(true) .to.be.true; }); test('evaluates conditional branches', async () => { const sandbox = new Sandbox( await parse(` let foo, bar; if (true) { foo = 1; } else { foo = 2; } if (await false) { bar = 1; } else { bar = 2; } `), ); let result; do { result = sandbox.step(); if (result.value?.async) { await result.value.value; } } while (!result.done); expect(sandbox.context) .to.deep.equal({ foo: 1, bar: 2, }); }); test('evaluates loops', async () => { const sandbox = new Sandbox( await parse(` let x = 0, y = 0, a = 0, b = 0, c = 0; for (let i = 0; i < 3; ++i) { x += 1; } for (let i = await 0; i < await 3; i = 1 + await i) { y += 1; } do { a += 1; } while (a < 3); do { b += 1; } while (await b < 3); while (c < 3) { c += 1; } `), ); let result; do { result = sandbox.step(); if (result.value?.async) { await result.value.value; } } while (!result.done); expect(sandbox.context) .to.deep.equal({ a: 3, b: 3, c: 3, x: 3, y: 3, }); }); test('retuns undefined for nonexistent variables in scope', async () => { const sandbox = new Sandbox( await parse(` const x = y `), ); sandbox.run(); expect(sandbox.context) .to.deep.equal({ x: undefined, }); }); test('sets variables in global scope', async () => { const sandbox = new Sandbox( await parse(` x = y `), ); sandbox.run(); expect(sandbox.context) .to.deep.equal({ x: undefined, }); }); test('runs arbitrary number of ops', async () => { const sandbox = new Sandbox( await parse(` const foo = []; for (let i = 0; i < 1500; ++i) { foo.push(i); } `), ); sandbox.run(1000); expect(sandbox.context.foo.length) .to.equal(1000); sandbox.run(1000); expect(sandbox.context.foo.length) .to.equal(1500); expect(true) .to.be.true; });