A 32-bit signed value can be treated as having a binary point immediately after its sign bit. This is equivalent
to dividing its signed integer value by 231, so that it can now represent numbers from –1 to (1 – 2–31). When
a 32-bit value is used to represent a fractional number in this fashion, it is known as a Q31 number.
Saturated additions, subtractions, and doublings can be performed on Q31 numbers using the same
instructions as are used for saturated integer arithmetic, since everything is simply scaled down by a factor
of 2–31.
If two Q15 numbers are multiplied together as integers, the resulting integer needs to be scaled down by a
factor of 2–15 × 2–15 == 2–30. For example, multiplying the Q15 number 0x8000 (representing –1) by itself
using an integer multiplication instruction yields the value 0x40000000, which is 230 times the desired
result of +1.
This means that the result of the integer multiplication instruction is not quite in Q31 form. To get it into
Q31 form, it must be doubled, so that the required scaling factor becomes 2–31. Furthermore, it is possible
that the doubling will cause integer overflow, so the result should in fact be doubled with saturation. In
particular, the result 0x40000000 from the multiplication of 0x8000 by itself should be doubled with
saturation to produce 0x7FFFFFFF (the closest possible Q31 number to the correct mathematical result of
–1 × –1 == +1). If it were doubled without saturation, it would instead produce 0x80000000, which is the
Q31 representation of –1.
To implement a saturated Q15 × Q15 --> Q31 multiplication, therefore, an integer multiply instruction
should be followed by a saturated integer doubling. The latter can be performed by a QADD instruction
adding the multiply result to itself.
A global Environment Record is used to represent the outer most scope that is shared by all of the ECMAScript Script
elements that are processed in a common realm. A global Environment Record provides the bindings for built-in
globals, properties of the global object(FunctionDeclaration or VariableStatement), and for all top-level declarations(the let and const declarations) that occur within a
Script.
A global Environment Record is logically a single record but it is specified as a composite encapsulating of object
Environment Record([[ObjectRecord]]) and a declarative Environment Record([[DeclarativeRecord]]).
The object Environment Record has as its base object the global object of the associated Realm Record. This global object is the value returned by the global Environment Record's GetThisBinding concrete method:
Let envRec be the global Environment Record for which the method was invoked.
Return envRec.[[GlobalThisValue]]
zxxu: according to ecma, Regular object Environment Records do not provide a this binding, so global Environment Record has a [[GlobalThisValue]] field
The object Environment Record contains the bindings for all built-in globals and all bindings introduced by a FunctionDeclaration
or VariableStatement contained in global code. The bindings for all other ECMAScript declarations(the let and const declarations) in global code are contained in the declarative Environment Record component.
Properties may exist upon a global object that were directly created rather than being declared using a var or function declaration. so global Environment Record also has a field [[VarNames]] for string names bound by FunctionDeclaration or VariableDeclaration.
If m is less than zero, return the String concatenation of the String "-" and ToString(-m).
If m is infinity, return the String "Infinity".
let n, k, and s be integers such that k >= 1, s in [10^(k-1), 10^k), the Number value for s * 10^(n-k) is m. Note that k is the number of digits in the decimal representation of s, that s is not divisible by 10.
if both k and n are no greater than 21:
if k is no greater than n, return the string-concatenation of:
the k digits of the decimal representation of s
n−k occurrences of the character 0
if n is greater than 0, return the string-concatenation of:
the code units of the most significant n digits of the decimal representation of s
the code unit 0x002E (FULL STOP)
the code units of the remaining k - n digits of the decimal representation of s
If NewTarget is not undefined, throw a TypeError exception.
Note: the Symbol Constructor is not intended to be used with the new operator(not the target for new)
If description is undefined, let descString be undefined; Else, let descString be ? ToString(description).
Return a new unique Symbol value whose [[Description]] value is descString.
Note: the Symbol() function returns a Symbol type instead of a Symbol object
Symbol Prototype Object
abstract operation thisSymbolValue(value)
If Type(value) is Symbol, return value.
If Type(value) is Object and value has a [[SymbolData]] internal slot
then Return value.[[SymbolData]] //a Symbol Object
Throw a TypeError exception.
Example
mySymbol = Symbol( "my symbol" )
// Object() performs a type conversion when called as a function rather than as a constructor.
mySymObj = Object(mySymbol)
console.log(mySymObj.toString()) // Symbol(my symbol)
function anInstanceOfFunction(data)
{
this.data = data;
}
thisArgument = {"data" : null};
// all instances of Function(function definitions or dynamical functions by `new Function`) has
// their [[prototype]] chained to the Function constructor's prototype property(Function.prototype)
anInstanceOfFunction.call(thisArgument, "dat");
console.log(thisArgument.data);
note Function.prototype itself is a function object(to ensure compatibility with es2015), which returns undefined when called; but the call here is `Function.prototype.` instead of `Function.prototype(`
If IsCallable(F) is false, throw a TypeError exception.//F is anInstanceOfFunction in our example
Pop from the execution context stack//the top execution context has no further use and optimized out
Let calleeContext be PrepareForOrdinaryCall(F, undefined):
base_obj = {
"constructor" : my_constructor,
}
function my_constr_stub()
{
console.log("in constructor stub:new.target=" + new.target);//undefined
}
function my_constructor()
{
console.log("in constructor:new.target=" + new.target);// function my_constructor(){...
my_constr_stub();
}
my_constructor.prototype = base_obj;
new my_constructor()
Object [[Construct]](a List of any, newTarget)
The second argument is the object to which the new operator was initially applied. For example, in following code,
the new operator is initially applied to the Square object:
factit = function factorial(n) {
console.log(n)
if (n < 2) {
return 1;
}
return n * factorial(n - 1);
}
non_recursive = function(){}
/*
can't visit factorial here:
as is indicated in `Runtime Semantics: Evaluation` of NAMED function expression,
we will NewDeclarativeEnvironment(scope) as a middle env to recv factorial
from ecma:
The BindingIdentifier in a FunctionExpression can be referenced
from inside the FunctionExpression's
FunctionBody to allow the function to call itself recursively.
However, unlike in a FunctionDeclaration, the BindingIdentifier in
a FunctionExpression cannot be referenced from and does
not affect the scope enclosing the FunctionExpression.
*/
StatementList : StatementList StatementListItem //StatementListItem can be Statement or Declaration
Let declarations be TopLevelVarScopedDeclarations of StatementList.
Append to declarations the elements of the TopLevelVarScopedDeclarations of StatementListItem.
Return declarations.
StatementListItem : Declaration
if is function Declaration, return a list contains the Declaration// function is not taken as Lex but top level Var!
Return the TopLevelVarScopedDeclarations of LabelledItem.
LabelledItem : Statement
// recursive to the last non-labelled Statement
If Statement is Statement : LabelledStatement , return TopLevelVarScopedDeclarations of Statement
Return VarScopedDeclarations of Statement.
StatementList : StatementList StatementListItem //StatementListItem can be Statement or Declaration
Let declarations be TopLevelLexicallyScopedDeclarations of StatementList.
Append to declarations the elements of the TopLevelLexicallyScopedDeclarations of StatementListItem.
Return declarations.
StatementListItem : Statement
Return a new empty List.//VariableStatement contribute to Var instead of Lex
StatementListItem : Declaration
if Declaration is `let ` or `const `, return a new List containing Declaration;
else Return a new empty List// TopLevel functions are taken as Var instead
StatementList : StatementList StatementListItem //StatementListItem can be Statement or Declaration
Let declarations be LexicallyScopedDeclarations of StatementList.
Append to declarations the elements of the LexicallyScopedDeclarations of StatementListItem.
Return declarations.
StatementListItem : Declaration
Return a new List containing the Declaration
FunctionStatementList : StatementList or Script
Return the TopLevelLexicallyScopedDeclarations of StatementList.
LabelledItem : FunctionDeclaration
Return a new List containing FunctionDeclaration.
Others
not documented in ecma documents
`catch ( CatchParameter ) Block` is not mentioned, but according to "Runtime Semantics: CatchClauseEvaluation", CatchParameter should be Lexically Declared
StatementList : StatementList StatementListItem //StatementListItem can be Statement or Declaration
Let declarations be VarScopedDeclarations of StatementList.
Append to declarations the elements of the VarScopedDeclarations of StatementListItem.
Return declarations.
StatementListItem : Declaration
Return a new empty List// `let ` or `const ` Declaration is Lex, funct decl is top Var
Variable Statement
Return a new List contains all VariableDeclaration
FunctionStatementList : StatementList or Script
Return the TopLevelVarScopedDeclarations of StatementList.
Statements contains subs
if/while/for/with/switch/label/try Statement, return a new List contains all VariableDeclaration of the sub(s)
for the case of `for(var `, the new List is pre-feed.
note in `catch ( CatchParameter ) Block`, CatchParameter is not included.
note in label Statement, `LabelledItem : FunctionDeclaration` Return a new empty List.
function outer_func()
{
{{
var var01 = "var01";
let innerLet = "innerLet";// const innerCst = "innerCst";
function inner_func()
{
alert("inner_func");
}
}}
// var01 is accessible here
// it's an early error to access innerLet here
inner_func();
}
outer_func();
12.3.7.1 Runtime Semantics: Evaluation of super . IdentifierName
SuperProperty : super . IdentifierName:
Let env be GetThisEnvironment()// loop up LexicalEnvironment until found an Environment who's HasThisBinding() returns true.
Let actualThis be ?env.GetThisBinding()
Let propertyKey be StringValue of IdentifierName
If the code matched by this SuperProperty is strict mode code, let strict be true; else let strict be false.
Let baseValue be ?env.GetSuperBase():
Let home be envRec.[[HomeObject]].
If home has the value undefined, return undefined.
Return ? home.[[GetPrototypeOf]]().
Return a value of type Reference that is a Super Reference whose base value component is baseValue, whose referenced
name component is propertyKey, whose thisValue component is actualThis, and whose strict reference flag is
strict.
There are following basic rules of semicolon insertion:
When a token is encountered is not allowed by any production of the grammar, then a semicolon is automatically inserted before if one or more of the following conditions is true:
The offending token is separated from the previous token by at least one LineTerminator.
The offending token is }.
The previous token is ) and the inserted semicolon would then be parsed as the terminating semicolon
of a do-while statement
When a token is allowed by some production of the grammar, but the production is a restricted production and
the token would be the first token for a terminal or nonterminal immediately following the annotation "[no LineTerminator here]" within the restricted production(and therefore such a token is called a restricted token)
the restricted token is separated from the previous token by at least one LineTerminator
However, there is an additional overriding condition on the preceding rules: a semicolon is never inserted
automatically if the semicolon would then be parsed as an empty statement or if that semicolon would become one of
the two semicolons in the header of a for-statement
example 01
The source
return
a + b
is transformed by automatic semicolon insertion into the following:
return;
a + b;
according to rule 2 and `return [no LineTerminator here] Expression`
IdentifierName can be devided into ReservedWord and Identifier.
A keyword is a token that matches IdentifierName, but also has a syntactic use.
Many keywords are reserved words, but some are reserved only in certain contexts. contextual keywords(await and yield) belong to ReservedWord but sometimes can be used as identifiers.
Followings belong to Identifier but not intepreted as so under certain syntactic productions:
let, static
implements, interface, package, private, protected, public; but in future, they will become reserved.