ECMA-262 (12th Edition) ECMAScript 2021 Language Specification - page 37

 

  Главная      Manuals     ECMA-262 (12th Edition) ECMAScript 2021 Language Specification

 

Search            copyright infringement  

 

 

 

 

 

 

 

 

 

 

 

Content      ..     35      36      37      38     ..

 

 

 

ECMA-262 (12th Edition) ECMAScript 2021 Language Specification - page 37

 

 

data race.

A program is data race free if all its executions are data race free.

The 

memory model

 guarantees sequential consistency of all events for data race free programs.

NOTE 1

NOTE 2

The following are guidelines for ECMAScript programmers working with shared memory.

We recommend programs be kept data race free, i.e., make it so that it is impossible for there to
be concurrent non-atomic operations on the same memory location. Data race free programs
have interleaving semantics where each step in the evaluation semantics of each 

agent

 are

interleaved with each other. For data race free programs, it is not necessary to understand the
details of the 

memory model

. The details are unlikely to build intuition that will help one to

better write ECMAScript.

More generally, even if a program is not data race free it may have predictable behaviour, so long
as atomic operations are not involved in any data races and the operations that race all have the
same access size. The simplest way to arrange for atomics not to be involved in races is to ensure
that different memory cells are used by atomic and non-atomic operations and that atomic
accesses of different sizes are not used to access the same cells at the same time. Effectively, the
program should treat shared memory as strongly typed as much as possible. One still cannot
depend on the ordering and timing of non-atomic accesses that race, but if memory is treated as
strongly typed the racing accesses will not "tear" (bits of their values will not be mixed).

The following are guidelines for ECMAScript implementers writing compiler transformations for
programs using shared memory.

It is desirable to allow most program transformations that are valid in a single-

agent

 setting in a

multi-

agent

 setting, to ensure that the performance of each 

agent

 in a multi-

agent

 program is as

good as it would be in a single-

agent

 setting. Frequently these transformations are hard to judge.

We outline some rules about program transformations that are intended to be taken as normative
(in that they are implied by the 

memory model

 or stronger than what the 

memory model

implies) but which are likely not exhaustive. These rules are intended to apply to program
transformations that precede the introductions of the events that make up the 

agent-order

.

Let an 

agent-order slice

 be the subset of the 

agent-order

 pertaining to a single 

agent

.

Let 

possible read values

 of a read event be the set of all values of 

ValueOfReadEvent

 for that event

across all valid executions.

Any transformation of an agent-order slice that is valid in the absence of shared memory is valid
in the presence of shared memory, with the following exceptions.

Atomics are carved in stone

: Program transformations must not cause the 

SeqCst

 events in

an agent-order slice to be reordered with its 

Unordered

 operations, nor its 

SeqCst

operations to be reordered with each other, nor may a program transformation remove a

SeqCst

 operation from the 

agent-order

.

29.11  Shared Memory Guidelines

810

NOTE 3

(In practice, the prohibition on reorderings forces a compiler to assume that every 

SeqCst

operation is a synchronization and included in the final 

memory-order

, which it would

usually have to assume anyway in the absence of inter-

agent

 program analysis. It also

forces the compiler to assume that every call where the callee's effects on the 

memory-

order

 are unknown may contain 

SeqCst

 operations.)

Reads must be stable

: Any given shared memory read must only observe a single value in

an execution.

(For example, if what is semantically a single read in the program is executed multiple
times then the program is subsequently allowed to observe only one of the values read. A
transformation known as rematerialization can violate this rule.)

Writes must be stable

: All observable writes to shared memory must follow from program

semantics in an execution.

(For example, a transformation may not introduce certain observable writes, such as by
using read-modify-write operations on a larger location to write a smaller datum, writing
a value to memory that the program could not have written, or writing a just-read value
back to the location it was read from, if that location could have been overwritten by
another 

agent

 after the read.)

Possible read values must be nonempty

: Program transformations cannot cause the possible

read values of a shared memory read to become empty.

(Counterintuitively, this rule in effect restricts transformations on writes, because writes
have force in 

memory model

 insofar as to be read by read events. For example, writes may

be moved and coalesced and sometimes reordered between two 

SeqCst

 operations, but

the transformation may not remove every write that updates a location; some write must
be preserved.)

Examples of transformations that remain valid are: merging multiple non-atomic reads from the
same location, reordering non-atomic reads, introducing speculative non-atomic reads, merging
multiple non-atomic writes to the same location, reordering non-atomic writes to different
locations, and hoisting non-atomic reads out of loops even if that affects termination. Note in
general that aliased TypedArrays make it hard to prove that locations are different.

The following are guidelines for ECMAScript implementers generating machine code for shared
memory accesses.

For architectures with memory models no weaker than those of ARM or Power, non-atomic
stores and loads may be compiled to bare stores and loads on the target architecture. Atomic
stores and loads may be compiled down to instructions that guarantee sequential consistency. If
no such instructions exist, memory barriers are to be employed, such as placing barriers on both
sides of a bare store or load. Read-modify-write operations may be compiled to read-modify-
write instructions on the target architecture, such as 

LOCK

LOCK

-prefixed instructions on x86, load-

exclusive/store-exclusive instructions on ARM, and load-link/store-conditional instructions on
Power.

Specifically, the 

memory model

 is intended to allow code generation as follows.

811

Every atomic operation in the program is assumed to be necessary.
Atomic operations are never rearranged with each other or with non-atomic operations.
Functions are always assumed to perform atomic operations.
Atomic operations are never implemented as read-modify-write operations on larger data,
but as non-lock-free atomics if the platform does not have atomic operations of the
appropriate size. (We already assume that every platform has normal memory access
operations of every interesting size.)

Naive code generation uses these patterns:

Regular loads and stores compile to single load and store instructions.
Lock-free atomic loads and stores compile to a full (sequentially consistent) fence, a
regular load or store, and a full fence.
Lock-free atomic read-modify-write accesses compile to a full fence, an atomic read-
modify-write instruction sequence, and a full fence.
Non-lock-free atomics compile to a spinlock acquire, a full fence, a series of non-atomic
load and store instructions, a full fence, and a spinlock release.

That mapping is correct so long as an atomic operation on an address range does not race with a
non-atomic write or with an atomic operation of different size. However, that is all we need: the

memory model

 effectively demotes the atomic operations involved in a race to non-atomic status.

On the other hand, the naive mapping is quite strong: it allows atomic operations to be used as
sequentially consistent fences, which the 

memory model

 does not actually guarantee.

A number of local improvements to those basic patterns are also intended to be legal:

There are obvious platform-dependent improvements that remove redundant fences. For
example, on x86 the fences around lock-free atomic loads and stores can always be
omitted except for the fence following a store, and no fence is needed for lock-free read-
modify-write instructions, as these all use LOCK-prefixed instructions. On many
platforms there are fences of several strengths, and weaker fences can be used in certain
contexts without destroying sequential consistency.
Most modern platforms support lock-free atomics for all the data sizes required by
ECMAScript atomics. Should non-lock-free atomics be needed, the fences surrounding the
body of the atomic operation can usually be folded into the lock and unlock steps. The
simplest solution for non-lock-free atomics is to have a single lock word per
SharedArrayBuffer.
There are also more complicated platform-dependent local improvements, requiring some
code analysis. For example, two back-to-back fences often have the same effect as a single
fence, so if code is generated for two atomic operations in sequence, only a single fence
need separate them. On x86, even a single fence separating atomic stores can be omitted,
as the fence following a store is only needed to separate the store from a subsequent load.

A  Grammar Summary

812

\

 

UnicodeEscapeSequence

<ZWNJ>

<ZWJ>

UnicodeIDStart

 

::

any Unicode code point with the Unicode property “ID_Start”

UnicodeIDContinue

 

::

any Unicode code point with the Unicode property “ID_Continue”

ReservedWord

 

::

 

one of

await

 

break

 

case

 

catch

 

class

 

const

 

continue

 

debugger

 

default

 

delete

 

do

 

else

 

enum

 

export

 

extends

 

false

 

finally

 

for

 

function

 

if

 

import

 

in

 

instanceof

 

new

 

null

 

return

 

super

 

switch

 

this

 

throw

 

true

 

try

 

typeof

 

var

 

void

 

while

 

with

 

yield

Punctuator

 

::

OptionalChainingPunctuator
OtherPunctuator

OptionalChainingPunctuator

 

::

?.

 [lookahead 

 

DecimalDigit

]

OtherPunctuator

 

::

 

one of

{

 

(

 

)

 

[

 

]

 

.

 

...

 

;

 

,

 

<

 

>

 

<=

 

>=

 

==

 

!=

 

===

 

!==

 

+

 

-

 

*

 

%

 

**

 

++

 

--

 

<<

 

>>

 

>>>

 

&

 

|

 

^

 

!

 

~

 

&&

 

||

 

??

 

?

 

:

 

=

 

+=

 

-=

 

*=

%=

 

**=

 

<<=

 

>>=

 

>>>=

 

&=

 

|=

 

^=

 

&&=

 

||=

 

??=

 

=>

DivPunctuator

 

::

/

/=

RightBracePunctuator

 

::

}

NullLiteral

 

::

null

BooleanLiteral

 

::

true

false

NumericLiteralSeparator

 

::

_

NumericLiteral

 

::

DecimalLiteral
DecimalBigIntegerLiteral
NonDecimalIntegerLiteral

[+Sep]

NonDecimalIntegerLiteral

[+Sep]

 

BigIntLiteralSuffix

DecimalBigIntegerLiteral

 

::

0

 

BigIntLiteralSuffix

NonZeroDigit

 

DecimalDigits

[+Sep]

opt

 

BigIntLiteralSuffix

NonZeroDigit

 

NumericLiteralSeparator

 

DecimalDigits

[+Sep]

 

BigIntLiteralSuffix

NonDecimalIntegerLiteral

[Sep]

 

::

BinaryIntegerLiteral

[?Sep]

OctalIntegerLiteral

[?Sep]

HexIntegerLiteral

[?Sep]

815

NoSubstitutionTemplate

 

::

`

 

TemplateCharacters

opt

 

`

TemplateHead

 

::

`

 

TemplateCharacters

opt

 

${

TemplateSubstitutionTail

 

::

TemplateMiddle
TemplateTail

TemplateMiddle

 

::

}

 

TemplateCharacters

opt

 

${

TemplateTail

 

::

}

 

TemplateCharacters

opt

 

`

TemplateCharacters

 

::

TemplateCharacter

 

TemplateCharacters

opt

TemplateCharacter

 

::

$

 [lookahead 

 

{

]

\

 

EscapeSequence

\

 

NotEscapeSequence

LineContinuation
LineTerminatorSequence
SourceCharacter

 but not one of 

`

 or 

\

 or 

$

 or 

LineTerminator

NotEscapeSequence

 

::

0

 

DecimalDigit

DecimalDigit

 but not 

0

x

 [lookahead 

 

HexDigit

]

x

 

HexDigit

 [lookahead 

 

HexDigit

]

u

 [lookahead 

 

HexDigit

]  [lookahead 

 

{

]

u

 

HexDigit

 [lookahead 

 

HexDigit

]

u

 

HexDigit

 

HexDigit

 [lookahead 

 

HexDigit

]

u

 

HexDigit

 

HexDigit

 

HexDigit

 [lookahead 

 

HexDigit

]

u

 

{

 [lookahead 

 

HexDigit

]

u

 

{

 

NotCodePoint

 [lookahead 

 

HexDigit

]

u

 

{

 

CodePoint

 [lookahead 

 

HexDigit

]  [lookahead 

 

}

]

NotCodePoint

 

::

HexDigits

[~Sep]

 but only if MV of 

HexDigits

 > 0x10FFFF

CodePoint

 

::

HexDigits

[~Sep]

 but only if MV of 

HexDigits

 

 0x10FFFF

IdentifierReference

[Yield, Await]

 

:

Identifier

[~Yield]

yield

[~Await]

await

BindingIdentifier

[Yield, Await]

 

:

A.2  Expressions

819

NumericLiteral
StringLiteral

ArrayLiteral

[Yield, Await]

 

:

[

 

Elision

opt

 

]

[

 

ElementList

[?Yield, ?Await]

 

]

[

 

ElementList

[?Yield, ?Await]

 

,

 

Elision

opt

 

]

ElementList

[Yield, Await]

 

:

Elision

opt

 

AssignmentExpression

[+In, ?Yield, ?Await]

Elision

opt

 

SpreadElement

[?Yield, ?Await]

ElementList

[?Yield, ?Await]

 

,

 

Elision

opt

 

AssignmentExpression

[+In, ?Yield, ?Await]

ElementList

[?Yield, ?Await]

 

,

 

Elision

opt

 

SpreadElement

[?Yield, ?Await]

Elision

 

:

,

Elision

 

,

SpreadElement

[Yield, Await]

 

:

...

 

AssignmentExpression

[+In, ?Yield, ?Await]

ObjectLiteral

[Yield, Await]

 

:

{

 

}

{

 

PropertyDefinitionList

[?Yield, ?Await]

 

}

{

 

PropertyDefinitionList

[?Yield, ?Await]

 

,

 

}

PropertyDefinitionList

[Yield, Await]

 

:

PropertyDefinition

[?Yield, ?Await]

PropertyDefinitionList

[?Yield, ?Await]

 

,

 

PropertyDefinition

[?Yield, ?Await]

PropertyDefinition

[Yield, Await]

 

:

IdentifierReference

[?Yield, ?Await]

CoverInitializedName

[?Yield, ?Await]

PropertyName

[?Yield, ?Await]

 

:

 

AssignmentExpression

[+In, ?Yield, ?Await]

MethodDefinition

[?Yield, ?Await]

...

 

AssignmentExpression

[+In, ?Yield, ?Await]

PropertyName

[Yield, Await]

 

:

LiteralPropertyName
ComputedPropertyName

[?Yield, ?Await]

LiteralPropertyName

 

:

IdentifierName
StringLiteral
NumericLiteral

ComputedPropertyName

[Yield, Await]

 

:

[

 

AssignmentExpression

[+In, ?Yield, ?Await]

 

]

CoverInitializedName

[Yield, Await]

 

:

IdentifierReference

[?Yield, ?Await]

 

Initializer

[+In, ?Yield, ?Await]

Initializer

[In, Yield, Await]

 

:

821

=

 

AssignmentExpression

[?In, ?Yield, ?Await]

TemplateLiteral

[Yield, Await, Tagged]

 

:

NoSubstitutionTemplate
SubstitutionTemplate

[?Yield, ?Await, ?Tagged]

SubstitutionTemplate

[Yield, Await, Tagged]

 

:

TemplateHead

 

Expression

[+In, ?Yield, ?Await]

 

TemplateSpans

[?Yield, ?Await, ?Tagged]

TemplateSpans

[Yield, Await, Tagged]

 

:

TemplateTail
TemplateMiddleList

[?Yield, ?Await, ?Tagged]

 

TemplateTail

TemplateMiddleList

[Yield, Await, Tagged]

 

:

TemplateMiddle

 

Expression

[+In, ?Yield, ?Await]

TemplateMiddleList

[?Yield, ?Await, ?Tagged]

 

TemplateMiddle

 

Expression

[+In, ?Yield, ?Await]

MemberExpression

[Yield, Await]

 

:

PrimaryExpression

[?Yield, ?Await]

MemberExpression

[?Yield, ?Await]

 

[

 

Expression

[+In, ?Yield, ?Await]

 

]

MemberExpression

[?Yield, ?Await]

 

.

 

IdentifierName

MemberExpression

[?Yield, ?Await]

 

TemplateLiteral

[?Yield, ?Await, +Tagged]

SuperProperty

[?Yield, ?Await]

MetaProperty

new

 

MemberExpression

[?Yield, ?Await]

 

Arguments

[?Yield, ?Await]

SuperProperty

[Yield, Await]

 

:

super

 

[

 

Expression

[+In, ?Yield, ?Await]

 

]

super

 

.

 

IdentifierName

MetaProperty

 

:

NewTarget
ImportMeta

NewTarget

 

:

new

 

.

 

target

ImportMeta

 

:

import

 

.

 

meta

NewExpression

[Yield, Await]

 

:

MemberExpression

[?Yield, ?Await]

new

 

NewExpression

[?Yield, ?Await]

CallExpression

[Yield, Await]

 

:

CoverCallExpressionAndAsyncArrowHead

[?Yield, ?Await]

SuperCall

[?Yield, ?Await]

ImportCall

[?Yield, ?Await]

CallExpression

[?Yield, ?Await]

 

Arguments

[?Yield, ?Await]

CallExpression

[?Yield, ?Await]

 

[

 

Expression

[+In, ?Yield, ?Await]

 

]

CallExpression

[?Yield, ?Await]

 

.

 

IdentifierName

CallExpression

[?Yield, ?Await]

 

TemplateLiteral

[?Yield, ?Await, +Tagged]

822

When processing an instance of the production 

CallExpression

[Yield, Await]

 

:

 

CoverCallExpressionAndAsyncArrowHead

[?Yield, ?Await]

 

the interpretation of 

CoverCallExpressionAndAsyncArrowHead

 is refined using the following grammar:

CallMemberExpression

[Yield, Await]

 

:

MemberExpression

[?Yield, ?Await]

 

Arguments

[?Yield, ?Await]

 

SuperCall

[Yield, Await]

 

:

super

 

Arguments

[?Yield, ?Await]

ImportCall

[Yield, Await]

 

:

import

 

(

 

AssignmentExpression

[+In, ?Yield, ?Await]

 

)

Arguments

[Yield, Await]

 

:

(

 

)

(

 

ArgumentList

[?Yield, ?Await]

 

)

(

 

ArgumentList

[?Yield, ?Await]

 

,

 

)

ArgumentList

[Yield, Await]

 

:

AssignmentExpression

[+In, ?Yield, ?Await]

...

 

AssignmentExpression

[+In, ?Yield, ?Await]

ArgumentList

[?Yield, ?Await]

 

,

 

AssignmentExpression

[+In, ?Yield, ?Await]

ArgumentList

[?Yield, ?Await]

 

,

 

...

 

AssignmentExpression

[+In, ?Yield, ?Await]

OptionalExpression

[Yield, Await]

 

:

MemberExpression

[?Yield, ?Await]

 

OptionalChain

[?Yield, ?Await]

CallExpression

[?Yield, ?Await]

 

OptionalChain

[?Yield, ?Await]

OptionalExpression

[?Yield, ?Await]

 

OptionalChain

[?Yield, ?Await]

OptionalChain

[Yield, Await]

 

:

?.

 

Arguments

[?Yield, ?Await]

?.

 

[

 

Expression

[+In, ?Yield, ?Await]

 

]

?.

 

IdentifierName

?.

 

TemplateLiteral

[?Yield, ?Await, +Tagged]

OptionalChain

[?Yield, ?Await]

 

Arguments

[?Yield, ?Await]

OptionalChain

[?Yield, ?Await]

 

[

 

Expression

[+In, ?Yield, ?Await]

 

]

OptionalChain

[?Yield, ?Await]

 

.

 

IdentifierName

OptionalChain

[?Yield, ?Await]

 

TemplateLiteral

[?Yield, ?Await, +Tagged]

LeftHandSideExpression

[Yield, Await]

 

:

NewExpression

[?Yield, ?Await]

CallExpression

[?Yield, ?Await]

OptionalExpression

[?Yield, ?Await]

UpdateExpression

[Yield, Await]

 

:

LeftHandSideExpression

[?Yield, ?Await]

LeftHandSideExpression

[?Yield, ?Await]

 [no 

LineTerminator

 here]  

++

823

LeftHandSideExpression

[?Yield, ?Await]

 [no 

LineTerminator

 here]  

--

++

 

UnaryExpression

[?Yield, ?Await]

--

 

UnaryExpression

[?Yield, ?Await]

UnaryExpression

[Yield, Await]

 

:

UpdateExpression

[?Yield, ?Await]

delete

 

UnaryExpression

[?Yield, ?Await]

void

 

UnaryExpression

[?Yield, ?Await]

typeof

 

UnaryExpression

[?Yield, ?Await]

+

 

UnaryExpression

[?Yield, ?Await]

-

 

UnaryExpression

[?Yield, ?Await]

~

 

UnaryExpression

[?Yield, ?Await]

!

 

UnaryExpression

[?Yield, ?Await]

[+Await]

AwaitExpression

[?Yield]

ExponentiationExpression

[Yield, Await]

 

:

UnaryExpression

[?Yield, ?Await]

UpdateExpression

[?Yield, ?Await]

 

**

 

ExponentiationExpression

[?Yield, ?Await]

MultiplicativeExpression

[Yield, Await]

 

:

ExponentiationExpression

[?Yield, ?Await]

MultiplicativeExpression

[?Yield, ?Await]

 

MultiplicativeOperator

 

ExponentiationExpression

[?Yield, ?Await]

MultiplicativeOperator

 

:

 

one of

*

 

/

 

%

AdditiveExpression

[Yield, Await]

 

:

MultiplicativeExpression

[?Yield, ?Await]

AdditiveExpression

[?Yield, ?Await]

 

+

 

MultiplicativeExpression

[?Yield, ?Await]

AdditiveExpression

[?Yield, ?Await]

 

-

 

MultiplicativeExpression

[?Yield, ?Await]

ShiftExpression

[Yield, Await]

 

:

AdditiveExpression

[?Yield, ?Await]

ShiftExpression

[?Yield, ?Await]

 

<<

 

AdditiveExpression

[?Yield, ?Await]

ShiftExpression

[?Yield, ?Await]

 

>>

 

AdditiveExpression

[?Yield, ?Await]

ShiftExpression

[?Yield, ?Await]

 

>>>

 

AdditiveExpression

[?Yield, ?Await]

RelationalExpression

[In, Yield, Await]

 

:

ShiftExpression

[?Yield, ?Await]

RelationalExpression

[?In, ?Yield, ?Await]

 

<

 

ShiftExpression

[?Yield, ?Await]

RelationalExpression

[?In, ?Yield, ?Await]

 

>

 

ShiftExpression

[?Yield, ?Await]

RelationalExpression

[?In, ?Yield, ?Await]

 

<=

 

ShiftExpression

[?Yield, ?Await]

RelationalExpression

[?In, ?Yield, ?Await]

 

>=

 

ShiftExpression

[?Yield, ?Await]

RelationalExpression

[?In, ?Yield, ?Await]

 

instanceof

 

ShiftExpression

[?Yield, ?Await]

[+In]

 

RelationalExpression

[+In, ?Yield, ?Await]

 

in

 

ShiftExpression

[?Yield, ?Await]

EqualityExpression

[In, Yield, Await]

 

:

RelationalExpression

[?In, ?Yield, ?Await]

824

EqualityExpression

[?In, ?Yield, ?Await]

 

==

 

RelationalExpression

[?In, ?Yield, ?Await]

EqualityExpression

[?In, ?Yield, ?Await]

 

!=

 

RelationalExpression

[?In, ?Yield, ?Await]

EqualityExpression

[?In, ?Yield, ?Await]

 

===

 

RelationalExpression

[?In, ?Yield, ?Await]

EqualityExpression

[?In, ?Yield, ?Await]

 

!==

 

RelationalExpression

[?In, ?Yield, ?Await]

BitwiseANDExpression

[In, Yield, Await]

 

:

EqualityExpression

[?In, ?Yield, ?Await]

BitwiseANDExpression

[?In, ?Yield, ?Await]

 

&

 

EqualityExpression

[?In, ?Yield, ?Await]

BitwiseXORExpression

[In, Yield, Await]

 

:

BitwiseANDExpression

[?In, ?Yield, ?Await]

BitwiseXORExpression

[?In, ?Yield, ?Await]

 

^

 

BitwiseANDExpression

[?In, ?Yield, ?Await]

BitwiseORExpression

[In, Yield, Await]

 

:

BitwiseXORExpression

[?In, ?Yield, ?Await]

BitwiseORExpression

[?In, ?Yield, ?Await]

 

|

 

BitwiseXORExpression

[?In, ?Yield, ?Await]

LogicalANDExpression

[In, Yield, Await]

 

:

BitwiseORExpression

[?In, ?Yield, ?Await]

LogicalANDExpression

[?In, ?Yield, ?Await]

 

&&

 

BitwiseORExpression

[?In, ?Yield, ?Await]

LogicalORExpression

[In, Yield, Await]

 

:

LogicalANDExpression

[?In, ?Yield, ?Await]

LogicalORExpression

[?In, ?Yield, ?Await]

 

||

 

LogicalANDExpression

[?In, ?Yield, ?Await]

CoalesceExpression

[In, Yield, Await]

 

:

CoalesceExpressionHead

[?In, ?Yield, ?Await]

 

??

 

BitwiseORExpression

[?In, ?Yield, ?Await]

CoalesceExpressionHead

[In, Yield, Await]

 

:

CoalesceExpression

[?In, ?Yield, ?Await]

BitwiseORExpression

[?In, ?Yield, ?Await]

ShortCircuitExpression

[In, Yield, Await]

 

:

LogicalORExpression

[?In, ?Yield, ?Await]

CoalesceExpression

[?In, ?Yield, ?Await]

ConditionalExpression

[In, Yield, Await]

 

:

ShortCircuitExpression

[?In, ?Yield, ?Await]

ShortCircuitExpression

[?In, ?Yield, ?Await]

 

?

 

AssignmentExpression

[+In, ?Yield, ?Await]

 

:

AssignmentExpression

[?In, ?Yield, ?Await]

AssignmentExpression

[In, Yield, Await]

 

:

ConditionalExpression

[?In, ?Yield, ?Await]

[+Yield]

YieldExpression

[?In, ?Await]

ArrowFunction

[?In, ?Yield, ?Await]

AsyncArrowFunction

[?In, ?Yield, ?Await]

LeftHandSideExpression

[?Yield, ?Await]

 

=

 

AssignmentExpression

[?In, ?Yield, ?Await]

LeftHandSideExpression

[?Yield, ?Await]

 

AssignmentOperator

 

AssignmentExpression

[?In, ?Yield, ?Await]

LeftHandSideExpression

[?Yield, ?Await]

 

&&=

 

AssignmentExpression

[?In, ?Yield, ?Await]

LeftHandSideExpression

[?Yield, ?Await]

 

||=

 

AssignmentExpression

[?In, ?Yield, ?Await]

825

 

 

 

 

 

 

 

Content      ..     35      36      37      38     ..