JavaScript’s object model
In today’s post, I am just trying to understand how JavaScript handles its object model.
This level of understanding is a must for security professionals to understand attacks and technology correctly.
Objects
JavaScript defines all objects as dictionaries, with string keys mapping to property attributes.
Let’s take an example of O1, defined as:
O1 = {a:1};Corresponding object will be represented as:
Arrays
Arrays are treated as special objects. One difference is that arrays have special handling of array indices. An array index is any valid index within that limit, i.e. any integer number from 0 to 2³²−2. Another difference is that arrays also have a magical length property.
Take an example:
Array = [10];Its runtime representation in JS engine will be as following:
Maps
In JavaScript programs, it’s common to have multiple objects with the same property keys.
Such objects have the same Maps.
JavaScript engines can optimize object property access based on the object’s map.
This map contains all the property names and attributes, except for their values.
Instead, the map contains the offset of the values, so that the JavaScript engine knows where to find the values.
Every object with the same map points to exactly this map instance.
Now every object only must store the values that are unique to this object.
For the following code:
O1 = {a:1, b:2};
O2 = {a:2, b:3};The run time representation will be following:
Shared Maps
The following objects both have a single property ‘a’ of type SMI (31-bit integers), so they can share the same map.
O1 = {a = 1};
O2 = {a = 100};For:
O3 = {a: 3.14};O3 will have a different map than O1 and O2, because a is now of type double(heapnumber) rather than integer or SMI. This is shown below:
Map transitions
When a new property is added to an object, if a map does not already exist for the new object layout, a new map will be created.
When this happens, the old and the new map are related by a transition.
O1 = {a = 1}; // from example 1
O2 = {a = 100}; // from example 1
O1.b = 2; // added newTransition Array
A map can store multiple transitions in a TransitionArray.
For example, if another property c is added to O2, then the TransitionArray will contain two transitions, one to property b and another to property c as shown below.
Addition:
O2.c = 33;will result in following maps.
There is a limited number of transitions that a map can hold.
Prior to adding a new transition, a check is carried out to ensure that the map can hold another transition.
If no more transitions can be added, then a new dictionary map will be created.
Maps deprecation
O1 = {a = 1};
O2 = {a = 100};O1.a = 3.1415; //newly addedAs ‘a’ is SMI, so it cannot hold double. This means objects and maps will be changed to store this. Change will be as shown below.
O1 and O2 will have different maps.
The map of O2 is also marked as deprecated. Marking deprecated means that when a new object of the same property layout is created, it’ll use the map of O1 (transition pointer)
This is because the map of O1 can represent both double and SMI.
References:
JavaScript engine fundamentals: Shapes and Inline Caches · Mathias Bynens










