|
ECMAScript 4 Netscape Proposal
Formal Description
Syntactic Semantics
|
   |
Monday, June 30, 2003
The syntactic semantics describe the actions the parser takes to evaluate an ECMAScript 4 program. For convenience, the syntactic
grammar is repeated here. The starting nonterminal is Program. See also the
description of the semantic notation.
The semantics are under construction. Many execution paths resulting in ???? represent semantics yet to be implemented.
This document is also available as a Word RTF file.
Terminals
General tokens: Identifier NegatedMinLong
Number RegularExpression String
VirtualSemicolon
Punctuation tokens: ! !=
!== % %=
& &&
&&= &=
( ) *
*= + ++
+= , -
-- -= .
... / /=
: :: ;
< <<
<<= <=
= == ===
> >=
>> >>=
>>> >>>=
? [ ]
^ ^= ^^
^^= { |
|= || ||=
} ~
Reserved words: as break
case catch
class const
continue default
delete do
else extends
false finally
for function
if import in
instanceof is
namespace new
null package
private public
return super
switch this
throw true
try typeof
use var void
while with
Future reserved words: abstract debugger
enum export
goto implements
interface native
protected synchronized
throws transient
volatile
Non-reserved words: get set
Data Model
Semantic Exceptions
Extended integers and rationals
Objects
Undefined
Null
Strings
Namespaces
Qualified Names
The notation
ns::
id is a shorthand for
QualifiedNamenamespace:
ns,
id:
id.
Attributes
Classes
Simple Instances
Slots
Uninstantiated Functions
record UninstantiatedFunction
end record;
Method Closures
Dates
Regular Expressions
Packages
Objects with Limits
References
Modes of expression evaluation
Contexts
Labels
Function Support
Environments
Properties
Miscellaneous
Data Operations
Numeric Utilities
proc unsignedWrap32(
i:
Integer): {0 ... 2
32 – 1}
end proc;
proc signedWrap32(
i:
Integer): {–2
31 ... 2
31 – 1}
if j 231 then j j – 232 end if;
return j
end proc;
proc unsignedWrap64(
i:
Integer): {0 ... 2
64 – 1}
end proc;
proc signedWrap64(
i:
Integer): {–2
63 ... 2
63 – 1}
if j 263 then j j – 264 end if;
return j
end proc;
case x of
{NaNf32, NaNf64, +f32, +f64, –f32, –f64} do return 0;
end case
end proc;
case i of
if j > limit then j limit end if;
if negativeFromEnd and j < 0 then j j + limit end if;
if j < 0 then j 0 end if;
note 0 j limit;
return j
end case
end proc;
case x of
{
NaNf32,
NaNf64,
+f32,
+f64,
–f32,
–f64}
do return none;
{+zerof32, +zerof64, –zerof32, –zerof64} do return 0;
end case
end proc;
if –263 i 263 – 1 then return ilong
elsif 263 i 264 – 1 then return iulong
else return if64
end if
end proc;
if 0 i 264 – 1 then return iulong
elsif –263 i –1 then return ilong
else return if64
end if
end proc;
elsif |q| 253 then return qf64
elsif q < –263 – 1/2 or q 264 – 1/2 then return qf64
else
Let i be the integer closest to q. If q is halfway between
two integers, pick i so that it is even.
note –263 i 264 – 1;
if i < 263 then return ilong else return iulong end if
end if
end proc;
elsif |q| 253 then return qf64
elsif q < –263 – 1/2 or q 264 – 1/2 then return qf64
else
Let i be the integer closest to q. If q is halfway between
two integers, pick i so that it is even.
note –263 i 264 – 1;
if i 0 then return iulong else return ilong end if
end if
end proc;
case q of
{
+zero}
do return +zerof32;
{
–zero}
do return –zerof32;
end case
end proc;
case q of
{
+zero}
do return +zerof64;
{
–zero}
do return –zerof64;
end case
end proc;
case x of
{+zerof32, +zerof64, –zerof32, –zerof64} do return 0;
end case
end proc;
case x of
{–f64} do return –f32;
{–zerof64} do return –zerof32;
{+zerof64} do return +zerof32;
{+f64} do return +f32;
{NaNf64} do return NaNf32;
end case
end proc;
if x {
NaNf32,
NaNf64}
or y {
NaNf32,
NaNf64}
then return unordered
elsif x {
+f32,
+f64}
and y {
+f32,
+f64}
then return equal
elsif x {
–f32,
–f64}
and y {
–f32,
–f64}
then return equal
elsif x {
+f32,
+f64}
or y {
–f32,
–f64}
then return greater
elsif x {
–f32,
–f64}
or y {
+f32,
+f64}
then return less
else
if xr <
yr then return less
end if
end if
end proc;
Character Utilities
proc integerToUTF16(
i: {0 ... 0x10FFFF}):
String
else
j: {0 ... 0xFFFFF} i – 0x10000;
return [high, low]
end if
end proc;
while i |s| do
if s[i] {‘«uD800»’ ... ‘«uDBFF»’} and
i + 1 |s| and
s[i + 1] {‘«uDC00»’ ... ‘«uDFFF»’} then
else ch s[i]; i i + 1
end if;
result result [ch]
end while;
return result
end proc;
return ch converted to a lower case character
using the Unicode full, locale-independent case mapping. A single character may be converted to multiple
characters. If
ch has no lower case equivalent, then the result is the string
char21ToUTF16(
ch).
end proc;
return ch converted to a lower case character
using the Unicode full case mapping in the host environment’s current locale. A single character may be
converted to multiple characters. If
ch has no lower case equivalent, then the result is the string
char21ToUTF16(
ch).
end proc;
return ch converted to a upper case character
using the Unicode full, locale-independent case mapping. A single character may be converted to multiple
characters. If
ch has no upper case equivalent, then the result is the string
char21ToUTF16(
ch).
end proc;
return ch converted to a upper case character
using the Unicode full case mapping in the host environment’s current locale. A single character may be
converted to multiple characters. If
ch has no upper case equivalent, then the result is the string
char21ToUTF16(
ch).
end proc;
Object Utilities
Object Class Inquiries
if c = d then return true
else
if s =
none then return false end if;
end if
end proc;
Object to Boolean Conversion
case o of
Float32 do return o {
+zerof32,
–zerof32,
NaNf32};
Float64 do return o {
+zerof64,
–zerof64,
NaNf64};
end case
end proc;
Object to Primitive Conversion
case h of
if toStringMethod none then
end if;
if valueOfMethod none then
end if;
if valueOfMethod none then
end if;
if toStringMethod none then
end if
end case;
throw a
TypeError exception
— cannot convert this object to a primitive
end proc;
Object to Number Conversions
case a of
Null {
false}
do return +zerof64;
{true} do return 1f64;
end case
end proc;
case a of
Null {
false}
do return +zerof32;
{true} do return 1f32;
end case
end proc;
case a of
Null {
false}
do return 0;
{true} do return 1;
{
+f32,
+f64}
do return +;
{
–f32,
–f64}
do return –;
{+zerof32, +zerof64, –zerof32, –zerof64} do return 0;
throw a
RangeError exception
— the value
a is not an integer
end if;
return r;
end case
end proc;
Apply the lexer grammar with the start symbol
StringNumericLiteral to the string
s.
throw a
TypeError exception
— the string
s does not contain a number
else
end if
end proc;
Object to String Conversions
case a of
{false} do return “false”;
{true} do return “true”;
end case
end proc;
if |digits| = 1 then mantissa digits
else mantissa [digits[0]] “.” digits[1 ...]
end if;
end proc;
case x of
{NaNf32} do return “NaN”;
{+zerof32, –zerof32} do return “0”;
{+f32} do return “Infinity”;
{–f32} do return “-Infinity”;
else
Let e, k, and s be integers such that k
1, 10k–1
s
10k,
(s10e+1–k)f32
= x, and k is as small as possible.
note k is the number of digits in
the decimal representation of s, s is not divisible by 10, and the least significant
digit of s is not necessarily uniquely determined by the above criteria.
When there are multiple possibilities for s according to the rules above,
implementations are encouraged but not required to select the one according to the following rule: Select
the value of s for which
s10e+1–k
is closest in value to r; if there are two such possible values of s, choose the one
that is even.
if k – 1
e 20
then return digits repeat(‘
0’,
e + 1 –
k)
elsif 0 e 20 then return digits[0 ... e] “.” digits[e + 1 ...]
elsif –6
e < 0
then return “
0.”
repeat(‘
0’, –(
e + 1))
digits
end if
end if
end case
end proc;
case x of
{NaNf64} do return “NaN”;
{+zerof64, –zerof64} do return “0”;
{+f64} do return “Infinity”;
{–f64} do return “-Infinity”;
else
Let e, k, and s be integers such that k
1, 10k–1
s
10k,
(s10e+1–k)f64
= x, and k is as small as possible.
note k is the number of digits in
the decimal representation of s, s is not divisible by 10, and the least significant
digit of s is not necessarily uniquely determined by the above criteria.
When there are multiple possibilities for s according to the rules above,
implementations are encouraged but not required to select the one according to the following rule: Select
the value of s for which
s10e+1–k
is closest in value to r; if there are two such possible values of s, choose the one
that is even.
if k – 1
e 20
then return digits repeat(‘
0’,
e + 1 –
k)
elsif 0 e 20 then return digits[0 ... e] “.” digits[e + 1 ...]
elsif –6
e < 0
then return “
0.”
repeat(‘
0’, –(
e + 1))
digits
end if
end if
end case
end proc;
Object to Qualified Name Conversion
Object to Class Conversion
Object to Attribute Conversion
else
note If o is not an attribute, try to
call it with no arguments.
end if
end proc;
Implicit Coercions
if result none then return result
else throw a
TypeError exception
— coercion failed
end if
end proc;
if result none then return result
else throw a
TypeError exception
— coercion failed
end if
end proc;
if result {
none,
null}
then return result
else throw a
TypeError exception
— coercion failed
end if
end proc;
if o =
null or is(
o,
c)
then return o else return none end if
end proc;
Attributes
if b = false then return false
elsif a {
none,
true}
then return b
elsif b = true then return a
if a = b then return a
return CompoundAttributenamespaces: {
a,
b},
explicit:
false,
enumerable:
false,
dynamic:
false,
category:
none,
overrideMod:
none,
prototype:
false,
unused:
false
end if
else
note At this point both a and
b are compound attributes.
throw an
AttributeError exception
— attributes
a and
b have conflicting contents
else
end if
end if
end proc;
case a of
return CompoundAttributenamespaces: {},
explicit:
false,
enumerable:
false,
dynamic:
false,
category:
none,
overrideMod:
none,
prototype:
false,
unused:
false;
return CompoundAttributenamespaces: {
a},
explicit:
false,
enumerable:
false,
dynamic:
false,
category:
none,
overrideMod:
none,
prototype:
false,
unused:
false;
end case
end proc;
Access Utilities
if a =
none then return {}
end if;
end proc;
matchingSlots:
Slot{} {
s |
s o.
slots such that s.
id =
id};
return the one element of matchingSlots
end proc;
case setup of
throw a
ConstantError exception
— a constant’s type or initialiser cannot depend on the value of that constant
end case
end proc;
throw a
ReferenceError exception
— cannot initialise a
const variable twice
end if;
return coercedValue
end proc;
Environmental Utilities
if some c env satisfies c Class then
Let
c be the first element of
env that is a
Class.
return c
end if;
end proc;
for each frame env do
end for each;
end proc;
end if;
return env[0 ... i]
end proc;
return regionalEnv[|regionalEnv| – 1]
end proc;
while env[
i]
Package do i i + 1
end while;
note Every environment ends with a
Package frame, so one will always be found.
return env[i]
end proc;
Property Lookup
note If the same property was found via several
different bindings b, then it will appear only once in the set matchingProperties.
if matchingProperties = {}
then return none
elsif |matchingProperties| = 1 then return the one element of matchingProperties
else
throw a
ReferenceError exception
— this access is ambiguous because the bindings it found belong to several different local
properties
end if
end proc;
if matches = {}
then return none
elsif |matches| = 1 then return the one element of matches
else
throw a
ReferenceError exception
— this access is ambiguous because it found several different instance properties in the same class
end if
end proc;
case o of
end case;
if m none then return m end if;
if flat then return none end if;
end proc;
note Start from the root class (Object)
and proceed through more specific classes that are ancestors of c.
if m none then return m end if
end for each;
end proc;
throw a
ReferenceError exception
— can’t access instance properties outside an instance method without supplying an instance
object
end if;
throw a
ReferenceError exception
— can’t access instance properties inside a non-instance method without supplying an instance
object
end if;
throw a
ReferenceError exception
— can’t access instance properties inside a non-instance method without supplying an instance
object
end if;
throw an
UninitializedError exception
— can’t access instance properties from within a constructor before the superconstructor has been
called
end if;
return this
end proc;
return findBaseInstanceProperty(
c, {
qname},
read)
none or
findBaseInstanceProperty(
c, {
qname},
write)
none or
findArchetypeProperty(
o, {
qname},
read,
flat)
none or
findArchetypeProperty(
o, {
qname},
write,
flat)
none
end proc;
Reading
case r of
end case;
if result none then return result
else
throw a
ReferenceError exception
— property not found, and no default value is available
end if
end proc;
throw a
ReferenceError exception
— property not found, and no default value is available
end if;
return result
end proc;
end if;
if length =
none then throw a
RangeError exception
— length not an integer
else throw a
RangeError exception
— length out of range
end if
end proc;
At the implementation’s discretion either do nothing, set
result to
none, or
throw a
ReferenceError.
end if;
return result
end proc;
if |args| 1 then
throw an
ArgumentError exception
— exactly one argument must be supplied
end if;
return limit.
read(
o,
limit, {
qname},
none,
undefinedIfMissing,
phase)
end proc;
while i < |env| do
case frame of
result limit.
read(
frame,
limit,
multiname,
env,
false,
phase);
case phase of
throw a
ConstantError exception
— cannot read a
with statement’s frame from a constant expression;
throw an
UninitializedError exception
— cannot read a
with statement’s frame before that statement’s
expression has been evaluated
end case
end if;
result limit.
read(
value,
limit,
multiname,
env,
false,
phase)
end case;
if result none then return result end if;
i i + 1
end while;
throw a
ReferenceError exception
— no property found with the name
multiname
end proc;
case m of
case phase of
throw a
ConstantError exception
— a constant expression cannot read dynamic properties;
end case
end if;
throw a
ReferenceError exception
— cannot read an instance property without supplying an instance
end if;
end case
end proc;
note readInstanceProperty
is only called in cases where the instance property is known to exist, so
mBase cannot be
none here.
end proc;
case m of
throw a
ConstantError exception
— a constant expression cannot read mutable variables
end if;
case phase of
throw a
ConstantError exception
— cannot read uninitalised
const variables from a constant expression;
throw an
UninitializedError exception
— cannot read a
const instance variable before it is initialised
end case
end if;
return v;
m cannot be an
InstanceSetter
because these are only represented as write-only properties.
end case
end proc;
case m of
throw a
ReferenceError exception
— cannot access a property defined in a scope outside the current region if any block inside the current
region shadows it;
throw a
ConstantError exception
— a constant expression cannot read mutable variables
end if;
return value;
throw a
ConstantError exception
— a constant expression cannot read mutable variables
end if;
case value of
note Try to run a const
variable’s initialiser if there is one.
case phase of
throw a
ConstantError exception
— a constant expression cannot access a constant with a missing or recursive
initialiser;
end case
end if;
try
note If initialisation failed, restore
m.
initializer to its original value so it can be
tried later.
throw x
end try;
return coercedValue;
note An uninstantiated function can only be
found when
phase =
compile.
throw a
ConstantError exception
— an uninstantiated function is not a constant expression
end case;
note An uninstantiated getter can only be found
when
phase =
compile.
throw a
ConstantError exception
— an uninstantiated getter is not a constant expression
end if;
return m.
call(
env,
phase);
m cannot be a
Setter because these are
only represented as write-only properties.
end case
end proc;
Writing
case r of
throw a
ReferenceError exception
— a non-reference is not a valid target of an assignment;
end case;
throw a
ReferenceError exception
— property not found and could not be created
end if
end proc;
result: {
none,
ok}
limit.
write(
o,
limit,
multiname,
none,
newValue,
true,
phase);
throw a
ReferenceError exception
— property not found and could not be created
end if
end proc;
throw a
RangeError exception
— length out of range
end if;
Evaluate
dotWrite(
o, {
public::“
length”},
lengthf64,
phase) and ignore its result
end proc;
end if;
if deleteResult = false then
end if
else
if writeResult =
none then
throw a
ReferenceError exception
— element not found and could not be created
end if
end if
end proc;
if |args| 1 then
throw an
ArgumentError exception
— exactly one argument must be supplied
end if;
return limit.
write(
o,
limit, {
qname},
none,
newValue,
createIfMissing,
phase)
end proc;
while i < |env| do
case frame of
result
limit.
write(
frame,
limit,
multiname,
env,
newValue,
false,
phase);
throw an
UninitializedError exception
— cannot read a
with statement’s frame before that statement’s expression
has been evaluated
end if;
result limit.
write(
value,
limit,
multiname,
env,
newValue,
false,
phase)
end case;
if result =
ok then return end if;
i i + 1
end while;
if createIfMissing then
note Try to write the variable into pkg
again, this time allowing new dynamic bindings to be created dynamically.
result: {
none,
ok}
limit.
write(
pkg,
limit,
multiname,
env,
newValue,
true,
phase);
if result =
ok then return end if
end if;
throw a
ReferenceError exception
— no existing property found with the name
multiname and one could not be created
end proc;
end if;
case m of
note Before trying to create a new dynamic
property named qname, check that there is no read-only fixed property with the same name.
end if
end if;
throw a
ReferenceError exception
— cannot write an instance property without supplying an instance
end if;
end case
end proc;
o.
localBindings
o.
localBindings
{
LocalBindingqname:
qname,
accesses:
readWrite,
explicit:
false,
enumerable:
enumerable,
content:
dv}
end proc;
case m of
throw a
ReferenceError exception
— cannot initialise a
const instance variable twice
end if;
throw a
ReferenceError exception
— cannot write to an instance method;
m cannot be an
InstanceGetter
because these are only represented as read-only properties.
end case
end proc;
case m of
throw a
ReferenceError exception
— cannot access a property defined in a scope outside the current region if any block inside the current
region shadows it;
m cannot be a
Getter because these are
only represented as read-only properties.
note All instances are resolved for the
run phase, so
env none.
Evaluate
m.
call(
newValue,
env,
phase) and ignore its result
end case
end proc;
Deleting
case r of
if strict then
throw a
ReferenceError exception
— a non-reference is not a valid target for
delete in strict mode
else result true
end if;
end case;
if result none then return result else return true end if
end proc;
if |args| 1 then
throw an
ArgumentError exception
— exactly one argument must be supplied
end if;
return limit.
delete(
o,
limit, {
qname},
none,
phase)
end proc;
while i < |env| do
case frame of
result limit.
delete(
frame,
limit,
multiname,
env,
phase);
throw an
UninitializedError exception
— cannot read a
with statement’s frame before that statement’s expression
has been evaluated
end if;
result limit.
delete(
value,
limit,
multiname,
env,
phase)
end case;
if result none then return result end if;
i i + 1
end while;
return true
end proc;
case m of
throw a
ReferenceError exception
— cannot access a property defined in a scope outside the current region if any block inside the current
region shadows it;
if o Class or env =
none then return false end if;
return false
end case
end proc;
Enumerating
end for each;
if super =
none then return e
end if
end proc;
end for each;
end if;
return e
end proc;
Calling Instances
case a of
Class do return a.
call(
this,
a,
args,
phase);
return f(this, a, args, phase);
end case
end proc;
note This function can be used in a constant
expression.
throw a
ConstantError exception
— cannot call a class before its definition has been compiled
end if;
if |args| 1 then
throw an
ArgumentError exception
— exactly one argument must be supplied
end if;
end proc;
Creating Instances
throw a
ConstantError exception
— cannot construct an instance of a class before its definition has been compiled
end if;
throw a
ConstantError exception
— a class constructor call is not a constant expression because it evaluates to a new object each time it
is evaluated
end if;
Evaluate
callInit(
this,
c,
args,
phase) and ignore its result;
return this
end proc;
end for each;
return new SimpleInstancelocalBindings: {},
archetype:
archetype,
sealed:
not c.
dynamic,
type:
c,
slots:
slots,
call:
call,
construct:
construct,
env:
env
end proc;
if init none then Evaluate
init(
this,
args,
phase) and ignore its result
else
if args [] then
throw an
ArgumentError exception
— the default constructor does not take any arguments
end if
end if
end proc;
Adding Local Definitions
throw an
AttributeError exception
— a local definition cannot have the
override attribute
end if;
if explicit and innerFrame Package then
throw an
AttributeError exception
— the
explicit attribute can only be used at the top level of a package
end if;
if namespaces2 = {}
then namespaces2 {
public}
end if;
multiname:
Multiname {
ns::
id |
ns namespaces2};
end if;
if innerFrame Class and id =
innerFrame.
name then
throw a
DefinitionError exception
— a
static property of a class cannot have the same name as the class, regardless of the
namespace
end if;
for each frame regionalEnv[1 ...] do
throw a
DefinitionError exception
— this definition would shadow a property defined in an outer scope within the same region
end if
end for each;
newBindings:
LocalBinding{}
{
LocalBindingqname:
qname,
accesses:
accesses,
explicit:
explicit,
enumerable:
true,
content:
m |
qname multiname};
note Mark the bindings of
multiname as
forbidden in all non-innermost frames in the current region if they
haven’t been marked as such already.
for each frame regionalEnv[1 ...] do
end for each;
return multiname
end proc;
regionalFrame:
Frame regionalEnv[|
regionalEnv| – 1];
note env is either a
Package or a
ParameterFrame because hoisting only occurs into package or
function scope.
existingBindings:
LocalBinding{}
{
b |
b regionalFrame.
localBindings such that b.
qname =
qname};
regionalFrame regionalEnv[|regionalEnv| – 2];
end if;
if existingBindings = {} then
regionalFrame.
localBindings
regionalFrame.
localBindings
{
LocalBindingqname:
qname,
accesses:
readWrite,
explicit:
false,
enumerable:
true,
content:
v};
return v
elsif |existingBindings| 1 then
throw a
DefinitionError exception
— a hoisted definition conflicts with a non-hoisted one
else
throw a
DefinitionError exception
— a hoisted definition conflicts with a non-hoisted one
end if;
note At this point a hoisted binding of the same
var already exists, so there is no need to create another one. Overwrite its initial value if the
new definition is a function definition.
regionalFrame.localBindings regionalFrame.localBindings – {b};
regionalFrame.
localBindings
regionalFrame.
localBindings
{
LocalBindingenumerable:
true, other fields from
b};
return m
end if
end proc;
Adding Instance Definitions
for each qname multiname do
if mBase =
none then mBase m
elsif m none and m mBase then
throw a
DefinitionError exception
— cannot override two separate superclass methods at the same time
end if
end for each
end if;
return mBase
end proc;
if explicit then
throw an
AttributeError exception
— the
explicit attribute can only be used at the top level of a package
end if;
requestedMultiname:
Multiname {
ns::
id |
ns namespaces};
if requestedMultiname = {} then
definedMultiname {
public::
id};
searchedMultiname openMultiname;
note definedMultiname searchedMultiname
because the public namespace is always open.
else definedMultiname requestedMultiname; searchedMultiname requestedMultiname
end if;
if not (requestedMultiname definedMultiname) then
throw a
DefinitionError exception
— cannot extend the set of a property’s namespaces when overriding it
end if;
case m of
end case;
if not goodKind then
throw a
DefinitionError exception
— a method can override only another method, a variable can override only another variable, a getter can
override only a getter or a variable, and a setter can override only a setter or a variable
end if;
if mOverridden.
final then
end if
end if;
end if;
case overrideMod of
throw a
DefinitionError exception
— a definition that overrides a superclass’s property must be marked with the
override attribute
end if;
throw a
DefinitionError exception
— this definition is hidden by one in a superclass when accessed without a namespace qualifier; in the
rare cases where this is intentional, use the
override(false) attribute
end if;
{false} do
throw a
DefinitionError exception
— this definition is marked with
override(false) but it overrides a superclass’s
property
end if;
{true} do
throw a
DefinitionError exception
— this definition is marked with
override or
override(true) but it
doesn’t override a superclass’s property
end if;
end case;
return mOverridden
end proc;
Instantiation
end if;
if instantiations {} then
Suppose that
instantiateFunction
were to choose at its discretion some element
i2 of
instantiations, assign
i2.
env env,
and return
i. If the behaviour of doing that assignment were observationally indistinguishable by the
rest of the program from the behaviour of returning
i without modifying
i2.
env, then the implementation may, but does not
have to,
return i2 now, discarding (or not even bothering to
create) the value of
i.
note The above rule allows an implementation to
avoid creating a fresh closure each time a local function is instantiated if it can show that the closures would
behave identically. This optimisation is not transparent to the programmer because the instantiations will be
=== to each other and share one set of properties (including the prototype property,
if applicable) rather than each having its own. ECMAScript programs should not rely on this distinction.
end if;
return i
end proc;
case m of
note m.
setup =
none
because
Setup must have been called on a frame before that frame can be
instantiated.
end if;
end case
end proc;
tuple PropertyTranslation
end tuple;
end proc;
return instantiatedFrame
end proc;
note properties will contain the set of
all
SingletonProperty records found in the
frame.
note If any of the parameters (including the rest
parameter) are anonymous, their bindings will not be present in
frame.
localBindings. In this situation, the following
steps add their
SingletonProperty records to
properties.
for each p frame.
parameters do properties properties {
p.
var}
end for each;
if rest none then properties properties {
rest}
end if;
end proc;
else instantiatedFrame.
rest translateProperty(
rest)
end if;
return instantiatedFrame
end proc;
Sealing
proc sealAllLocalProperties(
o:
Object)
end proc;
for each m matchingProperties do
end for each
end if
end proc;
Standard Class Utilities
if n |args| then return default end if;
if arg =
undefined then return default else return arg end if
end proc;
return LocalBindingqname:
qname,
accesses:
readWrite,
explicit:
false,
enumerable:
false,
content:
new Variabletype:
type,
value:
value,
immutable:
false,
setup:
none,
initializer:
none
end proc;
return the one element of matchingBindings
end proc;
Expressions
Syntax
{allowIn, noIn}
Terminal Actions
Body[
RegularExpression]:
String;
Flags[
RegularExpression]:
String;
Identifiers
Syntax
Semantics
Qualified Identifiers
Syntax
SimpleQualifiedIdentifier
Validation
Setup
Evaluation
throw a
TypeError exception
— the qualifier must be a namespace
end if;
end proc;
Primary Expressions
Syntax
null
| true
| false
| Number
| String
| this
| RegularExpression
Validation
throw a
SyntaxError exception
—
this can be used outside a function only in non-strict mode
end if
throw a
SyntaxError exception
— this function does not define
this
end if;
Evaluate
Validate[
ArrayLiteral](
cxt,
env) and ignore its result;
Evaluate
Validate[
ObjectLiteral](
cxt,
env) and ignore its result;
end proc;
throw a
SyntaxError exception
—
private is meaningful only inside a class
end if
end proc;
Setup
Evaluation
note If
Validate
passed,
this can be uninitialised only when
phase =
compile.
throw a
ConstantError exception
— a constant expression cannot read an uninitialised
this parameter
end if;
throw an
UninitializedError exception
— can’t access
this from within a constructor before the superconstructor has been
called
end if;
return this;
return Body[RegularExpression] “#” Flags[RegularExpression];
end proc;
note Validate
already ensured that
c none.
end proc;
Function Expressions
Syntax
Validation
Setup
Evaluation
throw a
ConstantError exception
— a
function expression is not a constant expression because it can evaluate to different
values
end if;
throw a
ConstantError exception
— a
function expression is not a constant expression because it can evaluate to different
values
end if;
return f
end proc;
Object Literals
Syntax
Validation
Setup
Setup[
FieldList]
() propagates the call to
Setup to nonterminals in the expansion of
FieldList.
Setup[
FieldName]
() propagates the call to
Setup to nonterminals in the expansion of
FieldName.
Evaluation
throw a
ConstantError exception
— an object literal is not a constant expression because it evaluates to a new object each time it is
evaluated
end if;
Evaluate
Eval[
FieldList](
env,
o,
phase) and ignore its result;
return o
end proc;
Evaluate
dotWrite(
o,
multiname,
value,
phase) and ignore its result
end proc;
Array Literals
Syntax
Validation
Setup
Evaluation
throw a
ConstantError exception
— an array literal is not a constant expression because it evaluates to a new object each time it is
evaluated
end if;
return o
end proc;
Evaluate
Eval[
LiteralElement](
env,
length,
o,
phase) and ignore its result;
return length + 1;
Evaluate
Eval[
LiteralElement](
env,
length,
o,
phase) and ignore its result;
end proc;
Evaluate
indexWrite(
o,
length,
value,
phase) and ignore its result
end proc;
Super Expressions
Syntax
Validation
throw a
SyntaxError exception
— a
super expression is meaningful only inside a class
end if;
throw a
SyntaxError exception
— a
super expression without an argument is meaningful only inside an instance method or a
constructor
end if;
throw a
SyntaxError exception
— a
super expression is meaningful only if the enclosing class has a superclass
end if;
throw a
SyntaxError exception
— a
super expression is meaningful only inside a class
end if;
throw a
SyntaxError exception
— a
super expression is meaningful only if the enclosing class has a superclass
end if;
end proc;
Setup
Evaluation
note If
Validate
passed,
this can be uninitialised only when
phase =
compile.
throw a
ConstantError exception
— a constant expression cannot read an uninitialised
this parameter
end if;
throw an
UninitializedError exception
— can’t access
super from within a constructor before the superconstructor has been
called
end if;
end proc;
note Validate ensured
that
limit cannot be
none at this point.
if coerced =
null then return null end if;
end proc;
Postfix Expressions
Syntax
Validation
Setup
Evaluation
case r of
end case;
return call(
base,
f,
args,
phase)
end proc;
case r of
end case;
return call(
base,
f,
args,
phase);
throw a
ConstantError exception
—
++ cannot be used in a constant expression
end if;
return b;
throw a
ConstantError exception
—
-- cannot be used in a constant expression
end if;
return b
end proc;
Property Operators
Syntax
Validation
Setup
Setup[
Brackets] ()
propagates the call to
Setup to nonterminals in the expansion of
Brackets.
Setup[
Arguments]
() propagates the call to
Setup to nonterminals in the expansion of
Arguments.
Evaluation
while i length do
An implementation may, at its discretion, either
throw
a
ReferenceError or treat the hole as a missing
argument, substituting the called function’s default parameter value if there is one,
undefined if the called function is unchecked, or
throwing an
ArgumentError exception otherwise. An implementation must
not replace such a hole with
undefined except when the called
function is unchecked or happens to have
undefined as its default
parameter value.
end if;
args args [arg];
i i + 1
end while;
return args
end proc;
Unary Operators
Syntax
Validation
Setup
Evaluation
throw a
ConstantError exception
—
delete cannot be used in a constant expression
end if;
throw a
ConstantError exception
—
++ cannot be used in a constant expression
end if;
return c;
throw a
ConstantError exception
—
-- cannot be used in a constant expression
end if;
return c;
end proc;
case x of
i: {0 ... 2
64 – 1}
x.
value;
end case
end proc;
Multiplicative Operators
Syntax
Validation
Setup
Evaluation
Additive Operators
Syntax
Validation
Setup
Evaluation
Bitwise Shift Operators
Syntax
Validation
Setup
Evaluation
Relational Operators
Syntax
RelationalExpressionallowIn
Validation
Setup
Evaluation
Equality Operators
Syntax
Validation
Setup
Evaluation
Binary Bitwise Operators
Syntax
Validation
Setup
Evaluation
return bitOr(
a,
b,
phase)
end proc;
Binary Logical Operators
Syntax
Validation
Setup
Evaluation
Conditional Operator
Syntax
Validation
Setup
Evaluation
Assignment Operators
Syntax
*=
| /=
| %=
| +=
| -=
| <<=
| >>=
| >>>=
| &=
| ^=
| |=
Semantics
Validation
Setup
Evaluation
throw a
ConstantError exception
— assignment cannot be used in a constant expression
end if;
return b;
throw a
ConstantError exception
— assignment cannot be used in a constant expression
end if;
return result;
throw a
ConstantError exception
— assignment cannot be used in a constant expression
end if;
end case;
return result
end proc;
Comma Expressions
Syntax
Validation
Setup
Evaluation
Type Expressions
Syntax
Validation
Setup and Evaluation
Statements
Syntax
{abbrev, noShortIf, full}
;
| VirtualSemicolon
| «empty»
SemicolonnoShortIf
;
| VirtualSemicolon
| «empty»
Semicolonfull
;
| VirtualSemicolon
Validation
Evaluate
Validate[
Block](
cxt,
env,
jt,
preinst) and ignore its result;
Evaluate
Validate[
IfStatement](
cxt,
env,
jt) and ignore its result;
Evaluate
Validate[
DoStatement](
cxt,
env,
sl,
jt) and ignore its result;
Evaluate
Validate[
WhileStatement](
cxt,
env,
sl,
jt) and ignore its result;
Evaluate
Validate[
ForStatement](
cxt,
env,
sl,
jt) and ignore its result;
Evaluate
Validate[
WithStatement](
cxt,
env,
jt) and ignore its result;
Evaluate
Validate[
TryStatement](
cxt,
env,
jt) and ignore its result
end proc;
Evaluate
Validate[
Statement](
cxt,
env,
sl,
jt,
false) and ignore its result;
Evaluate
Validate[
Attributes](
cxt,
env) and ignore its result;
Evaluate
Setup[
Attributes]() and ignore its result;
throw a
TypeError exception
— attributes other than
true and
false may be used in a statement but not a
substatement
end if;
if attr then Evaluate
Validate[
Substatements](
cxt,
env,
jt) and ignore its result
end if
end proc;
Evaluate
Validate[
Substatementabbrev](
cxt,
env, {},
jt) and ignore its result
end proc;
Evaluate
Validate[
Substatementfull](
cxt,
env, {},
jt) and ignore its result
end proc;
Setup
Setup[
Statement]
() propagates the call to
Setup to nonterminals in the expansion of
Statement.
Evaluation
Empty Statement
Syntax
Expression Statement
Syntax
Validation
Setup
Evaluation
Super Statement
Syntax
Validation
throw a
SyntaxError exception
— a
super statement is meaningful only inside a constructor
end if;
Evaluate
Validate[
Arguments](
cxt,
env) and ignore its result;
end proc;
Setup
Evaluation
throw a
ReferenceError exception
— the superconstructor cannot be called twice
end if;
return this
end proc;
Block Statement
Syntax
Validation
Evaluate
Validate[
Directives](
localCxt,
[frame] env,
jt,
preinst,
none)
and ignore its result
end proc;
CompileFrame[
Block]
compileFrame;
Preinstantiate[
Block]
preinst;
Evaluate
ValidateUsingFrame[
Block](
cxt,
env,
jt,
preinst,
compileFrame)
and ignore its result
end proc;
Setup
Setup[
Block] () propagates the call to
Setup to nonterminals in the expansion of
Block.
Evaluation
if Preinstantiate[
Block]
then runtimeFrame compileFrame
end if;
end proc;
Labeled Statements
Syntax
Validation
throw a
SyntaxError exception
— nesting labeled statements with the same label is not permitted
end if;
Evaluate
Validate[
Substatement](
cxt,
env,
sl {
name},
jt2) and ignore its result
end proc;
Setup
Evaluation