Синтаксис Определения Функций Генератора
GeneratorMethod [Yield, Await] :
* ClassElementName [?Yield, ?Await] ( UniqueFormalParameters [+Yield, ~Await] ) { GeneratorBody }
GeneratorDeclaration [Yield, Await, Default] :
function * BindingIdentifier [?Yield, ?Await] ( FormalParameters [+Yield, ~Await] ) { GeneratorBody }
[+Default] function * ( FormalParameters [+Yield, ~Await] ) { GeneratorBody }
function * BindingIdentifier [+Yield, ~Await] opt ( FormalParameters [+Yield, ~Await] ) { GeneratorBody }
FunctionBody [+Yield, ~Await]
YieldExpression [In, Await] :
yield
yield [no LineTerminator here] AssignmentExpression [?In, +Yield, ?Await]
yield [no LineTerminator here] * AssignmentExpression [?In, +Yield, ?Await]
Синтаксический контекст сразу после yield требует использования лексической цели InputElementRegExpOrTemplateTail.
YieldExpression нельзя использовать в FormalParameters функции генератора, поскольку любые выражения, являющиеся частью FormalParameters, оцениваются до того, как результирующий объект генератора перейдет в возобновляемое состояние.
Абстрактные операции, относящиеся к объектам-генераторам, определены в разделе 27.5.3.
Статическая семантика: Ранние Ошибки — Early Errors
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
- Это синтаксическая ошибка, если HasDirectSuper для GeneratorMethod является true (истинно).
- Это синтаксическая ошибка, если значение UniqueFormalParameters Содержит YieldExpression является true (истинно).
- Это синтаксическая ошибка, если для параметра FunctionBodyContainsUseStrict из GeneratorBody установлено значение true (истинно), а для параметра IsSimpleParameterList параметра UniqueFormalParameters — значение false (ложь).
- Это синтаксическая ошибка, если какой-либо элемент BoundNames из UniqueFormalParameters также встречается в LexicallyDeclaredNames объекта GeneratorBody.
function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
function * ( FormalParameters ) { GeneratorBody }
function * BindingIdentifier opt ( FormalParameters ) { GeneratorBody }
- Если исходный код, соответствующий FormalParameters, является кодом строгого режима, применяются правила ранней ошибки Early Error для UniqueFormalParameters : FormalParameters.
- Если BindingIdentifier присутствует и исходный код, соответствующий BindingIdentifier, является кодом в строгом режиме, это является синтаксической ошибкой, если строковое значение StringValue для BindingIdentifier имеет значение «eval» или «arguments«.
- Это синтаксическая ошибка, если для параметра FunctionBodyContainsUseStrict из GeneratorBody установлено значение true (истина), а для параметра IsSimpleParameterList параметра FormalParameters — значение false.
- Это синтаксическая ошибка, если какой-либо элемент BoundNames из FormalParameters также встречается в LexicallyDeclaredNames из GeneratorBody.
- Это синтаксическая ошибка, если FormalParameters Содержит YieldExpression является true (истинно).
- Это синтаксическая ошибка, если FormalParameters Содержит SuperProperty является true (истинно).
- Это синтаксическая ошибка, если GeneratorBody Содержит SuperProperty является true (истинно).
- Это синтаксическая ошибка, если FormalParameters Содержит SuperCall является true (истинно).
- Это синтаксическая ошибка, если GeneratorBody Содержит SuperCall является true (истинно).
Семантика среды выполнения: Оценить Тело Генератора — EvaluateGeneratorBody
С параметрами functionObject и argumentsList (Список).
1. Выполнить ? FunctionDeclarationInstantiation(functionObject, argumentsList). 2. Пусть G будет ? OrdinaryCreateFromConstructor(functionObject, "%GeneratorFunction.prototype.prototype%", «[[GeneratorState]], [[GeneratorContext]], [[GeneratorBrand]]»). 3. Установите G.[[GeneratorBrand]] в пустое значение empty. 4. Выполните GeneratorStart(G, FunctionBody). 5. Вернуть завершение Completion { [[Type]]: return, [[Value]]: G, [[Target]]: empty }.
Семантика времени выполнения: Создание Экземпляра Функционального Объекта Генератора — InstantiateGeneratorFunctionObject
С параметрами scope и privateScope.
GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
1. Пусть имя name будет строковым значением StringValue для BindingIdentifier. 2. Пусть sourceText будет исходным текстом, совпадающим с GeneratorDeclaration. 3. Пусть F будет OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, scope, privateScope). 4. Выполните SetFunctionName(F, name). 5. Пусть прототип prototype будет ! OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%). 6. Выполните DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). 7. Вернуть F.
GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody }
1. Пусть sourceText будет исходным текстом, совпадающим с GeneratorDeclaration. 2. Пусть F будет OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, scope, privateScope). 3. Выполнить SetFunctionName(F, "default"). 4. Пусть прототип prototype будет ! OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%). 5. Выполнить DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). 6. Вернуть F.
Анонимное объявление GeneratorDeclaration может возникать только как часть объявления экспорта по умолчанию — export default
, поэтому его функциональный код всегда является кодом строгого режима.
Семантика среды выполнения: Создание экземпляра выражения функции генератора — InstantiateGeneratorFunctionExpression
С необязательным параметром name.
GeneratorExpression : function * ( FormalParameters ) { GeneratorBody }
1. Если имя name не указано, установите для имени name значение "". 2. Пусть область видимости scope будет LexicalEnvironment текущего контекста выполнения. 3. Пусть privateScope будет PrivateEnvironment текущего контекста выполнения. 4. Пусть sourceText будет исходным текстом, совпадающим с GeneratorExpression. 5. Пусть замыкание closure будет OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, scope, privateScope). 6. Выполните SetFunctionName(closure, name). 7. Пусть прототип prototype будет ! OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%). 8. Выполните DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). 9. Вернуть closure.
GeneratorExpression : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
1. Утверждено: имя name не представлено. 2. Задайте для имя name строковое значение StringValue для BindingIdentifier. 3. Пусть область действия scope будет LexicalEnvironment текущего контекста выполнения. 4. Пусть funcEnv будет NewDeclarativeEnvironment(scope). 5. Выполните funcEnv.CreateImmutableBinding(name, false). 6. Пусть privateScope будет PrivateEnvironment текущего контекста выполнения. 7. Пусть sourceText будет исходным текстом, совпадающим с GeneratorExpression. 8. Пусть замыкание closure будет OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, funcEnv, privateScope). 9. Выполнить SetFunctionName(closure, name). 10. Пусть прототип prototype будет ! OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%). 11. Выполните DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). 12. Выполните funcEnv.InitializeBinding(name, closure). 13. Вернуть closure.
На BindingIdentifier в GeneratorExpression можно ссылаться изнутри GeneratorExpression FunctionBody, чтобы код генератора мог вызывать себя рекурсивно. Однако, в отличие от GeneratorDeclaration, на BindingIdentifier в GeneratorExpression нельзя ссылаться, и это не влияет на область, содержащую GeneratorExpression.
Семантика времени выполнения: Оценка — Evaluation
GeneratorExpression : function * BindingIdentifier opt ( FormalParameters ) { GeneratorBody }
1. Вернуть InstantiateGeneratorFunctionExpression из GeneratorExpression.
YieldExpression : yield
1. Вернуть ? Yield(undefined).
YieldExpression : yield AssignmentExpression
1. Пусть exprRef будет результатом вычисления AssignmentExpression. 2. Пусть value будет ? GetValue(exprRef). 3. Вернуть ? Yield(value).
YieldExpression : yield * AssignmentExpression
1. Пусть generatorKind будет ! GetGeneratorKind(). 2. Пусть exprRef будет результатом вычисления AssignmentExpression. 3. Пусть value будет ? GetValue(exprRef). 4. Пусть iteratorRecord будет ? GetIterator(value, generatorKind). 5. Пусть итератор iterator будет iteratorRecord.[[Iterator]]. 6. Пусть получено received будет NormalCompletion(undefined). 7. Повторите, а. Если received.[[Type]] является normal (нормально), то i. Пусть innerResult будет ? Вызов Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], «received.[[Value]]»). ii. Если generatorKind является async (асинхронным), установите для innerResult значение ? ожидайте Await(innerResult). iii. Если Type(innerResult) не является Object, вызовите исключение TypeError. iv. Пусть done будет ? IteratorComplete(innerResult). v. Если сделано done является true (верно), то 1. Вернуть ? IteratorValue(innerResult). vi. Если generatorKind является async (асинхронным), установите полученный AsyncGeneratorYield(? IteratorValue(innerResult)). vii. В противном случае установите received значение GeneratorYield(innerResult). b. Иначе, если received.[[Type]] является throw (выбросить), тогда i. Пусть throw будет? GetMethod(iterator, "throw"). ii. Если throw не является undefined (неопределенным), тогда 1. Пусть innerResult будет ? Вызов Call(throw, iterator, «received.[[Value]]»). 2. Если generatorKind является async (асинхронным), установите для innerResult значение ? Ожидайте Await(innerResult). 3. ПРИМЕЧАНИЕ. Исключения из метода throw внутреннего итератора распространяются. Нормальные завершения из внутреннего метода throw обрабатываются аналогично внутреннему next. 4. Если Type(innerResult) не является Object, выбросить исключение TypeError. 5. Пусть done будет ? IteratorComplete(innerResult). 6. Если done является true (истина), то а. Вернуть ? IteratorValue(innerResult). 7. Если generatorKind является async (асинхронным), установите значение received на AsyncGeneratorYield(? IteratorValue(innerResult)). 8. В противном случае установите полученное значение received на GeneratorYield(innerResult). iii. Иначе, 1. ПРИМЕЧАНИЕ. Если итератор iterator не имеет метода throw, этот throw завершит цикл yield*. Но сначала нам нужно дать итератору iterator возможность очиститься. 2. Пусть closeCompletion будет Completion { [[Type]]: normal, [[Value]]: empty, [[Target]]: empty }. 3. Если generatorKind является async (асинхронным), выполнить ? AsyncIteratorClose(iteratorRecord, closeCompletion). 4. Иначе выполнить ? IteratorClose(iteratorRecord, closeCompletion). 5. ПРИМЕЧАНИЕ. На следующем шаге возникает ошибка TypeError, указывающая на нарушение протокола yield* : итератор iterator не имеет метода throw. 6. Вызвать исключение TypeError. c. Иначе, i. Утверждено: received.[[Type]] является return. ii. Пусть return будет ? GetMethod(iterator, "return"). iii. Если return является undefined (не определен), тогда 1. Если generatorKind является async (асинхронным), установите значение received.[[Value]] на ? Ждать Await(received.[[Value]]). 2. Вернуть Completion(received). iv. Пусть innerReturnResult будет ? Вызов Call(return, iterator, «received.[[Value]]»). v. Если generatorKind является async (асинхронным), установите для innerReturnResult значение ? Ожидание Await(innerReturnResult). vi. Если Type(innerReturnResult) не является Object, вызовите исключение TypeError. vii. Пусть done будет ? IteratorComplete(innerReturnResult). viii. Если done является true (истиной), то 1. Пусть value будет ? IteratorValue(innerReturnResult). 2. Вернуть завершение Completion { [[Type]]: return, [[Value]]: value, [[Target]]: empty }. ix. Если generatorKind является async (асинхронным), установите значение AsyncGeneratorYield(? IteratorValue(innerReturnResult)). x. В противном случае установите значение received на GeneratorYield(innerReturnResult).
Информационные ссылки
Стандарт ECMAScript — Раздел «15.5 Generator Function Definitions» — https://tc39.es/ecma262/#sec-generator-function-definitions