Skip to content

Commit

Permalink
[BUGFIX] fix issue around how undefined stored in _values chain
Browse files Browse the repository at this point in the history
  • Loading branch information
bekzod committed Jan 3, 2019
1 parent afcbd47 commit 8d340f8
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 29 deletions.
32 changes: 9 additions & 23 deletions packages/@ember/-internals/meta/lib/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ export interface Meta {
writeValues(subkey: string, value: any): void;
peekValues(key: string): any;
deleteFromValues(key: string): any;
readInheritedValue(key: string, subkey: string): any;
readInheritedValue(key: string): any;
writeValue(obj: object, key: string, value: any): any;
writeBindings(subkey: string, value: any): void;
peekBindings(subkey: string): void;
Expand All @@ -798,34 +798,20 @@ if (DEBUG) {
);

let map = this._getOrCreateOwnMap('_values');
map[subkey] = value;
map[subkey] = value === undefined ? UNDEFINED : value;
};

Meta.prototype.peekValues = function(subkey: string) {
return this._findInherited2('_values', subkey);
Meta.prototype.peekValues = function(key: string) {
let val = this._findInherited2('_values', key);
return val === UNDEFINED ? undefined : val;
};

Meta.prototype.deleteFromValues = function(subkey: string) {
delete this._getOrCreateOwnMap('_values')[subkey];
Meta.prototype.deleteFromValues = function(key: string) {
delete this._getOrCreateOwnMap('_values')[key];
};

Meta.prototype.readInheritedValue = function(key, subkey) {
let internalKey = `_${key}`;

let pointer: Meta | null = this;

while (pointer !== null) {
let map = pointer[internalKey];
if (map !== undefined) {
let value = map[subkey];
if (value !== undefined || subkey in map) {
return value;
}
}
pointer = pointer.parent;
}

return UNDEFINED;
Meta.prototype.readInheritedValue = function(key: string) {
return this._findInherited2('_values', key);
};

Meta.prototype.writeValue = function(obj: object, key: string, value: any) {
Expand Down
8 changes: 5 additions & 3 deletions packages/@ember/-internals/metal/lib/properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,12 @@ export function INHERITING_GETTER_FUNCTION(name: string): InheritingGetterFuncti
let meta = peekMeta(this);
let val;
if (meta !== null) {
val = meta.readInheritedValue('values', name);
if (val === UNDEFINED) {
val = meta.readInheritedValue(name);
if (val === undefined) {
let proto = Object.getPrototypeOf(this);
return proto === null ? undefined : proto[name];
val = proto === null ? undefined : proto[name];
} else {
val = val === UNDEFINED ? undefined : val;
}
}

Expand Down
5 changes: 2 additions & 3 deletions packages/@ember/-internals/metal/lib/watch_key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
Meta,
meta as metaFor,
peekMeta,
UNDEFINED,
} from '@ember/-internals/meta';
import { lookupDescriptor } from '@ember/-internals/utils';
import { DEBUG } from '@glimmer/env';
Expand Down Expand Up @@ -134,8 +133,8 @@ export function unwatchKey(obj: object, keyName: string, _meta?: Meta): void {
maybeMandatoryDescriptor.get &&
(maybeMandatoryDescriptor.get as InheritingGetterFunction).isInheritingGetter
) {
let possibleValue = meta.readInheritedValue('values', keyName);
if (possibleValue === UNDEFINED) {
let possibleValue = meta.readInheritedValue(keyName);
if (possibleValue === undefined) {
delete obj[keyName];
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,25 @@ moduleFor(
assert.equal(get(obj, 'count'), 1, 'should invoke observer after change');
}

['@test setting `undefined` value on observed property behaves correctly'](assert) {
let MyClass = EmberObject.extend({
mood: 'good',
foo: observer('mood', function() {}),
});

let obj = MyClass.create();
assert.equal(get(obj, 'mood'), 'good');

set(obj, 'mood', 'bad');
assert.equal(get(obj, 'mood'), 'bad');

set(obj, 'mood', undefined);
assert.equal(get(obj, 'mood'), undefined);

set(obj, 'mood', 'awesome');
assert.equal(get(obj, 'mood'), 'awesome');
}

['@test observer on subclass'](assert) {
let MyClass = EmberObject.extend({
count: 0,
Expand Down

0 comments on commit 8d340f8

Please sign in to comment.