diff --git a/src/generator.js b/src/generator.js index cc31a44588..3c8ea6f319 100644 --- a/src/generator.js +++ b/src/generator.js @@ -55,6 +55,23 @@ function GeneratorObjectThrow(exn) { return %_GeneratorThrow(this, exn); } +function GeneratorFunctionPrototypeConstructor(x) { + if (%_IsConstructCall()) { + throw MakeTypeError('not_constructor', ['GeneratorFunctionPrototype']); + } +} + +function GeneratorFunctionConstructor(arg1) { // length == 1 + var source = NewFunctionString(arguments, 'function*'); + var global_receiver = %GlobalReceiver(global); + // Compile the string in the constructor and not a helper so that errors + // appear to come from here. + var f = %_CallFunction(global_receiver, %CompileString(source, true)); + %FunctionMarkNameShouldPrintAsAnonymous(f); + return f; +} + + function SetUpGenerators() { %CheckIsBootstrapping(); var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype; @@ -65,9 +82,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 e168b71abc..76eeac6a58 100644 --- a/src/v8natives.js +++ b/src/v8natives.js @@ -1786,30 +1786,36 @@ function FunctionBind(this_arg) { // Length is 1. } -function NewFunction(arg1) { // length == 1 - var n = %_ArgumentsLength(); +function NewFunctionString(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]) : ''; + return '(' + function_token + '(' + p + ') {\n' + body + '\n})'; +} + +function FunctionConstructor(arg1) { // length == 1 + var source = NewFunctionString(arguments, 'function'); var global_receiver = %GlobalReceiver(global); + // Compile the string in the constructor and not a helper so that errors + // appear to come from here. var f = %_CallFunction(global_receiver, %CompileString(source, true)); - %FunctionMarkNameShouldPrintAsAnonymous(f); return f; } @@ -1820,7 +1826,7 @@ function NewFunction(arg1) { // length == 1 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 01facd085c..2ca35f2ee8 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 7667deb7f6..aef063b6c8 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();