Wednesday, March 30, 2016

What is the “ownerID” in Immutable.js?

Leave a Comment

I'm going through Immutable.js's source code and there's an ownerID field that I don't understand.

Here's the source for Map.asMutable() and Map.asImmutable(): https://github.com/facebook/immutable-js/blob/master/src/Map.js#L171

It seems like the only difference between a mutable and an immutable object are their ownerIDs. What is an ownerID and what is it used for?

3 Answers

Answers 1

If you track back the property:

L#14:

import { DELETE, SHIFT, SIZE, MASK, NOT_SET, CHANGE_LENGTH, DID_ALTER, OwnerID,           MakeRef, SetRef, arrCopy } from './TrieUtils' 

in src/TrieUtils.js :

L#36:

// A function which returns a value representing an "owner" for transient writes // to tries. The return value will only ever equal itself, and will not equal // the return of any subsequent call of this function. export function OwnerID() {} 

It is some property they create like hash to represent a virtual owner.

Answers 2

It is used to ensure mutability in asMutable returned instances. When asMutable is invoked, it ensures an __ownerId and returns the current instance back -

asMutable() {     return this.__ownerID ? this : this.__ensureOwner(new OwnerID()); } 

Then any supported mutating operations return the current instance back, instead of creating a new instance with the changes (which is key for immutability).

E.g., here's how the "clear" method operates based on the presence of __ownerId -

clear() {     if (this.size === 0) {       return this;     }     if (this.__ownerID) {       this.size = 0;       this._root = null;       this.__hash = undefined;       this.__altered = true;       return this;     }     return emptyMap(); } 

Notice that when this.__ownerID is present, the method returns the current instance (thereby mutating itself). But when it is absent, it returns a new map for ensuring immutability.

Answers 3

From the source code:

// A function which returns a value representing an "owner" for transient writes // to tries. The return value will only ever equal itself, and will not equal // the return of any subsequent call of this function. function OwnerID() {} 

My understanding of the above is that the this.__ownerID field is used to compare objects. A Map being compared against itself will have the same ownerID, while a Map being compared against another Map will see two different ownerIDs.

You can see an example of this usage a little farther down in the file in question:

__ensureOwner(ownerID) {   if (ownerID === this.__ownerID) {     return this;   }   if (!ownerID) {     this.__ownerID = ownerID;     this.__altered = false;     return this;   }   return makeMap(this.size, this._root, ownerID, this.__hash); } 

In fact, searching the entire repo, you'll see that this function is common across data types, with each type having a slightly modified version to return a correct new version of that type.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment