Skip to content

Commit

Permalink
[BUGFIX] Use WeakMap to store tracked property values.
Browse files Browse the repository at this point in the history
  • Loading branch information
rwjblue committed Jun 12, 2019
1 parent 319e3ce commit 394904c
Showing 1 changed file with 13 additions and 12 deletions.
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

0 comments on commit 394904c

Please sign in to comment.