Skip to content

Commit

Permalink
implement more specific notification behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholasrice committed Jul 5, 2022
1 parent 1013266 commit ecdf0df
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,3 @@ Observable.getNotifier(token).subscribe({




### class: `ObservableMap`

#### Superclass

| Name | Module | Package |
| ----- | ------------------------------------ | ------- |
| `Map` | src/design-token-2/observable-map.ts | |

#### Methods

| Name | Privacy | Description | Parameters | Return | Inherited From |
| -------- | ------- | ----------- | ------------------ | ---------------- | -------------- |
| `set` | | | `key: T, value: K` | `this` | |
| `get` | | | `key: T` | `K or undefined` | |
| `delete` | | | `key: T` | `boolean` | |

<hr/>


Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,6 @@ describe.only("DesignTokenNode", () => {
ancestor.setTokenValue(dependency, 6);
ancestor.setTokenValue(token, (resolve) => resolve(dependency) * 2);


expect(target.getTokenValue(token)).to.equal(12);

target.setTokenValue(dependency, 7);
Expand Down Expand Up @@ -581,7 +580,7 @@ describe.only("DesignTokenNode", () => {
node.setTokenValue(token, 12);
Observable.getNotifier(token).subscribe(subscriber);

node.setTokenValue(token, ()=> 12);
node.setTokenValue(token, () => 12);

expect(handleChange).not.to.have.been.called();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,20 +105,15 @@ export class DesignTokenNode {
return typeof value === "function";
}

/**
* @returns {boolean} - true if the resulting value has changed, otherwise false.
*/
private static evaluateDerived<T>(
node: DesignTokenNode,
token: DesignToken<T>,
value: DerivedDesignTokenValue<T>
): boolean {
): StaticDesignTokenValue<T> {
const evaluator = DerivedValueEvaluator.getOrCreate(value);
const result = evaluator.evaluate(node, token);
const prev = node._derived.get(token);
node._derived.set(token, [value, result]);

return prev === undefined ? true : prev[1] !== result;
return result;
}

/**
Expand Down Expand Up @@ -234,30 +229,39 @@ export class DesignTokenNode {
}

public setTokenValue<T>(token: DesignToken<T>, value: DesignTokenValue<T>) {
const prev = this._values.get(token);
const prev = this.getLocalTokenValue(token);
this._values.set(token, value);
const isDerived = DesignTokenNode.isDerivedTokenValue(value);
const derivedContext = DesignTokenNode.collectDerivedContext(this);
const result = isDerived
? DesignTokenNode.evaluateDerived(this, token, value)
: value;

if (!isDerived && DesignTokenNode.isDerivedFor(this, token)) {
this._derived.delete(token);
}

const derived = DesignTokenNode.collectDerivedContext(this);

if (DesignTokenNode.isDerivedTokenValue(value)) {
DesignTokenNode.evaluateDerived(this, token, value) &&
DesignTokenNode.notifyToken(token, this);
if (prev !== result) {
DesignTokenNode.notifyToken(token, this);
}

this.notifyDerived(token, DerivedValueEvaluator.getOrCreate(value), this);
} else {
DesignTokenNode.isDerivedFor(this, token) && this._derived.delete(token);
isDerived
? this.notifyDerived(token, DerivedValueEvaluator.getOrCreate(value), this)
: this.notifyStatic(token, this);

derivedContext.forEach((fn, token) => {
// Skip over any derived values already established locally, because
// those will get updated via this.notifyDerived and this.notifyStatic
if (!DesignTokenNode.isDerivedFor(this, token)) {
const evaluator = DerivedValueEvaluator.getOrCreate(fn);
const prev = this.getLocalTokenValue(token);
const result = DesignTokenNode.evaluateDerived(this, token, fn);
if (prev !== result) {
DesignTokenNode.notifyToken(token, this);
}

if (prev !== value) {
DesignTokenNode.notifyToken(token, this);
this.notifyStatic(token, this);
this.notifyDerived(token, evaluator, this);
}
}

derived.forEach((fn, token) => {
const evaluator = DerivedValueEvaluator.getOrCreate(fn);
DesignTokenNode.evaluateDerived(this, token, fn) &&
DesignTokenNode.notifyToken(token, this);
this.notifyDerived(token, evaluator, this);
});
}

Expand Down Expand Up @@ -312,8 +316,11 @@ export class DesignTokenNode {
const evaluator = DerivedValueEvaluator.getOrCreate(source);

if (evaluator.dependencies.has(token)) {
DesignTokenNode.evaluateDerived(this, _token, source) &&
const prev = this.getLocalTokenValue(_token);
const value = DesignTokenNode.evaluateDerived(this, _token, source);
if (value !== prev) {
DesignTokenNode.notifyToken(_token, this);
}
this.notifyDerived(_token, evaluator, originator);
}
}
Expand All @@ -340,8 +347,16 @@ export class DesignTokenNode {
// has any dependencies of the token value. If so, we need to evaluate for this node
evaluator.dependencies.forEach(dep => {
if (DesignTokenNode.isAssigned(this, dep)) {
DesignTokenNode.evaluateDerived(this, token, evaluator.value) &&
const prev = this.getLocalTokenValue(token);
const value = DesignTokenNode.evaluateDerived(
this,
token,
evaluator.value
);

if (prev !== value) {
DesignTokenNode.notifyToken(token, this);
}
this.notifyDerived(token, evaluator, this);
}
});
Expand All @@ -361,8 +376,8 @@ export class DesignTokenNode {
const evaluator = DerivedValueEvaluator.getOrCreate(source);

if (evaluator.dependencies.has(token)) {
DesignTokenNode.evaluateDerived(this, _token, source) &&
DesignTokenNode.notifyToken(_token, this);
DesignTokenNode.evaluateDerived(this, _token, source);
DesignTokenNode.notifyToken(_token, this);
this.notifyDerived(_token, evaluator, originator);
}
}
Expand All @@ -371,4 +386,17 @@ export class DesignTokenNode {
this.children[i].notifyDerived(token, evaluator, originator);
}
}

/**
* Resolves the local value for a token if it exists, otherwise returns undefined.
*/
private getLocalTokenValue<T>(
token: DesignToken<T>
): StaticDesignTokenValue<T> | undefined {
return !DesignTokenNode.isAssigned(this, token)
? undefined
: DesignTokenNode.isDerivedFor(this, token)
? this._derived.get(token)![1]
: this._values.get(token);
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export class DesignToken<T> {}
let id = 0;
export class DesignToken<T> {
public readonly id = id++;
}

0 comments on commit ecdf0df

Please sign in to comment.