mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: Implement DeferredTrackedSet
(#27372)
For cases where you'd be using a TrackedSet to render something and then modifying that set throughout the same render cycle. (specifically it will be used in #27365)
This commit is contained in:
parent
ffec8163b0
commit
46ab4f0c4a
@ -1,4 +1,6 @@
|
|||||||
import { tracked } from "@glimmer/tracking";
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
import { next } from "@ember/runloop";
|
||||||
|
import { TrackedSet } from "@ember-compat/tracked-built-ins";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a tracked property on an object without needing to use the @tracked decorator.
|
* Define a tracked property on an object without needing to use the @tracked decorator.
|
||||||
@ -120,3 +122,57 @@ export function dedupeTracked(target, key, desc) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DeferredTrackedSet {
|
||||||
|
#set;
|
||||||
|
|
||||||
|
constructor(value) {
|
||||||
|
this.#set = new TrackedSet(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
has(value) {
|
||||||
|
return this.#set.has(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
entries() {
|
||||||
|
return this.#set.entries();
|
||||||
|
}
|
||||||
|
|
||||||
|
keys() {
|
||||||
|
return this.#set.keys();
|
||||||
|
}
|
||||||
|
|
||||||
|
values() {
|
||||||
|
return this.#set.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
forEach(fn) {
|
||||||
|
return this.#set.forEach(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
get size() {
|
||||||
|
return this.#set.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Symbol.iterator]() {
|
||||||
|
return this.#set[Symbol.iterator]();
|
||||||
|
}
|
||||||
|
|
||||||
|
get [Symbol.toStringTag]() {
|
||||||
|
return this.#set[Symbol.toStringTag];
|
||||||
|
}
|
||||||
|
|
||||||
|
add(value) {
|
||||||
|
next(() => this.#set.add(value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(value) {
|
||||||
|
next(() => this.#set.delete(value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
next(() => this.#set.clear());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { cached } from "@glimmer/tracking";
|
import { cached } from "@glimmer/tracking";
|
||||||
|
import { run } from "@ember/runloop";
|
||||||
|
import { settled } from "@ember/test-helpers";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import { dedupeTracked } from "discourse/lib/tracked-tools";
|
import { dedupeTracked, DeferredTrackedSet } from "discourse/lib/tracked-tools";
|
||||||
|
|
||||||
module("Unit | tracked-tools", function () {
|
module("Unit | tracked-tools", function () {
|
||||||
test("@dedupeTracked", async function (assert) {
|
test("@dedupeTracked", async function (assert) {
|
||||||
@ -45,4 +47,73 @@ module("Unit | tracked-tools", function () {
|
|||||||
"Initials getter re-evaluated"
|
"Initials getter re-evaluated"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("DeferredTrackedSet", async function (assert) {
|
||||||
|
class Player {
|
||||||
|
evaluationsCount = 0;
|
||||||
|
|
||||||
|
letters = new DeferredTrackedSet();
|
||||||
|
|
||||||
|
@cached
|
||||||
|
get score() {
|
||||||
|
this.evaluationsCount++;
|
||||||
|
return this.letters.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const player = new Player();
|
||||||
|
assert.strictEqual(player.score, 0, "score is correct");
|
||||||
|
assert.strictEqual(player.evaluationsCount, 1, "getter evaluated once");
|
||||||
|
|
||||||
|
run(() => {
|
||||||
|
player.letters.add("a");
|
||||||
|
|
||||||
|
assert.strictEqual(player.score, 0, "score does not change");
|
||||||
|
assert.strictEqual(
|
||||||
|
player.evaluationsCount,
|
||||||
|
1,
|
||||||
|
"getter does not evaluate"
|
||||||
|
);
|
||||||
|
|
||||||
|
player.letters.add("b");
|
||||||
|
player.letters.add("c");
|
||||||
|
|
||||||
|
assert.strictEqual(player.score, 0, "score still does not change");
|
||||||
|
assert.strictEqual(
|
||||||
|
player.evaluationsCount,
|
||||||
|
1,
|
||||||
|
"getter still does not evaluate"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await settled();
|
||||||
|
|
||||||
|
assert.strictEqual(player.score, 3, "score is correct");
|
||||||
|
assert.strictEqual(player.evaluationsCount, 2, "getter evaluated again");
|
||||||
|
|
||||||
|
run(() => {
|
||||||
|
player.letters.add("d");
|
||||||
|
});
|
||||||
|
await settled();
|
||||||
|
|
||||||
|
assert.strictEqual(player.score, 4, "score is correct");
|
||||||
|
assert.strictEqual(player.evaluationsCount, 3, "getter evaluated again");
|
||||||
|
|
||||||
|
run(() => {
|
||||||
|
player.letters.add("e");
|
||||||
|
|
||||||
|
assert.strictEqual(player.score, 4, "score is correct");
|
||||||
|
assert.strictEqual(
|
||||||
|
player.evaluationsCount,
|
||||||
|
3,
|
||||||
|
"getter does not evaluate"
|
||||||
|
);
|
||||||
|
|
||||||
|
player.letters.add("f");
|
||||||
|
});
|
||||||
|
await settled();
|
||||||
|
|
||||||
|
assert.strictEqual(player.score, 6, "score is correct");
|
||||||
|
assert.strictEqual(player.evaluationsCount, 4, "getter evaluated");
|
||||||
|
assert.deepEqual([...player.letters], ["a", "b", "c", "d", "e", "f"]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user