Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use WeakMap for storing Glimmer metadata #119

Merged
merged 3 commits into from
Mar 16, 2018
Merged

Use WeakMap for storing Glimmer metadata #119

merged 3 commits into from
Mar 16, 2018

Conversation

tomdale
Copy link
Contributor

@tomdale tomdale commented Mar 11, 2018

TL;DR

  • Use WeakMap instead of symbols to store tracked property metadata.
  • Fix the tests to run in strict mode, so mutating a frozen object actually throws an error. :trollface:

Tracked properties rely on storing unique tags for each property on an object. We store these and other metadata in instances of a class called Meta, which are created lazily the first time a tracked property is requested for a property on an object.

Prior to this PR, we used a symbol to store the object's Meta on itself. The symbol prevented inadvertent access or naming collisions. However, when in strict mode, setting a property throws an error if the object in question is frozen via Object.freeze. It is a common pattern for libraries to use Object.freeze on objects that should be read-only, such as Apollo (glimmerjs/glimmer-vm#632). Simply rendering a property from a frozen object in a template should not cause an exception to be thrown.

To fix this, this commit changes the implementation to use a WeakMap to map objects to their corresponding Meta instance. The new implementation is intended to be semantically identical to the previous implementation, but with compatibility with frozen objects.

This PR contains another important change. We have dealt with issues with frozen objects in the past, and even wrote quite a few tests to verify compatibility with them.

Unfortunately, due to a misconfiguration I made to the Rollup builds, our test suite was not actually running in strict mode. This meant that all of the tests testing frozen objects were invalid, because in sloppy mode, mutating a frozen object does not throw an error.

This PR changes the Rollup configuration to use the iife format rather than es, which puts them into strict mode. After I made this change, previously passing tests began to fail. However, they are addressed by the move to WeakMaps.

Previously, tests were not running in strict mode, because we were emitting them as a JavaScript module (which implies strict mode) but not consuming them as such, so they defaulted to sloppy mode.

In practice, this meant that several tests that verified compatibility with frozen objects were inappropriately passing, because mutation of frozen objects in sloppy mode is a no-op rather than an error.

This commit changes the Rollup configuration for tests to use `iife` as the target format rather than `es`, which produces the appropriate `"use strict";` pragma.
Tracked properties rely on storing unique tags for each property on an object. We store these and other metadata in instances of a class called Meta, which are created lazily the first time a tracked property is requested for a property on an object.

Previously, we used a symbol to store the object's Meta on itself. The symbol prevented inadvertent access or naming collisions. However, setting a property, even via a symbol, throws an error if the object in question is frozen via `Object.freeze`. It is a common pattern for libraries to use `Object.freeze` on objects that should be read-only, such as Apollo (#632). Simply reading a property from an object should not cause an exception.

To mitigate this, this commit changes the implementation to use a WeakMap to map objects to their corresponding Meta instance. The new implementation is intended to be semantically identical to the previous implementation, but with compatibility with frozen objects.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants