Skip to content

Commit

Permalink
[FEAT] Adds memoizeTracked
Browse files Browse the repository at this point in the history
Adds `memoizeTracked`, which is meant to clean up autotracking patterns
in general by simplifying them. Also introduces beginTrackFrame and
endTrackFrame for usage within the VM.

wip
  • Loading branch information
Chris Garrett committed Mar 22, 2020
1 parent 46cbc1b commit 4bf27f7
Show file tree
Hide file tree
Showing 18 changed files with 616 additions and 228 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
} from '@glimmer/interfaces';
import { Attrs, AttrsDiff } from './emberish-glimmer';
import { VersionedPathReference, PathReference } from '@glimmer/reference';
import { combine, createTag, dirty, DirtyableTag, Tag } from '@glimmer/validator';
import { combine, createTag, dirtyTag, DirtyableTag, Tag } from '@glimmer/validator';
import { keys, EMPTY_ARRAY, assign } from '@glimmer/util';
import { TestComponentDefinitionState } from './test-component';
import { PrimitiveReference } from '@glimmer/runtime';
Expand Down Expand Up @@ -78,7 +78,7 @@ export class EmberishCurlyComponent {

set(key: string, value: unknown) {
(this as any)[key] = value;
dirty(this.dirtinessTag);
dirtyTag(this.dirtinessTag);
}

setProperties(dict: Dict) {
Expand All @@ -87,11 +87,11 @@ export class EmberishCurlyComponent {
}

SELF_REF.get(this)!.dirty();
dirty(this.dirtinessTag);
dirtyTag(this.dirtinessTag);
}

recompute() {
dirty(this.dirtinessTag);
dirtyTag(this.dirtinessTag);
}

destroy() {}
Expand Down
8 changes: 4 additions & 4 deletions packages/@glimmer/integration-tests/lib/reference.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { RootReference, TemplateReferenceEnvironment } from '@glimmer/reference';
import { createUpdatableTag, dirty, UpdatableTag } from '@glimmer/validator';
import { createUpdatableTag, dirtyTag, UpdatableTag } from '@glimmer/validator';
import { Dict } from '@glimmer/interfaces';

/**
Expand All @@ -21,18 +21,18 @@ export class UpdatableRootReference<T = unknown> extends RootReference<T> {
let { inner } = this;

if (value !== inner) {
dirty(this.tag);
dirtyTag(this.tag);
this.inner = value;
}
}

forceUpdate(value: T) {
dirty(this.tag);
dirtyTag(this.tag);
this.inner = value;
}

dirty() {
dirty(this.tag);
dirtyTag(this.tag);
}

getDebugPath() {
Expand Down
12 changes: 6 additions & 6 deletions packages/@glimmer/reference/lib/reference.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Option, symbol } from '@glimmer/util';
import { Revision, Tag, Tagged, value, validate } from '@glimmer/validator';
import { Revision, Tag, Tagged, valueForTag, validateTag } from '@glimmer/validator';

export interface Reference<T> {
value(): T;
Expand Down Expand Up @@ -28,9 +28,9 @@ export abstract class CachedReference<T> implements VersionedReference<T> {
value(): T {
let { tag, lastRevision, lastValue } = this;

if (lastRevision === null || !validate(tag, lastRevision)) {
if (lastRevision === null || !validateTag(tag, lastRevision)) {
lastValue = this.lastValue = this.compute();
this.lastRevision = value(tag);
this.lastRevision = valueForTag(tag);
}

return lastValue as T;
Expand Down Expand Up @@ -74,11 +74,11 @@ export class ReferenceCache<T> implements Tagged {
let { reference, lastRevision } = this;
let tag = reference.tag;

if (validate(tag, lastRevision as number)) return NOT_MODIFIED;
if (validateTag(tag, lastRevision as number)) return NOT_MODIFIED;

let { lastValue } = this;
let currentValue = reference.value();
this.lastRevision = value(tag);
this.lastRevision = valueForTag(tag);

if (currentValue === lastValue) return NOT_MODIFIED;
this.lastValue = currentValue;
Expand All @@ -90,7 +90,7 @@ export class ReferenceCache<T> implements Tagged {
let { reference } = this;

let currentValue = (this.lastValue = reference.value());
this.lastRevision = value(reference.tag);
this.lastRevision = valueForTag(reference.tag);
this.initialized = true;

return currentValue;
Expand Down
28 changes: 14 additions & 14 deletions packages/@glimmer/reference/lib/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import {
combine,
createUpdatableTag,
UpdatableTag,
dirty,
update,
dirtyTag,
updateTag,
track,
Revision,
isConst,
isConstTag,
value,
validate,
valueForTag,
validateTag,
} from '@glimmer/validator';
import { VersionedPathReference } from './reference';
import { DEBUG } from '@glimmer/env';
Expand Down Expand Up @@ -160,15 +160,15 @@ export class HelperRootReference<T = unknown> extends RootReference<T> {
// If the args are constant, and the first computation is constant, then
// the helper itself is constant and will never update.
tag = this.tag = CONSTANT_TAG;
this.computeRevision = value(tag);
this.computeRevision = valueForTag(tag);
} else {
let valueTag = (this.valueTag = createUpdatableTag());
tag = this.tag = combine([args.tag, valueTag]);

if (computeTag !== null) {
// We computed once, so setup the cache state correctly
update(valueTag, computeTag);
this.computeRevision = value(tag);
updateTag(valueTag, computeTag);
this.computeRevision = valueForTag(tag);
}
}
}
Expand All @@ -182,10 +182,10 @@ export class HelperRootReference<T = unknown> extends RootReference<T> {
value(): T {
let { tag, computeRevision } = this;

if (computeRevision === null || !validate(tag, computeRevision)) {
if (computeRevision === null || !validateTag(tag, computeRevision)) {
this.compute();
update(this.valueTag!, this.computeTag!);
this.computeRevision = value(tag);
updateTag(this.valueTag!, this.computeTag!);
this.computeRevision = valueForTag(tag);
}

return this.computeValue!;
Expand Down Expand Up @@ -225,21 +225,21 @@ export class PropertyReference implements TemplatePathReference {
value() {
let { tag, lastRevision, lastValue, parentReference, valueTag, propertyKey } = this;

if (lastRevision === null || !validate(tag, lastRevision)) {
if (lastRevision === null || !validateTag(tag, lastRevision)) {
let parentValue = parentReference.value();

if (isDict(parentValue)) {
let combined = track(() => {
lastValue = this.env.getPath(parentValue, propertyKey);
}, DEBUG && this.env.getTemplatePathDebugContext(this));

update(valueTag, combined);
updateTag(valueTag, combined);
} else {
lastValue = undefined;
}

this.lastValue = lastValue;
this.lastRevision = value(tag);
this.lastRevision = valueForTag(tag);
}

return lastValue;
Expand Down Expand Up @@ -307,7 +307,7 @@ export class IterationItemReference<T = unknown> implements TemplatePathReferenc
}

update(value: T) {
dirty(this.tag);
dirtyTag(this.tag);
this.itemValue = value;
}

Expand Down
10 changes: 5 additions & 5 deletions packages/@glimmer/reference/test/references-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {
UpdatableTag,
createTag,
createUpdatableTag,
dirty,
update,
dirtyTag,
updateTag,
} from '@glimmer/validator';
import { dict } from '@glimmer/util';

Expand All @@ -24,7 +24,7 @@ class UpdatableRootReference<T> implements Reference<T> {
}

update(content: T) {
dirty(this._tag);
dirtyTag(this._tag);
return (this.content = content);
}
}
Expand All @@ -43,7 +43,7 @@ class TaggedDict<T> {
}

set(key: string, value: T) {
dirty(this._tag);
dirtyTag(this._tag);
return (this.data[key] = value);
}
}
Expand Down Expand Up @@ -125,7 +125,7 @@ QUnit.test('CachedReference caches nested computation correctly', assert => {

let dict = parent.value();

update(_tag, dict.tag);
updateTag(_tag, dict.tag);

return dict.get(key);
}
Expand Down
21 changes: 14 additions & 7 deletions packages/@glimmer/reference/test/template-test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { module, test } from './utils/qunit';

import { CONSTANT_TAG, createTag, consume, dirty, value, validate } from '@glimmer/validator';
import {
CONSTANT_TAG,
createTag,
consumeTag,
dirtyTag,
valueForTag,
validateTag,
} from '@glimmer/validator';

import {
ComponentRootReference,
Expand Down Expand Up @@ -81,7 +88,7 @@ module('@glimmer/reference: template', () => {
let tag = createTag();
let ref = new HelperRootReference(
() => {
consume(tag);
consumeTag(tag);
return 123;
},
EMPTY_ARGS,
Expand Down Expand Up @@ -152,12 +159,12 @@ module('@glimmer/reference: template', () => {
_foo: 123,

get foo() {
consume(tag);
consumeTag(tag);
return this._foo;
},

set foo(value) {
dirty(tag);
dirtyTag(tag);
this._foo = value;
},
};
Expand All @@ -167,12 +174,12 @@ module('@glimmer/reference: template', () => {
let fooRef = ref.get('foo');
assert.equal(fooRef.value(), component.foo);

let snapshot = value(fooRef.tag);
assert.equal(validate(fooRef.tag, snapshot), true);
let snapshot = valueForTag(fooRef.tag);
assert.equal(validateTag(fooRef.tag, snapshot), true);

component.foo = 234;

assert.equal(validate(fooRef.tag, snapshot), false);
assert.equal(validateTag(fooRef.tag, snapshot), false);
});

test('it correctly caches values', assert => {
Expand Down
14 changes: 7 additions & 7 deletions packages/@glimmer/runtime/lib/compiled/opcodes/dom.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Reference, ReferenceCache, VersionedReference } from '@glimmer/reference';
import { Revision, Tag, isConst, isConstTag, value, validate } from '@glimmer/validator';
import { Revision, Tag, isConst, isConstTag, valueForTag, validateTag } from '@glimmer/validator';
import { check, CheckString, CheckElement, CheckOption, CheckNode } from '@glimmer/debug';
import { Op, Option, ModifierManager } from '@glimmer/interfaces';
import { $t0 } from '@glimmer/vm';
Expand Down Expand Up @@ -134,15 +134,15 @@ export class UpdateModifierOpcode extends UpdatingOpcode {
private modifier: ModifierInstanceState
) {
super();
this.lastUpdated = value(tag);
this.lastUpdated = valueForTag(tag);
}

evaluate(vm: UpdatingVM) {
let { manager, modifier, tag, lastUpdated } = this;

if (!validate(tag, lastUpdated)) {
if (!validateTag(tag, lastUpdated)) {
vm.env.scheduleUpdateModifier(modifier, manager);
this.lastUpdated = value(tag);
this.lastUpdated = valueForTag(tag);
}
}
}
Expand Down Expand Up @@ -178,14 +178,14 @@ export class UpdateDynamicAttributeOpcode extends UpdatingOpcode {
super();
let { tag } = reference;
this.tag = tag;
this.lastRevision = value(tag);
this.lastRevision = valueForTag(tag);
}

evaluate(vm: UpdatingVM) {
let { attribute, reference, tag } = this;
if (!validate(tag, this.lastRevision)) {
if (!validateTag(tag, this.lastRevision)) {
attribute.update(reference.value(), vm.env);
this.lastRevision = value(tag);
this.lastRevision = valueForTag(tag);
}
}
}
8 changes: 4 additions & 4 deletions packages/@glimmer/runtime/lib/compiled/opcodes/vm.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CompilableTemplate, Option, Op } from '@glimmer/interfaces';
import { isModified, ReferenceCache } from '@glimmer/reference';
import { CONSTANT_TAG, isConst, Revision, Tag, value, validate } from '@glimmer/validator';
import { CONSTANT_TAG, isConst, Revision, Tag, valueForTag, validateTag } from '@glimmer/validator';
import { initializeGuid, assert, isHandle, HandleConstants, decodeHandle } from '@glimmer/util';
import {
CheckNumber,
Expand Down Expand Up @@ -252,19 +252,19 @@ export class JumpIfNotModifiedOpcode extends UpdatingOpcode {
constructor(tag: Tag, private target: LabelOpcode) {
super();
this.tag = tag;
this.lastRevision = value(tag);
this.lastRevision = valueForTag(tag);
}

evaluate(vm: UpdatingVM) {
let { tag, target, lastRevision } = this;

if (!vm.alwaysRevalidate && validate(tag, lastRevision)) {
if (!vm.alwaysRevalidate && validateTag(tag, lastRevision)) {
vm.goto(target);
}
}

didModify() {
this.lastRevision = value(this.tag);
this.lastRevision = valueForTag(this.tag);
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/@glimmer/runtime/lib/helpers/get-dynamic-var.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PathReference } from '@glimmer/reference';
import { Tag, UpdatableTag, combine, createUpdatableTag, update } from '@glimmer/validator';
import { Tag, UpdatableTag, combine, createUpdatableTag, updateTag } from '@glimmer/validator';
import { DynamicScope, VM as PublicVM, VMArguments, Helper } from '@glimmer/interfaces';

class DynamicVarReference implements PathReference<unknown> {
Expand All @@ -23,7 +23,7 @@ class DynamicVarReference implements PathReference<unknown> {
let name = String(this.nameRef.value());
let ref = this.scope.get(name);

update(this.varTag, ref.tag);
updateTag(this.varTag, ref.tag);

return ref;
}
Expand Down
8 changes: 4 additions & 4 deletions packages/@glimmer/runtime/lib/vm/content/text.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isEmpty, isString } from '../../dom/normalize';
import { UpdatingOpcode } from '../../opcodes';
import { VersionedReference } from '@glimmer/reference';
import { Tag, value, validate, Revision } from '@glimmer/validator';
import { Tag, valueForTag, validateTag, Revision } from '@glimmer/validator';
import { SimpleText } from '@simple-dom/interface';

export default class DynamicTextContent extends UpdatingOpcode {
Expand All @@ -17,14 +17,14 @@ export default class DynamicTextContent extends UpdatingOpcode {
) {
super();
this.tag = reference.tag;
this.lastRevision = value(this.tag);
this.lastRevision = valueForTag(this.tag);
}

evaluate() {
let { reference, tag } = this;

if (!validate(tag, this.lastRevision)) {
this.lastRevision = value(tag);
if (!validateTag(tag, this.lastRevision)) {
this.lastRevision = valueForTag(tag);
this.update(reference.value());
}
}
Expand Down
Loading

0 comments on commit 4bf27f7

Please sign in to comment.