diff --git a/app/astride/sandbox.js b/app/astride/sandbox.js index 0f11711..5a92f7f 100644 --- a/app/astride/sandbox.js +++ b/app/astride/sandbox.js @@ -150,7 +150,6 @@ export default class Sandbox { case 'ObjectExpression': case 'Identifier': case 'MemberExpression': - case 'UnaryExpression': case 'UpdateExpression': { result = this.evaluateToResult(node); if (result.yield) { @@ -523,6 +522,31 @@ export default class Sandbox { }; break; } + case 'UnaryExpression': { + if ('delete' === node.operator) { + let property; + if (node.argument.computed) { + property = this.executeSync(node.argument.property, depth + 1); + if (property.yield) { + return property; + } + } + else { + property = {value: node.argument.property.name, yield: YIELD_NONE}; + } + const scope = this.scopes.get(node); + const object = scope.get(node.argument.object.name, undefined); + delete object[property.value]; + result = {value: true, yield: YIELD_NONE}; + } + else { + result = this.evaluateToResult(node); + if (result.yield) { + return result; + } + } + break; + } case 'VariableDeclaration': { let skipping = isReplaying; for (const child of node.declarations) { diff --git a/app/astride/sandbox.test.js b/app/astride/sandbox.test.js index a23163e..de48b3d 100644 --- a/app/astride/sandbox.test.js +++ b/app/astride/sandbox.test.js @@ -121,6 +121,36 @@ test('runs arbitrary number of ops', async () => { .to.equal(150); }); +test('deletes', async () => { + const sandbox = new Sandbox( + await parse(` + delete foo.one; + delete foo['two']; + const x = 'three'; + delete foo[x]; + const y = 'four'; + delete foo[await y]; + `), + { + foo: { + one: 1, + two: 2, + three: 3, + four: 4, + }, + }, + ); + await finish(sandbox); + expect(sandbox.context.foo.one) + .to.be.undefined; + expect(sandbox.context.foo.two) + .to.be.undefined; + expect(sandbox.context.foo.three) + .to.be.undefined; + expect(sandbox.context.foo.four) + .to.be.undefined; +}); + test('evaluates conditional branches', async () => { const sandbox = new Sandbox( await parse(`