From 46a5ee568d8f1180cbb7f9b94dbefb9af5940694 Mon Sep 17 00:00:00 2001 From: Jimkwan Date: Fri, 8 Mar 2019 17:18:45 +0800 Subject: [PATCH] [Update] Full support of generator --- src/evaluate/declaration.ts | 12 +++++++++--- src/evaluate/expression.ts | 6 +++++- src/index.ts | 8 ++------ src/share/helper.ts | 11 +++-------- src/share/util.ts | 2 ++ test/class.test.ts | 11 ++++++++--- test/generator.test.ts | 16 ++++++++++++++++ 7 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/evaluate/declaration.ts b/src/evaluate/declaration.ts index 95cc45a..ade0bf4 100644 --- a/src/evaluate/declaration.ts +++ b/src/evaluate/declaration.ts @@ -3,7 +3,7 @@ import Scope from '../scope' import evaluate from '.' import { createFunc, pattern, createClass } from '../share/helper' import { VarKind } from '../scope/variable' -import { define } from '../share/util' +import { define, getDptor } from '../share/util' import { Identifier } from './identifier' @@ -107,18 +107,24 @@ export function* MethodDefinition(node: estree.MethodDefinition, scope: Scope, o configurable: true, }) break - case 'get': + case 'get': { + const oriDptor = getDptor(obj, key) define(obj, key, { get: value, + set: oriDptor && oriDptor.set, configurable: true, }) break - case 'set': + } + case 'set': { + const oriDptor = getDptor(obj, key) define(obj, key, { + get: oriDptor && oriDptor.get, set: value, configurable: true, }) break + } default: throw new SyntaxError('Unexpected token') } diff --git a/src/evaluate/expression.ts b/src/evaluate/expression.ts index eb2ecbc..5cadfaf 100644 --- a/src/evaluate/expression.ts +++ b/src/evaluate/expression.ts @@ -378,7 +378,11 @@ export function* ArrowFunctionExpression(node: estree.ArrowFunctionExpression, s } export function* YieldExpression(node: estree.YieldExpression, scope: Scope) { - yield yield* evaluate(node.argument, scope) + if (node.delegate) { + yield* yield* evaluate(node.argument, scope) + } else { + yield yield* evaluate(node.argument, scope) + } } export function* TemplateLiteral(node: estree.TemplateLiteral, scope: Scope) { diff --git a/src/index.ts b/src/index.ts index 0ac188d..59a54c9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,12 +18,8 @@ class Sval { constructor(options: SvalOptions = {}) { let { ecmaVer, sandBox = true } = options - if ( - ecmaVer !== 5 - && ecmaVer !== 6 - && ecmaVer !== 2015 - ) { - ecmaVer = 6 + if ([3, 5, 6, 7, 2015, 2016].indexOf(ecmaVer) === -1) { + ecmaVer = 7 } this.options.ecmaVersion = ecmaVer diff --git a/src/share/helper.ts b/src/share/helper.ts index f57954e..fd48fb0 100644 --- a/src/share/helper.ts +++ b/src/share/helper.ts @@ -162,14 +162,9 @@ export function* createFunc( } } - let func: any - if (node.generator) { - func = tmpGenerator - } else { - func = function (...args: any[]) { - runGenerator(tmpGenerator.bind(this), ...args) - } - } + const func: any = node.generator + ? tmpGenerator + : function (...args: any[]) { return runGenerator(tmpGenerator.bind(this), ...args) } if (node.type === 'FunctionDeclaration') { define(func, 'name', { diff --git a/src/share/util.ts b/src/share/util.ts index 6d3d3f6..ea569a5 100644 --- a/src/share/util.ts +++ b/src/share/util.ts @@ -2,6 +2,8 @@ export const freeze = Object.freeze export const define = Object.defineProperty +export const getDptor = Object.getOwnPropertyDescriptor + const hasOwnProperty = Object.prototype.hasOwnProperty export function hasOwn(obj: any, key: symbol | string): boolean { return hasOwnProperty.call(obj, key) diff --git a/test/class.test.ts b/test/class.test.ts index 5bed2d8..eef52ec 100644 --- a/test/class.test.ts +++ b/test/class.test.ts @@ -3,11 +3,15 @@ import Sval from '../src' describe('testing src/index.ts', () => { it('should create class normally', () => { const interpreter = new Sval() + interpreter.import({ JSON }) interpreter.run(` class A { constructor() { this.b = 1 } + p() { + this.b++ + } get k() { return this.b + 1 } @@ -17,9 +21,10 @@ describe('testing src/index.ts', () => { } exports.inst = new A() exports.inst.g = 3 + exports.inst.p() `) - expect(interpreter.exports.inst.b).toBe(3) - expect(interpreter.exports.inst.k).toBe(4) + expect(interpreter.exports.inst.b).toBe(4) + expect(interpreter.exports.inst.k).toBe(5) }) it('should extend class normally', () => { const interpreter = new Sval() @@ -56,7 +61,7 @@ describe('testing src/index.ts', () => { super.g = 1 } } - const k = new c() + const k = new C() exports.k = k.k `) expect(interpreter.exports.k).toBe(1) diff --git a/test/generator.test.ts b/test/generator.test.ts index 0a06d9a..b2f5edc 100644 --- a/test/generator.test.ts +++ b/test/generator.test.ts @@ -19,4 +19,20 @@ describe('testing src/index.ts', () => { `) expect(interpreter.exports.res).toEqual([1, 2, 3]) }) + it('should proxy generator normally', () => { + const interpreter = new Sval() + interpreter.run(` + function* a() { + yield* [1, 2, 3] + } + const f = a() + let result = f.next() + exports.res = [] + while (!result.done) { + exports.res.push(result.value) + result = f.next() + } + `) + expect(interpreter.exports.res).toEqual([1, 2, 3]) + }) })