diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c368f65b40..6e5d41b15c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -246,3 +246,37 @@ p.then(function () { ``` As above, exceptions that are thrown from a `then` clause are passed to a later `$DONE` function and reported asynchronously. + +## Procedurally-generated tests + +Some language features are expressed through a number of distinct syntactic forms. Test262 maintains these tests as a set of "test cases" and "test templates" in order to ensure equivalent coverage across all forms. The sub-directories within the `src/` directory describe the various language features that benefit from this approach. + +Test cases and test templates specify meta-data using the same YAML frontmatter pattern as so-called "static" (i.e. non-generated) tests. The expected attributes differ between test cases and test templates: + +- test cases (`*.case`) + - `template` - name of the sub-directory to locate templates for this test + - `description` (see above) + - `info` (see above) + - `features` (see above; merged with value defined by test template) +- test templates (`*.template`) + - `path` - location within the published test hierarchy to output files created from this template + - `name` - human-readable name of the syntactic form described by this template (used to generate the test file's `description` field) + - `esid` (see above) + - `es5id` (see above) + - `es6id` (see above) + - `info` (see above) + - `features` (see above; merged with value defined by test case) + +Generated files are managed using the `make.py` Python script located in the root of this repository. + +To create files: + + make.py + +To remove all generated files: + + make.py clean + +The executable located at `tools/generation/generator.py` offers additional control over the generation procedure. + + ./tools/generation/generator.py --help diff --git a/make.py b/make.py new file mode 100755 index 0000000000..2d440b9724 --- /dev/null +++ b/make.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# Copyright (C) 2016 the V8 project authors. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +import os, shutil, subprocess, sys + +OUT_DIR = os.environ.get('OUT_DIR') or 'test' +SRC_DIR = os.environ.get('SRC_DIR') or 'src' + +def shell(*args): + sp = subprocess.Popen(list(args), stdout=subprocess.PIPE) + cmd_str = ' '.join(args) + + print '> ' + cmd_str + + for line in iter(sp.stdout.readline, ''): + sys.stdout.write(line) + + sp.communicate() + + if sp.returncode == 1: + raise Exception('Command failed: ' + cmd_str) + +targets = dict() +def target(*deps): + def other(orig): + def wrapped(): + print 'Running target: ' + orig.__name__ + + for dep in deps: + targets[dep]() + return orig() + wrapped.__name__ = orig.__name__ + targets[orig.__name__] = wrapped + return wrapped + return other + +@target() +def build(): + shell(sys.executable, 'tools/generation/generator.py', + 'create', + '--out', OUT_DIR, + SRC_DIR) + +@target() +def clean(): + shell(sys.executable, 'tools/generation/generator.py', 'clean', OUT_DIR) + +if len(sys.argv) == 1: + targets['build']() + +for target in sys.argv[1:]: + if not target in targets: + sys.stderr.write('No target named: "' + target + '".\n' + + 'Available targets: ' + ', '.join(list(targets)) + '\n') + sys.exit(1) + targets[target]() diff --git a/src/dstr-binding/ary-name-iter-val.case b/src/dstr-binding/ary-name-iter-val.case new file mode 100644 index 0000000000..8c65a0868f --- /dev/null +++ b/src/dstr-binding/ary-name-iter-val.case @@ -0,0 +1,35 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +desc: SingleNameBinding with normal value iteration +template: default +info: | + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +//- elems +[x, y, z] +//- vals +[1, 2, 3] +//- body +assert.sameValue(x, 1); +assert.sameValue(y, 2); +assert.sameValue(z, 3); diff --git a/src/dstr-binding/default/arrow-function.template b/src/dstr-binding/default/arrow-function.template new file mode 100644 index 0000000000..7e87227e99 --- /dev/null +++ b/src/dstr-binding/default/arrow-function.template @@ -0,0 +1,46 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/arrow-function/dstr- +name: arrow function expression +es6id: 14.2.16 +info: | + ArrowFunction : ArrowParameters => ConciseBody + + [...] + 4. Let closure be FunctionCreate(Arrow, parameters, ConciseBody, scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +var f; +f = (/*{ elems }*/) => { + /*{ body }*/ + callCount = callCount + 1; +}; + +f(/*{ vals }*/); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/cls-decl-gen-meth-static.template b/src/dstr-binding/default/cls-decl-gen-meth-static.template new file mode 100644 index 0000000000..3f6b55e175 --- /dev/null +++ b/src/dstr-binding/default/cls-decl-gen-meth-static.template @@ -0,0 +1,69 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/statements/class/dstr-gen-meth-static- +name: static class expression generator method +es6id: 14.5.15 +info: | + ClassDeclaration : class BindingIdentifier ClassTail + + 1. Let className be StringValue of BindingIdentifier. + 2. Let value be the result of ClassDefinitionEvaluation of ClassTail with + argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + b. Else, + Let status be the result of performing PropertyDefinitionEvaluation for + m with arguments F and false. + [...] + + 14.4.13 Runtime Semantics: PropertyDefinitionEvaluation + + GeneratorMethod : * PropertyName ( StrictFormalParameters ) { GeneratorBody } + + 1. Let propKey be the result of evaluating PropertyName. + 2. ReturnIfAbrupt(propKey). + 3. If the function code for this GeneratorMethod is strict mode code, + let strict be true. Otherwise let strict be false. + 4. Let scope be the running execution context's LexicalEnvironment. + 5. Let closure be GeneratorFunctionCreate(Method, + StrictFormalParameters, GeneratorBody, scope, strict). + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +class C { + static *method(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; + } +}; + +C.method(/*{ vals }*/).next(); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/cls-decl-gen-meth.template b/src/dstr-binding/default/cls-decl-gen-meth.template new file mode 100644 index 0000000000..0579b3ca6f --- /dev/null +++ b/src/dstr-binding/default/cls-decl-gen-meth.template @@ -0,0 +1,69 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/statements/class/dstr-gen-meth- +name: class expression method +es6id: 14.5.16 +info: | + ClassDeclaration : class BindingIdentifier ClassTail + + 1. Let className be StringValue of BindingIdentifier. + 2. Let value be the result of ClassDefinitionEvaluation of ClassTail with + argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + i. Let status be the result of performing + PropertyDefinitionEvaluation for m with arguments proto and + false. + [...] + + 14.4.13 Runtime Semantics: PropertyDefinitionEvaluation + + GeneratorMethod : * PropertyName ( StrictFormalParameters ) { GeneratorBody } + + 1. Let propKey be the result of evaluating PropertyName. + 2. ReturnIfAbrupt(propKey). + 3. If the function code for this GeneratorMethod is strict mode code, + let strict be true. Otherwise let strict be false. + 4. Let scope be the running execution context's LexicalEnvironment. + 5. Let closure be GeneratorFunctionCreate(Method, + StrictFormalParameters, GeneratorBody, scope, strict). + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +class C { + *method(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; + } +}; + +new C().method(/*{ vals }*/).next(); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/cls-decl-meth-static.template b/src/dstr-binding/default/cls-decl-meth-static.template new file mode 100644 index 0000000000..0f1fff2b7e --- /dev/null +++ b/src/dstr-binding/default/cls-decl-meth-static.template @@ -0,0 +1,67 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/statements/class/dstr-meth-static- +name: static class expression method +es6id: 14.5.15 +info: | + ClassDeclaration : class BindingIdentifier ClassTail + + 1. Let className be StringValue of BindingIdentifier. + 2. Let value be the result of ClassDefinitionEvaluation of ClassTail with + argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + b. Else, + Let status be the result of performing PropertyDefinitionEvaluation for + m with arguments F and false. + [...] + + 14.3.8 Runtime Semantics: DefineMethod + + MethodDefinition : PropertyName ( StrictFormalParameters ) { FunctionBody } + + [...] + 6. Let closure be FunctionCreate(kind, StrictFormalParameters, FunctionBody, + scope, strict). If functionPrototype was passed as a parameter then pass its + value as the functionPrototype optional argument of FunctionCreate. + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +class C { + static method(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; + } +}; + +C.method(/*{ vals }*/); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/cls-decl-meth.template b/src/dstr-binding/default/cls-decl-meth.template new file mode 100644 index 0000000000..1a7ba2fc24 --- /dev/null +++ b/src/dstr-binding/default/cls-decl-meth.template @@ -0,0 +1,67 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/statements/class/dstr-meth- +name: class expression method +es6id: 14.5.15 +info: | + ClassDeclaration : class BindingIdentifier ClassTail + + 1. Let className be StringValue of BindingIdentifier. + 2. Let value be the result of ClassDefinitionEvaluation of ClassTail with + argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + i. Let status be the result of performing + PropertyDefinitionEvaluation for m with arguments proto and + false. + [...] + + 14.3.8 Runtime Semantics: DefineMethod + + MethodDefinition : PropertyName ( StrictFormalParameters ) { FunctionBody } + + [...] + 6. Let closure be FunctionCreate(kind, StrictFormalParameters, FunctionBody, + scope, strict). If functionPrototype was passed as a parameter then pass its + value as the functionPrototype optional argument of FunctionCreate. + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +class C { + method(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; + } +}; + +new C().method(/*{ vals }*/); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/cls-expr-gen-meth-static.template b/src/dstr-binding/default/cls-expr-gen-meth-static.template new file mode 100644 index 0000000000..340945db7b --- /dev/null +++ b/src/dstr-binding/default/cls-expr-gen-meth-static.template @@ -0,0 +1,71 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/class/dstr-gen-meth-static- +name: static class expression generator method +es6id: 14.5.16 +info: | + ClassExpression : class BindingIdentifieropt ClassTail + + 1. If BindingIdentifieropt is not present, let className be undefined. + 2. Else, let className be StringValue of BindingIdentifier. + 3. Let value be the result of ClassDefinitionEvaluation of ClassTail + with argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + b. Else, + Let status be the result of performing PropertyDefinitionEvaluation + for m with arguments F and false. + [...] + + 14.4.13 Runtime Semantics: PropertyDefinitionEvaluation + + GeneratorMethod : + * PropertyName ( StrictFormalParameters ) { GeneratorBody } + + 1. Let propKey be the result of evaluating PropertyName. + 2. ReturnIfAbrupt(propKey). + 3. If the function code for this GeneratorMethod is strict mode code, + let strict be true. Otherwise let strict be false. + 4. Let scope be the running execution context's LexicalEnvironment. + 5. Let closure be GeneratorFunctionCreate(Method, + StrictFormalParameters, GeneratorBody, scope, strict). + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +var C = class { + static *method(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; + } +}; + +C.method(/*{ vals }*/).next(); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/cls-expr-gen-meth.template b/src/dstr-binding/default/cls-expr-gen-meth.template new file mode 100644 index 0000000000..c4c0d4c8f4 --- /dev/null +++ b/src/dstr-binding/default/cls-expr-gen-meth.template @@ -0,0 +1,71 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/class/dstr-gen-meth- +name: class expression method +es6id: 14.5.16 +info: | + ClassExpression : class BindingIdentifieropt ClassTail + + 1. If BindingIdentifieropt is not present, let className be undefined. + 2. Else, let className be StringValue of BindingIdentifier. + 3. Let value be the result of ClassDefinitionEvaluation of ClassTail + with argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + i. Let status be the result of performing + PropertyDefinitionEvaluation for m with arguments proto and + false. + [...] + + 14.4.13 Runtime Semantics: PropertyDefinitionEvaluation + + GeneratorMethod : + * PropertyName ( StrictFormalParameters ) { GeneratorBody } + + 1. Let propKey be the result of evaluating PropertyName. + 2. ReturnIfAbrupt(propKey). + 3. If the function code for this GeneratorMethod is strict mode code, + let strict be true. Otherwise let strict be false. + 4. Let scope be the running execution context's LexicalEnvironment. + 5. Let closure be GeneratorFunctionCreate(Method, + StrictFormalParameters, GeneratorBody, scope, strict). + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +var C = class { + *method(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; + } +}; + +new C().method(/*{ vals }*/).next(); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/cls-expr-meth-static.template b/src/dstr-binding/default/cls-expr-meth-static.template new file mode 100644 index 0000000000..aff8b8a63e --- /dev/null +++ b/src/dstr-binding/default/cls-expr-meth-static.template @@ -0,0 +1,68 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/class/dstr-meth-static- +name: static class expression method +es6id: 14.5.16 +info: | + ClassExpression : class BindingIdentifieropt ClassTail + + 1. If BindingIdentifieropt is not present, let className be undefined. + 2. Else, let className be StringValue of BindingIdentifier. + 3. Let value be the result of ClassDefinitionEvaluation of ClassTail + with argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + b. Else, + Let status be the result of performing PropertyDefinitionEvaluation for + m with arguments F and false. + [...] + + 14.3.8 Runtime Semantics: DefineMethod + + MethodDefinition : PropertyName ( StrictFormalParameters ) { FunctionBody } + + [...] + 6. Let closure be FunctionCreate(kind, StrictFormalParameters, FunctionBody, + scope, strict). If functionPrototype was passed as a parameter then pass its + value as the functionPrototype optional argument of FunctionCreate. + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +var C = class { + static method(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; + } +}; + +C.method(/*{ vals }*/); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/cls-expr-meth.template b/src/dstr-binding/default/cls-expr-meth.template new file mode 100644 index 0000000000..a97f94827c --- /dev/null +++ b/src/dstr-binding/default/cls-expr-meth.template @@ -0,0 +1,68 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/class/dstr-meth- +name: class expression method +es6id: 14.5.16 +info: | + ClassExpression : class BindingIdentifieropt ClassTail + + 1. If BindingIdentifieropt is not present, let className be undefined. + 2. Else, let className be StringValue of BindingIdentifier. + 3. Let value be the result of ClassDefinitionEvaluation of ClassTail + with argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + i. Let status be the result of performing + PropertyDefinitionEvaluation for m with arguments proto and + false. + [...] + + 14.3.8 Runtime Semantics: DefineMethod + + MethodDefinition : PropertyName ( StrictFormalParameters ) { FunctionBody } + + [...] + 6. Let closure be FunctionCreate(kind, StrictFormalParameters, FunctionBody, + scope, strict). If functionPrototype was passed as a parameter then pass its + value as the functionPrototype optional argument of FunctionCreate. + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +var C = class { + method(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; + } +}; + +new C().method(/*{ vals }*/); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/const-stmt.template b/src/dstr-binding/default/const-stmt.template new file mode 100644 index 0000000000..aeddb7a8fc --- /dev/null +++ b/src/dstr-binding/default/const-stmt.template @@ -0,0 +1,21 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/statements/const/dstr- +name: > + `const` statement +es6id: 13.3.1.4 +info: | + LexicalBinding : BindingPattern Initializer + + 1. Let rhs be the result of evaluating Initializer. + 2. Let value be GetValue(rhs). + 3. ReturnIfAbrupt(value). + 4. Let env be the running execution context's LexicalEnvironment. + 5. Return the result of performing BindingInitialization for BindingPattern + using value and env as the arguments. +---*/ + +const /*{ elems }*/ = /*{ vals }*/; + +/*{ body }*/ diff --git a/src/dstr-binding/default/func-decl.template b/src/dstr-binding/default/func-decl.template new file mode 100644 index 0000000000..7dd6b58f26 --- /dev/null +++ b/src/dstr-binding/default/func-decl.template @@ -0,0 +1,46 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/statements/function/dstr- +name: function declaration +es6id: 14.1.19 +info: | + FunctionDeclaration : + function BindingIdentifier ( FormalParameters ) { FunctionBody } + + [...] + 3. Let F be FunctionCreate(Normal, FormalParameters, FunctionBody, + scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +function f(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; +}; +f(/*{ vals }*/); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/func-expr.template b/src/dstr-binding/default/func-expr.template new file mode 100644 index 0000000000..58d7cd99ac --- /dev/null +++ b/src/dstr-binding/default/func-expr.template @@ -0,0 +1,47 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/function/dstr- +name: function expression +es6id: 14.1.20 +info: | + FunctionExpression : function ( FormalParameters ) { FunctionBody } + + [...] + 3. Let closure be FunctionCreate(Normal, FormalParameters, FunctionBody, + scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +var f; +f = function(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; +}; + +f(/*{ vals }*/); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/gen-func-decl.template b/src/dstr-binding/default/gen-func-decl.template new file mode 100644 index 0000000000..4e0403562e --- /dev/null +++ b/src/dstr-binding/default/gen-func-decl.template @@ -0,0 +1,45 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/statements/generators/dstr- +name: generator function declaration +es6id: 14.4.12 +info: | + GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody } + + [...] + 2. Let F be GeneratorFunctionCreate(Normal, FormalParameters, + GeneratorBody, scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +function* f(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; +}; +f(/*{ vals }*/).next(); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/gen-func-expr.template b/src/dstr-binding/default/gen-func-expr.template new file mode 100644 index 0000000000..b930bc59e2 --- /dev/null +++ b/src/dstr-binding/default/gen-func-expr.template @@ -0,0 +1,47 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/generators/dstr- +name: generator function expression +es6id: 14.4.14 +info: | + GeneratorExpression : function * ( FormalParameters ) { GeneratorBody } + + [...] + 3. Let closure be GeneratorFunctionCreate(Normal, FormalParameters, + GeneratorBody, scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +var f; +f = function*(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; +}; + +f(/*{ vals }*/).next(); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/gen-meth.template b/src/dstr-binding/default/gen-meth.template new file mode 100644 index 0000000000..5119178207 --- /dev/null +++ b/src/dstr-binding/default/gen-meth.template @@ -0,0 +1,53 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/object/dstr-gen-meth- +name: generator method +es6id: 14.4.13 +info: | + GeneratorMethod : + * PropertyName ( StrictFormalParameters ) { GeneratorBody } + + 1. Let propKey be the result of evaluating PropertyName. + 2. ReturnIfAbrupt(propKey). + 3. If the function code for this GeneratorMethod is strict mode code, + let strict be true. Otherwise let strict be false. + 4. Let scope be the running execution context's LexicalEnvironment. + 5. Let closure be GeneratorFunctionCreate(Method, + StrictFormalParameters, GeneratorBody, scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +var obj = { + *method(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; + } +}; + +obj.method(/*{ vals }*/).next(); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/let-stmt.template b/src/dstr-binding/default/let-stmt.template new file mode 100644 index 0000000000..33ffd86125 --- /dev/null +++ b/src/dstr-binding/default/let-stmt.template @@ -0,0 +1,21 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/statements/let/dstr- +name: > + `let` statement +es6id: 13.3.1.4 +info: | + LexicalBinding : BindingPattern Initializer + + 1. Let rhs be the result of evaluating Initializer. + 2. Let value be GetValue(rhs). + 3. ReturnIfAbrupt(value). + 4. Let env be the running execution context's LexicalEnvironment. + 5. Return the result of performing BindingInitialization for BindingPattern + using value and env as the arguments. +---*/ + +let /*{ elems }*/ = /*{ vals }*/; + +/*{ body }*/ diff --git a/src/dstr-binding/default/meth.template b/src/dstr-binding/default/meth.template new file mode 100644 index 0000000000..363cc16840 --- /dev/null +++ b/src/dstr-binding/default/meth.template @@ -0,0 +1,50 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/object/dstr-meth- +name: method +es6id: 14.3.8 +info: | + MethodDefinition : PropertyName ( StrictFormalParameters ) { FunctionBody } + + [...] + 6. Let closure be FunctionCreate(kind, StrictFormalParameters, + FunctionBody, scope, strict). If functionPrototype was passed as a + parameter then pass its value as the functionPrototype optional argument + of FunctionCreate. + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] +---*/ + +var callCount = 0; +var obj = { + method(/*{ elems }*/) { + /*{ body }*/ + callCount = callCount + 1; + } +}; + +obj.method(/*{ vals }*/); +assert.sameValue(callCount, 1); diff --git a/src/dstr-binding/default/var-stmt.template b/src/dstr-binding/default/var-stmt.template new file mode 100644 index 0000000000..a4511eb3b4 --- /dev/null +++ b/src/dstr-binding/default/var-stmt.template @@ -0,0 +1,20 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/statements/variable/dstr- +name: > + `var` statement +es6id: 13.3.2.4 +info: | + VariableDeclaration : BindingPattern Initializer + + 1. Let rhs be the result of evaluating Initializer. + 2. Let rval be GetValue(rhs). + 3. ReturnIfAbrupt(rval). + 4. Return the result of performing BindingInitialization for + BindingPattern passing rval and undefined as arguments. +---*/ + +var /*{ elems }*/ = /*{ vals }*/; + +/*{ body }*/ diff --git a/src/spread/default/call-expr.template b/src/spread/default/call-expr.template new file mode 100644 index 0000000000..4f1017889a --- /dev/null +++ b/src/spread/default/call-expr.template @@ -0,0 +1,28 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/call/spread- +name: CallExpression +es6id: 12.3.4.1 +info: | + CallExpression : MemberExpression Arguments + + [...] + 9. Return EvaluateDirectCall(func, thisValue, Arguments, tailCall). + + 12.3.4.3 Runtime Semantics: EvaluateDirectCall + + 1. Let argList be ArgumentListEvaluation(arguments). + [...] + 6. Let result be Call(func, thisValue, argList). + [...] +---*/ + +var callCount = 0; + +(function(/*{ params }*/) { + /*{ body }*/ + callCount += 1; +}(/*{ args }*/)); + +assert.sameValue(callCount, 1); diff --git a/src/spread/default/member-expr.template b/src/spread/default/member-expr.template new file mode 100644 index 0000000000..6069bff04f --- /dev/null +++ b/src/spread/default/member-expr.template @@ -0,0 +1,28 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/new/spread- +name: > + `new` operator +es6id: 12.3.3.1 +info: | + MemberExpression : new MemberExpression Arguments + + 1. Return EvaluateNew(MemberExpression, Arguments). + + 12.3.3.1.1 Runtime Semantics: EvaluateNew + + 6. If arguments is empty, let argList be an empty List. + 7. Else, + a. Let argList be ArgumentListEvaluation of arguments. + [...] +---*/ + +var callCount = 0; + +new function(/*{ params }*/) { + /*{ body }*/ + callCount += 1; +}(/*{ args }*/); + +assert.sameValue(callCount, 1); diff --git a/src/spread/default/super-call.template b/src/spread/default/super-call.template new file mode 100644 index 0000000000..7a91e9d3cf --- /dev/null +++ b/src/spread/default/super-call.template @@ -0,0 +1,34 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/super/spread- +name: SuperCall +es6id: 12.3.5.1 +info: | + SuperCall : super Arguments + + 1. Let newTarget be GetNewTarget(). + 2. If newTarget is undefined, throw a ReferenceError exception. + 3. Let func be GetSuperConstructor(). + 4. ReturnIfAbrupt(func). + 5. Let argList be ArgumentListEvaluation of Arguments. + [...] +---*/ + +var callCount = 0; + +class Test262ParentClass { + constructor(/*{ params }*/) { + /*{ body }*/ + callCount += 1; + } +} + +class Test262ChildClass extends Test262ParentClass { + constructor() { + super(/*{ args }*/); + } +} + +new Test262ChildClass(); +assert.sameValue(callCount, 1); diff --git a/src/spread/error/call-expr.template b/src/spread/error/call-expr.template new file mode 100644 index 0000000000..69d6e380ef --- /dev/null +++ b/src/spread/error/call-expr.template @@ -0,0 +1,23 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/call/spread-err- +name: CallExpression +es6id: 12.3.4.1 +info: | + CallExpression : MemberExpression Arguments + + [...] + 9. Return EvaluateDirectCall(func, thisValue, Arguments, tailCall). + + 12.3.4.3 Runtime Semantics: EvaluateDirectCall + + 1. Let argList be ArgumentListEvaluation(arguments). + [...] + 6. Let result be Call(func, thisValue, argList). + [...] +---*/ + +assert.throws(/*{ error }*/, function() { + (function(/*{ params }*/) {}(/*{ args }*/)); +}); diff --git a/src/spread/error/member-expr.template b/src/spread/error/member-expr.template new file mode 100644 index 0000000000..b70627f3cb --- /dev/null +++ b/src/spread/error/member-expr.template @@ -0,0 +1,23 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/new/spread-err- +name: > + `new` operator +es6id: 12.3.3.1 +info: | + MemberExpression : new MemberExpression Arguments + + 1. Return EvaluateNew(MemberExpression, Arguments). + + 12.3.3.1.1 Runtime Semantics: EvaluateNew + + 6. If arguments is empty, let argList be an empty List. + 7. Else, + a. Let argList be ArgumentListEvaluation of arguments. + [...] +---*/ + +assert.throws(/*{ error }*/, function() { + new function(/*{ params }*/) {}(/*{ args }*/); +}); diff --git a/src/spread/error/super-call.template b/src/spread/error/super-call.template new file mode 100644 index 0000000000..eb3ec04661 --- /dev/null +++ b/src/spread/error/super-call.template @@ -0,0 +1,30 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +path: language/expressions/super/spread-err- +name: SuperCall +es6id: 12.3.5.1 +info: | + SuperCall : super Arguments + + 1. Let newTarget be GetNewTarget(). + 2. If newTarget is undefined, throw a ReferenceError exception. + 3. Let func be GetSuperConstructor(). + 4. ReturnIfAbrupt(func). + 5. Let argList be ArgumentListEvaluation of Arguments. + [...] +---*/ + +class Test262ParentClass { + constructor(/*{ params }*/) {} +} + +class Test262ChildClass extends Test262ParentClass { + constructor() { + super(/*{ args }*/); + } +} + +assert.throws(/*{ error }*/, function() { + new Test262ChildClass(); +}); diff --git a/src/spread/sngl-err-expr-throws.case b/src/spread/sngl-err-expr-throws.case new file mode 100644 index 0000000000..389a9366eb --- /dev/null +++ b/src/spread/sngl-err-expr-throws.case @@ -0,0 +1,22 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +desc: Spread operator applied to the only argument when evaluation throws +template: error +features: [generators] +info: | + 12.3.6.1 Runtime Semantics: ArgumentListEvaluation + + ArgumentList : ... AssignmentExpression + + 1. Let list be an empty List. + 2. Let spreadRef be the result of evaluating AssignmentExpression. + 3. Let spreadObj be GetValue(spreadRef). + 4. Let iterator be GetIterator(spreadObj). + 5. ReturnIfAbrupt(iterator). +---*/ + +//- error +Test262Error +//- args +...function*() { throw new Test262Error(); }() diff --git a/src/spread/sngl-iter.case b/src/spread/sngl-iter.case new file mode 100644 index 0000000000..594b072370 --- /dev/null +++ b/src/spread/sngl-iter.case @@ -0,0 +1,42 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +desc: Spread operator applied to the only argument with a valid iterator +template: default +features: [Symbol.iterator] +info: | + 12.3.6.1 Runtime Semantics: ArgumentListEvaluation + + ArgumentList : ... AssignmentExpression + + 1. Let list be an empty List. + 2. Let spreadRef be the result of evaluating AssignmentExpression. + 3. Let spreadObj be GetValue(spreadRef). + 4. Let iterator be GetIterator(spreadObj). + 5. ReturnIfAbrupt(iterator). + 6. Repeat + a. Let next be IteratorStep(iterator). + b. ReturnIfAbrupt(next). + c. If next is false, return list. + d. Let nextArg be IteratorValue(next). + e. ReturnIfAbrupt(nextArg). + f. Append nextArg as the last element of list. +---*/ + +//- setup +var iter = {}; +iter[Symbol.iterator] = function() { + var callCount = 0; + return { + next: function() { + callCount += 1; + return { done: callCount === 3, value: callCount }; + } + }; +}; +//- args +...iter +//- body +assert.sameValue(arguments.length, 2); +assert.sameValue(arguments[0], 1); +assert.sameValue(arguments[1], 2); diff --git a/test/language/expressions/arrow-function/dstr-ary-name-iter-val.js b/test/language/expressions/arrow-function/dstr-ary-name-iter-val.js new file mode 100644 index 0000000000..fe684355ed --- /dev/null +++ b/test/language/expressions/arrow-function/dstr-ary-name-iter-val.js @@ -0,0 +1,69 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/arrow-function.template +/*--- +description: SingleNameBinding with normal value iteration (arrow function expression) +es6id: 14.2.16 +flags: [generated] +info: > + ArrowFunction : ArrowParameters => ConciseBody + + [...] + 4. Let closure be FunctionCreate(Arrow, parameters, ConciseBody, scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +var f; +f = ([x, y, z]) => { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; +}; + +f([1, 2, 3]); +assert.sameValue(callCount, 1); diff --git a/test/language/expressions/call/spread-err-sngl-err-expr-throws.js b/test/language/expressions/call/spread-err-sngl-err-expr-throws.js new file mode 100644 index 0000000000..2d70fa3d73 --- /dev/null +++ b/test/language/expressions/call/spread-err-sngl-err-expr-throws.js @@ -0,0 +1,36 @@ +// This file was procedurally generated from the following sources: +// - src/spread/sngl-err-expr-throws.case +// - src/spread/error/call-expr.template +/*--- +description: Spread operator applied to the only argument when evaluation throws (CallExpression) +es6id: 12.3.4.1 +features: [generators] + +flags: [generated] +info: > + CallExpression : MemberExpression Arguments + + [...] + 9. Return EvaluateDirectCall(func, thisValue, Arguments, tailCall). + + 12.3.4.3 Runtime Semantics: EvaluateDirectCall + + 1. Let argList be ArgumentListEvaluation(arguments). + [...] + 6. Let result be Call(func, thisValue, argList). + [...] + + 12.3.6.1 Runtime Semantics: ArgumentListEvaluation + + ArgumentList : ... AssignmentExpression + + 1. Let list be an empty List. + 2. Let spreadRef be the result of evaluating AssignmentExpression. + 3. Let spreadObj be GetValue(spreadRef). + 4. Let iterator be GetIterator(spreadObj). + 5. ReturnIfAbrupt(iterator). +---*/ + +assert.throws(Test262Error, function() { + (function() {}(...function*() { throw new Test262Error(); }())); +}); diff --git a/test/language/expressions/call/spread-sngl-iter.js b/test/language/expressions/call/spread-sngl-iter.js new file mode 100644 index 0000000000..d6d86102bf --- /dev/null +++ b/test/language/expressions/call/spread-sngl-iter.js @@ -0,0 +1,60 @@ +// This file was procedurally generated from the following sources: +// - src/spread/sngl-iter.case +// - src/spread/default/call-expr.template +/*--- +description: Spread operator applied to the only argument with a valid iterator (CallExpression) +es6id: 12.3.4.1 +features: [Symbol.iterator] + +flags: [generated] +info: > + CallExpression : MemberExpression Arguments + + [...] + 9. Return EvaluateDirectCall(func, thisValue, Arguments, tailCall). + + 12.3.4.3 Runtime Semantics: EvaluateDirectCall + + 1. Let argList be ArgumentListEvaluation(arguments). + [...] + 6. Let result be Call(func, thisValue, argList). + [...] + + 12.3.6.1 Runtime Semantics: ArgumentListEvaluation + + ArgumentList : ... AssignmentExpression + + 1. Let list be an empty List. + 2. Let spreadRef be the result of evaluating AssignmentExpression. + 3. Let spreadObj be GetValue(spreadRef). + 4. Let iterator be GetIterator(spreadObj). + 5. ReturnIfAbrupt(iterator). + 6. Repeat + a. Let next be IteratorStep(iterator). + b. ReturnIfAbrupt(next). + c. If next is false, return list. + d. Let nextArg be IteratorValue(next). + e. ReturnIfAbrupt(nextArg). + f. Append nextArg as the last element of list. +---*/ +var iter = {}; +iter[Symbol.iterator] = function() { + var callCount = 0; + return { + next: function() { + callCount += 1; + return { done: callCount === 3, value: callCount }; + } + }; +}; + +var callCount = 0; + +(function() { + assert.sameValue(arguments.length, 2); + assert.sameValue(arguments[0], 1); + assert.sameValue(arguments[1], 2); + callCount += 1; +}(...iter)); + +assert.sameValue(callCount, 1); diff --git a/test/language/expressions/class/dstr-gen-meth-ary-name-iter-val.js b/test/language/expressions/class/dstr-gen-meth-ary-name-iter-val.js new file mode 100644 index 0000000000..10b822b6f3 --- /dev/null +++ b/test/language/expressions/class/dstr-gen-meth-ary-name-iter-val.js @@ -0,0 +1,94 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/cls-expr-gen-meth.template +/*--- +description: SingleNameBinding with normal value iteration (class expression method) +es6id: 14.5.16 +flags: [generated] +info: > + ClassExpression : class BindingIdentifieropt ClassTail + + 1. If BindingIdentifieropt is not present, let className be undefined. + 2. Else, let className be StringValue of BindingIdentifier. + 3. Let value be the result of ClassDefinitionEvaluation of ClassTail + with argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + i. Let status be the result of performing + PropertyDefinitionEvaluation for m with arguments proto and + false. + [...] + + 14.4.13 Runtime Semantics: PropertyDefinitionEvaluation + + GeneratorMethod : + * PropertyName ( StrictFormalParameters ) { GeneratorBody } + + 1. Let propKey be the result of evaluating PropertyName. + 2. ReturnIfAbrupt(propKey). + 3. If the function code for this GeneratorMethod is strict mode code, + let strict be true. Otherwise let strict be false. + 4. Let scope be the running execution context's LexicalEnvironment. + 5. Let closure be GeneratorFunctionCreate(Method, + StrictFormalParameters, GeneratorBody, scope, strict). + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +var C = class { + *method([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; + } +}; + +new C().method([1, 2, 3]).next(); +assert.sameValue(callCount, 1); diff --git a/test/language/expressions/class/dstr-gen-meth-static-ary-name-iter-val.js b/test/language/expressions/class/dstr-gen-meth-static-ary-name-iter-val.js new file mode 100644 index 0000000000..dab262ab38 --- /dev/null +++ b/test/language/expressions/class/dstr-gen-meth-static-ary-name-iter-val.js @@ -0,0 +1,94 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/cls-expr-gen-meth-static.template +/*--- +description: SingleNameBinding with normal value iteration (static class expression generator method) +es6id: 14.5.16 +flags: [generated] +info: > + ClassExpression : class BindingIdentifieropt ClassTail + + 1. If BindingIdentifieropt is not present, let className be undefined. + 2. Else, let className be StringValue of BindingIdentifier. + 3. Let value be the result of ClassDefinitionEvaluation of ClassTail + with argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + b. Else, + Let status be the result of performing PropertyDefinitionEvaluation + for m with arguments F and false. + [...] + + 14.4.13 Runtime Semantics: PropertyDefinitionEvaluation + + GeneratorMethod : + * PropertyName ( StrictFormalParameters ) { GeneratorBody } + + 1. Let propKey be the result of evaluating PropertyName. + 2. ReturnIfAbrupt(propKey). + 3. If the function code for this GeneratorMethod is strict mode code, + let strict be true. Otherwise let strict be false. + 4. Let scope be the running execution context's LexicalEnvironment. + 5. Let closure be GeneratorFunctionCreate(Method, + StrictFormalParameters, GeneratorBody, scope, strict). + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +var C = class { + static *method([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; + } +}; + +C.method([1, 2, 3]).next(); +assert.sameValue(callCount, 1); diff --git a/test/language/expressions/class/dstr-meth-ary-name-iter-val.js b/test/language/expressions/class/dstr-meth-ary-name-iter-val.js new file mode 100644 index 0000000000..4bbf523732 --- /dev/null +++ b/test/language/expressions/class/dstr-meth-ary-name-iter-val.js @@ -0,0 +1,91 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/cls-expr-meth.template +/*--- +description: SingleNameBinding with normal value iteration (class expression method) +es6id: 14.5.16 +flags: [generated] +info: > + ClassExpression : class BindingIdentifieropt ClassTail + + 1. If BindingIdentifieropt is not present, let className be undefined. + 2. Else, let className be StringValue of BindingIdentifier. + 3. Let value be the result of ClassDefinitionEvaluation of ClassTail + with argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + i. Let status be the result of performing + PropertyDefinitionEvaluation for m with arguments proto and + false. + [...] + + 14.3.8 Runtime Semantics: DefineMethod + + MethodDefinition : PropertyName ( StrictFormalParameters ) { FunctionBody } + + [...] + 6. Let closure be FunctionCreate(kind, StrictFormalParameters, FunctionBody, + scope, strict). If functionPrototype was passed as a parameter then pass its + value as the functionPrototype optional argument of FunctionCreate. + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +var C = class { + method([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; + } +}; + +new C().method([1, 2, 3]); +assert.sameValue(callCount, 1); diff --git a/test/language/expressions/class/dstr-meth-static-ary-name-iter-val.js b/test/language/expressions/class/dstr-meth-static-ary-name-iter-val.js new file mode 100644 index 0000000000..bcf43ba715 --- /dev/null +++ b/test/language/expressions/class/dstr-meth-static-ary-name-iter-val.js @@ -0,0 +1,91 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/cls-expr-meth-static.template +/*--- +description: SingleNameBinding with normal value iteration (static class expression method) +es6id: 14.5.16 +flags: [generated] +info: > + ClassExpression : class BindingIdentifieropt ClassTail + + 1. If BindingIdentifieropt is not present, let className be undefined. + 2. Else, let className be StringValue of BindingIdentifier. + 3. Let value be the result of ClassDefinitionEvaluation of ClassTail + with argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + b. Else, + Let status be the result of performing PropertyDefinitionEvaluation for + m with arguments F and false. + [...] + + 14.3.8 Runtime Semantics: DefineMethod + + MethodDefinition : PropertyName ( StrictFormalParameters ) { FunctionBody } + + [...] + 6. Let closure be FunctionCreate(kind, StrictFormalParameters, FunctionBody, + scope, strict). If functionPrototype was passed as a parameter then pass its + value as the functionPrototype optional argument of FunctionCreate. + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +var C = class { + static method([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; + } +}; + +C.method([1, 2, 3]); +assert.sameValue(callCount, 1); diff --git a/test/language/expressions/function/dstr-ary-name-iter-val.js b/test/language/expressions/function/dstr-ary-name-iter-val.js new file mode 100644 index 0000000000..b6861fbd0e --- /dev/null +++ b/test/language/expressions/function/dstr-ary-name-iter-val.js @@ -0,0 +1,70 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/func-expr.template +/*--- +description: SingleNameBinding with normal value iteration (function expression) +es6id: 14.1.20 +flags: [generated] +info: > + FunctionExpression : function ( FormalParameters ) { FunctionBody } + + [...] + 3. Let closure be FunctionCreate(Normal, FormalParameters, FunctionBody, + scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +var f; +f = function([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; +}; + +f([1, 2, 3]); +assert.sameValue(callCount, 1); diff --git a/test/language/expressions/generators/dstr-ary-name-iter-val.js b/test/language/expressions/generators/dstr-ary-name-iter-val.js new file mode 100644 index 0000000000..afa9503847 --- /dev/null +++ b/test/language/expressions/generators/dstr-ary-name-iter-val.js @@ -0,0 +1,70 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/gen-func-expr.template +/*--- +description: SingleNameBinding with normal value iteration (generator function expression) +es6id: 14.4.14 +flags: [generated] +info: > + GeneratorExpression : function * ( FormalParameters ) { GeneratorBody } + + [...] + 3. Let closure be GeneratorFunctionCreate(Normal, FormalParameters, + GeneratorBody, scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +var f; +f = function*([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; +}; + +f([1, 2, 3]).next(); +assert.sameValue(callCount, 1); diff --git a/test/language/expressions/new/spread-err-sngl-err-expr-throws.js b/test/language/expressions/new/spread-err-sngl-err-expr-throws.js new file mode 100644 index 0000000000..a2b21ad2a2 --- /dev/null +++ b/test/language/expressions/new/spread-err-sngl-err-expr-throws.js @@ -0,0 +1,35 @@ +// This file was procedurally generated from the following sources: +// - src/spread/sngl-err-expr-throws.case +// - src/spread/error/member-expr.template +/*--- +description: Spread operator applied to the only argument when evaluation throws (`new` operator) +es6id: 12.3.3.1 +features: [generators] + +flags: [generated] +info: > + MemberExpression : new MemberExpression Arguments + + 1. Return EvaluateNew(MemberExpression, Arguments). + + 12.3.3.1.1 Runtime Semantics: EvaluateNew + + 6. If arguments is empty, let argList be an empty List. + 7. Else, + a. Let argList be ArgumentListEvaluation of arguments. + [...] + + 12.3.6.1 Runtime Semantics: ArgumentListEvaluation + + ArgumentList : ... AssignmentExpression + + 1. Let list be an empty List. + 2. Let spreadRef be the result of evaluating AssignmentExpression. + 3. Let spreadObj be GetValue(spreadRef). + 4. Let iterator be GetIterator(spreadObj). + 5. ReturnIfAbrupt(iterator). +---*/ + +assert.throws(Test262Error, function() { + new function() {}(...function*() { throw new Test262Error(); }()); +}); diff --git a/test/language/expressions/new/spread-sngl-iter.js b/test/language/expressions/new/spread-sngl-iter.js new file mode 100644 index 0000000000..af9cfe2332 --- /dev/null +++ b/test/language/expressions/new/spread-sngl-iter.js @@ -0,0 +1,59 @@ +// This file was procedurally generated from the following sources: +// - src/spread/sngl-iter.case +// - src/spread/default/member-expr.template +/*--- +description: Spread operator applied to the only argument with a valid iterator (`new` operator) +es6id: 12.3.3.1 +features: [Symbol.iterator] + +flags: [generated] +info: > + MemberExpression : new MemberExpression Arguments + + 1. Return EvaluateNew(MemberExpression, Arguments). + + 12.3.3.1.1 Runtime Semantics: EvaluateNew + + 6. If arguments is empty, let argList be an empty List. + 7. Else, + a. Let argList be ArgumentListEvaluation of arguments. + [...] + + 12.3.6.1 Runtime Semantics: ArgumentListEvaluation + + ArgumentList : ... AssignmentExpression + + 1. Let list be an empty List. + 2. Let spreadRef be the result of evaluating AssignmentExpression. + 3. Let spreadObj be GetValue(spreadRef). + 4. Let iterator be GetIterator(spreadObj). + 5. ReturnIfAbrupt(iterator). + 6. Repeat + a. Let next be IteratorStep(iterator). + b. ReturnIfAbrupt(next). + c. If next is false, return list. + d. Let nextArg be IteratorValue(next). + e. ReturnIfAbrupt(nextArg). + f. Append nextArg as the last element of list. +---*/ +var iter = {}; +iter[Symbol.iterator] = function() { + var callCount = 0; + return { + next: function() { + callCount += 1; + return { done: callCount === 3, value: callCount }; + } + }; +}; + +var callCount = 0; + +new function() { + assert.sameValue(arguments.length, 2); + assert.sameValue(arguments[0], 1); + assert.sameValue(arguments[1], 2); + callCount += 1; +}(...iter); + +assert.sameValue(callCount, 1); diff --git a/test/language/expressions/object/dstr-gen-meth-ary-name-iter-val.js b/test/language/expressions/object/dstr-gen-meth-ary-name-iter-val.js new file mode 100644 index 0000000000..6533c3c74d --- /dev/null +++ b/test/language/expressions/object/dstr-gen-meth-ary-name-iter-val.js @@ -0,0 +1,76 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/gen-meth.template +/*--- +description: SingleNameBinding with normal value iteration (generator method) +es6id: 14.4.13 +flags: [generated] +info: > + GeneratorMethod : + * PropertyName ( StrictFormalParameters ) { GeneratorBody } + + 1. Let propKey be the result of evaluating PropertyName. + 2. ReturnIfAbrupt(propKey). + 3. If the function code for this GeneratorMethod is strict mode code, + let strict be true. Otherwise let strict be false. + 4. Let scope be the running execution context's LexicalEnvironment. + 5. Let closure be GeneratorFunctionCreate(Method, + StrictFormalParameters, GeneratorBody, scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +var obj = { + *method([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; + } +}; + +obj.method([1, 2, 3]).next(); +assert.sameValue(callCount, 1); diff --git a/test/language/expressions/object/dstr-meth-ary-name-iter-val.js b/test/language/expressions/object/dstr-meth-ary-name-iter-val.js new file mode 100644 index 0000000000..d9bfb6f4d9 --- /dev/null +++ b/test/language/expressions/object/dstr-meth-ary-name-iter-val.js @@ -0,0 +1,73 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/meth.template +/*--- +description: SingleNameBinding with normal value iteration (method) +es6id: 14.3.8 +flags: [generated] +info: > + MethodDefinition : PropertyName ( StrictFormalParameters ) { FunctionBody } + + [...] + 6. Let closure be FunctionCreate(kind, StrictFormalParameters, + FunctionBody, scope, strict). If functionPrototype was passed as a + parameter then pass its value as the functionPrototype optional argument + of FunctionCreate. + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +var obj = { + method([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; + } +}; + +obj.method([1, 2, 3]); +assert.sameValue(callCount, 1); diff --git a/test/language/expressions/super/spread-err-sngl-err-expr-throws.js b/test/language/expressions/super/spread-err-sngl-err-expr-throws.js new file mode 100644 index 0000000000..33809221ea --- /dev/null +++ b/test/language/expressions/super/spread-err-sngl-err-expr-throws.js @@ -0,0 +1,43 @@ +// This file was procedurally generated from the following sources: +// - src/spread/sngl-err-expr-throws.case +// - src/spread/error/super-call.template +/*--- +description: Spread operator applied to the only argument when evaluation throws (SuperCall) +es6id: 12.3.5.1 +features: [generators] + +flags: [generated] +info: > + SuperCall : super Arguments + + 1. Let newTarget be GetNewTarget(). + 2. If newTarget is undefined, throw a ReferenceError exception. + 3. Let func be GetSuperConstructor(). + 4. ReturnIfAbrupt(func). + 5. Let argList be ArgumentListEvaluation of Arguments. + [...] + + 12.3.6.1 Runtime Semantics: ArgumentListEvaluation + + ArgumentList : ... AssignmentExpression + + 1. Let list be an empty List. + 2. Let spreadRef be the result of evaluating AssignmentExpression. + 3. Let spreadObj be GetValue(spreadRef). + 4. Let iterator be GetIterator(spreadObj). + 5. ReturnIfAbrupt(iterator). +---*/ + +class Test262ParentClass { + constructor() {} +} + +class Test262ChildClass extends Test262ParentClass { + constructor() { + super(...function*() { throw new Test262Error(); }()); + } +} + +assert.throws(Test262Error, function() { + new Test262ChildClass(); +}); diff --git a/test/language/expressions/super/spread-sngl-iter.js b/test/language/expressions/super/spread-sngl-iter.js new file mode 100644 index 0000000000..b4ae03e8b4 --- /dev/null +++ b/test/language/expressions/super/spread-sngl-iter.js @@ -0,0 +1,66 @@ +// This file was procedurally generated from the following sources: +// - src/spread/sngl-iter.case +// - src/spread/default/super-call.template +/*--- +description: Spread operator applied to the only argument with a valid iterator (SuperCall) +es6id: 12.3.5.1 +features: [Symbol.iterator] + +flags: [generated] +info: > + SuperCall : super Arguments + + 1. Let newTarget be GetNewTarget(). + 2. If newTarget is undefined, throw a ReferenceError exception. + 3. Let func be GetSuperConstructor(). + 4. ReturnIfAbrupt(func). + 5. Let argList be ArgumentListEvaluation of Arguments. + [...] + + 12.3.6.1 Runtime Semantics: ArgumentListEvaluation + + ArgumentList : ... AssignmentExpression + + 1. Let list be an empty List. + 2. Let spreadRef be the result of evaluating AssignmentExpression. + 3. Let spreadObj be GetValue(spreadRef). + 4. Let iterator be GetIterator(spreadObj). + 5. ReturnIfAbrupt(iterator). + 6. Repeat + a. Let next be IteratorStep(iterator). + b. ReturnIfAbrupt(next). + c. If next is false, return list. + d. Let nextArg be IteratorValue(next). + e. ReturnIfAbrupt(nextArg). + f. Append nextArg as the last element of list. +---*/ +var iter = {}; +iter[Symbol.iterator] = function() { + var callCount = 0; + return { + next: function() { + callCount += 1; + return { done: callCount === 3, value: callCount }; + } + }; +}; + +var callCount = 0; + +class Test262ParentClass { + constructor() { + assert.sameValue(arguments.length, 2); + assert.sameValue(arguments[0], 1); + assert.sameValue(arguments[1], 2); + callCount += 1; + } +} + +class Test262ChildClass extends Test262ParentClass { + constructor() { + super(...iter); + } +} + +new Test262ChildClass(); +assert.sameValue(callCount, 1); diff --git a/test/language/statements/class/dstr-gen-meth-ary-name-iter-val.js b/test/language/statements/class/dstr-gen-meth-ary-name-iter-val.js new file mode 100644 index 0000000000..5420f0f2a8 --- /dev/null +++ b/test/language/statements/class/dstr-gen-meth-ary-name-iter-val.js @@ -0,0 +1,92 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/cls-decl-gen-meth.template +/*--- +description: SingleNameBinding with normal value iteration (class expression method) +es6id: 14.5.16 +flags: [generated] +info: > + ClassDeclaration : class BindingIdentifier ClassTail + + 1. Let className be StringValue of BindingIdentifier. + 2. Let value be the result of ClassDefinitionEvaluation of ClassTail with + argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + i. Let status be the result of performing + PropertyDefinitionEvaluation for m with arguments proto and + false. + [...] + + 14.4.13 Runtime Semantics: PropertyDefinitionEvaluation + + GeneratorMethod : * PropertyName ( StrictFormalParameters ) { GeneratorBody } + + 1. Let propKey be the result of evaluating PropertyName. + 2. ReturnIfAbrupt(propKey). + 3. If the function code for this GeneratorMethod is strict mode code, + let strict be true. Otherwise let strict be false. + 4. Let scope be the running execution context's LexicalEnvironment. + 5. Let closure be GeneratorFunctionCreate(Method, + StrictFormalParameters, GeneratorBody, scope, strict). + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +class C { + *method([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; + } +}; + +new C().method([1, 2, 3]).next(); +assert.sameValue(callCount, 1); diff --git a/test/language/statements/class/dstr-gen-meth-static-ary-name-iter-val.js b/test/language/statements/class/dstr-gen-meth-static-ary-name-iter-val.js new file mode 100644 index 0000000000..33490cd0c4 --- /dev/null +++ b/test/language/statements/class/dstr-gen-meth-static-ary-name-iter-val.js @@ -0,0 +1,92 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/cls-decl-gen-meth-static.template +/*--- +description: SingleNameBinding with normal value iteration (static class expression generator method) +es6id: 14.5.15 +flags: [generated] +info: > + ClassDeclaration : class BindingIdentifier ClassTail + + 1. Let className be StringValue of BindingIdentifier. + 2. Let value be the result of ClassDefinitionEvaluation of ClassTail with + argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + b. Else, + Let status be the result of performing PropertyDefinitionEvaluation for + m with arguments F and false. + [...] + + 14.4.13 Runtime Semantics: PropertyDefinitionEvaluation + + GeneratorMethod : * PropertyName ( StrictFormalParameters ) { GeneratorBody } + + 1. Let propKey be the result of evaluating PropertyName. + 2. ReturnIfAbrupt(propKey). + 3. If the function code for this GeneratorMethod is strict mode code, + let strict be true. Otherwise let strict be false. + 4. Let scope be the running execution context's LexicalEnvironment. + 5. Let closure be GeneratorFunctionCreate(Method, + StrictFormalParameters, GeneratorBody, scope, strict). + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +class C { + static *method([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; + } +}; + +C.method([1, 2, 3]).next(); +assert.sameValue(callCount, 1); diff --git a/test/language/statements/class/dstr-meth-ary-name-iter-val.js b/test/language/statements/class/dstr-meth-ary-name-iter-val.js new file mode 100644 index 0000000000..d811ee11f4 --- /dev/null +++ b/test/language/statements/class/dstr-meth-ary-name-iter-val.js @@ -0,0 +1,90 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/cls-decl-meth.template +/*--- +description: SingleNameBinding with normal value iteration (class expression method) +es6id: 14.5.15 +flags: [generated] +info: > + ClassDeclaration : class BindingIdentifier ClassTail + + 1. Let className be StringValue of BindingIdentifier. + 2. Let value be the result of ClassDefinitionEvaluation of ClassTail with + argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + i. Let status be the result of performing + PropertyDefinitionEvaluation for m with arguments proto and + false. + [...] + + 14.3.8 Runtime Semantics: DefineMethod + + MethodDefinition : PropertyName ( StrictFormalParameters ) { FunctionBody } + + [...] + 6. Let closure be FunctionCreate(kind, StrictFormalParameters, FunctionBody, + scope, strict). If functionPrototype was passed as a parameter then pass its + value as the functionPrototype optional argument of FunctionCreate. + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +class C { + method([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; + } +}; + +new C().method([1, 2, 3]); +assert.sameValue(callCount, 1); diff --git a/test/language/statements/class/dstr-meth-static-ary-name-iter-val.js b/test/language/statements/class/dstr-meth-static-ary-name-iter-val.js new file mode 100644 index 0000000000..f760fc0e97 --- /dev/null +++ b/test/language/statements/class/dstr-meth-static-ary-name-iter-val.js @@ -0,0 +1,90 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/cls-decl-meth-static.template +/*--- +description: SingleNameBinding with normal value iteration (static class expression method) +es6id: 14.5.15 +flags: [generated] +info: > + ClassDeclaration : class BindingIdentifier ClassTail + + 1. Let className be StringValue of BindingIdentifier. + 2. Let value be the result of ClassDefinitionEvaluation of ClassTail with + argument className. + [...] + + 14.5.14 Runtime Semantics: ClassDefinitionEvaluation + + 21. For each ClassElement m in order from methods + a. If IsStatic of m is false, then + b. Else, + Let status be the result of performing PropertyDefinitionEvaluation for + m with arguments F and false. + [...] + + 14.3.8 Runtime Semantics: DefineMethod + + MethodDefinition : PropertyName ( StrictFormalParameters ) { FunctionBody } + + [...] + 6. Let closure be FunctionCreate(kind, StrictFormalParameters, FunctionBody, + scope, strict). If functionPrototype was passed as a parameter then pass its + value as the functionPrototype optional argument of FunctionCreate. + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +class C { + static method([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; + } +}; + +C.method([1, 2, 3]); +assert.sameValue(callCount, 1); diff --git a/test/language/statements/const/dstr-ary-name-iter-val.js b/test/language/statements/const/dstr-ary-name-iter-val.js new file mode 100644 index 0000000000..9c0dfe7d91 --- /dev/null +++ b/test/language/statements/const/dstr-ary-name-iter-val.js @@ -0,0 +1,43 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/const-stmt.template +/*--- +description: SingleNameBinding with normal value iteration (`const` statement) +es6id: 13.3.1.4 +flags: [generated] +info: > + LexicalBinding : BindingPattern Initializer + + 1. Let rhs be the result of evaluating Initializer. + 2. Let value be GetValue(rhs). + 3. ReturnIfAbrupt(value). + 4. Let env be the running execution context's LexicalEnvironment. + 5. Return the result of performing BindingInitialization for BindingPattern + using value and env as the arguments. + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +const [x, y, z] = [1, 2, 3]; + +assert.sameValue(x, 1); +assert.sameValue(y, 2); +assert.sameValue(z, 3); diff --git a/test/language/statements/function/dstr-ary-name-iter-val.js b/test/language/statements/function/dstr-ary-name-iter-val.js new file mode 100644 index 0000000000..a1d408404b --- /dev/null +++ b/test/language/statements/function/dstr-ary-name-iter-val.js @@ -0,0 +1,69 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/func-decl.template +/*--- +description: SingleNameBinding with normal value iteration (function declaration) +es6id: 14.1.19 +flags: [generated] +info: > + FunctionDeclaration : + function BindingIdentifier ( FormalParameters ) { FunctionBody } + + [...] + 3. Let F be FunctionCreate(Normal, FormalParameters, FunctionBody, + scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +function f([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; +}; +f([1, 2, 3]); +assert.sameValue(callCount, 1); diff --git a/test/language/statements/generators/dstr-ary-name-iter-val.js b/test/language/statements/generators/dstr-ary-name-iter-val.js new file mode 100644 index 0000000000..74098d854c --- /dev/null +++ b/test/language/statements/generators/dstr-ary-name-iter-val.js @@ -0,0 +1,68 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/gen-func-decl.template +/*--- +description: SingleNameBinding with normal value iteration (generator function declaration) +es6id: 14.4.12 +flags: [generated] +info: > + GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody } + + [...] + 2. Let F be GeneratorFunctionCreate(Normal, FormalParameters, + GeneratorBody, scope, strict). + [...] + + 9.2.1 [[Call]] ( thisArgument, argumentsList) + + [...] + 7. Let result be OrdinaryCallEvaluateBody(F, argumentsList). + [...] + + 9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList ) + + 1. Let status be FunctionDeclarationInstantiation(F, argumentsList). + [...] + + 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) + + [...] + 23. Let iteratorRecord be Record {[[iterator]]: + CreateListIterator(argumentsList), [[done]]: false}. + 24. If hasDuplicates is true, then + [...] + 25. Else, + b. Let formalStatus be IteratorBindingInitialization for formals with + iteratorRecord and env as arguments. + [...] + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var callCount = 0; +function* f([x, y, z]) { + assert.sameValue(x, 1); + assert.sameValue(y, 2); + assert.sameValue(z, 3); + callCount = callCount + 1; +}; +f([1, 2, 3]).next(); +assert.sameValue(callCount, 1); diff --git a/test/language/statements/let/dstr-ary-name-iter-val.js b/test/language/statements/let/dstr-ary-name-iter-val.js new file mode 100644 index 0000000000..0fa4fcd8e0 --- /dev/null +++ b/test/language/statements/let/dstr-ary-name-iter-val.js @@ -0,0 +1,43 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/let-stmt.template +/*--- +description: SingleNameBinding with normal value iteration (`let` statement) +es6id: 13.3.1.4 +flags: [generated] +info: > + LexicalBinding : BindingPattern Initializer + + 1. Let rhs be the result of evaluating Initializer. + 2. Let value be GetValue(rhs). + 3. ReturnIfAbrupt(value). + 4. Let env be the running execution context's LexicalEnvironment. + 5. Return the result of performing BindingInitialization for BindingPattern + using value and env as the arguments. + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +let [x, y, z] = [1, 2, 3]; + +assert.sameValue(x, 1); +assert.sameValue(y, 2); +assert.sameValue(z, 3); diff --git a/test/language/statements/variable/dstr-ary-name-iter-val.js b/test/language/statements/variable/dstr-ary-name-iter-val.js new file mode 100644 index 0000000000..a0a70ce74e --- /dev/null +++ b/test/language/statements/variable/dstr-ary-name-iter-val.js @@ -0,0 +1,42 @@ +// This file was procedurally generated from the following sources: +// - src/dstr-binding/ary-name-iter-val.case +// - src/dstr-binding/default/var-stmt.template +/*--- +description: SingleNameBinding with normal value iteration (`var` statement) +es6id: 13.3.2.4 +flags: [generated] +info: > + VariableDeclaration : BindingPattern Initializer + + 1. Let rhs be the result of evaluating Initializer. + 2. Let rval be GetValue(rhs). + 3. ReturnIfAbrupt(rval). + 4. Return the result of performing BindingInitialization for + BindingPattern passing rval and undefined as arguments. + + 13.3.3.6 Runtime Semantics: IteratorBindingInitialization + + SingleNameBinding : BindingIdentifier Initializeropt + + [...] + 4. If iteratorRecord.[[done]] is false, then + a. Let next be IteratorStep(iteratorRecord.[[iterator]]). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, set iteratorRecord.[[done]] to true. + e. Else, + [...] + i. Let v be IteratorValue(next). + ii. If v is an abrupt completion, set + iteratorRecord.[[done]] to true. + iii. ReturnIfAbrupt(v). + 5. If iteratorRecord.[[done]] is true, let v be undefined. + [...] + 8. Return InitializeReferencedBinding(lhs, v). +---*/ + +var [x, y, z] = [1, 2, 3]; + +assert.sameValue(x, 1); +assert.sameValue(y, 2); +assert.sameValue(z, 3); diff --git a/tools/generation/generator.py b/tools/generation/generator.py new file mode 100755 index 0000000000..754f00fcf5 --- /dev/null +++ b/tools/generation/generator.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# Copyright (C) 2016 the V8 project authors. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +from __future__ import print_function +import argparse +import os, sys + +from lib.expander import Expander +from lib.test import Test + +def print_error(*values): + print('ERROR:', *values, file=sys.stderr) + +def find_cases(location): + # When a file is specified, return the file name and its containing + # directory + if os.path.isfile(location): + return location, [os.path.dirname(location)] + + # When a directory is specified, if that directory contains a sub-directory + # names "default" interpret it as a "case directory" + if (os.path.isdir(os.path.join(location, 'default'))): + return None, [location] + else: + return None, map( + lambda x: os.path.join(args.cases, x), os.listdir(args.cases)) + +def clean(args): + for (subdir, _, fileNames) in os.walk(args.directory): + for fileName in map(lambda x: os.path.join(subdir, x), fileNames): + test = Test(fileName) + test.load() + if test.is_generated(): + print('Deleting file "' + fileName + '"...') + os.remove(fileName) + +def create(args): + caseFile, caseDirs = find_cases(args.cases) + + for caseDir in caseDirs: + exp = Expander(caseDir) + for test in exp.expand('utf-8', caseFile): + if args.out: + try: + test.load(args.out) + + if args.no_clobber: + print_error( + 'Refusing to overwrite file: ' + test.file_name) + exit(1) + + if not test.is_generated(): + print_error( + 'Refusing to overwrite non-generated file: ' + + test.file_name) + exit(1) + except IOError: + pass + + test.write(args.out, parents=args.parents) + else: + print(test.to_string()) + +parser = argparse.ArgumentParser(description='Test262 test generator tool') +subparsers = parser.add_subparsers() + +create_parser = subparsers.add_parser('create', + help='''Generate test material''') +create_parser.add_argument('-o', '--out', help='''The directory to write the + compiled tests. If unspecified, tests will be written to standard out.''') +create_parser.add_argument('-p', '--parents', action='store_true', + help='''Create non-existent directories as necessary.''') +create_parser.add_argument('-n', '--no-clobber', action='store_true', + help='''Do not produce test if a corresponding file exists within this + directory.''') +create_parser.add_argument('cases', + help='''Test cases to generate. May be a file or a directory.''') +create_parser.set_defaults(func=create) + +clean_parser = subparsers.add_parser('clean', + help='''Remove previously-generated files''') +clean_parser.add_argument('directory', + help='''Remove any generated tests from this directory''') +clean_parser.set_defaults(func=clean) + +args = parser.parse_args() +args.func(args) diff --git a/tools/generation/lib/__init__.py b/tools/generation/lib/__init__.py new file mode 100644 index 0000000000..2ae28399f5 --- /dev/null +++ b/tools/generation/lib/__init__.py @@ -0,0 +1 @@ +pass diff --git a/tools/generation/lib/case.py b/tools/generation/lib/case.py new file mode 100644 index 0000000000..f43d4f664b --- /dev/null +++ b/tools/generation/lib/case.py @@ -0,0 +1,44 @@ +# Copyright (C) 2016 the V8 project authors. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +import re + +from util.find_comments import find_comments +from util.parse_yaml import parse_yaml + +regionStartPattern = re.compile(r'-\s+(\S+)') + +class Case: + def __init__(self, file_name): + self.attribs = dict(meta=None, regions=dict()) + + with open(file_name) as handle: + self.attribs = self._parse(handle.read()) + + def _parse(self, source): + case = dict(meta=None, regions=dict()) + region_name = None + region_start = 0 + lines = source.split('\n') + + for comment in find_comments(source): + meta = parse_yaml(comment['source']) + if meta: + case['meta'] = meta + continue + + match = regionStartPattern.match(comment['source']) + if match: + if region_name: + case['regions'][region_name] = \ + '\n'.join(lines[region_start:comment['lineno'] - 1]) + + region_name = match.group(1) + region_start = comment['lineno'] + continue + + if region_name: + case['regions'][region_name] = \ + '\n'.join(lines[region_start:-1]) + + return case diff --git a/tools/generation/lib/expander.py b/tools/generation/lib/expander.py new file mode 100644 index 0000000000..5703a698b6 --- /dev/null +++ b/tools/generation/lib/expander.py @@ -0,0 +1,58 @@ +# Copyright (C) 2016 the V8 project authors. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +import re, os + +from case import Case +from template import Template + +caseFilenamePattern = re.compile(r'^[^\.].*\.case$') +templateFilenamePattern = re.compile(r'^[^\.].*\.template$') + +class Expander: + def __init__(self, case_dir): + self.templates = dict() + self.case_dir = case_dir + + def _load_templates(self, template_class): + directory = os.path.join(self.case_dir, template_class) + file_names = map( + lambda x: os.path.join(directory, x), + filter(self.is_template_file, os.listdir(directory)) + ) + + self.templates[template_class] = [Template(x) for x in file_names] + + def _get_templates(self, template_class): + if not template_class in self.templates: + self._load_templates(template_class) + + return self.templates[template_class] + + def is_template_file(self, filename): + return re.match(templateFilenamePattern, filename) + + def list_cases(self): + for name in os.listdir(self.case_dir): + full = os.path.join(self.case_dir, name) + if os.path.isfile(full) and caseFilenamePattern.match(name): + yield full + + def expand(self, encoding, case_file = None): + if case_file: + case_files = [case_file] + else: + case_files = self.list_cases() + + for case_file in case_files: + for test in self.expand_case(case_file, encoding): + yield test + + def expand_case(self, file_name, encoding): + case = Case(file_name) + + template_class = case.attribs['meta']['template'] + templates = self.templates.get(template_class) + + for template in self._get_templates(template_class): + yield template.expand(file_name, os.path.basename(file_name[:-5]), case.attribs, encoding) diff --git a/tools/generation/lib/template.py b/tools/generation/lib/template.py new file mode 100644 index 0000000000..fa891f00be --- /dev/null +++ b/tools/generation/lib/template.py @@ -0,0 +1,160 @@ +# Copyright (C) 2016 the V8 project authors. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +import os, re +import codecs, yaml + +from util.find_comments import find_comments +from util.parse_yaml import parse_yaml +from test import Test + +indentPattern = re.compile(r'^(\s*)') +interpolatePattern = re.compile(r'\{\s*(\S+)\s*\}') + +def indent(text, prefix = ' '): + '''Prefix a block of text (as defined by the "line break" control + character) with some character sequence.''' + + if isinstance(text, list): + lines = text + else: + lines = text.split('\n') + + return prefix + ('\n' + prefix).join(lines) + +class Template: + def __init__(self, filename): + self.filename = filename + + with open(filename) as template_file: + self.source = template_file.read() + + self.attribs = dict() + self.regions = [] + + self._parse() + + def _remove_comment(self, comment): + '''Create a region that is not intended to be referenced by any case, + ensuring that the comment is not emitted in the rendered file.''' + name = '__remove_comment_' + str(comment['firstchar']) + '__' + + # When a removed comment ends the line, the following newline character + # should also be removed from the generated file. + lastchar = comment['lastchar'] + if self.source[lastchar] == '\n': + comment['lastchar'] = comment['lastchar'] + 1 + + self.regions.insert(0, dict(name=name, **comment)) + + def _parse(self): + for comment in find_comments(self.source): + meta = parse_yaml(comment['source']) + + # Do not emit the template's frontmatter in generated files + # (file-specific frontmatter is generated as part of the rendering + # process) + if meta: + self.attribs['meta'] = meta + self._remove_comment(comment) + continue + + # Do not emit license information in generated files (recognized as + # comments preceeding the YAML frontmatter) + if not self.attribs.get('meta'): + self._remove_comment(comment) + continue + + match = interpolatePattern.match(comment['source']) + + if match == None: + continue + + self.regions.insert(0, dict(name=match.group(1), **comment)) + + def expand_regions(self, source, context): + lines = source.split('\n') + + for region in self.regions: + whitespace = indentPattern.match(lines[region['lineno']]).group(1) + value = context['regions'].get(region['name'], '') + source = source[:region['firstchar']] + \ + indent(value, whitespace).lstrip() + \ + source[region['lastchar']:] + + setup = context['regions'].get('setup') + + if setup: + source = setup + '\n' + source + + teardown = context['regions'].get('teardown') + + if teardown: + source += '\n' + teardown + '\n' + + return source + + def _frontmatter(self, case_filename, case_values): + description = case_values['meta']['desc'].strip() + \ + ' (' + self.attribs['meta']['name'].strip() + ')' + lines = [] + + lines += [ + '// This file was procedurally generated from the following sources:', + '// - ' + case_filename, + '// - ' + self.filename, + '/*---', + 'description: ' + description, + ] + + esid = self.attribs['meta'].get('esid') + if esid: + lines.append('esid: ' + esid) + + es6id = self.attribs['meta'].get('es6id') + if es6id: + lines.append('es6id: ' + es6id) + + features = [] + features += case_values['meta'].get('features', []) + features += self.attribs['meta'].get('features', []) + if len(features): + lines += ['features: ' + yaml.dump(features)] + + flags = ['generated'] + flags += case_values['meta'].get('flags', []) + flags += self.attribs['meta'].get('flags', []) + lines += ['flags: ' + yaml.dump(flags).strip()] + + includes = [] + includes += case_values['meta'].get('includes', []) + includes += self.attribs['meta'].get('includes', []) + if len(includes): + lines += ['includes: ' + yaml.dump(includes).strip()] + + if case_values['meta'].get('negative'): + lines += ['negative: ' + case_values['meta'].get('negative')] + + info = [] + + if 'info' in self.attribs['meta']: + info.append(indent(self.attribs['meta']['info'])) + if 'info' in case_values['meta']: + if len(info): + info.append('') + info.append(indent(case_values['meta']['info'])) + + if len(info): + lines.append('info: >') + lines += info + + lines.append('---*/') + + return '\n'.join(lines) + + def expand(self, case_filename, case_name, case_values, encoding): + frontmatter = self._frontmatter(case_filename, case_values) + body = self.expand_regions(self.source, case_values) + + return Test(self.attribs['meta']['path'] + case_name + '.js', + source=codecs.encode(frontmatter + '\n' + body, encoding)) diff --git a/tools/generation/lib/test.py b/tools/generation/lib/test.py new file mode 100644 index 0000000000..1dd6d45f73 --- /dev/null +++ b/tools/generation/lib/test.py @@ -0,0 +1,63 @@ +# Copyright (C) 2016 the V8 project authors. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +import os, re + +from util.find_comments import find_comments +from util.parse_yaml import parse_yaml + +class Test: + """Representation of a generated test. Specifies a file location which may + or may not exist.""" + def __init__(self, file_name, source=None): + self.file_name = file_name + self.source = source + self.attribs = dict(meta=None) + + if self.source: + self._parse() + + def load(self, prefix = None): + location = os.path.join(prefix or '', self.file_name) + with open(location) as handle: + self.source = handle.read() + self._parse() + + def _parse(self): + for comment in find_comments(self.source): + meta = parse_yaml(comment['source']) + if meta: + self.attribs['meta'] = meta + break + + def is_generated(self): + if not self.attribs['meta']: + return False + flags = self.attribs['meta'].get('flags') + + if not flags: + return False + + return 'generated' in flags + + def to_string(self): + return '\n'.join([ + '/**', + ' * ----------------------------------------------------------------', + ' * ' + self.file_name, + ' * ----------------------------------------------------------------', + ' */', + self.source, + '\n']) + + def write(self, prefix, parents=False): + location = os.path.join(prefix, self.file_name) + path = os.path.dirname(location) + if not os.path.exists(path): + if parents: + os.makedirs(path) + else: + raise Exception('Directory does not exist: ' + path) + + with open(location, 'w') as handle: + handle.write(self.source) diff --git a/tools/generation/lib/util/__init__.py b/tools/generation/lib/util/__init__.py new file mode 100644 index 0000000000..2ae28399f5 --- /dev/null +++ b/tools/generation/lib/util/__init__.py @@ -0,0 +1 @@ +pass diff --git a/tools/generation/lib/util/find_comments.py b/tools/generation/lib/util/find_comments.py new file mode 100644 index 0000000000..81ad0ab552 --- /dev/null +++ b/tools/generation/lib/util/find_comments.py @@ -0,0 +1,68 @@ +# Copyright (C) 2016 the V8 project authors. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +def find_comments(source): + '''Parse input string describing JavaScript source and yield dictionaries + describing the JavaScript comments in the order they appear in the source. + + Each dictionary defines the following attributes: + + - source: the source text of the comment + - firstchar: the zero-indexed position of the token that begins the comment + - lastchar: the zero-indexed position of the token that closes the comment + - lineno: the zero-indexed offset of the line on which the comment appears + ''' + in_string = False + in_s_comment = False + in_m_comment = False + follows_escape = False + comment = '' + lineno = 0 + + for idx in xrange(len(source)): + if source[idx] == '\n': + lineno += 1 + + # Within comments and strings, any odd number of back-slashes begins an + # escape sequence. + if source[idx - 1] == '\\': + follows_escape = not follows_escape + else: + follows_escape = False + + if in_s_comment: + if source[idx] == '\n': + in_s_comment = False + yield dict( + source=comment[1:], + firstchar=idx - len(comment) - 1, + lastchar=idx, + lineno=lineno) + continue + elif in_m_comment: + if source[idx - 1] == '*' and source[idx] == '/': + in_m_comment = False + yield dict( + source=comment[1:-1], + firstchar=idx - len(comment) - 1, + lastchar=idx + 1, + lineno=lineno) + continue + elif in_string: + if source[idx] == in_string and not follows_escape: + in_string = False + elif source[idx] == '\n' and in_string != '`' and not follows_escape: + in_string = False + continue + + if in_m_comment or in_s_comment: + comment += source[idx] + continue + + in_m_comment = source[idx] == '/' and source[idx + 1] == '*' + in_s_comment = source[idx] == '/' and source[idx + 1] == '/' + + if in_m_comment or in_s_comment: + comment = '' + elif source[idx] == '\'' or source[idx] == '"' or source[idx] == '`': + in_string = source[idx] diff --git a/tools/generation/lib/util/parse_yaml.py b/tools/generation/lib/util/parse_yaml.py new file mode 100644 index 0000000000..3ad356db8c --- /dev/null +++ b/tools/generation/lib/util/parse_yaml.py @@ -0,0 +1,17 @@ +# Copyright (C) 2016 the V8 project authors. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +import yaml, re + +yamlPattern = re.compile(r'\---\n([\s]*)((?:\s|\S)*)[\n\s*]---', + flags=re.DOTALL|re.MULTILINE) + +def parse_yaml(string): + match = yamlPattern.match(string) + if not match: + return False + + unindented = re.sub('^' + match.group(1), '', + match.group(2), flags=re.MULTILINE) + + return yaml.safe_load(unindented) diff --git a/tools/generation/requirements.txt b/tools/generation/requirements.txt new file mode 100644 index 0000000000..efb082d8de --- /dev/null +++ b/tools/generation/requirements.txt @@ -0,0 +1 @@ +PyYAML==3.11 diff --git a/tools/generation/test/expected/normal/nested/path2-normal.js b/tools/generation/test/expected/normal/nested/path2-normal.js new file mode 100644 index 0000000000..d9da70500a --- /dev/null +++ b/tools/generation/test/expected/normal/nested/path2-normal.js @@ -0,0 +1,19 @@ +// This file was procedurally generated from the following sources: +// - tools/generation/test/fixtures/normal.case +// - tools/generation/test/fixtures/normal/normal2.template +/*--- +description: foobar (Second template name) +esid: sec-a-generic-id +flags: [generated, a, b] +includes: [foo.js, bar.js] +info: > + template info + + case info +---*/ + +before-Third valueSecond value-after + +/* Improperly-terminated comments should not break the tokenizer * + +'This is "teardown" code.'; diff --git a/tools/generation/test/expected/normal/no-info-normal.js b/tools/generation/test/expected/normal/no-info-normal.js new file mode 100644 index 0000000000..903028036b --- /dev/null +++ b/tools/generation/test/expected/normal/no-info-normal.js @@ -0,0 +1,15 @@ +// This file was procedurally generated from the following sources: +// - tools/generation/test/fixtures/normal.case +// - tools/generation/test/fixtures/normal/no-info.template +/*--- +description: foobar (First template name) +es6id: 1.2.3 +flags: [generated, a, b] +includes: [foo.js] +info: > + case info +---*/ + +First value + +'This is "teardown" code.'; diff --git a/tools/generation/test/expected/normal/path1-normal.js b/tools/generation/test/expected/normal/path1-normal.js new file mode 100644 index 0000000000..3bc10d0e9f --- /dev/null +++ b/tools/generation/test/expected/normal/path1-normal.js @@ -0,0 +1,33 @@ +// This file was procedurally generated from the following sources: +// - tools/generation/test/fixtures/normal.case +// - tools/generation/test/fixtures/normal/normal.template +/*--- +description: foobar (First template name) +es6id: 1.2.3 +flags: [generated, a, b, c, d] +includes: [foo.js] +info: > + template info + + case info +---*/ + +before-First value-between-Third value-after + +before*Second value*between*First value*after + +before/* " */Third valueafter + +The following should not be expanded: + +/* */*{ first }*/ +/* +*/*{ first }*/ +//*{ first }*/ +// /*{ first }*/ +"/*{ first }*/" +'/*{ first }*/' +` +/*{ first }*/` + +'This is "teardown" code.'; diff --git a/tools/generation/test/fixtures/normal.case b/tools/generation/test/fixtures/normal.case new file mode 100644 index 0000000000..276b58ccdd --- /dev/null +++ b/tools/generation/test/fixtures/normal.case @@ -0,0 +1,27 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +template: normal +desc: foobar +info: case info +flags: [a, b] +includes: [foo.js] +---*/ + +Because this test appears before any "region" delimiters, it should not appear +in the generated files. + +// - first +this is not a valid region delimiter + +/* *//- first +this is also not a valid region delimiter + +//- first +First value +//- second +Second value +//- third +Third value +//- teardown +'This is "teardown" code.'; diff --git a/tools/generation/test/fixtures/normal/no-info.template b/tools/generation/test/fixtures/normal/no-info.template new file mode 100644 index 0000000000..0f1b340ea3 --- /dev/null +++ b/tools/generation/test/fixtures/normal/no-info.template @@ -0,0 +1,9 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +name: First template name +path: normal/no-info- +es6id: 1.2.3 +---*/ + +/*{ first }*/ diff --git a/tools/generation/test/fixtures/normal/normal.template b/tools/generation/test/fixtures/normal/normal.template new file mode 100644 index 0000000000..ac0bea1e15 --- /dev/null +++ b/tools/generation/test/fixtures/normal/normal.template @@ -0,0 +1,27 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +name: First template name +path: normal/path1- +es6id: 1.2.3 +info: template info +flags: [c, d] +---*/ + +before-/*{ first }*/-between-/*{ third }*/-after + +before*/*{ second }*/*between*/*{ first }*/*after + +before/* " *//*{ third }*/after + +The following should not be expanded: + +/* */*{ first }*/ +/* +*/*{ first }*/ +//*{ first }*/ +// /*{ first }*/ +"/*{ first }*/" +'/*{ first }*/' +` +/*{ first }*/` diff --git a/tools/generation/test/fixtures/normal/normal2.template b/tools/generation/test/fixtures/normal/normal2.template new file mode 100644 index 0000000000..f7ae0b6830 --- /dev/null +++ b/tools/generation/test/fixtures/normal/normal2.template @@ -0,0 +1,13 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +name: Second template name +path: normal/nested/path2- +esid: sec-a-generic-id +includes: [bar.js] +info: template info +---*/ + +before-/*{ third }*//*{ second }*/-after + +/* Improperly-terminated comments should not break the tokenizer * diff --git a/tools/generation/test/run.py b/tools/generation/test/run.py new file mode 100755 index 0000000000..297815d679 --- /dev/null +++ b/tools/generation/test/run.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# Copyright (C) 2016 the V8 project authors. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +import shutil, subprocess, sys, os, unittest + +testDir = os.path.dirname(os.path.relpath(__file__)) +OUT_DIR = os.path.join(testDir, 'out') +EXPECTED_DIR = os.path.join(testDir, 'expected') +ex = os.path.join(testDir, '..', 'generator.py') + +class TestGeneration(unittest.TestCase): + maxDiff = None + + def fixture(self, name): + relpath = os.path.relpath(os.path.join(testDir, 'fixtures', name)) + sp = subprocess.Popen( + [ex, 'create', '-o', OUT_DIR, '-p', relpath], + stdout=subprocess.PIPE) + stdout, stderr = sp.communicate() + return dict(stdout=stdout, stderr=stderr, returncode=sp.returncode) + + def getFiles(self, path): + names = [] + for root, _, fileNames in os.walk(path): + for fileName in filter(lambda x: x[0] != '.', fileNames): + names.append(os.path.join(root, fileName)) + names.sort() + return names + + def compareTrees(self, targetName): + expectedPath = os.path.join(EXPECTED_DIR, targetName) + actualPath = os.path.join(OUT_DIR, targetName) + + expectedFiles = self.getFiles(expectedPath) + actualFiles = self.getFiles(actualPath) + + self.assertListEqual( + map(lambda x: os.path.relpath(x, expectedPath), expectedFiles), + map(lambda x: os.path.relpath(x, actualPath), actualFiles)) + + for expectedFile, actualFile in zip(expectedFiles, actualFiles): + with open(expectedFile) as expectedHandle: + with open(actualFile) as actualHandle: + self.assertMultiLineEqual( + expectedHandle.read(), + actualHandle.read()) + + def tearDown(self): + shutil.rmtree(OUT_DIR, ignore_errors=True) + + def test_normal(self): + result = self.fixture('normal.case') + self.assertEqual(result['returncode'], 0) + self.compareTrees('normal') + +if __name__ == '__main__': + unittest.main()