The object that misbehaved — window.performance.memory
Tags: javascript, research, troubleshooting, performance
Published: 2019-07-11 23:05:16

#How I troubleshoot issues that don’t make sense
![](https://thepracticaldev.s3.amazonaws.com/i/o5knc5kj2ovoxce7eaia.png)

Today we wanted to start tracking some new performance metrics on our landing pages, and more specifically, the memory usage.
As usual, we got the data from our trusty `window.performance` object (from now on will be referred to as _"the enemy"_), stringified it before sending and…

Surprisingly, all we got was `"{}"`!

How can it be? We have an object, with properties we can access, but stringifying it returns an empty object!

---

###Down the rabbit hole I go
I started digging deeper into it, with the goal of turning _the enemy_ into a string without hard coding the property names.

#####I tried spreading it
```javascript
  const result = { ...window.performance.memory };
  console.log(result); // {}
```
#####I tried getting its components
```javascript
  const keys = Object.keys(window.performance.memory);
  const values = Object.values(window.performance.memory);
  console.log(keys); // []
  console.log(values); // []
```

#####I tried destructuring it
```javascript
  const { jsHeapSizeLimit } = window.performance.memory;
  console.log(jsHeapSizeLimit); // 2330000000
```

And surprisingly — it worked!

With great confidence that I’m going to crack this I tried "rest" destructuring:
```javascript
  const { ...rest } = window.performance.memory;
  console.log(rest); // {}
```

What is going on? Why does this specific object refuse to play nice?

---

###A light at the end of the tunnel (that turns out to be a train)
After some more tinkering I found another thing that didn’t make sense.
```javascript
  for (const prop in window.performance.memory)
    console.log(`${prop}: ${window.performance.memory[prop]}`)
  // totalJSHeapSize: 13400000
  // usedJSHeapSize: 12700000
  // jsHeapSizeLimit: 2330000000
```
Iterating over the enemy’s properties does work, but getting its properties names doesn’t? Even Object.getOwnPropertyNames failed!

Although this solution could work for me (remember, my original goal was "turning _the enemy_ into a string without hard coding the property names") I wanted to find a more elegant solution, and wanted to get to the bottom of this.

---

###The first solution, AKA "not good enough"
The next part of my trip was when I started playing around with the prototype of _the enemy_, called `MemoryInfo`. I tried changing the prototype, assigning _the enemy_ to a new object with a different prototype, creating an array from the enemy, and eventually playing around with a combination of all the techniques mentioned above.
```javascript
  Object.getOwnPropertyNames(window.performance.memory); // []
  Object.getOwnPropertyNames(window.performance.memory.__proto__) // 
  ["totalJSHeapSize", "usedJSHeapSize", "jsHeapSizeLimit", "constructor"]
```

Success! Well… Sort of. I got the prototype property names, and I could use this array to get what I want using the following snippet

```javascript
  const success = JSON.stringify(Object.getOwnPropertyNames(window.performance.memory.__proto__).reduce((acc,key) => {
       if (key !== 'constructor')
         acc[key] = window.performance.memory[key];
       return acc;
    }, {})
  );

  console.log(success) // " {"totalJSHeapSize":20500000,"usedJSHeapSize":18200000,"jsHeapSizeLimit":2330000000}"
```
######<center>_Not great, not terrible._</center>


And it does work (and it is a one-liner like I love), don’t get me wrong, but it’s just not as elegant as I wanted it to be, and nothing made any sense anymore.

---

###I am one with the code
Fast forward 1 hour and I discovered that objects have properties, and these properties have metadata (called descriptor) and this metadata defines whether we can enumerate over the property, change it, and how we get it from the object.

So it must be that the properties have some sort of a metadata tag that prevents getting them in the conventional ways. From MDN I figured that `enumerable` is the property that interests me:

>`true` if and only if this property shows up during enumeration of the properties on the corresponding object.
```javascript
  Object.getOwnPropertyDescriptors(window.performance.memory.__proto__);
// {..., jsHeapSizeLimit: {get: ƒ, set: undefined, enumerable: true, configurable: true}, ...}
```

But the properties do have the `enumerable` metadata-property turned on, why aren’t they showing up when using `Object.keys` or `Object.values`?

---

###The not-so-grand finale
Finally, I succeeded in "turning on" the enumerable flags on _the enemy_, and my data stringified beautifly

```javascript
  const finale = JSON.stringify(Object.defineProperties(window.performance.memory, Object.getOwnPropertyDescriptors(window.performance.memory.__proto__)));
  console.log(finale); // "{"totalJSHeapSize":29400000,"usedJSHeapSize":23100000,"jsHeapSizeLimit":2330000000}"
```
######<center>_Sweet, sweet one-liner_</center>

So what’s going on here?

We already saw that the descriptors of the `MemoryInfo` prototype should be fine, so the only explanation is that somehow they are not set (or overridden) on _the enemy_ itself.

Using `Object.defineProperties` I am able to get a copy of _the enemy_, but with the correct descriptors (which we can just get from the prototype using `Object.getOwnPropertyDescriptors`)

Then just stringify and ship!

![](https://thepracticaldev.s3.amazonaws.com/i/zbc1zinz2o233pfvpaou.png)