Skip to content

Commit

Permalink
[BUGFIX release] Ensure tag updates are buffered (#18698)
Browse files Browse the repository at this point in the history
[BUGFIX release] Ensure tag updates are buffered
  • Loading branch information
Chris Garrett authored Jan 25, 2020
2 parents 3196d7a + 2a54362 commit deefc2e
Show file tree
Hide file tree
Showing 3 changed files with 284 additions and 101 deletions.
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@
},
"devDependencies": {
"@babel/preset-env": "^7.6.0",
"@glimmer/compiler": "0.38.5-alpha.3",
"@glimmer/compiler": "0.38.5-alpha.4",
"@glimmer/env": "^0.1.7",
"@glimmer/interfaces": "0.38.5-alpha.3",
"@glimmer/node": "0.38.5-alpha.3",
"@glimmer/opcode-compiler": "0.38.5-alpha.3",
"@glimmer/program": "0.38.5-alpha.3",
"@glimmer/reference": "0.38.5-alpha.3",
"@glimmer/runtime": "0.38.5-alpha.3",
"@glimmer/interfaces": "0.38.5-alpha.4",
"@glimmer/node": "0.38.5-alpha.4",
"@glimmer/opcode-compiler": "0.38.5-alpha.4",
"@glimmer/program": "0.38.5-alpha.4",
"@glimmer/reference": "0.38.5-alpha.4",
"@glimmer/runtime": "0.38.5-alpha.4",
"@types/qunit": "^2.5.4",
"@types/rsvp": "^4.0.3",
"@typescript-eslint/parser": "^2.7.0",
Expand Down
183 changes: 183 additions & 0 deletions packages/@ember/-internals/metal/tests/computed_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1042,3 +1042,186 @@ moduleFor(
}
}
);

class LazyObject {
value = 123;

@computed('_value')
get value() {
return get(this, '_value');
}

set value(value) {
set(this, '_value', value);
}

static create() {
let obj = new LazyObject();

// ensure a tag exists for the value computed
get(obj, 'value');

return obj;
}
}

moduleFor(
'computed - lazy dependencies',
class extends AbstractTestCase {
'@test computed properties with lazy dependencies work as expected'(assert) {
let calledCount = 0;
let lazyObject = LazyObject.create();

class ObjectWithLazyDep {
@computed('lazyObject.value')
get someProp() {
return ++calledCount;
}

@computed('otherProp')
get lazyObject() {
return lazyObject;
}
}

let obj = new ObjectWithLazyDep();

// Get someProp and setup the lazy dependency
assert.equal(obj.someProp, 1, 'called the first time');
assert.equal(obj.someProp, 1, 'returned cached value the second time');

// Finish the lazy dependency
assert.equal(obj.lazyObject.value, 123, 'lazyObject returns expected value');
assert.equal(
obj.someProp,
1,
'someProp was not dirtied by propB being calculated for the first time'
);

set(lazyObject, 'value', 456);
assert.equal(obj.someProp, 2, 'someProp dirtied by lazyObject.value changing');

set(lazyObject, 'value', 789);
assert.equal(
obj.someProp,
3,
'someProp still dirtied by otherProp when lazyObject.value is dirty'
);
}

'@test computed properties with lazy dependencies do not dirty until dependencies have been read at least once'(
assert
) {
let calledCount = 0;
let lazyObject = LazyObject.create();

class ObjectWithLazyDep {
@computed('lazyObject.value')
get someProp() {
return ++calledCount;
}

@computed('otherProp')
get lazyObject() {
return lazyObject;
}
}

let obj = new ObjectWithLazyDep();

assert.equal(obj.someProp, 1, 'called the first time');
assert.equal(obj.someProp, 1, 'returned cached value the second time');

// dirty the object value before the dependency has been finished
set(lazyObject, 'value', 456);

assert.equal(obj.lazyObject.value, 456, 'propB returns expected value');
assert.equal(
obj.someProp,
1,
'someProp was not dirtied by propB being dirtied before it has been calculated'
);
}

'@test computed properties with lazy dependencies work correctly if lazy dependency is more recent'(
assert
) {
let calledCount = 0;
let lazyObject = LazyObject.create();

class ObjectWithLazyDep {
@computed('lazyObject.value')
get someProp() {
return ++calledCount;
}

@computed('otherProp')
get lazyObject() {
return lazyObject;
}
}

let obj = new ObjectWithLazyDep();

set(lazyObject, 'value', 456);

assert.equal(obj.someProp, 1, 'called the first time');
assert.equal(obj.someProp, 1, 'returned cached value the second time');

assert.equal(obj.lazyObject.value, 456, 'lazyObject returns expected value');

assert.equal(
obj.someProp,
1,
'someProp was not dirtied by lazyObject being dirtied before it has been calculated'
);
}
}
);

moduleFor(
'computed - observer interop',
class extends AbstractTestCase {
async '@test observers that do not consume computed properties still work'(assert) {
assert.expect(2);

class Foo {
otherProp = 123;

@computed('otherProp')
get someProp() {
return this.otherProp;
}
}

let foo = new Foo();

addObserver(
foo,
'otherProp',
foo,
() => assert.ok(true, 'otherProp observer called when it was changed'),
false
);

addObserver(
foo,
'someProp',
foo,
() => assert.ok(false, 'someProp observer called when it was not changed'),
false
);

set(foo, 'otherProp', 456);

await runLoopSettled();

assert.equal(get(foo, 'someProp'), 456, '');

addObserver(foo, 'anotherProp', foo, () => {}, false);
set(foo, 'anotherProp', 123);

await runLoopSettled();
}
}
);
Loading

0 comments on commit deefc2e

Please sign in to comment.