0

When describing DOM trees, most sources I found online describe the DOM tree as consisting of nodes.

I found this incredibly confusing, as I thought the DOM tree was actually just a tree of JS objects built into the Browser Runtime Environment.

My questions are as follows:

  • Is the DOM tree really just consisting of ECMAScript objects?
  • How are these objects connected to create the tree? E.g., is there a children property on each?
  • Is Node an actual object, to which other objects are prototype linked? For example, an element in a HTML document is represented in the DOM tree as an instance of the HTMLElement constructor function (const foo = new HTMLElement()), which in turn is [[prototype]]-linked to Element.prototype, which in turn is [[prototype]]-linked to Node.protoype?
Magnus
  • 6,791
  • 8
  • 53
  • 84
  • 3
    Exactly what sort of objects DOM nodes are is not part of the spec. They *might* be JavaScript objects, but in other environments they might be something else. All the spec stipulates is that they work as documented. – Pointy Jan 03 '23 at 23:01
  • Also not all runtime environments support a DOM. – Pointy Jan 03 '23 at 23:01
  • one answer that may help is at https://stackoverflow.com/questions/9979172/difference-between-node-object-and-element-object – DeeGee Jan 03 '23 at 23:06
  • @DeeGee Thanks. I actually saw all those posts comparing node and element. That is not the confusing part to me, for some reason. It seems likely that an element is an object instance of Element, which is [[prototype]]-linked to Node.prototype. Thus, instances of Element has access to all the instance methods seen on Node.prototype. – Magnus Jan 03 '23 at 23:12
  • 3
    The DOM tree has bindings for ECMAScript (and Java) but is not per se a set of ECMAScript objects. – DeeGee Jan 03 '23 at 23:12
  • @Pointy Fair, though in the browser runtime environment the DOM tree is a tree of JS objects, right? Since we can operate on it via the DOM API in JS, i mean. – Magnus Jan 03 '23 at 23:15
  • 1
    @DeeGee perhaps you could add an answer describing how the DOM tree built by a browser differs from, and relates to, the apparent tree of JS objects available in a JS script in a HTML document? Does the browser maintain two separate trees, or how does it work under the hood? – Magnus Jan 03 '23 at 23:18
  • They do keep one tree, and then expose JS wrapper objects that do reflect the actual DOM nodes. – Kaiido Jan 03 '23 at 23:34
  • @Kaiido I do not understand exactly how the DOM tree and the JS objects representing it are related. Any sources, specs with relevant info, or an answer would be appreciated. – Magnus Jan 03 '23 at 23:43
  • 1
    I thought I'd find a dupe but it takes more time than expected and I don't have enough to compose an answer either, but some initial readings: https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/core/v8/V8BindingDesign.md#design-of-v8-bindings and https://doc.servo.org/script/dom/ – Kaiido Jan 03 '23 at 23:49
  • 1
    The JavaScript runtime has an "external" layer that something like a browser can use to introduce objects that are visible "inside" the runtime, but which are in fact (for example) C++ objects. The (now removed) Java `ScriptEngine` mechanism had something similar, so that Java objects could be visible to JavaScript code launched from Java. – Pointy Jan 03 '23 at 23:54
  • In general in the weird world of web standards, the standards for one domain (like HTML or the DOM) barely acknowledge the existence of the others. That's why the W3C DOM spec doesn't talk about JavaScript (except maybe here and there in an example), and all the APIs are described as interfaces. – Pointy Jan 03 '23 at 23:57
  • @Pointy Do you know of any spec, or other sources, that describe, in detail, when the ECMAScript objects representing the DOM are created? I know from the ECMAScript spec that the global object (window) is created when the host realm is initialized, but I could not find anything about objects such as Document or HTMLElement. – Magnus Jan 04 '23 at 00:04
  • No. That's up to the implementation. And again, there's no requirement that DOM nodes are JavaScript objects; they certainly (and painfully) weren't in Internet Explorer. They just have to work as if they are, and then only to the point of following the DOM interface specs. The DOM specification is quite detailed and specific, including telling you where implementations have leeway. – Pointy Jan 04 '23 at 00:14
  • It's kind-of like when you type some browser function (like `alert`) and log the result of calling `.toString()`: it says "native code". The DOM nodes can be like that: give the appearance of JavaScript, but have innards via some other implementation. Now I strongly suspect that in a modern browser the easiest way to make a DOM node act like a JavaScript object is to make it be some kind of hybrid, a JavaScript wrapper with possible native methods. Try `console.log(HTMLElement.prototype.querySelectorAll.toString())`: native code. – Pointy Jan 04 '23 at 00:18
  • [Another question on basically the same topic.](https://stackoverflow.com/questions/7614317/what-is-the-difference-between-native-objects-and-host-objects) – Pointy Jan 04 '23 at 00:31
  • 1
    @Pointy What you say on the standards is wrong, HTML completely relies on the DOM standards, and they both clearly acknowledge JS implementations, as most web standards, at least through WebIDL which provides hooks and conversion steps. As for native/host objects that's only tangentially related, even in node where everything is implemented in JS you have the same concepts. The DOM and its JS wrappers/reflectors are a different beast. – Kaiido Jan 04 '23 at 01:28
  • https://chromium.googlesource.com/chromium/blink/+/9eb0e6c1fe924dbb30a1aafefff5ad0658b26b5f/Source/core/dom/Node.cpp#453 https://chromium.googlesource.com/chromium/blink/+/9eb0e6c1fe924dbb30a1aafefff5ad0658b26b5f/Source/core/dom/ContainerNode.cpp#553 https://chromium.googlesource.com/chromium/blink/+/9eb0e6c1fe924dbb30a1aafefff5ad0658b26b5f/Source/core/dom/Element.cpp#2350 Can see roughly a Node can be a ContainerNode and can have children added to it or it can be any other Node that can't have children but exists in the "tree" in memory. – shaunhusain Jan 04 '23 at 01:57
  • Just wanted to add as the answer below says this is just one implementation but the specifications don't require this particular implementation (still maybe helps to see the various classes used under the hood) – shaunhusain Jan 04 '23 at 01:58
  • @Kaiido what I meant was not something as dogmatic as it sounds. Yes, especially over the recent past, there is bleed-over between the different standard domains. The HTML standard and the DOM standard are of course closely related, *but they are still separate standards*. CSS is designed to work with any kind of hierarchically structure document system. And JavaScript the programming language doesn't specify how DOM APIs work. That's all I meant: the standards are worked out independently by people of course not in a vacuum, but they're separate. – Pointy Jan 04 '23 at 02:51
  • @Pointy [HTML is dependent on the DOM specs](https://html.spec.whatwg.org/multipage/infrastructure.html#dependencies), you can't have a compliant HTML impl. without a compliant DOM impl. Even the DOM specs have many places that are written only to accommodate HTML specs. And both have common dependencies. And it's no surprises that the same WG edits these specs. It's even written in the same section that some parts only support JS as the scripting language. And when new JS types are added, HTML needs updates, e.g `structuredClone` recently had to handle resizeable ArrayBuffers. – Kaiido Jan 04 '23 at 06:24
  • Yes, indeed, as I said in my previous comment, "the HTML standard and the DOM standard are of course closely related". – Pointy Jan 04 '23 at 13:21

1 Answers1

3

Is the DOM tree really just consisting of ECMAScript objects?

No. The Document Object Model describes generic objects, specifying how their attributes and methods model a document. It does not say anything about how those objects are constructed or what language they are implemented in. You'll find DOM implementations written in C++, Rust, Java, JavaScript, and probably more.

How are these objects connected to create the tree? E.g., is there a children property on each?

Not all objects in the DOM are tree nodes, but for those that are, yes: childNodes and parentNode form a tree. The nodeName, nodeValue and attributes model the contents of the tree.

Is Node an actual object, to which other objects are prototype linked?

Yes, the ECMAScript bindings for the DOM (via WebIDL) stipulate that nodes are represented as ECMAScript objects with a prototype inheritance chain for interfaces like Node.

I thought the DOM tree was actually just a tree of JS objects built into the Browser Runtime Environment.

They might be native JS objects, but most commonly they are host objects that wrap/proxy the builtin DOM implementation of the browser. The wrappers are often constructed on the spot by getters only when they are accessed, not already created when the page is loaded.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thank you, Bergi, as clear as always. The Web IDL was fantastic, it answered a lot of my questions. Quick follow-up questions: 1) Are `platform objects` and `interface objects` (both defined in the Web IDL) the same? 2) Could you perhaps add information on how exactly the browser knows which DOM node an interface object (which is always a `built-in function object`) corresponds to? 3) When you say wrapper, what do they wrap / how does it work? – Magnus Jan 04 '23 at 17:00
  • One additional follow-up: Do you know when exactly DOM objects are created and added to the global object, by the browser runtime environment? The ECMAScript spec defines the point in time when the global object is created (i.e. when the host realm is initialized), however, it does not specify when non-standard built-in objects (like the `document` object) are created and added to the global object. – Magnus Jan 04 '23 at 17:15
  • I found the answer to my last question above. If others are interested in when `initial objects`, including `interface objects` based on interfaces defined in Web APIs, are added as properties to the global object, it happens in step 11 of `InitializeHostDefinedRealm ( )`, right after the global object has been created and the `standard built-in objects` have been added: https://tc39.es/ecma262/#sec-initializehostdefinedrealm – Magnus Jan 04 '23 at 17:35
  • 1
    No, platform objects are not the same as interface objects. An [interface object](https://webidl.spec.whatwg.org/#dfn-interface-object) is an object representing the interface itself (not a particular instance), like `HTMLElement`, `Node`, `EventTarget` etc. An interface object has an [interface prototype object](https://webidl.spec.whatwg.org/#interface-prototype-object), like `HTMLElement.prototype`, `Node.prototype` etc. These are [initialised with the realm](https://webidl.spec.whatwg.org/#dfn-initial-object). – Bergi Jan 04 '23 at 17:37
  • 1
    [Platform objects](https://webidl.spec.whatwg.org/#dfn-platform-object) on the other hand are the actual instances, like the global `document` or the result of `createElement()`. They are [created when needed](https://webidl.spec.whatwg.org/#new). – Bergi Jan 04 '23 at 17:38
  • Brilliant, thank you. When ECMAScript talks about creating the global object (during host realm initialization), it just creates an empty ordinary object [[prototype]]-linked to Object.prototype, adds standard built-in properties to it, and finally gets the host to add members of the Window interface directly to that global object. That way this global object then acts as an instance (`platform object`) of the Window interface. Is that right? I.e. is an `interface object` for the Window interface never really created? – Magnus Jan 04 '23 at 19:46
  • Ugh, sorry, I struggle to understand: 1) When are instances of the Window interface object created? 2) When do we create instances of the members of the Window interface, and add those to the window instance (e.g. when do we create instances of the Document interface and add that to the window instance)? – Magnus Jan 04 '23 at 20:22
  • @Magnus [Ping me in chat](https://chat.stackoverflow.com/rooms/250856/room-for-magnus-and-bergi-web-idl) – Bergi Jan 05 '23 at 03:48
  • For others benefit, here is a long conversation about how ECMAScript implements interfaces and the global object: https://chat.stackoverflow.com/rooms/250856/room-for-magnus-and-bergi-web-idl – Magnus Jan 05 '23 at 17:29