From e5a80731bc3de431b870bf79226de1f0caaf00be Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Thu, 13 Dec 2018 14:36:33 -0500 Subject: [PATCH 1/3] Give lazy functions ability to assert list of inner functions. - There is a new [Linkable] attribute extension, which tells the surface encoding that the [Linkable] attribute must be random accessible. - The NodeLink type that opaquely references a [Linkable] attribute. - All lazy functions can have a FrozenArray of inner functions that reference the immediately inner functions (i.e. not nested within another inner function). - There are Linkable variants of all function forms. Both eager and lazy functions are linkable, but only lazy functions have the inner function list. - All inner functions in the list must be found to be actual inner functions at Delazify time. --- spec.html | 95 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 11 deletions(-) diff --git a/spec.html b/spec.html index 1f45e05..0e781ae 100644 --- a/spec.html +++ b/spec.html @@ -26,7 +26,14 @@

Tree Grammar

This section is derived from Shift AST Spec and parts are Copyright 2014-2017 Shape Security, Inc.

Unlike the Shift AST spec, interface types are not used to inherit fields to control over ordering of fields. Type hierarchies that are not used to discriminate are collapsed to make space costs simple. Nor are they used to discriminate types, for which explicitly discriminated unions types are used.

Whereas Shift AST's design principle is ease of search-and-replace of node types, binary AST's design principle is ease of verification and ease of associating different behaviors with syntactically different (but possibly lexically similar) productions. -

The grammar is presented in WebIDL with the `[TypeIndicator]` and `[NonEmpty]` extensions per Shift AST spec. The `[Lazy]` extension serves as a hint to the surface encoding that the `[Lazy]` attribute should be skippable in the byte stream in constant time. The `typedefs` of `or` types are to be read as recursive sum types. In text below, the "is a `Foo`" prose is shorthand for checking the node's `type` attribute being equal to `"Foo"`.

+

The grammar is presented in WebIDL with the `[TypeIndicator]` and `[NonEmpty]` extensions per Shift AST spec, as well as the listed extensions below.

+

 // Type aliases and enums.
@@ -193,6 +200,7 @@ 

Tree Grammar

EmptyStatement or ExpressionStatement or FunctionDeclaration or + LinkableFunctionDeclaration or IfStatement or IterationStatement or LabelledStatement or @@ -217,6 +225,7 @@

Tree Grammar

LiteralRegExpExpression or ArrayExpression or ArrowExpression or + LinkableArrowExpression or AssignmentExpression or BinaryExpression or CallExpression or @@ -225,6 +234,7 @@

Tree Grammar

ConditionalExpression or ClassExpression or FunctionExpression or + LinkableFunctionExpression or IdentifierExpression or NewExpression or NewTargetExpression or @@ -243,7 +253,12 @@

Tree Grammar

LiteralPropertyName) PropertyName; -typedef (Method or Getter or Setter) MethodDefinition; +typedef (Method or + Getter or + Setter or + LinkableMethod or + LinkableGetter or + LinkableSetter) MethodDefinition; typedef (MethodDefinition or DataProperty or @@ -462,14 +477,20 @@

Tree Grammar

// `export VariableStatement`, `export Declaration` interface Export : Node { - attribute (FunctionDeclaration or ClassDeclaration or VariableDeclaration) declaration; + attribute (FunctionDeclaration or + LinkableFunctionDeclaration or + ClassDeclaration or + VariableDeclaration) declaration; }; // `export default HoistableDeclaration`, // `export default ClassDeclaration`, // `export default AssignmentExpression` interface ExportDefault : Node { - attribute (FunctionDeclaration or ClassDeclaration or Expression) body; + attribute (FunctionDeclaration or + LinkableFunctionDeclaration or + ClassDeclaration or + Expression) body; }; // `ExportSpecifier`, as part of an `ExportFrom`. @@ -513,8 +534,12 @@

Tree Grammar

// `length` property of this method. attribute unsigned long length; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> innerLazyFunctions; [Lazy] attribute FunctionOrMethodContents contents; }; +interface LinkableMethod : Node { + [Linkable] attribute Method method; +}; // `get PropertyName ( ) { FunctionBody }` interface EagerGetter : Node { @@ -525,8 +550,12 @@

Tree Grammar

interface LazyGetter : Node { attribute PropertyName name; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> innerLazyFunctions; [Lazy] attribute GetterContents contents; }; +interface LinkableGetter : Node { + [Linkable] Getter getter; +}; interface GetterContents : Node { attribute boolean isThisCaptured; @@ -547,8 +576,12 @@

Tree Grammar

// `length` property of this setter function. attribute unsigned long length; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> innerLazyFunctions; [Lazy] attribute SetterContents contents; }; +interface LinkableSetter : Node { + [Linkable] attribute Setter setter; +}; interface SetterContents : Node { attribute boolean isThisCaptured; @@ -635,6 +668,7 @@

Tree Grammar

// `length` property of this arrow function. attribute unsigned long length; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> innerLazyFunctions; [Lazy] attribute ArrowExpressionContentsWithFunctionBody contents; }; interface EagerArrowExpressionWithExpression : Node { @@ -649,8 +683,12 @@

Tree Grammar

attribute boolean isAsync; // `length` property of this arrow function. attribute unsigned long length; + attribute FrozenArray<NodeLink> innerLazyFunctions; [Lazy] attribute ArrowExpressionContentsWithExpression contents; }; +interface LinkableArrowExpression : Node { + [Linkable] attribute ArrowExpression arrow; +}; interface ArrowExpressionContentsWithFunctionBody : Node { attribute AssertedParameterScope parameterScope; @@ -743,8 +781,12 @@

Tree Grammar

// `length` property of this function. attribute unsigned long length; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> innerLazyFunctions; [Lazy] attribute FunctionExpressionContents contents; }; +interface LinkableFunctionExpression : Node { + [Linkable] attribute FunctionExpression fun; +}; interface FunctionExpressionContents : Node { attribute boolean isFunctionNameCaptured; @@ -1000,7 +1042,6 @@

Tree Grammar

attribute FrozenArray<Directive> directives; attribute FunctionOrMethodContents contents; }; - interface LazyFunctionDeclaration : Node { attribute boolean isAsync; attribute boolean isGenerator; @@ -1008,8 +1049,12 @@

Tree Grammar

// `length` property of this function. attribute unsigned long length; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> innerLazyFunctions; [Lazy] attribute FunctionOrMethodContents contents; }; +interface LinkableFunctionDeclaration : Node { + [Linkable] attribute FunctionDeclaration fun; +} interface FunctionOrMethodContents : Node { attribute boolean isThisCaptured; @@ -1096,7 +1141,7 @@

StatementListEcmaify ( _stmts_ )

1. Let _emptyStmt_ be |StatementListItem| : |EmptyStatement|. 1. Set _list_ to |StatementList| : _emptyStmt_. 1. For each _stmt_ in _stmts_, do - 1. If _stmt_ is a `FunctionDeclaration`, then + 1. If _stmt_ is a `FunctionDeclaration` or a `LinkableFunctionDeclaration`, then 1. Set _n_ to |HoistableDeclaration|: ? Ecmaify(_stmt_). 1. Set _n_ to be |Declaration| : _n_. 1. Else if _stmt_ an `ExpressionStatement` and _stmt_`.expression` is a `LiteralStringExpression`: @@ -1307,7 +1352,7 @@

PrimaryExpressionEcmaify ( _e_ )

1. Assert: _e_ is an `Expression`, an `AssignmentTarget`, or an `AssignmentTargetWithInitializer`. 1. If _e_ is a `ThisExpression`, then return ? Ecmaify(_e_). - 1. Else if _pn_ is an `IdentifierExpression`, a `Literal`, an `ArrayExpression`, an `ObjectExpression`, a `FunctionExpression`, a `ClassExpression`, a `LiteralRegExpExpression`, a `TemplateExpression`, an `AssignmentTargetIdentifier`, an `ArrayAssignmentExpression`, or an `ObjectAssignmentExpression`, then return |PrimaryExpression| : ? Ecmaify(_e_). + 1. Else if _pn_ is an `IdentifierExpression`, a `Literal`, an `ArrayExpression`, an `ObjectExpression`, a `FunctionExpression`, a `LinkableFunctionExpression`, a `ClassExpression`, a `LiteralRegExpExpression`, a `TemplateExpression`, an `AssignmentTargetIdentifier`, an `ArrayAssignmentExpression`, or an `ObjectAssignmentExpression`, then return |PrimaryExpression| : ? Ecmaify(_e_). 1. Else, 1. Let _parenthesized_ be |ParenthesizedExpression| : ( ? ExpressionEcmaify(_e_) ). 1. Return |PrimaryExpression| : _parenthesized_. @@ -1501,7 +1546,7 @@

AssignmentExpressionEcmaify ( _e_ )

1. Assert: _e_ is an `Expression`, an `AssignmentTarget`, or an `AssignmentTargetWithInitializer`. 1. If _e_ is an `AssignmentExpression`, a `CompoundAssignmentExpression`, or an `AssignmentTargetWithInitializer`, then return ? Ecmaify(_e_). - 1. Else if _e_ is a `YieldExpression` or an `ArrowExpression`, then return |AssignmentExpression| : ? Ecmaify(_e_). + 1. Else if _e_ is a `YieldExpression`, an `ArrowExpression`, or a `LinkableArrowExpression`, then return |AssignmentExpression| : ? Ecmaify(_e_). 1. Else, 1. Let _n_ be ? ConditionalExpressionEcmaify(_e_). 1. Return |AssignmentExpression| : _n_. @@ -2004,8 +2049,10 @@

EcmaifyLabelledStatement ( _labelled_ )

1. Assert _labelled_ is a `LabelledStatement`. 1. Let _body_ be an empty Parse Node. - 1. If _labelled_`.body` is a `FunctionDeclaration`, then - 1. If _labelled_`.body.isAsync` is true or _labelled_`.body.isGenerator` is *true*, then throw a *SyntaxError* exception. + 1. If _labelled_`.body` is a `FunctionDeclaration` or a `LinkableFunctionDeclaration`, then + 1. Let _funNode_ be _labelled_`.body`. + 1. If _funNode_ is a `LinkableFunctionDeclaration`, then set _funNode_ to _funNode_`.fun`. + 1. If _funNode_`.isAsync` is true or _funNode_`.isGenerator` is *true*, then throw a *SyntaxError* exception. 1. Set _body_ to ? Ecmaify(_labelled_`.body`). 1. Else set _body_ to ? StatementEcmaify(_labelled_`.body`). 1. Let _item_ be |LabelledItem| : _body_. @@ -2785,6 +2832,7 @@

Ecmaify ( _node_ )

1. Else if _node_ is a `EmptyStatement`, then return ? EcmaifyEmptyStatement(_node_). 1. Else if _node_ is a `ExpressionStatement`, then return ? EcmaifyExpressionStatement(_node_). 1. Else if _node_ is a `FunctionDeclaration`, then return ? EcmaifyFunctionDeclaration(_node_). + 1. Else if _node_ is a `LinkableFunctionDeclaration`, then return ? EcmaifyFunctionDeclaration(_node_`.fun`). 1. Else if _node_ is a `IfStatement`, then return ? EcmaifyIfStatement(_node_). 1. Else if _node_ is a `DoWhileStatement`, then return ? EcmaifyDoWhileStatement(_node_). 1. Else if _node_ is a `ForInStatement`, then return ? EcmaifyForInStatement(_node_). @@ -2808,6 +2856,7 @@

Ecmaify ( _node_ )

1. Else if _node_ is a `LiteralRegExpExpression`, then return ? EcmaifyLiteralRegExpExpression(_node_). 1. Else if _node_ is a `ArrayExpression`, then return ? EcmaifyArrayExpression(_node_). 1. Else if _node_ is a `ArrowExpression`, then return ? EcmaifyArrowExpression(_node_). + 1. Else if _node_ is a `LinkableArrowExpression`, then return ? EcmaifyArrowExpression(_node_`.arrow`). 1. Else if _node_ is a `AssignmentExpression`, then return ? EcmaifyAssignmentExpression(_node_). 1. Else if _node_ is a `BinaryExpression`, then return ? EcmaifyBinaryExpression(_node_). 1. Else if _node_ is a `CallExpression`, then return ? EcmaifyCallExpression(_node_). @@ -2816,6 +2865,7 @@

Ecmaify ( _node_ )

1. Else if _node_ is a `ConditionalExpression`, then return ? EcmaifyConditionalExpression(_node_). 1. Else if _node_ is a `ClassExpression`, then return ? EcmaifyClassExpression(_node_). 1. Else if _node_ is a `FunctionExpression`, then return ? EcmaifyFunctionExpression(_node_). + 1. Else if _node_ is a `LinkableFunctionExpression`, then return ? EcmaifyFunctionExpression(_node_`.fun`). 1. Else if _node_ is a `IdentifierExpression`, then return ? EcmaifyIdentifierExpression(_node_). 1. Else if _node_ is a `NewExpression`, then return ? EcmaifyNewExpression(_node_). 1. Else if _node_ is a `NewTargetExpression`, then return ? EcmaifyNewTargetExpression(_node_). @@ -2832,8 +2882,11 @@

Ecmaify ( _node_ )

1. Else if _node_ is a `LiteralPropertyName`, then return ? EcmaifyLiteralPropertyName(_node_). 1. Else if _node_ is a `LiteralPropertyName`, then return ? EcmaifyLiteralPropertyName(_node_). 1. Else if _node_ is a `Method`, then return ? EcmaifyMethod(_node_). + 1. Else if _node_ is a `LinkableMethod`, then return ? EcmaifyMethod(_node_`.method`). 1. Else if _node_ is a `Getter`, then return ? EcmaifyGetter(_node_). + 1. Else if _node_ is a `LinkableGetter`, then return ? EcmaifyGetter(_node_`.getter`). 1. Else if _node_ is a `Setter`, then return ? EcmaifySetter(_node_). + 1. Else if _node_ is a `LinkableSetter`, then return ? EcmaifySetter(_node_`.setter`). 1. Else if _node_ is a `DataProperty`, then return ? EcmaifyDataProperty(_node_). 1. Else if _node_ is a `ShorthandProperty`, then return ? EcmaifyShorthandProperty(_node_). 1. Else if _node_ is a `ExportAllFrom`, then return ? EcmaifyExportAllFrom(_node_). @@ -3029,7 +3082,7 @@

CheckRestParameterName ( _expectedParams_, _restParameterName_ )

- +

CheckBoundNames ( _expectedBound_, _actualBound_ )

1. Let _unseen_ be a new empty List. @@ -3042,6 +3095,25 @@

CheckBoundNames ( _expectedBound_, _actualBound_ )

+ +

CheckInnerLazyFunctions ( _funcNode_ )

+ + 1. Assert: _funcNode_ is a `LazyFunctionDeclaration`, a `LazyFunctionExpression`, a `LazyMethod`, a `LazyGetter`, a `LazySetter`, or a `LazyArrowExpression`. + 1. NOTE: All asserted immediately inner (i.e. not nested within another inner function) lazy functions in `innerLazyFunctions` must be found. + 1. Let _innerFunctions_ be a new empty List. + 1. For each _link_ in _funcNode_`.innerLazyFunctions`, do + 1. Let _linkedNode_ be the node linked to by _link_. + 1. NOTE: The above step is up to the surface encoding. + 1. Assert: _linkedNode_ is a `LinkableFunctionDeclaration`, a `LinkableFunctionExpression`, a `LinkableMethod`, a `LinkableGetter`, a `LinkableSetter`, or a `LinkableArrowExpression`. + 1. Add _linkedNode_ as the last element of _innerFunctions_. + 1. For each `FunctionDeclaration`, `FunctionExpression`, `Method`, `Getter`, `Setter`, or `ArrowExpression` _candidateInnerFunction_ contained in _funcNode_, do + 1. If the the path from _funcNode_ to _candidateInnerFunction_ contains no other `FunctionDeclaration`, `FunctionExpression`, `Method`, `Getter`, `Setter`, or `ArrowExpression`, then + 1. If _candidateInnerFunction_ is not in _innerFunctions_, then throw a *SyntaxError* exception. + 1. Remove _candidateInnerFunction_ from _innerFunctions_. + 1. If _innerFunctions_ is not empty, then throw a *SyntaxError* exception. + +
+

CheckAssertedScope ( _scope_ , _parseTree_ )

@@ -3609,6 +3681,7 @@

Runtime Semantics: Delazify

1. Let _delazifiedBody_ be ? EcmaifyFunctionBody(_funcNode_). 1. Perform ? ValidateAndUpdateFunctionObject(_funcNode_, _functionObject_, _delazifiedBody_, _delazifiedParams_). 1. If _funcNode_ is not a `LazyGetter`, then perform ? CheckAssertedScope(_contents_`.parameterScope`, _delazifiedParams_). + 1. Perform ? CheckInnerLazyFunctions(_funcNode_). 1. Perform ? CheckAssertedScope(_contents_`.bodyScope`, _delazifiedBody_). 1. If _funcNode_ is a `LazyArrowExpression`, then 1. Perform ? CheckThisCapture(_contents_`.parameterScope`, _delazifiedParams_). From dc7a010afe1c0c51f992a4f9c684b41b9d9518db Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Mon, 17 Dec 2018 12:25:01 -0500 Subject: [PATCH 2/3] Rename innerLazyFunctions and fix unwrapping in CheckInnerFunctions. --- spec.html | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/spec.html b/spec.html index 0e781ae..fc0fd3c 100644 --- a/spec.html +++ b/spec.html @@ -6,7 +6,7 @@ Binary AST

Binary AST

@@ -534,7 +534,7 @@

Tree Grammar

// `length` property of this method. attribute unsigned long length; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerLazyFunctions; + attribute FrozenArray<NodeLink> innerFunctions; [Lazy] attribute FunctionOrMethodContents contents; }; interface LinkableMethod : Node { @@ -550,7 +550,7 @@

Tree Grammar

interface LazyGetter : Node { attribute PropertyName name; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerLazyFunctions; + attribute FrozenArray<NodeLink> innerFunctions; [Lazy] attribute GetterContents contents; }; interface LinkableGetter : Node { @@ -576,7 +576,7 @@

Tree Grammar

// `length` property of this setter function. attribute unsigned long length; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerLazyFunctions; + attribute FrozenArray<NodeLink> innerFunctions; [Lazy] attribute SetterContents contents; }; interface LinkableSetter : Node { @@ -668,7 +668,7 @@

Tree Grammar

// `length` property of this arrow function. attribute unsigned long length; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerLazyFunctions; + attribute FrozenArray<NodeLink> innerFunctions; [Lazy] attribute ArrowExpressionContentsWithFunctionBody contents; }; interface EagerArrowExpressionWithExpression : Node { @@ -683,7 +683,7 @@

Tree Grammar

attribute boolean isAsync; // `length` property of this arrow function. attribute unsigned long length; - attribute FrozenArray<NodeLink> innerLazyFunctions; + attribute FrozenArray<NodeLink> innerFunctions; [Lazy] attribute ArrowExpressionContentsWithExpression contents; }; interface LinkableArrowExpression : Node { @@ -781,7 +781,7 @@

Tree Grammar

// `length` property of this function. attribute unsigned long length; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerLazyFunctions; + attribute FrozenArray<NodeLink> innerFunctions; [Lazy] attribute FunctionExpressionContents contents; }; interface LinkableFunctionExpression : Node { @@ -1049,7 +1049,7 @@

Tree Grammar

// `length` property of this function. attribute unsigned long length; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerLazyFunctions; + attribute FrozenArray<NodeLink> innerFunctions; [Lazy] attribute FunctionOrMethodContents contents; }; interface LinkableFunctionDeclaration : Node { @@ -3095,16 +3095,23 @@

CheckBoundNames ( _expectedBound_, _actualBound_ )

- -

CheckInnerLazyFunctions ( _funcNode_ )

+ +

CheckInnerFunctions ( _funcNode_ )

1. Assert: _funcNode_ is a `LazyFunctionDeclaration`, a `LazyFunctionExpression`, a `LazyMethod`, a `LazyGetter`, a `LazySetter`, or a `LazyArrowExpression`. - 1. NOTE: All asserted immediately inner (i.e. not nested within another inner function) lazy functions in `innerLazyFunctions` must be found. + 1. NOTE: All asserted immediately inner (i.e. not nested within another inner function) lazy functions in `innerFunctions` must be found. 1. Let _innerFunctions_ be a new empty List. - 1. For each _link_ in _funcNode_`.innerLazyFunctions`, do + 1. For each _link_ in _funcNode_`.innerFunctions`, do 1. Let _linkedNode_ be the node linked to by _link_. 1. NOTE: The above step is up to the surface encoding. - 1. Assert: _linkedNode_ is a `LinkableFunctionDeclaration`, a `LinkableFunctionExpression`, a `LinkableMethod`, a `LinkableGetter`, a `LinkableSetter`, or a `LinkableArrowExpression`. + 1. If _linkedNode_ is a `LinkableFunctionDeclaration`, then set _linkedNode_ to _linkedNode_`.fun`. + 1. Else if _linkedNode_ is a `LinkableFunctionExpression`, then set _linkedNode_ to _linkedNode_`.fun`. + 1. Else if _linkedNode_ is a `LinkableMethod`, then set _linkedNode_ to _linkedNode_`.method`. + 1. Else if _linkedNode_ is a `LinkableGetter`, then set _linkedNode_ to _linkedNode_`.getter`. + 1. Else if _linkedNode_ is a `LinkableSetter`, then set _linkedNode_ to _linkedNode_`.setter`. + 1. Else, + 1. Assert: _linkedNode_ is a `LinkableArrowExpression`. + 1. Set _linkedNode_ to _linkedNode_`.arrow`. 1. Add _linkedNode_ as the last element of _innerFunctions_. 1. For each `FunctionDeclaration`, `FunctionExpression`, `Method`, `Getter`, `Setter`, or `ArrowExpression` _candidateInnerFunction_ contained in _funcNode_, do 1. If the the path from _funcNode_ to _candidateInnerFunction_ contains no other `FunctionDeclaration`, `FunctionExpression`, `Method`, `Getter`, `Setter`, or `ArrowExpression`, then @@ -3681,7 +3688,7 @@

Runtime Semantics: Delazify

1. Let _delazifiedBody_ be ? EcmaifyFunctionBody(_funcNode_). 1. Perform ? ValidateAndUpdateFunctionObject(_funcNode_, _functionObject_, _delazifiedBody_, _delazifiedParams_). 1. If _funcNode_ is not a `LazyGetter`, then perform ? CheckAssertedScope(_contents_`.parameterScope`, _delazifiedParams_). - 1. Perform ? CheckInnerLazyFunctions(_funcNode_). + 1. Perform ? CheckInnerFunctions(_funcNode_). 1. Perform ? CheckAssertedScope(_contents_`.bodyScope`, _delazifiedBody_). 1. If _funcNode_ is a `LazyArrowExpression`, then 1. Perform ? CheckThisCapture(_contents_`.parameterScope`, _delazifiedParams_). From 1ea47a42425eaa35b890e86e09d630344d349c70 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Mon, 17 Dec 2018 13:42:06 -0500 Subject: [PATCH 3/3] Rename innerFunctions to directChildFunctions for clarity; change CheckDirectChildFunctions to be non-exhaustive. --- spec.html | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/spec.html b/spec.html index fc0fd3c..8f83398 100644 --- a/spec.html +++ b/spec.html @@ -534,7 +534,7 @@

Tree Grammar

// `length` property of this method. attribute unsigned long length; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerFunctions; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute FunctionOrMethodContents contents; }; interface LinkableMethod : Node { @@ -550,7 +550,7 @@

Tree Grammar

interface LazyGetter : Node { attribute PropertyName name; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerFunctions; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute GetterContents contents; }; interface LinkableGetter : Node { @@ -576,7 +576,7 @@

Tree Grammar

// `length` property of this setter function. attribute unsigned long length; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerFunctions; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute SetterContents contents; }; interface LinkableSetter : Node { @@ -668,7 +668,7 @@

Tree Grammar

// `length` property of this arrow function. attribute unsigned long length; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerFunctions; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute ArrowExpressionContentsWithFunctionBody contents; }; interface EagerArrowExpressionWithExpression : Node { @@ -683,7 +683,7 @@

Tree Grammar

attribute boolean isAsync; // `length` property of this arrow function. attribute unsigned long length; - attribute FrozenArray<NodeLink> innerFunctions; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute ArrowExpressionContentsWithExpression contents; }; interface LinkableArrowExpression : Node { @@ -781,7 +781,7 @@

Tree Grammar

// `length` property of this function. attribute unsigned long length; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerFunctions; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute FunctionExpressionContents contents; }; interface LinkableFunctionExpression : Node { @@ -1049,7 +1049,7 @@

Tree Grammar

// `length` property of this function. attribute unsigned long length; attribute FrozenArray<Directive> directives; - attribute FrozenArray<NodeLink> innerFunctions; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute FunctionOrMethodContents contents; }; interface LinkableFunctionDeclaration : Node { @@ -3095,13 +3095,13 @@

CheckBoundNames ( _expectedBound_, _actualBound_ )

- -

CheckInnerFunctions ( _funcNode_ )

+ +

CheckDirectChildFunctions ( _funcNode_ )

1. Assert: _funcNode_ is a `LazyFunctionDeclaration`, a `LazyFunctionExpression`, a `LazyMethod`, a `LazyGetter`, a `LazySetter`, or a `LazyArrowExpression`. - 1. NOTE: All asserted immediately inner (i.e. not nested within another inner function) lazy functions in `innerFunctions` must be found. - 1. Let _innerFunctions_ be a new empty List. - 1. For each _link_ in _funcNode_`.innerFunctions`, do + 1. NOTE: All asserted direct child functions (i.e. not nested within another inner function) in _funcNode_`.directChildFunctions` must be found. It is not required that all direct child functions be in _funcNode_`.directChildFunctions`. + 1. Let _directChildFunctions_ be a new empty List. + 1. For each _link_ in _funcNode_`.directChildFunctions`, do 1. Let _linkedNode_ be the node linked to by _link_. 1. NOTE: The above step is up to the surface encoding. 1. If _linkedNode_ is a `LinkableFunctionDeclaration`, then set _linkedNode_ to _linkedNode_`.fun`. @@ -3112,12 +3112,11 @@

CheckInnerFunctions ( _funcNode_ )

1. Else, 1. Assert: _linkedNode_ is a `LinkableArrowExpression`. 1. Set _linkedNode_ to _linkedNode_`.arrow`. - 1. Add _linkedNode_ as the last element of _innerFunctions_. - 1. For each `FunctionDeclaration`, `FunctionExpression`, `Method`, `Getter`, `Setter`, or `ArrowExpression` _candidateInnerFunction_ contained in _funcNode_, do - 1. If the the path from _funcNode_ to _candidateInnerFunction_ contains no other `FunctionDeclaration`, `FunctionExpression`, `Method`, `Getter`, `Setter`, or `ArrowExpression`, then - 1. If _candidateInnerFunction_ is not in _innerFunctions_, then throw a *SyntaxError* exception. - 1. Remove _candidateInnerFunction_ from _innerFunctions_. - 1. If _innerFunctions_ is not empty, then throw a *SyntaxError* exception. + 1. Add _linkedNode_ as the last element of _directChildFunctions_. + 1. For each `FunctionDeclaration`, `FunctionExpression`, `Method`, `Getter`, `Setter`, or `ArrowExpression` _candidateChildFunction_ contained in _funcNode_, do + 1. If the the path from _funcNode_ to _candidateChildFunction_ contains no other `FunctionDeclaration`, `FunctionExpression`, `Method`, `Getter`, `Setter`, or `ArrowExpression`, then + 1. If _candidateChildFunction_ is in _directChildFunctions_, then remove _candidateChildFunction_ from _directChildFunctions_. + 1. If _directChildFunctions_ is not empty, then throw a *SyntaxError* exception.
@@ -3688,7 +3687,7 @@

Runtime Semantics: Delazify

1. Let _delazifiedBody_ be ? EcmaifyFunctionBody(_funcNode_). 1. Perform ? ValidateAndUpdateFunctionObject(_funcNode_, _functionObject_, _delazifiedBody_, _delazifiedParams_). 1. If _funcNode_ is not a `LazyGetter`, then perform ? CheckAssertedScope(_contents_`.parameterScope`, _delazifiedParams_). - 1. Perform ? CheckInnerFunctions(_funcNode_). + 1. Perform ? CheckDirectChildFunctions(_funcNode_). 1. Perform ? CheckAssertedScope(_contents_`.bodyScope`, _delazifiedBody_). 1. If _funcNode_ is a `LazyArrowExpression`, then 1. Perform ? CheckThisCapture(_contents_`.parameterScope`, _delazifiedParams_).