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 lts] Ensures that tracked properties initialize property #19172

Merged
merged 1 commit into from Sep 30, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -14,6 +14,44 @@ import { Component } from '../../utils/helpers';
moduleFor(
'Component Tracked Properties',
class extends RenderingTestCase {
'@test simple test using classic component'() {
let personId = 0;
class Person {
@tracked first;
@tracked last;

constructor(first, last) {
this.id = personId++;
this.first = first;
this.last = last;
}
}

class PersonComponent extends Component {
@tracked first;
@tracked last;

get person() {
return new Person(this.first, this.last);
}
}

this.registerComponent('person-wrapper', {
ComponentClass: PersonComponent,
template: '{{@first}} {{@last}} | {{this.person.first}} {{this.person.last}}',
});

this.render('<PersonWrapper @first={{first}} @last={{last}} />', {
first: 'robert',
last: 'jackson',
});

this.assertText('robert jackson | robert jackson');

runTask(() => this.context.set('first', 'max'));
this.assertText('max jackson | max jackson');
}

'@test simple test using glimmerish component'() {
let personId = 0;
class Person {
Expand Down
9 changes: 1 addition & 8 deletions packages/@ember/-internals/metal/lib/decorator.ts
@@ -1,6 +1,5 @@
import { Meta, meta as metaFor, peekMeta } from '@ember/-internals/meta';
import { assert } from '@ember/debug';
import { _WeakSet as WeakSet } from '@glimmer/util';

export type DecoratorPropertyDescriptor = (PropertyDescriptor & { initializer?: any }) | undefined;

Expand Down Expand Up @@ -80,17 +79,11 @@ function DESCRIPTOR_SETTER_FUNCTION(
name: string,
descriptor: ComputedDescriptor
): (value: any) => void {
let func = function CPSETTER_FUNCTION(this: object, value: any): void {
return function CPSETTER_FUNCTION(this: object, value: any): void {
return descriptor.set(this, name, value);
};

CP_SETTER_FUNCS.add(func);

return func;
}

export const CP_SETTER_FUNCS = new WeakSet();

export function makeComputedDecorator(
desc: ComputedDescriptor,
DecoratorClass: { prototype: object }
Expand Down
16 changes: 5 additions & 11 deletions packages/@ember/-internals/metal/lib/property_set.ts
@@ -1,13 +1,8 @@
import {
HAS_NATIVE_PROXY,
lookupDescriptor,
setWithMandatorySetter,
toString,
} from '@ember/-internals/utils';
import { HAS_NATIVE_PROXY, setWithMandatorySetter, toString } from '@ember/-internals/utils';
import { assert } from '@ember/debug';
import EmberError from '@ember/error';
import { DEBUG } from '@glimmer/env';
import { CP_SETTER_FUNCS } from './decorator';
import { descriptorForProperty } from './decorator';
import { isPath } from './path_cache';
import { notifyPropertyChange } from './property_events';
import { _getPath as getPath, getPossibleMandatoryProxyValue } from './property_get';
Expand Down Expand Up @@ -72,11 +67,10 @@ export function set(obj: object, keyName: string, value: any, tolerant?: boolean
return setPath(obj, keyName, value, tolerant);
}

let descriptor = lookupDescriptor(obj, keyName);
let setter = descriptor === null ? undefined : descriptor.set;
let descriptor = descriptorForProperty(obj, keyName);

if (setter !== undefined && CP_SETTER_FUNCS.has(setter)) {
obj[keyName] = value;
if (descriptor !== undefined) {
descriptor.set(obj, keyName, value);
return value;
}

Expand Down
20 changes: 15 additions & 5 deletions packages/@ember/-internals/metal/lib/tracked.ts
Expand Up @@ -5,7 +5,6 @@ import { DEBUG } from '@glimmer/env';
import { consumeTag, dirtyTagFor, tagFor, trackedData } from '@glimmer/validator';
import { CHAIN_PASS_THROUGH } from './chain-tags';
import {
CP_SETTER_FUNCS,
Decorator,
DecoratorPropertyDescriptor,
isElementDescriptor,
Expand Down Expand Up @@ -183,10 +182,21 @@ function descriptorForField([target, key, desc]: [
set,
};

metaFor(target).writeDescriptors(key, newDesc);

CP_SETTER_FUNCS.add(set);
CHAIN_PASS_THROUGH.add(newDesc);
metaFor(target).writeDescriptors(key, new TrackedDescriptor(get, set));

return newDesc;
}

class TrackedDescriptor {
constructor(private _get: () => unknown, private _set: (value: unknown) => void) {
CHAIN_PASS_THROUGH.add(this);
}

get(obj: object) {
return this._get.call(obj);
}

set(obj: object, _key: string, value: unknown) {
this._set.call(obj, value);
}
}