Skip to content

Commit 8635659

Browse files
author
Chris Garrett
authored
Merge pull request #19232 from emberjs/bugfix/restore-previous-set-behavior
[BUGFIX beta] Restores the shadowed property set behavior
2 parents b6c8a37 + 5e7e543 commit 8635659

File tree

4 files changed

+24
-38
lines changed

4 files changed

+24
-38
lines changed

packages/@ember/-internals/metal/lib/decorator.ts

+14-13
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,10 @@ export abstract class ComputedDescriptor {
7171
abstract set(obj: object, keyName: string, value: any | null | undefined): any | null | undefined;
7272
}
7373

74-
export let CPGETTERS: WeakSet<() => unknown>;
75-
export let CPSETTERS: WeakSet<(value: unknown) => void>;
74+
export let COMPUTED_GETTERS: WeakSet<() => unknown>;
7675

7776
if (DEBUG) {
78-
CPGETTERS = new WeakSet();
79-
CPSETTERS = new WeakSet();
77+
COMPUTED_GETTERS = new WeakSet();
8078
}
8179

8280
function DESCRIPTOR_GETTER_FUNCTION(name: string, descriptor: ComputedDescriptor): () => unknown {
@@ -85,7 +83,7 @@ function DESCRIPTOR_GETTER_FUNCTION(name: string, descriptor: ComputedDescriptor
8583
}
8684

8785
if (DEBUG) {
88-
CPGETTERS.add(getter);
86+
COMPUTED_GETTERS.add(getter);
8987
}
9088

9189
return getter;
@@ -94,18 +92,18 @@ function DESCRIPTOR_GETTER_FUNCTION(name: string, descriptor: ComputedDescriptor
9492
function DESCRIPTOR_SETTER_FUNCTION(
9593
name: string,
9694
descriptor: ComputedDescriptor
97-
): (value: unknown) => void {
98-
function setter(this: object, value: unknown): void {
95+
): (value: any) => void {
96+
let set = function CPSETTER_FUNCTION(this: object, value: any): void {
9997
return descriptor.set(this, name, value);
100-
}
98+
};
10199

102-
if (DEBUG) {
103-
CPSETTERS.add(setter);
104-
}
100+
COMPUTED_SETTERS.add(set);
105101

106-
return setter;
102+
return set;
107103
}
108104

105+
export const COMPUTED_SETTERS = new WeakSet();
106+
109107
export function makeComputedDecorator(
110108
desc: ComputedDescriptor,
111109
DecoratorClass: { prototype: object }
@@ -119,7 +117,10 @@ export function makeComputedDecorator(
119117
): DecoratorPropertyDescriptor {
120118
assert(
121119
`Only one computed property decorator can be applied to a class field or accessor, but '${key}' was decorated twice. You may have added the decorator to both a getter and setter, which is unnecessary.`,
122-
isClassicDecorator || !propertyDesc || !propertyDesc.get || !CPGETTERS.has(propertyDesc.get)
120+
isClassicDecorator ||
121+
!propertyDesc ||
122+
!propertyDesc.get ||
123+
!COMPUTED_GETTERS.has(propertyDesc.get)
123124
);
124125

125126
let meta = arguments.length === 3 ? metaFor(target) : maybeMeta;

packages/@ember/-internals/metal/lib/property_set.ts

+4-15
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
import { assert } from '@ember/debug';
88
import EmberError from '@ember/error';
99
import { DEBUG } from '@glimmer/env';
10-
import { CPSETTERS, descriptorForProperty } from './decorator';
10+
import { COMPUTED_SETTERS } from './decorator';
1111
import { isPath } from './path_cache';
1212
import { notifyPropertyChange } from './property_events';
1313
import { _getPath as getPath, getPossibleMandatoryProxyValue } from './property_get';
@@ -72,21 +72,10 @@ export function set<T = unknown>(obj: object, keyName: string, value: T, toleran
7272
return setPath(obj, keyName, value, tolerant);
7373
}
7474

75-
let descriptor = descriptorForProperty(obj, keyName);
75+
let descriptor = lookupDescriptor(obj, keyName);
7676

77-
if (descriptor !== undefined) {
78-
if (DEBUG) {
79-
let instanceDesc = lookupDescriptor(obj, keyName);
80-
81-
assert(
82-
`Attempted to set \`${toString(
83-
obj
84-
)}.${keyName}\` using Ember.set(), but the property was a computed or tracked property that was shadowed by another property declaration. This can happen if you defined a tracked or computed property on a parent class, and then redefined it on a subclass.`,
85-
instanceDesc && instanceDesc.set && CPSETTERS.has(instanceDesc.set)
86-
);
87-
}
88-
89-
descriptor.set(obj, keyName, value);
77+
if (descriptor !== null && COMPUTED_SETTERS.has(descriptor.set!)) {
78+
obj[keyName] = value;
9079
return value;
9180
}
9281

packages/@ember/-internals/metal/lib/tracked.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ import { DEBUG } from '@glimmer/env';
55
import { consumeTag, dirtyTagFor, tagFor, trackedData } from '@glimmer/validator';
66
import { CHAIN_PASS_THROUGH } from './chain-tags';
77
import {
8-
CPGETTERS,
9-
CPSETTERS,
8+
COMPUTED_SETTERS,
109
Decorator,
1110
DecoratorPropertyDescriptor,
1211
isElementDescriptor,
@@ -184,10 +183,7 @@ function descriptorForField([target, key, desc]: [
184183
set,
185184
};
186185

187-
if (DEBUG) {
188-
CPGETTERS.add(get);
189-
CPSETTERS.add(set);
190-
}
186+
COMPUTED_SETTERS.add(set);
191187

192188
metaFor(target).writeDescriptors(key, new TrackedDescriptor(get, set));
193189

packages/@ember/-internals/metal/tests/tracked/set_test.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ moduleFor(
3232
}
3333
}
3434

35-
['@test set should throw an error when setting on shadowed properties']() {
35+
['@test set should not throw an error when setting on shadowed properties'](assert) {
3636
class Obj {
3737
@tracked value = 'emberjs';
3838

@@ -43,9 +43,9 @@ moduleFor(
4343

4444
let newObj = new Obj();
4545

46-
expectAssertion(() => {
47-
set(newObj, 'value', 123);
48-
}, /Attempted to set `\[object Object\].value` using Ember.set\(\), but the property was a computed or tracked property that was shadowed by another property declaration. This can happen if you defined a tracked or computed property on a parent class, and then redefined it on a subclass/);
46+
set(newObj, 'value', 123);
47+
48+
assert.equal(newObj.value, 123, 'it worked');
4949
}
5050
}
5151
);

0 commit comments

Comments
 (0)