I was trying to learn the design of why V8 API is structured the way it is and found a helpful doc as to relationship between various things like isolates, contexts etc: Link to V8 Binding
There, I am confused by a certain paragraph:
For compatibility reasons, we need to make sure that the same DOM wrapper is returned to JavaScript as long as the underlying C++ DOM object is alive. We should not return different DOM wrappers for the same C++ DOM object.
Here is an example:
var div = document.createElement("div");
div.foo = 1234; // expando
var p = document.createElement("p");
p.appendChild(div);
div = null;
gc();
console.log(p.firstChild.foo); // This should be 1234, not undefined
To accomplish the semantics that the same DOM wrapper is returned to JavaScript as long as the underlying C++ DOM object is alive, we need a mapping from the C++ DOM objects to the DOM wrappers. In addition, we need to sandbox DOM wrappers in each world. To meet the requirements, we make each world hold a DOM wrapper storage that stores a mapping from the C++ DOM objects to the DOM wrappers in that world.
As a result, we have multiple DOM wrapper storages in one isolate. The mapping of the main world is written in ScriptWrappable. If ScriptWrappable::main_world_wrapper_ has a non-empty value, it is a DOM wrapper of the C++ DOM object of the main world. The mapping of other worlds are written in DOMDataStore.
I am still trying to understand the whole paragraph but the specific code example and the immediate explanation does not make sense to me. I never would have expected the code snippet to print undefined
even if it was a purely JavaScript API.
I feel the example is not correct but then without a proper example, it is difficult for me to wrap my head around the concept.