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

[BUGFIX] Use WeakMap to store tracked property values. #18091

Merged
merged 1 commit into from
Jun 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions packages/@ember/-internals/metal/lib/tracked.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HAS_NATIVE_SYMBOL, isEmberArray, symbol as emberSymbol } from '@ember/-internals/utils';
import { isEmberArray } from '@ember/-internals/utils';
import { EMBER_NATIVE_DECORATOR_SUPPORT } from '@ember/canary-features';
import { assert } from '@ember/debug';
import { DEBUG } from '@glimmer/env';
Expand All @@ -9,10 +9,6 @@ import { markObjectAsDirty, tagForProperty, update } from './tags';

type Option<T> = T | null;

// For some reason TS can't infer that these two functions are compatible-ish,
// so we need to corece the type
let symbol = (HAS_NATIVE_SYMBOL ? Symbol : emberSymbol) as (debugKey: string) => string;

/**
An object that that tracks @tracked properties that were consumed.

Expand Down Expand Up @@ -192,7 +188,8 @@ function descriptorForField([_target, key, desc]: [
);

let initializer = desc ? desc.initializer : undefined;
let secretKey = symbol(key);
let values = new WeakMap();
let hasInitializer = typeof initializer === 'function';

return {
enumerable: true,
Expand All @@ -203,26 +200,30 @@ function descriptorForField([_target, key, desc]: [

if (CURRENT_TRACKER) CURRENT_TRACKER.add(propertyTag);

let value;

// If the field has never been initialized, we should initialize it
if (!(secretKey in this)) {
this[secretKey] = typeof initializer === 'function' ? initializer.call(this) : undefined;
}
if (hasInitializer && !values.has(this)) {
value = initializer.call(this);

let value = this[secretKey];
values.set(this, value);
} else {
value = values.get(this);
}

// Add the tag of the returned value if it is an array, since arrays
// should always cause updates if they are consumed and then changed
if (Array.isArray(value) || isEmberArray(value)) {
update(propertyTag, tagForProperty(value, '[]'));
}

return this[secretKey];
return value;
},

set(newValue: any): void {
markObjectAsDirty(this, key);

this[secretKey] = newValue;
values.set(this, newValue);

if (propertyDidChange !== null) {
propertyDidChange();
Expand Down
4 changes: 2 additions & 2 deletions packages/@ember/controller/tests/controller_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ moduleFor(
assert.expect(3);
expectNoDeprecation();

let controller = Controller.extend({
let controller = Controller.create({
content: 'foo-bar',
model: 'blammo',
}).create();
});

assert.equal(get(controller, 'content'), 'foo-bar');
assert.equal(get(controller, 'model'), 'blammo');
Expand Down
25 changes: 15 additions & 10 deletions packages/ember/tests/routing/decoupled_basic_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,9 @@ moduleFor(
this.add(
'controller:homepage',
Controller.extend({
model: {
home: 'Comes from homepage',
init() {
this._super(...arguments);
this.model = { home: 'Comes from homepage' };
},
})
);
Expand All @@ -183,16 +184,18 @@ moduleFor(
this.add(
'controller:foo',
Controller.extend({
model: {
home: 'Comes from foo',
init() {
this._super(...arguments);
this.model = { home: 'Comes from foo' };
},
})
);
this.add(
'controller:homepage',
Controller.extend({
model: {
home: 'Comes from homepage',
init() {
this._super(...arguments);
this.model = { home: 'Comes from homepage' };
},
})
);
Expand Down Expand Up @@ -220,8 +223,9 @@ moduleFor(
this.add(
'controller:home',
Controller.extend({
model: {
home: 'Comes from home.',
init() {
this._super(...arguments);
this.model = { home: 'Comes from home.' };
},
})
);
Expand All @@ -241,8 +245,9 @@ moduleFor(
this.add(
'controller:home',
Controller.extend({
model: {
home: 'YES I AM HOME',
init() {
this._super(...arguments);
this.model = { home: 'YES I AM HOME' };
},
})
);
Expand Down