Javascript: Where getter/setter values are stored? [duplicate] - javascript

I was thinking about this today and I realized I don't have a clear picture here.
Here are some statements I think to be true (please correct me if I'm wrong):
the DOM is a collection of interfaces specified by W3C.
when parsing HTML source code, the browser creates a DOM tree which has nodes that implement DOM interfaces.
the ECMAScript spec has no reference of browser host objects (DOM, BOM, HTML5 APIs etc.).
how the DOM is actually implemented depends on browser internals and is probably different among most of them.
modern JS interpreters use JIT to improve the code performance and translate it to bytecode
I am curious about what happens behind the scenes when I call document.getElementById('foo'). Does the call get delegated to browser native code by the interpreter or does the browser have JS implementations of all host objects? Do you know about any optimizations they do in regard to this?
I read this overview of browser internals but it didn't mention anything about this. I will look through the Chrome and FF source when I have time, but I thought about asking here first. :)

All of your bullet points are correct, except:
modern JS interpreters use JIT to improve the code performance and translate it to bytecode
should be "...and translate it to native code". SpiderMonkey (the JS engine in Firefox) worked as a bytecode interpreter for a long time before the current JS speed arms race.
On Mozilla's JS-to-DOM bridge:
The host objects are typically implemented in C++, though there is an experiment underway to implement DOM in JS. So when a web page calls document.getElementById('foo'), the actual work of retrieving the element by its ID is done in a C++ method, as hsivonen noted.
The specific way the underlying C++ implementation gets called depends on the API and also changed over time (note that I'm not involved in the development, so might be wrong about some details, here's a blog post by jst, who was actually involved in creating much of this code):
At the lowest level every JS engine provides APIs to define host objects. For example, the browser can call JS_DefineFunctions (as demonstrated in the SpiderMonkey User Guide) to let the engine know that whenever script calls a function with the specified name, a provided C callback should be called. Same for other aspects of the host objects (e.g. enumeration, property getters/setters, etc.)
For the core ECMAScript functionality and in some tricky DOM cases the JS engine/the browser uses these APIs directly to define host objects and their behaviors, but it requires a lot of common boilerplate code for e.g. checking parameter types, converting them to the appropriate C++ types, error handling etc.
For reasons I won't go into, let's say historically, Mozilla made heavy use of XPCOM for many of its objects, including much of the DOM. One feature of XPCOM is its binding to JS called XPConnect. Among other things, XPConnect can take an interface definition in IDL (such as nsIDOMDocument; or more precisely its compiled representation), expose an object with the specified properties to the script, and later, when a script calls getElementById, perform the necessary parameter checks/conversions and route the call directly to a C++ method (nsDocument::GetElementById(const nsAString& aId, nsIDOMElement** aReturn))
The way XPConnect worked was quite inefficient: it registered generic functions as callbacks to be executed when a script accesses a host object, and these generic functions figured out what they needed to do in every particular case dynamically. This post about quickstubs walks you through one example.
"Quick stubs" mentioned in the previous link is a way to optimize JS->C++ calls time by trading some code size for it: instead of always using generic C++ functions that know how to make any kind of call, the specialized code is automatically generated at the Firefox build time for a pre-defined list of "hot" calls.
Later on the JIT (tracemonkey at that time) was taught to generate the code calling C++ methods as part of the native code generated for "hot" paths in JS. I'm not sure how the newer JITs (jaegermonkey) work in this regard.
With "paris bindings" the objects are exposed to webpage JS without any reliance on XPConnect, instead generating all the necessary glue JSClass code based on WebIDL (instead of XPCOM-era IDL). See also posts by developers who worked on this: jst and khuey. Also see How is the web-exposed DOM implemented?
I'm fuzzy on details of the three last points in particular, so take it with a grain of salt.
The most recent improvements are listed as dependencies of bug 622298, but I don't follow them closely.

JS calls to DOM methods like getElementById cause the JS engine to call into the C++ code that implements the DOM. For example, in Firefox, the call ends up in nsDocument::GetElementById(const nsAString& aId, nsIDOMElement** aReturn).
As you can see, Firefox maintains a hashtable that maps ids to elements in C++ as an optimization in this case, so it doesn't walk the whole DOM tree looking for the id.

The DOM is implemented as a language-independent library pretty much in all major browser implementations, which means it's in a different library from the Javascript engine. For example in IE, the JS engine is implemented in jscript.dll while the DOM is implemented in mshtml.dll. Safari has Nitro(JS) and WebCore(DOM). Chrome has V8(JS) and WebCore(DOM), and Firefox has SpiderMonkey/TraceMonkey(JS) and Gecko(DOM).
What this means is that anytime your JS has to access the DOM, it has to reach over to the DOM library - which is inherently slow because of all the marshaling that has to take place. An analogy that has been used is 2 pieces of land connected by a toll bridge, any time you touch the DOM, you must cross over the bridge and cross back - paying a performance toll.
References
Video: Building High Performance Web Applications and Sites
Book: High Performance Javascript (Chapter 3 on the DOM)

Related

How do the Render Engine and JavaScript Engine Communicate in a browser?

I'm looking for a detailed answer on this.
What I already Know
So I have some understanding about the call stack and callbacks, and that the browser add functionality through web APIs which add callbacks through the event loop. I also read somewhere about the JS engine having an API.
What I want to understand
How are the web APIs exposed to the JS engine? (If this is about the
JS engine having an API, some description on how that API works would
do)
How can the behavior of the Render Engine be manipulated through
JavaScript, like manipulating the DOM, CSSOM etc.? (If I understood
correctly, this is the equivalent of asking how web APIs work)
Thanks!
From a (C++ etc.) application development perspective, JavaScript engines are embeddable libraries; and a browser is one such embedder. Any library defines a public interface through which it can be used -- its Application Programming Interface (or API for short). There is no standard for what a JS engine's API should look like; each engine defines its own, and evolves it as necessary over time. V8's is here.
The core functionality of a JS engine's API is to allow the embedder to provide objects and functions to the JavaScript environment that are backed by the embedder's own C++ implementations. Essentially, this defines a mapping, sometimes also called "bindings". For example, the embedder can say "I want there to be a document object, and it should appear to have a property .location that's backed by my getter function DocumentLocationGetter() {...}, and it should (appear to) have a method .createElement() that's backed by my other function DocumentCreateElement(...) {...}", and so on.
And that's the answer to both of your questions: the browser exposes certain functions to JavaScript that can then be called from there. The browser decides what to do when such a function is called (e.g.: add or remove a DOM node, change a CSS property, store an event handler in some element's event handlers list, ...). Of course the browser/embedder can also call into the JS engine, for example when invoking an event handler, it can tell the engine "please execute function button1_clicked now".
For more details, see e.g. v8.dev/docs/embed.

Benefits of inline caching

Is there any way to figure out how many and what accesses in JavaScript program are actually utilizing inline caching technique? or are majorly contributing to improve overall performance using inline caching?
If you refer to V8 Chrome page then you will find it there:
V8 compiles JavaScript source code directly into machine code when it is first executed. There are no intermediate byte codes, no interpreter. Property access is handled by inline cache code that may be patched with other machine instructions as V8 executes.
During initial execution of the code for accessing a property of a given object, V8 determines the object's current hidden class. V8 optimizes property access by predicting that this class will also be used for all future objects accessed in the same section of code and uses the information in the class to patch the inline cache code to use the hidden class. If V8 has predicted correctly the property's value is assigned (or fetched) in a single operation. If the prediction is incorrect, V8 patches the code to remove the optimisation.

Are DOM objects javascript objects?

This is something I cannot find an official answer about. For some, DOM objects are JS objects, for others they differ. What is the right answer?
By searching in stackoverflow, you may see controversial opinions.
For example, does the object document.body belongs to DOM API only or may it be considered as part of javascript engine too?
Does Javascript create an internal representation of it or does it just communicates with DOM to access it?
The DOM API is a collection of standards which have implementations in a variety of programming languages.
The DOM available to JavaScript in a browser provides things in the form of JavaScript objects. Large portions of it are written in native code (so are handled by libraries not written in JavaScript but made available through a JavaScript API).
Where JavaScript leaves off and native code begins doesn't really matter, it is an implementation detail and probably varies from browser to browser. The point of having a standard API is that developers using it interact with that API and don't need to worry about how it is implemented under the hood.
Strictly speaking, no. The JavaScript runtime has access to them, and in that capacity they can function as JavaScript objects. But they are defined in a way that is not bound to any particular language, and in most DOM implementations, they're native code. Most DOM implementations take care to make the objects function the same way you'd expect other objects in the chosen language to work, but that's not always the same way that JavaScript objects do: for example, you can't go around adding dynamic properties to objects when you're working in Java.
For most practical purposes, when you're working in the browser or in some other JavaScript runtime, yes. As I stated above, most DOM implementations try to make the DOM objects work the same way as other objects in the language, and for JavaScript, that means making them work like "real" JavaScript objects. Although IE took a while to really get this right (you need IE9+ to take full advantage), these days you can pretty much use DOM objects the same way you'd use any other JavaScript object.
If you inspect deeply the __proto__ of document.body for instance, you would find this :
HTMLBodyElement > HTMLElement > Element > Node > EventTarget > Object
So yes : in the browser's context, DOM objects are JS objects, this is not reciprocal of course.
But DOM API is not exclusive to Javascript, it defines interfaces which can be implemented in any languages, for instance Python has a DOM API too and in this case, DOM objects are Python objects.
The DOM objects are not part of the JavaScript language, they are part of the environment that is provided when JavaScript runs in a browser.
When JavaScript runs in another environment, for example in Node.js, then there is no DOM. Instead there are other objects that make up the environment that the script works with.
The DOM objects are there just for JavaScript so the script works directly with the objects, there is no extra wrapper to make them available to JavaScript.

Convert Actionscript to Javascript

I was just wondering is there anyway to convert Actionscript to Javascript. When I say Actionscript I mean Actionscript 3. I've used google swiffy but Actionscript 3 is hardly supported. I've also heard of Jangaroo but its not what I want. Even if its a code comparison! Thanks!
Javascript and ActionScript (especially AS3) are syntactically similar languages and both are based on the ECMAScript Specification. There are some small differences in the actual code such as:
//Actionscript:
var a:String = new PlayerName();
//JavaScript:
var a = new PlayerName();
This is a demonstration that JavaScript does not have explicit variable type declarations, but this is not the real problem.
What you're asking goes much further than syntactic incompatibilities, as JS and AS work with completely different APIs. ActionScript has stages, frames and other Flash-based things which do not exist in JavaScript's environment. JavaScript - usually running in a browser - is used to manipulate documents, DOM nodes and CSS properties.
This means that unless you're just doing simple function calls and mathematics (without any dependency on the user or their environment) the things your program is doing simply cannot be transferred to another environment. For example, you cannot tell JavaScript to play() or goToAndStop() because there are no frames to play, stop or go to in a HTML document.
Unfortunately, I think what you're wondering is valid, but the question is almost certainly incorrect. If you have an application created in Flash or any other AS-enabled environment, you probably want to think about porting or re-writing it to the new context.
You might have a look at Falcon JS: https://github.com/apache/flex-falcon
http://www.gotoandlearn.com/play.php?id=172
Just check it out the above. It might be useful.

Learning how JavaScript optimizes execution, if at all

Is there a way to learn at how JavaScript is interpreted and executed? In .NET or JAVA for instance, you could look at the generated byte code, in C you could look at the generated assembly instruction but from what I gather, JavaScript is interpreted line by line and then it varies on the JS engine in different browsers.
Still is there a way to learn how JavaScript does this? Does the interpreter in modern browsers tend to look ahead and optimize as a compiler might?
For instance, if I did:
$('#div1').css('background-color','red');
$('#div1').css('color','white');
Could I have a perf gain by doing:
var x = $('#div1');
x.css('background-color','red');
x.css('color','white');
The point of this question is to get some information how one might gain some insight as to how JavaScript is run in the browser.
The optimization steps taken, as always, depend on the compiler. I know that SpiderMonkey is fairly well documented, open source, and I believe does JIT compilation. You can use it outside of the browser to tinker with, so that's one less black-box to deal with when experimenting. I'm not sure if there's any way to dump the compiled code as it runs to see how it optimizes in your code, but since there's no standard concept of an intermediate representation of Javascript (like there is with .NET/Java bytecode) it would be specific to the engine anyway.
EDIT: With some more research, it does seem that you can get SpiderMonkey to dump its bytecode. Note, however that optimizations can take place both in the interpreter that generates the bytecode and the JIT compiler that consumes/compiles/executes the bytecode, so you are only halfway there to understanding any optimizations that may occur (as is true with Java and .NET bytecodes).
V8 does some amazing things internally. It compiles to machine code and creates hidden classes for your objects. Mind-blowing details here: https://developers.google.com/v8/design
Ofcourse when it comes to the DOM, performing lookups can only go that fast. Which is why chaining or temp variables can make a difference, especially in loops and during animations.
Besides that, using the right selectors can be helpful. #id lookups are undoubtedly the fastest. Simple tagname or class lookups are reasonably fast as well. jQuery selectors like :not can't fall back on builtins and are considerably slower.
Besides reducing lookups, another good rule of thumb with the DOM is: If you need to do a lot of DOM manipulation, take out some parent node, do the manipulations, and reinsert it. This could save a whole lot of reflows/repaints.
Yes, you will get a performance gain. The DOM is not queried twice, and only one jQuery object is instantiated.
Yet you should not do this for performance (the gain will be negligible), but for code quality. Also, you do not need a variable, jQuery supports chaining:
$('#div1').css('background-color','red').css('color','white');
and the .css method also can take an object:
$('#div1').css({'background-color': 'red', 'color': 'white'});

Categories

Resources