Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 3 additions & 23 deletions packages/@ember/-internals/metal/lib/computed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ import toString from '@ember/-internals/utils/lib/to-string';
import inspect from '@ember/debug/lib/inspect';
import { assert } from '@ember/debug';
import { isDestroyed } from '@glimmer/destroyable';
import { DEBUG } from '@glimmer/env';
import type { UpdatableTag } from '@glimmer/interfaces';
import {
ALLOW_CYCLES,
UPDATE_TAG as updateTag,
validateTag,
valueForTag,
Expand Down Expand Up @@ -392,35 +389,27 @@ export class ComputedProperty extends ComputedDescriptor {
let meta = metaFor(obj);
let tagMeta = tagMetaFor(obj);

let propertyTag = tagFor(obj, keyName, tagMeta) as UpdatableTag;
let propertyTag = tagFor(obj, keyName, tagMeta);

let ret;

let revision = meta.revisionFor(keyName);

if (revision !== undefined && validateTag(propertyTag, revision)) {
ret = meta.valueFor(keyName);
} else {
// For backwards compatibility, we only throw if the CP has any dependencies. CPs without dependencies
// should be allowed, even after the object has been destroyed, which is why we check _dependentKeys.
assert(
`Attempted to access the computed ${obj}.${keyName} on a destroyed object, which is not allowed`,
this._dependentKeys === undefined || !isDestroyed(obj)
);

let { _getter, _dependentKeys } = this;

// Create a tracker that absorbs any trackable actions inside the CP
untrack(() => {
ret = _getter!.call(obj, keyName);
});

if (_dependentKeys !== undefined) {
updateTag(propertyTag, getChainTagsForKeys(obj, _dependentKeys, tagMeta, meta));

if (DEBUG) {
ALLOW_CYCLES!.set(propertyTag, true);
}
}

meta.setValueFor(keyName, ret);
Expand Down Expand Up @@ -489,16 +478,11 @@ export class ComputedProperty extends ComputedDescriptor {
finishLazyChains(meta, keyName, ret);

let tagMeta = tagMetaFor(obj);
let propertyTag = tagFor(obj, keyName, tagMeta) as UpdatableTag;
let propertyTag = tagFor(obj, keyName, tagMeta);

let { _dependentKeys } = this;

if (_dependentKeys !== undefined) {
updateTag(propertyTag, getChainTagsForKeys(obj, _dependentKeys, tagMeta, meta));

if (DEBUG) {
ALLOW_CYCLES!.set(propertyTag, true);
}
}

meta.setRevisionFor(keyName, valueForTag(propertyTag));
Expand Down Expand Up @@ -556,10 +540,9 @@ class AutoComputedProperty extends ComputedProperty {
let meta = metaFor(obj);
let tagMeta = tagMetaFor(obj);

let propertyTag = tagFor(obj, keyName, tagMeta) as UpdatableTag;
let propertyTag = tagFor(obj, keyName, tagMeta);

let ret;

let revision = meta.revisionFor(keyName);

if (revision !== undefined && validateTag(propertyTag, revision)) {
Expand All @@ -572,7 +555,6 @@ class AutoComputedProperty extends ComputedProperty {

let { _getter } = this;

// Create a tracker that absorbs any trackable actions inside the CP
let tag = track(() => {
ret = _getter!.call(obj, keyName);
});
Expand All @@ -587,8 +569,6 @@ class AutoComputedProperty extends ComputedProperty {

consumeTag(propertyTag);

// Add the tag of the returned value if it is an array, since arrays
// should always cause updates if they are consumed and then changed
if (Array.isArray(ret)) {
consumeTag(tagFor(ret, '[]', tagMeta));
}
Expand Down
62 changes: 8 additions & 54 deletions packages/@glimmer/interfaces/lib/tags.d.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,11 @@
declare const TYPE: unique symbol;
export type TagTypeSymbol = typeof TYPE;

declare const COMPUTE: unique symbol;
export type TagComputeSymbol = typeof COMPUTE;

export type DIRTYABLE_TAG_ID = 0;
export type UPDATABLE_TAG_ID = 1;
export type COMBINATOR_TAG_ID = 2;
export type CONSTANT_TAG_ID = 3;

/**
* This union represents all of the possible tag types for the monomorphic tag class.
* Other custom tag classes can exist, such as CurrentTag and VolatileTag, but for
* performance reasons, any type of tag that is meant to be used frequently should
* be added to the monomorphic tag.
*/
export type MonomorphicTagId =
| DIRTYABLE_TAG_ID
| UPDATABLE_TAG_ID
| COMBINATOR_TAG_ID
| CONSTANT_TAG_ID;

export type VOLATILE_TAG_ID = 100;
export type CURRENT_TAG_ID = 101;

export type PolymorphicTagId = VOLATILE_TAG_ID | CURRENT_TAG_ID;

export type TagId = MonomorphicTagId | PolymorphicTagId;

export type Revision = number;

export interface Tag {
readonly [TYPE]: TagId;
readonly subtag?: Tag | Tag[] | null | undefined;
[COMPUTE](): Revision;
}

export interface MonomorphicTag extends Tag {
readonly [TYPE]: MonomorphicTagId;
}

export interface UpdatableTag extends MonomorphicTag {
readonly [TYPE]: UPDATABLE_TAG_ID;
}

export interface DirtyableTag extends MonomorphicTag {
readonly [TYPE]: DIRTYABLE_TAG_ID;
}

export interface ConstantTag extends MonomorphicTag {
readonly [TYPE]: CONSTANT_TAG_ID;
}
// A Tag is just a callable that returns the current revision. Reading it
// inside an alien-signals subscriber registers a dependency.
export type Tag = () => Revision;

export interface CombinatorTag extends MonomorphicTag {
readonly [TYPE]: COMBINATOR_TAG_ID;
}
export type MonomorphicTag = Tag;
export type UpdatableTag = Tag;
export type DirtyableTag = Tag;
export type ConstantTag = Tag;
export type CombinatorTag = Tag;
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,11 @@ import {
wrap,
} from '@glimmer/debug/lib/stack-check';
import { REFERENCE, UNDEFINED_REFERENCE } from '@glimmer/reference/lib/reference';
import { COMPUTE } from '@glimmer/validator/lib/validators';

import { ScopeImpl } from '../../scope';
import { VMArgumentsImpl } from '../../vm/arguments';
import { ComponentElementOperations } from './component';

export const CheckTag: Checker<Tag> = CheckInterface({
[COMPUTE]: CheckFunction,
});
export const CheckTag: Checker<Tag> = CheckFunction as unknown as Checker<Tag>;

export const CheckOperations: Checker<Nullable<ComponentElementOperations>> = wrap(() =>
CheckNullable(CheckInstanceof(ComponentElementOperations))
Expand Down
6 changes: 0 additions & 6 deletions packages/@glimmer/validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,20 @@ export {
untrack,
} from './lib/tracking';
export {
ALLOW_CYCLES,
bump,
combine,
COMPUTE,
CONSTANT,
CONSTANT_TAG,
createTag,
createUpdatableTag,
CURRENT_TAG,
CurrentTag,
DIRTY_TAG as dirtyTag,
INITIAL,
isConstTag,
type Revision,
UPDATE_TAG as updateTag,
validateTag,
valueForTag,
VOLATILE,
VOLATILE_TAG,
VolatileTag,
} from './lib/validators';
export type {
CombinatorTag,
Expand Down
4 changes: 2 additions & 2 deletions packages/@glimmer/validator/lib/meta.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DEBUG } from '@glimmer/env';
import type { ConstantTag, UpdatableTag } from '@glimmer/interfaces';
import type { UpdatableTag } from '@glimmer/interfaces';

import type { Indexable } from './utils';

Expand Down Expand Up @@ -59,7 +59,7 @@ export function tagFor<T extends object>(
obj: T,
key: keyof T | string | symbol,
meta?: TagMeta
): UpdatableTag | ConstantTag {
): UpdatableTag {
let tags = meta === undefined ? tagMetaFor(obj) : meta;
let tag = tags.get(key);

Expand Down
Loading
Loading