Wednesday, December 28, 2022

Symbol

Symbol

The Symbol Constructor

Symbol ( [ description ] )

  1. If NewTarget is not undefined, throw a TypeError exception.
  2. Note: the Symbol Constructor is not intended to be used with the new operator(not the target for new)
  3. If description is undefined, let descString be undefined; Else, let descString be ? ToString(description).
  4. Return a new unique Symbol value whose [[Description]] value is descString.
  5. Note: the Symbol() function returns a Symbol type instead of a Symbol object

Symbol Prototype Object

abstract operation thisSymbolValue(value)

  1. If Type(value) is Symbol, return value.
  2. If Type(value) is Object and value has a [[SymbolData]] internal slot
  3. then Return value.[[SymbolData]] //a Symbol Object
  4. 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)

Tuesday, December 27, 2022

Function.prototype.call

Function.prototype.call ( thisArgument, argumentsList )

Example

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);

Function.prototype.call ( thisArgument, argumentsList )

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(`

  1. If IsCallable(F) is false, throw a TypeError exception.//F is anInstanceOfFunction in our example
  2. Pop from the execution context stack//the top execution context has no further use and optimized out
  3. Let calleeContext be PrepareForOrdinaryCall(F, undefined):
            calleeContext = {
                "Function" : F,
                "LexicalEnvironment" : new NewFunctionEnvironment(F),
            }
            calleeContext.VariableEnvironment = calleeContext.LexicalEnvironment
            Push calleeContext onto the execution context stack
            return calleeContext
        
    
  4. calleeContext.LexicalEnvironment.EnvironmentRecord.[[ThisValue]] = thisArgument
  5. Let result be Evaluate F with argumentsList.
  6. Remove(exactly, Pop) calleeContext from the execution context stack
  7. If result.[[Type]] is return, return NormalCompletion(result.[[Value]]).
  8. ReturnIfAbrupt(result).
  9. Return NormalCompletion(undefined).

Function.prototype.bind

Function.prototype.bind( boundThis, ...boundArgs )

Example

const person = {
    getFullName: function () {
        return this.firstName + " " + this.lastName;
    }
}

const thisPerson = {
	firstName   :   "John",
	lastName    :   "Xu",
}

let getFullName = person.getFullName.bind(thisPerson);

console.log( getFullName() )

Function.prototype.bind( boundThis, ...boundArgs )

  1. Let targetFunction be the this value. // for our example, person.getFullName
  2. If IsCallable(targetFunction) is false, throw a TypeError exception.
  3. Let boundArgs be a new List consisting of all of the argument values provided after boundThis(for our example, empty) .
  4. Let F be ?BoundFunctionCreate(targetFunction, boundThis, boundArgs)
            return {
                [[BoundTargetFunction]]: targetFunction,
                [[BoundThis]]: boundThis,
                [[BoundArguments]]: boundArgs,
                [[Prototype]]:targetFunction.[[Prototype]],
            }
        
  5. Perform SetFunctionName(F, name = Get(Target, "name"), prefix = "bound").

NewTarget and new.target

NewTarget

example 01


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:

class Rectangle {
  constructor(height, width) {
    console.log("in Rectangle:new.target=" + new.target);
    this.name = 'Rectangle';
    this.height = height;
    this.width = width;
  }
}

class Square extends Rectangle {
  constructor(length) {
    console.log("in Square:new.target=" + new.target);
    super(length, length);

    this.name = 'Square';
  }
}

aS = new Square(2);
console.log(
    "name=" + aS.name +
    ";height=" + aS.height
);

Friday, December 23, 2022

function expression

function expression
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.
*/

Thursday, December 22, 2022

TopLevelVarScopedDeclarations

TopLevelVarScopedDeclarations

Block

  1. Block : { }
        Return a new empty List.
    
  2. 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.
    
  3. StatementListItem : Declaration
        if is function Declaration, return a list contains the Declaration// function is not taken as Lex but top level Var!
    

Label Statement

LabelledStatement : LabelIdentifier : LabelledItem

    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.

Others

not documented in ecma documents

TopLevelLexicallyScopedDeclarations

TopLevelLexicallyScopedDeclarations

Block

  1. Block : { }
        Return a new empty List.
    
  2. 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.
    
  3. StatementListItem : Statement
        Return a new empty List.//VariableStatement contribute to Var instead of Lex
    
  4. 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
    

Labelled Statements

Return a new empty List

Others

not documented in ecma documents

LexicallyScopedDeclarations

LexicallyScopedDeclarations

Block

  1. 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.
    
  2. 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

VarScopedDeclarations

VarScopedDeclarations

Block

  1. Block : { }
        Return a new empty List.
    
  2. 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.
    
  3. 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.

Others

not documented in ecma documents

Wednesday, December 21, 2022

let, var and const

let, var and const
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();

Monday, December 19, 2022

GetSuperConstructor

12.3.7.2 Runtime Semantics: GetSuperConstructor ( )

return GetThisEnvironment().[[FunctionObject]].[[GetPrototypeOf]]()

example

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super : super([arguments]) // calls the parent constructor.

12.3.7.1 Runtime Semantics: Evaluation of super . IdentifierName

12.3.7.1 Runtime Semantics: Evaluation of super . IdentifierName SuperProperty : super . IdentifierName:
  1. Let env be GetThisEnvironment()// loop up LexicalEnvironment until found an Environment who's HasThisBinding() returns true.
  2. Let actualThis be ?env.GetThisBinding()
  3. Let propertyKey be StringValue of IdentifierName
  4. If the code matched by this SuperProperty is strict mode code, let strict be true; else let strict be false.
  5. Let baseValue be ?env.GetSuperBase():
    • Let home be envRec.[[HomeObject]].
    • If home has the value undefined, return undefined.
    • Return ? home.[[GetPrototypeOf]]().
  6. 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.

Sunday, December 18, 2022

Automatic Semicolon Insertion

Automatic Semicolon Insertion

There are following basic rules of semicolon insertion:

  1. 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
  2. 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`

Saturday, December 17, 2022

ReservedWord

ReservedWord

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.
  • as, async, from, get, meta, of, set

Friday, December 16, 2022

Proxy Objects

Proxy Objects

A proxy object is an exotic object whose essential internal methods are partially implemented using ECMAScript code. Every proxy object has an internal slot called [[ProxyHandler]]. The value of [[ProxyHandler]] is an object, called the proxy's handler object, or null. Every proxy object also has an internal slot called [[ProxyTarget]] whose value is either an object or the null value. This object is called the proxy's target object.

When a handler method is called to provide the implementation of a proxy object internal method, the handler method is passed the proxy's target object as a parameter. Invoking an internal method on the proxy results in the invocation of the corresponding internal method on the proxy's target object if the handler object does not have a method corresponding to the internal trap.

[[GetPrototypeOf]] ( )

  1. Let trap be ? GetMethod(handler, "getPrototypeOf").
  2. If not IsExtensible(target) or trap is undefined, Return ? target.[[GetPrototypeOf]]().
  3. return call trap on target to get target's prototype

[[SetPrototypeOf]] ( V )

  1. if not IsExtensible(target), return true
  2. Let trap be ? GetMethod(handler, "setPrototypeOf").
  3. If trap is undefined, Return ? target.[[SetPrototypeOf]](V).
  4. return call trap on target&V to set target's prototype

Arguments Exotic Objects

Arguments Exotic Objects

Most ECMAScript functions make an arguments object available to their code. Depending upon the characteristics of the function definition, its arguments object is either an ordinary object or an arguments exotic object.

An arguments exotic object is an exotic object whose array index properties map to the formal parameters bindings.

Arguments exotic objects have a [[ParameterMap]] internal slot. Ordinary arguments objects also have a [[ParameterMap]] internal slot whose value is always undefined.

[[GetOwnProperty]] ( P )

  1. Let args be the arguments object.
  2. Let desc be OrdinaryGetOwnProperty(args, P).
  3. If desc is undefined, return desc.
  4. Let map be args.[[ParameterMap]].
  5. Let isMapped be HasOwnProperty(map, P).
  6. If isMapped, set desc.[[Value]] to Get(map, P)
  7. Return desc.

[[DefineOwnProperty]] ( P, Desc )

  1. Let newArgDesc be Desc.
  2. If isMapped and Desc.[[Value]] is not present and Desc.[[Writable]] is false,
        Set newArgDesc to a copy of Desc except newArgDesc.[[Value]] as Get(map, P)
        
  3. if not OrdinaryDefineOwnProperty(args, P, newArgDesc), return false.
  4. If isMapped is false, return true
  5. If IsAccessorDescriptor(Desc), call map.[[Delete]](P) and return true
  6. If Desc.[[Value]] is present, Set(map, P, Desc.[[Value]], false).
  7. If Desc.[[Writable]] is false, Call map.[[Delete]](P)

Tuesday, December 13, 2022

PrepareForOrdinaryCall

PrepareForOrdinaryCall( F, newTarget )

PrepareForOrdinaryCall( F, newTarget ) where F is a function object and newTarget is Undefined or Object:

  1. let calleeContext be a new code execution context as:
  2. Push calleeContext onto the execution context stack; suspending the old while making calleeContext the running context
  3. return calleeContext

Monday, December 12, 2022

SameValue, SameValueZero and Strict Equality Comparison

SameValue, SameValueZero and Strict Equality Comparison

SameValue differs from the Strict Equality Comparison Algorithm in its treatment of signed zeroes and NaNs: +0 === -0 and !(NaN === NaN)

SameValueZero differs from SameValue only in its treatment of +0 and -0.

NewGlobalEnvironment

NewGlobalEnvironment ( G, thisValue )

NewGlobalEnvironment ( G, thisValue ) returns a new global env who's outer lexical environment is null and its global Environment Record created as globalRec:

  1. .[[ObjectRecord]]: a new object Environment Record who's binding object is G
  2. .[[DeclarativeRecord]]: a new declarative Environment Record; [[VarNames]]: a new empty List.
  3. .[[GlobalThisValue]]: thisValue (zxxu: thisValue and G means different stuff? according to SetRealmGlobalObject and InitializeHostDefinedRealm, they can be the same but also can be different)

NewFunctionEnvironment

NewFunctionEnvironment ( F, newTarget )

NewFunctionEnvironment ( F, newTarget ):

  1. Assert: Type(newTarget) is Undefined or Object.
  2. Let envRec be a new function Environment Record containing no bindings.
  3. Set envRec.[[FunctionObject]] to F.
  4. If F.[[ThisMode]] is lexical, set envRec.[[ThisBindingStatus]] to lexical.
  5. Else, set envRec.[[ThisBindingStatus]] to uninitialized.
  6. Set envRec.[[HomeObject]] to F.[[HomeObject]].
  7. Set envRec.[[NewTarget]] to newTarget.
  8. Return a new Lexical Environment who's EnvironmentRecord is envRec and outer lexical environment is F.[[Environment]].

Sunday, December 11, 2022

Consent letter for children travelling outside Canada

Countries have their own entry and exit requirements for children. The consent letter may not be considered sufficient by a country’s immigration authorities and there is no guarantee that they will recognize it. For more information, check the entry and exit requirements in the Travel Advice and Advisories for your destination country or contact the nearest embassy or consulate of the destination country before travelling. For example, to check for requirements for America , can send a letter to armcanadaembassy@mfa.am such as:


hi, armembassycanada.ca:

If my child will travel to America without myself, is there a consent form to submit ONLINE indicating her/his temp guardian as my friend when she/he is in America?

thanks

A sample Consent letter can be found at https://travel.gc.ca/travelling/children/consent-letter

Function Environment Record

Function Environment Record

GetSuperBase():

  • Let envRec be the function Environment Record for which the method was invoked.
  • Let home be envRec.[[HomeObject]].
  • If home has the value undefined, return undefined.
  • Return home.[[Prototype]].
  • would it better to rename it into GetSuper or GetSuperObject()?

GetThisBinding():

  • Assert: envRec.[[ThisBindingStatus]] is not lexical.
  • If envRec.[[ThisBindingStatus]] is uninitialized, throw a ReferenceError exception.
  • Return envRec.[[ThisValue]].

HasSuperBinding():

  • If envRec.[[ThisBindingStatus]] is lexical, return false.
  • If envRec.[[HomeObject]] has the value undefined, return false; otherwise, return true.
  • zxxu:[[HomeObject]] is meanful only when has super accesses; ecma: [[HomeObject]] is the object that the function is bound to as a method; zxxu: [[HomeObject]] is added since es6 to support class definitions

HasThisBinding(): If envRec.[[ThisBindingStatus]] is lexical, return false; otherwise, return true.

BindThisValue(V):

  • Assert: envRec.[[ThisBindingStatus]] is not lexical.
  • If envRec.[[ThisBindingStatus]] is initialized, throw a ReferenceError exception.
  • Set envRec.[[ThisValue]] to V.
  • Set envRec.[[ThisBindingStatus]] to initialized.
  • Return V.

Saturday, December 10, 2022

the this keyword of JS

the this keyword of JS
class Polygon {
  constructor() {
    this.name = 'Polygon';
  }
}

const poly1 = new Polygon();

console.log(poly1.name); //Polygon


function outer_func()
{
    function inner_func()
    {
        this.prop01 = "value of prop01";
    }
    inner_func();
}

outer_func()

console.log( "prop01=" + prop01 )//value of prop01

var prop02 = "value of prop02";
console.log( "prop02=" + this.prop02 )//value of prop02

outer_func.inner_func2 = function (){
    this.prop03 = "value of prop03";
}
outer_func.inner_func2();
console.log( "prop03=" + outer_func.prop03 )//value of prop03

Thursday, December 1, 2022

Hyperscan basics

Hyperscan basics

---requirements---

On writing this document, we're using 5.4.0 and it requires:

  • CMake 2.8.11
  • Ragel 6.9
  • Python 2.7
  • Boost 1.57

If the Hyperscan library is used on x86 systems without SSSE3, the runtime API functions will resolve to functions that return HS_ARCH_ERROR instead of potentially executing illegal instructions.

To build an AVX512VBMI runtime, the CMake variable BUILD_AVX512VBMI must be enabled manually during configuration(-DBUILD_AVX512VBMI=on).

---concepts---

--scan interface--

Patterns are provided to a compilation interface which generates an immutable pattern database. The scan interface then can be used to scan a target data buffer

--Vectored mode--

the target data consists of a list of non-contiguous blocks that are available all at once. As for block mode, no retention of state is required(Streaming mode requires retention of states).

--Stream state--

some state space is required to store data that persists between scan calls for each stream. This allows Hyperscan to track matches that span multiple blocks of data.

--All matches--

scanning /foo.*bar/ against fooxyzbarbar will return two matches from Hyperscan. at the points corresponding to the ends of fooxyzbar and fooxyzbarbar. In contrast, libpcre semantics by default would report only one match at fooxyzbarbar (greedy semantics) or, if non-greedy semantics were switched on, one match at fooxyzbar. This means that switching between greedy and non-greedy semantics is a no-op in Hyperscan.

---hs_common.h---

  • HS_INVALID: A parameter passed to this function was invalid.
  • hs_error_t hs_stream_size(const hs_database_t *database, size_t *stream_size): Provides the size of the stream state allocated by a single stream opened against the given database; note database decide state space's size(refer to --Stream state-- for the concept of Stream state)
  • hs_error_t hs_serialized_database_size(const char *bytes, const size_t length, size_t *deserialized_size):This API can be used to allocate a (shared) memory region prior to deserializing with the hs_deserialize_database_at() function.
  • hs_error_t hs_valid_platform(void): This function can be called on any x86 platform to determine if the system provides the required instruction set.

---hs_compile.h---

  • HS_FLAG_MULTILINE:This flag instructs the expression to make the ^ and $ tokens match newline characters as well as the start and end of the stream.
  • HS_FLAG_SINGLEMATCH: If a group of expressions sharing a match ID specify the flag, then at most one match with the match ID will be generated per stream. so better don't share ID between expressions
  • HS_FLAG_COMBINATION:This flag instructs Hyperscan to parse this expression as logical combination syntax.

    To illustrate, here is an example combination expression: ((301 OR 302) AND 303) AND (304 OR NOT 305) If expression (zxxu:with ID) 301 matches at offset 10, the logical value of 301 is true while the other patterns’ values are false. Hence, the whole combination’s value is false. Then expression 303 matches at offset 20. Now the values of 301 and 303 are true while the other patterns’ values are still false. In this case, the combination’s value is true, so the combination expression raises a match at offset 20. Finally, expression 305 has matches at offset 30. Now the values of 301, 303 and 305 are true while the other patterns’ values are still false. In this case, the combination’s value is false and no match is raised.

  • HS_TUNE_FAMILY_GENERIC:This indicates that the compiled database should not be tuned for any particular target platform.

---hs_runtime.h---

---limits---

The version of Hyperscan used to produce a compiled pattern database must match the version of Hyperscan used to scan with it.

Using the SOM flag entails a number of trade-offs and limitations:

  • Reduced pattern support
  • Increased stream state: more memory required
  • Performance overhead
  • Incompatible features: Some other Hyperscan pattern flags can NOT be used in combination with SOM.
  • the start offset returned for a match may refer to a point in the stream before the current block being scanned. Hyperscan provides no facility for accessing earlier blocks; if the calling application needs to inspect historical data, then it must store it itself.