diff --git a/packages/@glimmer/tracking/src/cached.ts b/packages/@glimmer/tracking/src/cached.ts index aa35d905f..df62c1821 100644 --- a/packages/@glimmer/tracking/src/cached.ts +++ b/packages/@glimmer/tracking/src/cached.ts @@ -1,5 +1,6 @@ import { DEBUG } from '@glimmer/env'; import { createCache, getValue } from '@glimmer/validator'; +import { CACHED } from './debug'; /** * @decorator @@ -87,6 +88,7 @@ export const cached: PropertyDecorator = (...args: any[]) => { return getValue(caches.get(this)); }; + (descriptor.get as any)[CACHED] = true; }; function throwCachedExtraneousParens(): never { diff --git a/packages/@glimmer/tracking/src/debug.ts b/packages/@glimmer/tracking/src/debug.ts new file mode 100644 index 000000000..5ea1a5a69 --- /dev/null +++ b/packages/@glimmer/tracking/src/debug.ts @@ -0,0 +1,15 @@ +export const TRACKED = Symbol('TRACKED') +export const CACHED = Symbol('CACHED') + +export function isTracked(obj: Object, key: string) { + const proto = Object.getPrototypeOf(obj); + const desc = Object.getOwnPropertyDescriptor(obj, key) || proto && Object.getOwnPropertyDescriptor(proto, key) + return desc.get && (desc.get as any)[TRACKED] || false; +} + + +export function isCached(obj: Object, key: string) { + const proto = Object.getPrototypeOf(obj); + const desc = Object.getOwnPropertyDescriptor(obj, key) || proto && Object.getOwnPropertyDescriptor(proto, key) + return desc.get && (desc.get as any)[CACHED] || false; +} diff --git a/packages/@glimmer/tracking/src/tracked.ts b/packages/@glimmer/tracking/src/tracked.ts index 85c7ffbc5..f57c67adc 100644 --- a/packages/@glimmer/tracking/src/tracked.ts +++ b/packages/@glimmer/tracking/src/tracked.ts @@ -1,5 +1,6 @@ import { DEBUG } from '@glimmer/env'; import { trackedData } from '@glimmer/validator'; +import { TRACKED } from './debug'; /** * @decorator @@ -129,18 +130,21 @@ function descriptorForField( const { getter, setter } = trackedData(key, desc && desc.initializer); + function get(this: T): any { + return getter(this) + } + + function set(this: T, newValue: any): void { + setter(this, newValue); + } + + (get as any)[TRACKED] = true; + return { enumerable: true, configurable: true, - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - get(this: T): any { - return getter(this); - }, - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - set(this: T, newValue: any): void { - setter(this, newValue); - }, + get, + set, }; } + diff --git a/packages/@glimmer/tracking/test/cached-decorator-test.ts b/packages/@glimmer/tracking/test/cached-decorator-test.ts index abf5aec4b..731b6dc11 100644 --- a/packages/@glimmer/tracking/test/cached-decorator-test.ts +++ b/packages/@glimmer/tracking/test/cached-decorator-test.ts @@ -1,4 +1,6 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { isCached, isTracked } from '../src/debug'; + const { test } = QUnit; import { DEBUG } from '@glimmer/env'; @@ -25,6 +27,13 @@ test('it works', function (assert) { } const person = new Person(); + + + test('cached properties can be detected for inspector', (assert) => { + assert.strictEqual(isCached(person, 'fullName'), true); + assert.strictEqual(isCached(person, 'lastName'), false); + }); + assert.verifySteps([], 'getter is not called after class initialization'); assert.strictEqual(person.fullName, 'Jen Weber'); diff --git a/packages/@glimmer/tracking/test/tracked-decorator-test.ts b/packages/@glimmer/tracking/test/tracked-decorator-test.ts index a827be5bd..e31f02d00 100644 --- a/packages/@glimmer/tracking/test/tracked-decorator-test.ts +++ b/packages/@glimmer/tracking/test/tracked-decorator-test.ts @@ -1,4 +1,6 @@ /* tslint:disable:no-unused-expression */ +import { isTracked } from '../src/debug'; + const { test } = QUnit; import { DEBUG } from '@glimmer/env'; @@ -23,6 +25,12 @@ import { assertValidAfterUnrelatedBump } from './helpers/tags'; assert.strictEqual(obj.firstName, 'Edsger'); }); + test('tracked properties can be detected for inspector', (assert) => { + const obj = new F.Toran(); + assert.strictEqual(isTracked(obj, 'firstName'), true); + assert.strictEqual(isTracked(obj, 'lastName'), false); + }); + test('can request a tag for a property', (assert) => { const obj = new F.Tom(); assert.strictEqual(obj.firstName, 'Tom');