Anne van Kesteren

Web platform and JavaScript

As most object-oriented systems, objects within the web platform consist of internal slots (private state) and public members that expose and manipulate the internal slots. The public members are shared through a common prototype object. The internal slots are allocated at object-creation time. In contemporary implementations the internal slots are typically a C++ (nay Rust) affair, while prototype objects are available from JavaScript.

Until fairly recently there was no way to implement a lot of web platform objects in JavaScript. TC39 made this a priority. Rationalizing web platform objects as a giant JavaScript library. (Yes, The Extensible Web Manifesto.) E.g. WeakMap will help explain internal slots. JavaScript proxies help explain some of the more esoteric (largely legacy now) object design. Chromium and Gecko have projects that works on implementing bits of the platform in JavaScript making the idea more concrete: Blink-in-JavaScript and implementing IDL through JavaScript.

There are still downsides as a C++ implementation can be shared across many JavaScript realms (a realm is the owner of a global object, most implementers refer to a realm as “global object”), whereas a JavaScript implementations is tied to a realm. A C++ implementation therefore uses much less memory. Even with more browsers moving into process isolation (e.g. e10s) this still holds as there are tricks to share memory across processes (e.g. Firefox OS’ Nuwa). More concretely, this means that an implementation of Array.prototype.map in JavaScript will end up existing in each realm, whereas an identical implementation of that feature in C++ will only exists once. If we want to do more in JavaScript itself, this needs to be tackled somehow, perhaps with new language features.

(It was pointed out to me that SpiderMonkey has some tricks to share the bytecode of a JavaScript implementation of a feature across realms, though not across threads (still expensive for workers). And SpiderMonkey has the ability to load these JavaScript implementations lazily and collect them when no longer used, further reducing memory footprint. However, this requires very special code that is currently not available for features outside of SpiderMonkey. Whether that is feasible might be up for investigation at some point.)

Another thing that is done differently between web platform objects (e.g. XMLHttpRequest) and objects defined by JavaScript (e.g. WeakMap) is identity. For web platform objects we typically say “if x is an XMLHttpRequest object” whereas JavaScript proper has a duck typing approach along the lines of “if x has a [[WeakMapData]] internal slot”. To more fully explain what web platform objects do requires branding of sorts of which the exact details are left up to implementations. Note that instanceof does not work as it is not reliable across global objects. It should also be noted that although JavaScript proper has a duck typing approach the names it uses for its internal slots are sufficiently unique to also allow a branding-based implementation. What implementations actually do is unclear.

Evidently, work remains to be done to fully bridge the two worlds, but we are getting there.

(Thanks to Andrew McCreight, Boris Zbarsky, and Till Schneidereit for their invaluable feedback.)