import {parse as acornParse} from 'acorn'; import {expect, test} from 'vitest'; import Sandbox from '@/astride/sandbox.js'; function parse(code, options = {}) { return acornParse(code, { ecmaVersion: 'latest', sourceType: 'module', ...options, }) } const testCases = [ // [ // ` // const {one, two: {three, four: {five, six: {seven}}}} = value; // `, // { // value: { // one: 1, // two: { // three: 3, // four: { // five: 5, // six: { // seven: 7, // }, // }, // }, // }, // }, // { // one: 1, // three: 3, // five: 5, // seven: 7 // }, // ], [ ` const x = 123; { const x = 234; } `, {}, { x: 123, }, ], [ ` let x = []; for (let i = 0; i < 100; ++i) { x[i] = i; } `, {}, { x: Array(100).fill(0).map((n, i) => i), }, ], [ ` let x = 0, y; for (let i = 0; i < 4; ++i) { x += 1; } if (x % 2) { y = false } else { y = true } `, {}, { y: true, }, ], [ ` let x = 0; while (x < 100) { x += 1; } `, {}, { x: 100, }, ], [ ` let x = 0; do { x += 1; } while (x < 100); `, {}, { x: 100, }, ], [ ` let x = 0; do { x += 1; } while (x < 100); `, {}, { x: 100, }, ], ] test('performs well', async () => { let sandbox; for (const testCase of testCases) { sandbox = new Sandbox(await parse(testCase[0])); for (const key in testCase[1]) { sandbox.context[key] = testCase[1][key]; } sandbox.run(); expect(sandbox.context) .to.deep.include(testCase[2]); const N = 1000; let last; for (let i = 0; i < 100000 / N; ++i) { sandbox.run(); } last = performance.now(); for (let i = 0; i < N; ++i) { sandbox.run(); } const astrideSyncTime = (performance.now() - last) / N; const native = new Function( Object.keys(testCase[1]).map((arg) => `{${arg}}`).join(', '), testCase[0], ); for (let i = 0; i < 100000 / N; ++i) { native(testCase[1]); } last = performance.now(); for (let i = 0; i < N; ++i) { native(testCase[1]); } const nativeTime = (performance.now() - last) / N; // console.log( // testCase[0], // `${Math.round(astrideSyncTime / nativeTime)}x slower`, // ); expect(astrideSyncTime) .to.be.lessThan(nativeTime * 500); } });