From f183d2d79f7035d8e581cef32e4a2092c6c84f08 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 11 Sep 2015 18:12:58 -0700 Subject: [PATCH 1/3] WeakMap RFC --- text/0066-template.md | 90 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 text/0066-template.md diff --git a/text/0066-template.md b/text/0066-template.md new file mode 100644 index 0000000000..3ef031f87d --- /dev/null +++ b/text/0066-template.md @@ -0,0 +1,90 @@ +- Start Date: 2015-09-11 +- RFC PR: https://github.com/emberjs/ember.js/pull/12224 +- Ember Issue: (leave this empty) + +# Summary + +Introduce `Ember.WeakMap` (`@ember/weakmap`), an ES6 enspired WeakMap. A +WeakMap provides a mechanism for storing and retriving private state. The +WeakMap itself does not retain a reference to the state, allowing the state to +be reclaimed when the key is reclaimed. + +A traditional WeakMap (and the one that will be part of the language) allows +for weakness from key -> map, and also from map -> key. This allows either the +Map, or the key being reclaimed to also release the state. + +Unforunately, this bi-directional weakness is problemative to polyfil. Luckily, +uni-directional weakness, in either direction, "just works". A polyfil must +just choose a direction. + +*Note: Just like ES2015 WeakMap, only non null Objects can be used as keys* +*Note: `Ember.WeakMap` can be used interchangibly with the ES2015 WeakMap. This +will allow us to eventually cut over entirely to the Native WeakMap.* + +# Motivation + +It is a common pattern to want to store private state about a specific object. +When one stores this private state off-object, it can be tricky to understand +when to release the state. When one stores this state on-object, it will be +released when the object is released. Unfortunately, storing the state +on-object without poluting the object itself is non-obvious. + +As it turns out, Ember's Meta already solves this problem for +listeners/caches/chains/descriptors etc. Unfortunately today, there is no +public API for apps or addons to utilize this. `Ember.WeakMap` aims to be +exactly that API. + +# Detailed design + +## Public API + +```js +import WeakMap from '@ember/weak-map' + +var private = new WeakMap(); +var object = {}; +var otherObject = {}; + +private.set(object, { + id: 1, + name: 'My File', + progress: 0 +}) === private; + +private.get(object) === { + id: 1, + name: 'My File', + progress: 0 +}); + + +private.has(object) === true; +private.has(otherObject) === false; + +private.delete(object) === private; +private.has(object) === false; +``` + +## Implementation Details + +The backing store for `Ember.WeakMap` will reside in a lazy `ownMap` named +`weak` on the key objects `__meta__` object. + +Each `WeakMap` has its own internal GUID, which will be the name of its slot, +in the key objects meta weak bucket. This will allow one object to belong in +multiple weakMaps without chance of collision. + +Concrete Implementation: https://github.com/emberjs/ember.js/pull/12224 + +# Drawbacks + +* implementing bi-direction Weakness in userland is problematic. +* Using WeakMap will insert a non-enumerable `meta` onto the key Object. + +# Alternatives + +* Weakness could be implemented in the other direction, but this has questionable utility. + +# Unresolved questions + +N/A From 89f08b9dcdda132b75eab878687cc312e502562c Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Sat, 12 Sep 2015 14:26:32 -0700 Subject: [PATCH 2/3] Update 0066-template.md --- text/0066-template.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/text/0066-template.md b/text/0066-template.md index 3ef031f87d..e8e6a8728c 100644 --- a/text/0066-template.md +++ b/text/0066-template.md @@ -34,6 +34,11 @@ listeners/caches/chains/descriptors etc. Unfortunately today, there is no public API for apps or addons to utilize this. `Ember.WeakMap` aims to be exactly that API. +Some examples: + +* https://github.com/offirgolan/ember-cp-validations/blob/master/addon/utils/cycle-breaker.js +* https://github.com/stefanpenner/ember-state-services/ (will soon utilize the user-land polyfil of this) to prevent common leaks. + # Detailed design ## Public API From ddf743b73cb9f046c84268c3f840133b48799eac Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Thu, 24 Sep 2015 10:53:04 -0700 Subject: [PATCH 3/3] Update 0066-template.md --- text/0066-template.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0066-template.md b/text/0066-template.md index e8e6a8728c..f71171d650 100644 --- a/text/0066-template.md +++ b/text/0066-template.md @@ -80,6 +80,7 @@ in the key objects meta weak bucket. This will allow one object to belong in multiple weakMaps without chance of collision. Concrete Implementation: https://github.com/emberjs/ember.js/pull/12224 +Polyfill: https://www.npmjs.com/package/ember-weakmap # Drawbacks