How does Javascript runtime identify setTimeout() as a WEB API? - javascript

When javascript runtime finds setTimeout() method, it sends it to Event table. How does runtime know that setTimeout() is a WEB API? Does it first look for setTimeout() method in the current context and then if not found assumes it as a WEB API?

When javascript runtime finds setTimeout() method, it sends it to Event table.
JavaScript doesn't "know" or care what setTimeout does. :-) It's just that setTimeout is one of the functions defined in the host environment provided to the JavaScript engine by the host (the browser, in your example). When you use JavaScript to call the function, the function's implementation (provided by the host environment) is executed with the information you provide. It's the host, not the JavaScript engine, that knows what to do with the arguments you provide to setTimeout.
When the host (the browser or Node.js or whatever) needs to create a new runtime environment (for instance, for a window), one of the things it does is create an object to be the host-provided global object for that environment (more properly called a realm), including putting any properties on that object (like setTimeout) that provide host-defined features. It provides that object to the JavaScript engine via what the JavaScript specification calls the InitializeHostDefinedRealm abstract operation. When the JavaScript engine runs your code that uses setTimeout, it sees the identifier setTimeout and looks in the current execution context to see if setTimeout is defined there; if it isn't, the engine looks at the parent execution context, and so on, until it reaches the global execution context, which gets its globals from the host-provided global environment (in part; it also has other globals). So, having found the function matching setTimeout, the JavaScript engine calls that function — which runs the host-defined code for the function, which sets the timer.
So the JavaScript engine doesn't know what setTimeout does, just that there is a setTimeout function on the global object it got from the host.

In terms of identifying which function to run, it doesn't make any difference whether a function is built into the engine, or added at run-time (this fact is really useful, allowing functions to be "polyfilled" if the engine doesn't provide them).
When you write foo(), JS actually looks for a variable with that name (this unification of variables, properties, functions and methods is an unusual feature of JS). It looks for it first in the local scope, then in the parent of that scope, and so on up the "scope chain".
The last place it looks is the "global object", which in a browser is the window object. So if you define window.foo as a function, you can call foo() from anywhere that doesn't have its own function called foo in scope.
Built-in functions work just the same way: when the JS engine starts up, it (conceptually) defines a whole bunch of functions on the window object, with special implementations referring to internal operations in the engine rather than composed of JS code.
So when you call setTimeout, JS walks up the scope chain, and if it doesn't find anything else, will find the setTimeout function registered by the engine, and runs it. The engine then does whatever it wants to do with that - hopefully, something that complies with the behaviours described in the current ECMAScript standard.

Related

Read codebase of javascript function

I just realize that I can use the function console.log to read a codebase of any javascript function. Anyone how it happens? and what behind the sense of this action (read codebase)
Example:
Open chrome console and paste this code
function superMan(){
var i=i+1;
var j=i+1;
}
then you use the function console.log like console.log(superMan) and you can see the codebase of SuperMan
In javascript, When a program is run a execution context is created. There are 2 phases in which its created namely below.
Creation phase
Execution phase
What you are referring to in the question is mostly related to the creation phase. In this phase all the variables are declared and initialized to undefined ( incase of var) and for variables with let and const they are declared in the Temporal Dead Zone and are unreachable and only reachable when the code is executed in execution context.
For functions(specifically Function statements and not function expressions) these are taken in as it is in memory and stored. So, when you try to log in the function in console.log it shows the variable in memory. This will be also true for function expression once the execution runs over it(since before its treated like a normal variable and not function). They will be showed as it will now be pointing to the function directly assigned to that variable. Also, You need to understand function in Javascript are first-class functions meaning it can be passed and treated like a normal variable (containing a number) and so.
It's part of the spec but a good reason to use it is in edge-cases where the code of the function could be important to its execution (usually for an API, interface or some form of abstraction) where you need to know a bit more about the function before acting upon it. There are many use-cases, but it can be particularly useful to try to detect and handle edge-cases for a transpiler (the code you write isn't verbatim to the code that the browser sees)

Is global execution context is created by function?

I was learning JS and execution contexts. Also, I found out that there is a special execution context which is executed by default which is fglobal execution context. The question is "Is global execution context a function which is executed behind the scenes"?
It's not a function, it's an abstraction that holds certain information about the context within which javascript is running. It is set up by the javascript engine before it starts to execute any code so it is created by a "function behind the scenes", but it is not itself a function. In the browser, the globsal execution context will include various functions and objects (like the document object). In node on the server, it will be something different. It is closely related to the global scope, but execution context and scope are not identical. It's quite a complex subject, so you may want to read this for more information: https://codeburst.io/js-demystified-04-execution-context-97dea52c8ac6

what is the lifetime of javascript anonymous function?

If I write this in global scope:
(function(){})();
is the anonymous function created when the statement is executed and destroyed immediately after the statement is executed?
if I write this in a function:
function foo()
{
var a=1;
(function(){})();
a++;
}
Does the anonymous function exist until foo returns, or just exist during the execution of that statement?
In this particular case, most engines will optimize that function entirely away, because it does not do anything.
But let's assume that function contains code and is indeed executed. In this case, the function will exist all the time, either as compiled code, as bytecode or as AST for the interpreter.
The part that won't exist all the time is the scope and the possible created closure. The scope created for that function and the closure will only exist as long as the function is executed or a reference to the function with a specific bound scope/closure exists.
So the combination function reference + scope will be allocated at the time the statement (function(){})(); is executed, and can be released after that statement. But the compiled version of function(){} might still exist in memory for later use.
For engines that do just in time compiling and optimization, a function might even exist in different compiled versions.
The JIT+optimizer part of modern js engines is a complex topic, a rough description of v8 can be found here html5rocks: JavaScript Compilation:
In V8, the Full compiler runs on all code, and starts executing code as soon as possible, quickly generating good but not great code. This compiler assumes almost nothing about types at compilation time - it expects that types of variables can and will change at runtime.
In parallel with the full compiler, V8 re-compiles "hot" functions (that is, functions that are run many times) with an optimizing compiler. [...] In the optimizing compiler, operations get speculatively inlined (directly placed where they are called). This speeds execution (at the cost of memory footprint), but also enables other optimizations.
Therefore it may be that the generated code has hardly any similarities to the original one.
So a immediately-invoked function expression might even be completely optimized away using inlining.
If I write this in global scope:
(function(){})();
is the anonymous function created when the statement is executed and destroyed immediately after the statement is executed?
As t.niese said, odds are the engine will optimize that function away entirely. So let's assume it has some code in it:
// At global scope
(function(){ console.log("Hi there"); })();
The engine can't guarantee that that code won't throw an error (for instance, if you replaced console with something else), so I'm fairly sure it can't just inline that.
Now the answer is: It depends.
From a language/specification level, all code in a compilation unit (roughly: script) is parsed when the compilation unit is first loaded. Then, that function is created when the code reaches it in step-by-step execution, executed after being created (which involves creating an execution context for the call), and immediately eligible for garbage collection when done (along with the execution context) because nothing has a reference to it. But that's just theory/high-level specification.
From a JavaScript engine perspective:
The function is parsed before any code runs. The result of that parsing (bytecode or machine code) will be associated with that function expression. This doesn't wait for execution to reach the function, it's done early (in the background on V8 [Google's engine in Chrome and Node.js]).
Once the function has been executed and nothing else can refer to it:
The function object and the execution context associated with calling it are both eligible for GC. When and how that happens depends on the JavaScript engine.
Which leaves the function's underlying code, either bytecode (modern versions of V8 using Ignition, possibly others) or compiled machine code (somehow the function got used so much it got compiled for TurboFan, or older versions of V8 using Full-codegen, others). Whether the JavaScript engine can then throw away that bytecode or machine code will depend on the engine. I doubt engines throw away byte/machine code they've generated for a function if they may need it again (e.g., for a new anonymous function created by a new call to foo). If foo became unreachable, maybe foo's byte/machine code and the anonymous function's could be tossed as unnecessary. I have no idea whether engines do that. On the one hand, it seems like low-hanging fruit; on the other, it seems like something that would be so uncommon it's not worth bothering with. (Remember, here we're not talking about code attached to a function instance, but the code that has been produced from the source that gets attached to an instance when the instance is created, and may get attached to multiple instances over time.)
Here are a couple of articles on the V8 blog that make interesting reading:
26 March 2018: Background compilation
15 May 2017: Launching Ignition and TurboFan
23 August 2016: Firing up the Ignition interpreter (some information outdated and updated by the May 2017 article)
Ignition (some of the Ignition information appears to be slightly out of date relative to the May 2017 article above)
if I write this in a function:
function foo()
{
var a=1;
(function(){})();
a++;
}
Does the anonymous function exist until foo returns, or just exist during the execution of that statement?
Let's assume again there's a console.log in that function, and that I'm correct (it is an assumption on my part) that the fact it relies on a writable global (console) means it can't just be inlined.
The high-level/specification answer is the same: The function is parsed when the script is loaded, created when it's reached, executed, and eligible for GC when it's done executing. But again, that's just high-level concept.
Things are probably different at the engine level:
The code will be parsed before any code in the script runs.
Bytecode or machine code is likely generated before any code in the script runs, although I seem to recall something from the V8 blog about parsing but not immediately compiling the contents of top-level functions. I can't find that article, though, if it wasn't just in my head.
When execution reaches the function, a function object for it is created along with an execution context (unless the engine is sure it can optimize that away without it being observable in code).
Once execution ends, the function object and that execution context are eligible for GC. (They may well have been on the stack, making GC trivial when foo returns.)
The underlying code, though, sticks around in memory in order to be used again (and if used often enough, optimized).

Strategy for JavaScript interpreter implementation (functions) -- am I making sense?

I'm writing a js-to-js interpreter (that is, a Javascript program that takes a Javascript program as an argument and executes it). I'm not trained in compiler theory, I'm just faking it. The expression-evaluation machine is working (using a kind of clunky operator-precedence algorithm), but not yet for functions. So here's my question.
The way I'm thinking of implementing functions looks something like this: When a function is invoked, I'll create a namespace / context for it, also allowing access to the namespaces of enclosing functions and the global namespace.
I'm not yet implementing closures, but these namespaces are designed to work for them. Basically, as I understand it, closures are just the way Javascript refuses to forget the context of a function when it hasn't forgotten the variable which holds the function.
So, when the function is invoked, I'll pass into its context object a copy of the statement which invokes it, along with a pointer to the expression that triggered the function call. Each expression in that statement that has been evaluated already will remember its value. When we return from the function, that statement becomes the current statement, and I start to execute it again -- but I don't re-evaluate expressions that have already been evaluated, including the function just completed. So then I go merrily along with the rest of the statement, potentially calling more functions, etc.
Each statement, expression, and function has an abstract representation built during parsing. During execution, only the current statement has any actual existence, aside from that abstract representation, because really all I need to remember at any given time is:
variables in the current context
variables in enclosing contexts (that is, the most recent invocation of a function -- including the global context -- which encloses the current function)
the current statement
what statement is next
what blocks I'm inside of (just so I know what to do when I hit
the end of one)
the call stack, which is a stack of contexts including variables and the
statement that triggered the call, with its expressions.
A pointer to the specific expression to update with return value from the function / context.
So am I making sense? Thanks for your help!
What you're describing is basically what an interpreter does, yes, but I'd still strongly recommend rethinking your approach. Interpreting Javascript in Javascript is going to run extremely slowly as soon as you're doing anything more complex than adding numbers. Is there some reason you can't separate your debugger from actual execution? If that's not possible, I'd really suggest doing your interpreter in a plug-in or something that gives you lower level speed. Or consider mod'ing something like this: https://developers.google.com/blockly/installation/js-interpreter?hl=en

What triggers JavaScript code execution?

In case you don't know what I'm talking about, please read John Resig - How JavaScript Timers Work and Is JavaScript guaranteed to be single-threaded?
There are several triggers that enqueue tasks in the JS engines' execution FiFo. This is not part of any standard, so I'm trying to find an exhausive list of those triggers. (I guess it all boils down to internal event handlers, like script load events or timer events, but I'd rather ignore the engine's internals and look at things from the user's point of view.)
So far I have identified
<script> elements in the initial document (including the ones added by document.write)*
<script> elements inserted by JS at runtime*
Event handlers
-- these include a wide variety of cases, such as user interaction, Error events, Web Worker messages or Ajax callbacks ...
window.setTimeout
window.setInterval
*) only in Browser/DOM environments
Any more? Any differences between JS engines?
"JavaScript" as a language name should not really be used it is too broad.
ECMAScript is what you are referring to. You can find information on ECMAScript at http://www.ecmascript.org/
The language standard is called ECMA-262 with the 5.1 Edition supported by most browsers.
setTimeout, setInterval, DOM events, and more are not part of the language. These are provided by the host environment as host objects. Writing ECMAScript for a wide range of host environment should take special care when using host objects.
ECMAScript code is executed within an execution context. This takes the form of a stack and will hold the state of the current execution context at the top.
There are 3 ways to push an execution context. Global code, eval, and function. This is the only way to start code. Host environments will use these methods to execute code.
The host environment can supply a call stack. This is used to stack function calls generated by host objects which may run in independent threads. Typically an event such as setTimeout will add a function to the call stack. The host environment will then wait until the execution context stack is empty then pop the function from the call stack, create a new execution context, execute the code until completed. It will repeat this until the call stack is empty.
Attempting to build a comprehensive list of host object execution context managers is futile.
To answer the questions.
Any more?
Yes there are many more. This is beyond the scope of this answer. Refer to the particular host environment you wish to use.
Any differences between JS engines? (ECMAScript Host environments).
Yes. Again this beyond the scope of this answer and dependent on the host
There are dozens of host environments, with new ones created all the time. What triggers the creation of a new execution context is highly dependent on the host environment.

Categories

Resources