From: wingo@igalia.com Date: Wed, 15 May 2013 13:22:05 +0000 (+0000) Subject: GeneratorFunction() makes generator instances X-Git-Tag: upstream/4.7.83~14228 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e24cc3201175afabb5f56036b0564b542049bea2;p=platform%2Fupstream%2Fv8.git GeneratorFunction() makes generator instances The current specification has GeneratorFunction() be like Function(), except that it makes generator instances. This commit implements that behavior. It also fills in a piece of the implementation where otherwise calling GeneratorFunction or GeneratorFunctionPrototype would cause an abort because they have no code. R=mstarzinger@chromium.org, rossberg@chromium.org TEST=mjsunit/harmony/generators-iteration TEST=mjsunit/harmony/generators-runtime BUG=v8:2355 BUG=v8:2680 Review URL: https://codereview.chromium.org/14857009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14684 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/generator.js b/src/generator.js index 5e61091..a65aae4 100644 --- a/src/generator.js +++ b/src/generator.js @@ -65,6 +65,17 @@ function GeneratorObjectThrow(exn) { return %_GeneratorThrow(this, exn); } +function GeneratorFunctionPrototypeConstructor(x) { + if (%_IsConstructCall()) { + throw MakeTypeError('not_constructor', ['GeneratorFunctionPrototype']); + } +} + +function GeneratorFunctionConstructor(arg1) { // length == 1 + return NewFunction(arguments, 'function*'); +} + + function SetUpGenerators() { %CheckIsBootstrapping(); var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype; @@ -76,9 +87,11 @@ function SetUpGenerators() { %SetProperty(GeneratorObjectPrototype, "constructor", GeneratorFunctionPrototype, DONT_ENUM | DONT_DELETE | READ_ONLY); %SetPrototype(GeneratorFunctionPrototype, $Function.prototype); + %SetCode(GeneratorFunctionPrototype, GeneratorFunctionPrototypeConstructor); %SetProperty(GeneratorFunctionPrototype, "constructor", GeneratorFunction, DONT_ENUM | DONT_DELETE | READ_ONLY); %SetPrototype(GeneratorFunction, $Function); + %SetCode(GeneratorFunction, GeneratorFunctionConstructor); } SetUpGenerators(); diff --git a/src/v8natives.js b/src/v8natives.js index b2ea749..61f2d85 100644 --- a/src/v8natives.js +++ b/src/v8natives.js @@ -1757,26 +1757,27 @@ function FunctionBind(this_arg) { // Length is 1. } -function NewFunction(arg1) { // length == 1 - var n = %_ArgumentsLength(); +function NewFunction(arguments, function_token) { + var n = arguments.length; var p = ''; if (n > 1) { - p = new InternalArray(n - 1); - for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i); - p = Join(p, n - 1, ',', NonStringToString); + p = ToString(arguments[0]); + for (var i = 1; i < n - 1; i++) { + p += ',' + ToString(arguments[i]); + } // If the formal parameters string include ) - an illegal // character - it may make the combined function expression // compile. We avoid this problem by checking for this early on. if (%_CallFunction(p, ')', StringIndexOf) != -1) { - throw MakeSyntaxError('paren_in_arg_string',[]); + throw MakeSyntaxError('paren_in_arg_string', []); } // If the formal parameters include an unbalanced block comment, the // function must be rejected. Since JavaScript does not allow nested // comments we can include a trailing block comment to catch this. p += '\n/' + '**/'; } - var body = (n > 0) ? ToString(%_Arguments(n - 1)) : ''; - var source = '(function(' + p + ') {\n' + body + '\n})'; + var body = (n > 0) ? ToString(arguments[n - 1]) : ''; + var source = '(' + function_token + '(' + p + ') {\n' + body + '\n})'; var global_receiver = %GlobalReceiver(global); var f = %_CallFunction(global_receiver, %CompileString(source, true)); @@ -1786,12 +1787,17 @@ function NewFunction(arg1) { // length == 1 } +function FunctionConstructor(arg1) { // length == 1 + return NewFunction(arguments, 'function'); +} + + // ---------------------------------------------------------------------------- function SetUpFunction() { %CheckIsBootstrapping(); - %SetCode($Function, NewFunction); + %SetCode($Function, FunctionConstructor); %SetProperty($Function.prototype, "constructor", $Function, DONT_ENUM); InstallFunctions($Function.prototype, DONT_ENUM, $Array( diff --git a/test/mjsunit/harmony/generators-iteration.js b/test/mjsunit/harmony/generators-iteration.js index e717f1b..39e6866 100644 --- a/test/mjsunit/harmony/generators-iteration.js +++ b/test/mjsunit/harmony/generators-iteration.js @@ -324,6 +324,28 @@ TestGenerator( "foo", [2, "1foo3", 5, "4foo6", "foofoo"]); +// Generator function instances. +TestGenerator(GeneratorFunction(), + [undefined], + "foo", + [undefined]); + +TestGenerator(new GeneratorFunction(), + [undefined], + "foo", + [undefined]); + +TestGenerator(GeneratorFunction('yield 1;'), + [1, undefined], + "foo", + [1, undefined]); + +TestGenerator( + function() { return GeneratorFunction('x', 'y', 'yield x + y;')(1, 2) }, + [3, undefined], + "foo", + [3, undefined]); + function TestTryCatch(instantiate) { function* g() { yield 1; try { yield 2; } catch (e) { yield e; } yield 3; } function Sentinel() {} diff --git a/test/mjsunit/harmony/generators-runtime.js b/test/mjsunit/harmony/generators-runtime.js index b4e8f95..4c589a6 100644 --- a/test/mjsunit/harmony/generators-runtime.js +++ b/test/mjsunit/harmony/generators-runtime.js @@ -110,6 +110,9 @@ function TestGeneratorFunction() { // Not all functions are generators. assertTrue(f instanceof Function); // Sanity check. assertTrue(!(f instanceof GeneratorFunction)); + + assertTrue((new GeneratorFunction()) instanceof GeneratorFunction); + assertTrue(GeneratorFunction() instanceof GeneratorFunction); } TestGeneratorFunction();