From 823a326f1a48ff3656cafca0e3f2f7c0ab340359 Mon Sep 17 00:00:00 2001 From: Chris Garrett Date: Fri, 26 Apr 2019 16:08:27 -0700 Subject: [PATCH 1/5] [FEATURE beta] Various bugfixes and perf improvements including: - No longer fetching leaf nodes when traversing chains - No longer creating arrays when traversing chains - Correctly memoizing alias tag chains - Adding `untrack` to fully ignore trackable contexts - Using a map instead of an array for lazy tag chains - Flattening tag chains --- packages/@ember/-internals/meta/lib/meta.ts | 2 +- packages/@ember/-internals/metal/lib/alias.ts | 25 ++++-- .../@ember/-internals/metal/lib/chain-tags.ts | 77 ++++++++++------ .../@ember/-internals/metal/lib/computed.ts | 90 +++++++++---------- .../@ember/-internals/metal/lib/observer.ts | 12 +-- .../@ember/-internals/metal/lib/tracked.ts | 11 +++ .../-internals/metal/tests/observer_test.js | 1 + .../-internals/runtime/lib/mixins/-proxy.js | 2 +- .../runtime/lib/system/array_proxy.js | 5 +- .../tests/system/object/computed_test.js | 27 ++++++ .../computed/dependent-key-compat-test.js | 3 + 11 files changed, 165 insertions(+), 90 deletions(-) diff --git a/packages/@ember/-internals/meta/lib/meta.ts b/packages/@ember/-internals/meta/lib/meta.ts index 867d3488317..40d88bf0c00 100644 --- a/packages/@ember/-internals/meta/lib/meta.ts +++ b/packages/@ember/-internals/meta/lib/meta.ts @@ -368,7 +368,7 @@ export class Meta { let lazyChains = this._getOrCreateOwnMap('_lazyChains'); if (!(key in lazyChains)) { - lazyChains[key] = []; + lazyChains[key] = Object.create(null); } return lazyChains[key]; diff --git a/packages/@ember/-internals/metal/lib/alias.ts b/packages/@ember/-internals/metal/lib/alias.ts index 2788e86ea0c..82aeaec7f88 100644 --- a/packages/@ember/-internals/metal/lib/alias.ts +++ b/packages/@ember/-internals/metal/lib/alias.ts @@ -3,8 +3,14 @@ import { inspect } from '@ember/-internals/utils'; import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import { assert } from '@ember/debug'; import EmberError from '@ember/error'; +import { combine } from '@glimmer/reference'; import { finishLazyChains, getChainTagsForKey } from './chain-tags'; -import { getCachedValueFor, getCacheFor, setLastRevisionFor } from './computed_cache'; +import { + getCachedValueFor, + getCacheFor, + getLastRevisionFor, + setLastRevisionFor, +} from './computed_cache'; import { addDependentKeys, ComputedDescriptor, @@ -18,7 +24,7 @@ import { defineProperty } from './properties'; import { get } from './property_get'; import { set } from './property_set'; import { tagForProperty, update } from './tags'; -import { consume, track } from './tracked'; +import { consume, untrack } from './tracked'; const CONSUMED = Object.freeze({}); @@ -98,16 +104,19 @@ export class AliasedProperty extends ComputedDescriptor { // We don't use the tag since CPs are not automatic, we just want to avoid // anything tracking while we get the altKey - track(() => { + untrack(() => { ret = get(obj, this.altKey); }); - let altPropertyTag = getChainTagsForKey(obj, this.altKey); - update(propertyTag, altPropertyTag); - consume(propertyTag); + let lastRevision = getLastRevisionFor(obj, keyName); - finishLazyChains(obj, keyName, ret); - setLastRevisionFor(obj, keyName, propertyTag.value()); + if (!propertyTag.validate(lastRevision)) { + update(propertyTag, combine(getChainTagsForKey(obj, this.altKey))); + setLastRevisionFor(obj, keyName, propertyTag.value()); + finishLazyChains(obj, keyName, ret); + } + + consume(propertyTag); } else { ret = get(obj, this.altKey); this.consume(obj, keyName, metaFor(obj)); diff --git a/packages/@ember/-internals/metal/lib/chain-tags.ts b/packages/@ember/-internals/metal/lib/chain-tags.ts index d6e17da1723..63d34f46200 100644 --- a/packages/@ember/-internals/metal/lib/chain-tags.ts +++ b/packages/@ember/-internals/metal/lib/chain-tags.ts @@ -6,7 +6,7 @@ import { getLastRevisionFor, peekCacheFor } from './computed_cache'; import { descriptorForProperty } from './descriptor_map'; import get from './property_get'; import { tagForProperty } from './tags'; -import { track } from './tracked'; +import { untrack } from './tracked'; export const ARGS_PROXY_TAGS = new WeakMap(); @@ -19,14 +19,18 @@ export function finishLazyChains(obj: any, key: string, value: any) { } if (value === null || (typeof value !== 'object' && typeof value !== 'function')) { - lazyTags.length = 0; + for (let path in lazyTags) { + delete lazyTags[path]; + } return; } - while (lazyTags.length > 0) { - let [path, tag] = lazyTags.pop()!; + for (let path in lazyTags) { + let tag = lazyTags[path]; + + tag.inner.update(combine(getChainTagsForKey(value, path))); - tag.inner.update(getChainTagsForKey(value, path)); + delete lazyTags[path]; } } @@ -34,22 +38,22 @@ export function getChainTagsForKeys(obj: any, keys: string[]) { let chainTags: Tag[] = []; for (let i = 0; i < keys.length; i++) { - chainTags.push(getChainTagsForKey(obj, keys[i])); + chainTags.push(...getChainTagsForKey(obj, keys[i])); } - return combine(chainTags); + return chainTags; } -export function getChainTagsForKey(obj: any, key: string) { +export function getChainTagsForKey(obj: any, path: string) { let chainTags: Tag[] = []; let current: any = obj; - let segments = key.split('.'); + let segmentEnd = -1; // prevent closures let segment: string, descriptor: any; - while (segments.length > 0) { + while (true) { let currentType = typeof current; if (current === null || (currentType !== 'object' && currentType !== 'function')) { @@ -57,15 +61,28 @@ export function getChainTagsForKey(obj: any, key: string) { break; } - segment = segments.shift()!; + let lastSegmentEnd = segmentEnd + 1; + segmentEnd = path.indexOf('.', lastSegmentEnd); + + if (segmentEnd === -1) { + segmentEnd = path.length; + } + + segment = path.slice(lastSegmentEnd, segmentEnd); - if (segment === '@each' && segments.length > 0) { + if (segment === '@each' && segmentEnd !== path.length) { assert( `When using @each, the value you are attempting to watch must be an array, was: ${current.toString()}`, Array.isArray(current) || isEmberArray(current) ); - segment = segments.shift()!; + segment = path.substr(segmentEnd + 1)!; + + // There shouldn't be any more segments after an `@each`, so break + assert( + `When using @each, you can only chain one property level deep`, + segment.indexOf('.') === -1 + ); // Push the tags for each item's property let tags = (current as Array).map(item => { @@ -80,28 +97,26 @@ export function getChainTagsForKey(obj: any, key: string) { // Push the tag for the array length itself chainTags.push(...tags, tagForProperty(current, '[]')); - // There shouldn't be any more segments after an `@each`, so break - assert(`When using @each, you can only chain one property level deep`, segments.length === 0); - break; } if (segment === 'args' && ARGS_PROXY_TAGS.has(current.args)) { assert( `When watching the 'args' on a GlimmerComponent, you must watch a value on the args. You cannot watch the object itself, as it never changes.`, - segments.length > 0 + segmentEnd !== path.length ); - segment = segments.shift()!; + segment = path.substr(segmentEnd + 1)!; + segmentEnd = path.indexOf('.', segmentEnd); let namedArgs = ARGS_PROXY_TAGS.get(current.args); let ref = namedArgs.get(segment); chainTags.push(ref.tag); - if (segments.length > 0) { + if (segmentEnd !== -1) { current = ref.value(); - segment = segments.shift()!; + segment = path.substr(segmentEnd + 1); continue; } } @@ -110,6 +125,10 @@ export function getChainTagsForKey(obj: any, key: string) { chainTags.push(propertyTag); + if (segmentEnd === path.length) { + break; + } + descriptor = descriptorForProperty(current, segment); if (descriptor === undefined) { @@ -126,18 +145,22 @@ export function getChainTagsForKey(obj: any, key: string) { if (propertyTag.validate(lastRevision)) { if (typeof descriptor.altKey === 'string') { // it's an alias, so just get the altkey without tracking - track(() => { + untrack(() => { current = get(current, descriptor.altKey); }); } else { current = peekCacheFor(current).get(segment); } - } else if (segments.length > 0) { - let placeholderTag = UpdatableTag.create(CONSTANT_TAG); + } else { + let lazyChains = metaFor(current).writableLazyChainsFor(segment); + + let rest = path.substr(segmentEnd + 1); - metaFor(current) - .writableLazyChainsFor(segment) - .push([segments.join('.'), placeholderTag]); + let placeholderTag = lazyChains[rest]; + + if (placeholderTag === undefined) { + placeholderTag = lazyChains[rest] = UpdatableTag.create(CONSTANT_TAG); + } chainTags.push(placeholderTag); @@ -146,5 +169,5 @@ export function getChainTagsForKey(obj: any, key: string) { } } - return combine(chainTags); + return chainTags; } diff --git a/packages/@ember/-internals/metal/lib/computed.ts b/packages/@ember/-internals/metal/lib/computed.ts index 83dc6078b13..e694ee0226f 100644 --- a/packages/@ember/-internals/metal/lib/computed.ts +++ b/packages/@ember/-internals/metal/lib/computed.ts @@ -32,7 +32,7 @@ import { defineProperty } from './properties'; import { beginPropertyChanges, endPropertyChanges, notifyPropertyChange } from './property_events'; import { set } from './property_set'; import { tagForProperty, update } from './tags'; -import { consume, track } from './tracked'; +import { consume, track, untrack } from './tracked'; export type ComputedPropertyGetter = (keyName: string) => any; export type ComputedPropertySetter = (keyName: string, value: any, cachedValue?: any) => any; @@ -522,52 +522,46 @@ export class ComputedProperty extends ComputedDescriptor { if (EMBER_METAL_TRACKED_PROPERTIES) { propertyTag = tagForProperty(obj, keyName); - if (cache.has(keyName)) { - let lastRevision = getLastRevisionFor(obj, keyName); - - if (propertyTag.validate(lastRevision)) { - return cache.get(keyName); - } - } - } else { - if (cache.has(keyName)) { - return cache.get(keyName); - } - } - - let ret; + let ret; - if (EMBER_METAL_TRACKED_PROPERTIES) { - // 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 || !metaFor(obj).isMetaDestroyed() - ); + if (cache.has(keyName) && propertyTag.validate(getLastRevisionFor(obj, keyName))) { + ret = cache.get(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 || !metaFor(obj).isMetaDestroyed() + ); - // Create a tracker that absorbs any trackable actions inside the CP - let tag = track(() => { - ret = this._getter!.call(obj, keyName); - }); + let upstreamTag: Tag | undefined = undefined; + + if (this._auto === true) { + upstreamTag = track(() => { + ret = this._getter!.call(obj, keyName); + }); + } else { + // Create a tracker that absorbs any trackable actions inside the CP + untrack(() => { + ret = this._getter!.call(obj, keyName); + }); + } - finishLazyChains(obj, keyName, ret); + finishLazyChains(obj, keyName, ret); - let upstreamTags: Tag[] = []; + if (this._dependentKeys !== undefined) { + let tag = combine(getChainTagsForKeys(obj, this._dependentKeys)); - if (this._auto === true) { - upstreamTags.push(tag); - } + upstreamTag = upstreamTag === undefined ? tag : combine([upstreamTag, tag]); + } - if (this._dependentKeys !== undefined) { - upstreamTags.push(getChainTagsForKeys(obj, this._dependentKeys)); - } + if (upstreamTag !== undefined) { + update(propertyTag!, upstreamTag); + } - if (upstreamTags.length > 0) { - update(propertyTag!, combine(upstreamTags)); + setLastRevisionFor(obj, keyName, propertyTag!.value()); } - setLastRevisionFor(obj, keyName, propertyTag!.value()); - consume(propertyTag!); // Add the tag of the returned value if it is an array, since arrays @@ -575,22 +569,28 @@ export class ComputedProperty extends ComputedDescriptor { if (Array.isArray(ret) || isEmberArray(ret)) { consume(tagForProperty(ret, '[]')); } + + cache.set(keyName, ret); + + return ret; } else { - ret = this._getter!.call(obj, keyName); - } + if (cache.has(keyName)) { + return cache.get(keyName); + } - cache.set(keyName, ret); + let ret = this._getter!.call(obj, keyName); + + cache.set(keyName, ret); - if (!EMBER_METAL_TRACKED_PROPERTIES) { let meta = metaFor(obj); let chainWatchers = meta.readableChainWatchers(); if (chainWatchers !== undefined) { chainWatchers.revalidate(keyName); } addDependentKeys(this, obj, keyName, meta); - } - return ret; + return ret; + } } set(obj: object, keyName: string, value: any): any { @@ -618,7 +618,7 @@ export class ComputedProperty extends ComputedDescriptor { let propertyTag = tagForProperty(obj, keyName); if (this._dependentKeys !== undefined) { - update(propertyTag, getChainTagsForKeys(obj, this._dependentKeys)); + update(propertyTag, combine(getChainTagsForKeys(obj, this._dependentKeys))); } setLastRevisionFor(obj, keyName, propertyTag.value()); diff --git a/packages/@ember/-internals/metal/lib/observer.ts b/packages/@ember/-internals/metal/lib/observer.ts index 973ce28eebf..aa7dca33c70 100644 --- a/packages/@ember/-internals/metal/lib/observer.ts +++ b/packages/@ember/-internals/metal/lib/observer.ts @@ -2,7 +2,7 @@ import { ENV } from '@ember/-internals/environment'; import { peekMeta } from '@ember/-internals/meta'; import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import { schedule } from '@ember/runloop'; -import { CURRENT_TAG, Tag } from '@glimmer/reference'; +import { combine, CURRENT_TAG, Tag } from '@glimmer/reference'; import { getChainTagsForKey } from './chain-tags'; import changeEvent from './change_event'; import { addListener, removeListener, sendEvent } from './events'; @@ -105,7 +105,7 @@ export function activateObserver(target: object, eventName: string, sync = false activeObservers.get(eventName)!.count++; } else { let [path] = eventName.split(':'); - let tag = getChainTagsForKey(target, path); + let tag = combine(getChainTagsForKey(target, path)); activeObservers.set(eventName, { count: 1, @@ -147,14 +147,14 @@ export function deactivateObserver(target: object, eventName: string, sync = fal export function revalidateObservers(target: object) { if (ASYNC_OBSERVERS.has(target)) { ASYNC_OBSERVERS.get(target)!.forEach(observer => { - observer.tag = getChainTagsForKey(target, observer.path); + observer.tag = combine(getChainTagsForKey(target, observer.path)); observer.lastRevision = observer.tag.value(); }); } if (SYNC_OBSERVERS.has(target)) { SYNC_OBSERVERS.get(target)!.forEach(observer => { - observer.tag = getChainTagsForKey(target, observer.path); + observer.tag = combine(getChainTagsForKey(target, observer.path)); observer.lastRevision = observer.tag.value(); }); } @@ -183,7 +183,7 @@ export function flushAsyncObservers() { try { sendEvent(target, eventName, [target, observer.path]); } finally { - observer.tag = getChainTagsForKey(target, observer.path); + observer.tag = combine(getChainTagsForKey(target, observer.path)); observer.lastRevision = observer.tag.value(); } }); @@ -212,7 +212,7 @@ export function flushSyncObservers() { sendEvent(target, eventName, [target, observer.path]); } finally { observer.suspended = false; - observer.tag = getChainTagsForKey(target, observer.path); + observer.tag = combine(getChainTagsForKey(target, observer.path)); observer.lastRevision = observer.tag.value(); } } diff --git a/packages/@ember/-internals/metal/lib/tracked.ts b/packages/@ember/-internals/metal/lib/tracked.ts index 15fd76c9289..c70fac74e40 100644 --- a/packages/@ember/-internals/metal/lib/tracked.ts +++ b/packages/@ember/-internals/metal/lib/tracked.ts @@ -268,6 +268,17 @@ export function isTracking() { return CURRENT_TRACKER !== null; } +export function untrack(callback: () => void) { + let parent = CURRENT_TRACKER; + CURRENT_TRACKER = null; + + try { + callback(); + } finally { + CURRENT_TRACKER = parent; + } +} + export type Key = string; export interface Interceptors { diff --git a/packages/@ember/-internals/metal/tests/observer_test.js b/packages/@ember/-internals/metal/tests/observer_test.js index b66a576577c..19a7c87817e 100644 --- a/packages/@ember/-internals/metal/tests/observer_test.js +++ b/packages/@ember/-internals/metal/tests/observer_test.js @@ -15,6 +15,7 @@ import { changeProperties, get, set, + alias, } from '..'; import { moduleFor, AbstractTestCase, runLoopSettled } from 'internal-test-helpers'; import { FUNCTION_PROTOTYPE_EXTENSIONS } from '@ember/deprecated-features'; diff --git a/packages/@ember/-internals/runtime/lib/mixins/-proxy.js b/packages/@ember/-internals/runtime/lib/mixins/-proxy.js index a2ae8c7fb48..2ed537a9787 100644 --- a/packages/@ember/-internals/runtime/lib/mixins/-proxy.js +++ b/packages/@ember/-internals/runtime/lib/mixins/-proxy.js @@ -88,7 +88,7 @@ export default Mixin.create({ }, [UNKNOWN_PROPERTY_TAG](key) { - return getChainTagsForKey(this, `content.${key}`); + return combine(getChainTagsForKey(this, `content.${key}`)); }, unknownProperty(key) { diff --git a/packages/@ember/-internals/runtime/lib/system/array_proxy.js b/packages/@ember/-internals/runtime/lib/system/array_proxy.js index 2a81ad00a0a..2e33e2031a3 100644 --- a/packages/@ember/-internals/runtime/lib/system/array_proxy.js +++ b/packages/@ember/-internals/runtime/lib/system/array_proxy.js @@ -16,6 +16,7 @@ import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import EmberObject from './object'; import { isArray, MutableArray } from '../mixins/array'; import { assert } from '@ember/debug'; +import { combine } from '@glimmer/reference'; const ARRAY_OBSERVER_MAPPING = { willChange: '_arrangedContentArrayWillChange', @@ -106,7 +107,7 @@ export default class ArrayProxy extends EmberObject { if (EMBER_METAL_TRACKED_PROPERTIES) { this._arrangedContentIsUpdating = false; - this._arrangedContentTag = getChainTagsForKey(this, 'arrangedContent'); + this._arrangedContentTag = combine(getChainTagsForKey(this, 'arrangedContent')); this._arrangedContentRevision = this._arrangedContentTag.value(); } @@ -318,7 +319,7 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { this._updateArrangedContentArray(); this._arrangedContentIsUpdating = false; - this._arrangedContentTag = getChainTagsForKey(this, 'arrangedContent'); + this._arrangedContentTag = combine(getChainTagsForKey(this, 'arrangedContent')); this._arrangedContentRevision = this._arrangedContentTag.value(); } }; diff --git a/packages/@ember/-internals/runtime/tests/system/object/computed_test.js b/packages/@ember/-internals/runtime/tests/system/object/computed_test.js index 7bbf03b4bfd..3c01e196311 100644 --- a/packages/@ember/-internals/runtime/tests/system/object/computed_test.js +++ b/packages/@ember/-internals/runtime/tests/system/object/computed_test.js @@ -7,6 +7,7 @@ import { observer, defineProperty, } from '@ember/-internals/metal'; +import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import { oneWay as reads } from '@ember/object/computed'; import EmberObject from '../../../lib/system/object'; import { moduleFor, AbstractTestCase } from 'internal-test-helpers'; @@ -376,5 +377,31 @@ moduleFor( assert.equal(obj.get('foo'), 2); } + + ['@test native getters and setters work'](assert) { + if (!EMBER_METAL_TRACKED_PROPERTIES) { + return assert.expect(0); + } + + let MyClass = EmberObject.extend({ + bar: 123, + + foo: computed({ + get() { + return this.bar; + }, + + set(key, value) { + this.bar = value; + }, + }), + }); + + let instance = MyClass.create(); + + assert.equal(instance.foo, 123, 'getters work'); + instance.foo = 456; + assert.equal(instance.bar, 456, 'setters work'); + } } ); diff --git a/packages/@ember/object/tests/computed/dependent-key-compat-test.js b/packages/@ember/object/tests/computed/dependent-key-compat-test.js index f2541b6d30b..561645f9adf 100644 --- a/packages/@ember/object/tests/computed/dependent-key-compat-test.js +++ b/packages/@ember/object/tests/computed/dependent-key-compat-test.js @@ -85,6 +85,9 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { assert.equal(count, 0); + // check the alias, and bootstrap it + assert.equal(tom.givenName, 'Tom', 'alias works'); + tom.firstName = 'Thomas'; await runLoopSettled(); From d7f3cda038bd86edcb2bdbe170240fadbbbf9026 Mon Sep 17 00:00:00 2001 From: Chris Garrett Date: Sun, 21 Jul 2019 17:23:39 -0700 Subject: [PATCH 2/5] [FEATURE beta] Update to functional tag API Updates to the latest version of Glimmer with the functional tag API and perf improvements/tuning. --- package.json | 14 +- .../glimmer/lib/component-managers/curly.ts | 6 +- .../glimmer/lib/component-managers/mount.ts | 8 +- .../-internals/glimmer/lib/component.ts | 6 +- .../@ember/-internals/glimmer/lib/helper.ts | 6 +- .../-internals/glimmer/lib/helpers/get.ts | 10 +- .../glimmer/lib/helpers/if-unless.ts | 8 +- .../@ember/-internals/glimmer/lib/renderer.ts | 8 +- .../lib/utils/curly-component-state-bucket.ts | 4 +- .../-internals/glimmer/lib/utils/iterable.ts | 12 +- .../-internals/glimmer/lib/utils/outlet.ts | 13 +- .../glimmer/lib/utils/references.ts | 83 ++++---- packages/@ember/-internals/meta/lib/meta.ts | 16 +- packages/@ember/-internals/metal/index.ts | 8 +- packages/@ember/-internals/metal/lib/alias.ts | 10 +- .../@ember/-internals/metal/lib/chain-tags.ts | 8 +- .../@ember/-internals/metal/lib/computed.ts | 23 +- .../@ember/-internals/metal/lib/observer.ts | 20 +- packages/@ember/-internals/metal/lib/tags.ts | 47 +---- .../@ember/-internals/metal/lib/tracked.ts | 6 +- .../-internals/metal/tests/alias_test.js | 17 +- .../tests/tracked/classic_classes_test.js | 15 +- .../metal/tests/tracked/validation_test.js | 107 +++++----- .../-internals/runtime/lib/mixins/-proxy.js | 6 +- .../runtime/lib/system/array_proxy.js | 8 +- packages/@ember/object/compat.ts | 4 +- yarn.lock | 198 +++++++++--------- 27 files changed, 323 insertions(+), 348 deletions(-) diff --git a/package.json b/package.json index e6fac211500..4b250e6a968 100644 --- a/package.json +++ b/package.json @@ -94,14 +94,14 @@ "@babel/plugin-transform-shorthand-properties": "^7.2.0", "@babel/plugin-transform-spread": "^7.2.2", "@babel/plugin-transform-template-literals": "^7.4.4", - "@glimmer/compiler": "0.38.5-alpha.1", + "@glimmer/compiler": "0.38.5-alpha.2", "@glimmer/env": "^0.1.7", - "@glimmer/interfaces": "0.38.5-alpha.1", - "@glimmer/node": "0.38.5-alpha.1", - "@glimmer/opcode-compiler": "0.38.5-alpha.1", - "@glimmer/program": "0.38.5-alpha.1", - "@glimmer/reference": "0.38.5-alpha.1", - "@glimmer/runtime": "0.38.5-alpha.1", + "@glimmer/interfaces": "0.38.5-alpha.2", + "@glimmer/node": "0.38.5-alpha.2", + "@glimmer/opcode-compiler": "0.38.5-alpha.2", + "@glimmer/program": "0.38.5-alpha.2", + "@glimmer/reference": "0.38.5-alpha.2", + "@glimmer/runtime": "0.38.5-alpha.2", "@types/qunit": "^2.5.4", "@types/rsvp": "^4.0.2", "auto-dist-tag": "^1.0.0", diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts b/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts index 63981fe7c94..376f8e5ce51 100644 --- a/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts +++ b/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts @@ -19,7 +19,7 @@ import { Simple, VMHandle, } from '@glimmer/interfaces'; -import { combine, Tag, VersionedPathReference } from '@glimmer/reference'; +import { combine, Tag, validate, value, VersionedPathReference } from '@glimmer/reference'; import { Arguments, Bounds, @@ -414,10 +414,10 @@ export default class CurlyComponentManager bucket.finalizer = _instrumentStart('render.component', rerenderInstrumentDetails, component); - if (args && !args.tag.validate(argsRevision)) { + if (args && !validate(args.tag, argsRevision)) { let props = processComponentArgs(args!); - bucket.argsRevision = args!.tag.value(); + bucket.argsRevision = value(args!.tag); component[IS_DISPATCHING_ATTRS] = true; component.setProperties(props); diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/mount.ts b/packages/@ember/-internals/glimmer/lib/component-managers/mount.ts index 0d6e554993b..35a35432b07 100644 --- a/packages/@ember/-internals/glimmer/lib/component-managers/mount.ts +++ b/packages/@ember/-internals/glimmer/lib/component-managers/mount.ts @@ -1,6 +1,6 @@ import { DEBUG } from '@glimmer/env'; import { ComponentCapabilities } from '@glimmer/interfaces'; -import { CONSTANT_TAG, Tag, VersionedPathReference } from '@glimmer/reference'; +import { CONSTANT_TAG, Tag, validate, value, VersionedPathReference } from '@glimmer/reference'; import { ComponentDefinition, Invocation, WithDynamicLayout } from '@glimmer/runtime'; import { Destroyable, Opaque, Option } from '@glimmer/util'; @@ -96,7 +96,7 @@ class MountManager bucket = { engine, controller, self, tag }; } else { let model = modelRef.value(); - let modelRev = modelRef.tag.value(); + let modelRev = value(modelRef.tag); controller = controllerFactory.create({ model }); self = new RootReference(controller); tag = modelRef.tag; @@ -126,9 +126,9 @@ class MountManager update(bucket: EngineWithModelState): void { let { controller, modelRef, modelRev } = bucket; - if (!modelRef.tag.validate(modelRev!)) { + if (!validate(modelRef.tag, modelRev!)) { let model = modelRef.value(); - bucket.modelRev = modelRef.tag.value(); + bucket.modelRev = value(modelRef.tag); controller.set('model', model); } } diff --git a/packages/@ember/-internals/glimmer/lib/component.ts b/packages/@ember/-internals/glimmer/lib/component.ts index a44995007ab..6c548ef6487 100644 --- a/packages/@ember/-internals/glimmer/lib/component.ts +++ b/packages/@ember/-internals/glimmer/lib/component.ts @@ -13,7 +13,7 @@ import { } from '@ember/-internals/views'; import { assert, deprecate } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; -import { DirtyableTag } from '@glimmer/reference'; +import { createTag, dirty } from '@glimmer/reference'; import { normalizeProperty, SVG_NAMESPACE } from '@glimmer/runtime'; import { RootReference, UPDATE } from './utils/references'; @@ -721,7 +721,7 @@ const Component = CoreView.extend( init() { this._super(...arguments); this[IS_DISPATCHING_ATTRS] = false; - this[DIRTY_TAG] = DirtyableTag.create(); + this[DIRTY_TAG] = createTag(); this[ROOT_REF] = new RootReference(this); this[BOUNDS] = null; @@ -776,7 +776,7 @@ const Component = CoreView.extend( }, rerender() { - this[DIRTY_TAG].inner.dirty(); + dirty(this[DIRTY_TAG]); this._super(); }, diff --git a/packages/@ember/-internals/glimmer/lib/helper.ts b/packages/@ember/-internals/glimmer/lib/helper.ts index 6ef7f405086..56bc9235f60 100644 --- a/packages/@ember/-internals/glimmer/lib/helper.ts +++ b/packages/@ember/-internals/glimmer/lib/helper.ts @@ -7,7 +7,7 @@ import { FrameworkObject, setFrameworkClass } from '@ember/-internals/runtime'; import { symbol } from '@ember/-internals/utils'; import { join } from '@ember/runloop'; import { Dict, Opaque } from '@glimmer/interfaces'; -import { DirtyableTag } from '@glimmer/reference'; +import { createTag, dirty } from '@glimmer/reference'; export const RECOMPUTE_TAG = symbol('RECOMPUTE_TAG'); @@ -85,7 +85,7 @@ export function isSimpleHelper(helper: SimpleHelper | HelperInstance): helper is let Helper = FrameworkObject.extend({ init() { this._super(...arguments); - this[RECOMPUTE_TAG] = DirtyableTag.create(); + this[RECOMPUTE_TAG] = createTag(); }, /** @@ -116,7 +116,7 @@ let Helper = FrameworkObject.extend({ @since 1.13.0 */ recompute() { - join(() => this[RECOMPUTE_TAG].inner.dirty()); + join(() => dirty(this[RECOMPUTE_TAG])); }, /** diff --git a/packages/@ember/-internals/glimmer/lib/helpers/get.ts b/packages/@ember/-internals/glimmer/lib/helpers/get.ts index b3782431513..a57119a6ea8 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/get.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/get.ts @@ -2,12 +2,12 @@ import { set } from '@ember/-internals/metal'; import { Opaque } from '@glimmer/interfaces'; import { combine, - CONSTANT_TAG, + createUpdatableTag, isConst, PathReference, Tag, - TagWrapper, UpdatableTag, + update, VersionedPathReference, } from '@glimmer/reference'; import { Arguments, NULL_REFERENCE, VM } from '@glimmer/runtime'; @@ -85,7 +85,7 @@ class GetHelperReference extends CachedReference { public pathReference: PathReference; public lastPath: string | null; public innerReference: VersionedPathReference; - public innerTag: TagWrapper; + public innerTag: UpdatableTag; public tag: Tag; static create( @@ -111,7 +111,7 @@ class GetHelperReference extends CachedReference { this.lastPath = null; this.innerReference = NULL_REFERENCE; - let innerTag = (this.innerTag = UpdatableTag.create(CONSTANT_TAG)); + let innerTag = (this.innerTag = createUpdatableTag()); this.tag = combine([sourceReference.tag, pathReference.tag, innerTag]); } @@ -122,7 +122,7 @@ class GetHelperReference extends CachedReference { if (path !== lastPath) { innerReference = referenceFromPath(this.sourceReference, path); - innerTag.inner.update(innerReference.tag); + update(innerTag, innerReference.tag); this.innerReference = innerReference; this.lastPath = path; } diff --git a/packages/@ember/-internals/glimmer/lib/helpers/if-unless.ts b/packages/@ember/-internals/glimmer/lib/helpers/if-unless.ts index 4270099b894..832b308041a 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/if-unless.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/if-unless.ts @@ -3,12 +3,12 @@ */ import { assert } from '@ember/debug'; -import { combine, CONSTANT_TAG, isConst, TagWrapper, UpdatableTag } from '@glimmer/reference'; +import { combine, createUpdatableTag, isConst, UpdatableTag, update } from '@glimmer/reference'; import { Arguments, PrimitiveReference, VM } from '@glimmer/runtime'; import { CachedReference, ConditionalReference } from '../utils/references'; class ConditionalHelperReference extends CachedReference { - public branchTag: TagWrapper; + public branchTag: UpdatableTag; public tag: any; public cond: any; public truthy: any; @@ -30,7 +30,7 @@ class ConditionalHelperReference extends CachedReference { constructor(cond: any, truthy: any, falsy: any) { super(); - this.branchTag = UpdatableTag.create(CONSTANT_TAG); + this.branchTag = createUpdatableTag(); this.tag = combine([cond.tag, this.branchTag]); this.cond = cond; @@ -41,7 +41,7 @@ class ConditionalHelperReference extends CachedReference { compute() { let branch = this.cond.value() ? this.truthy : this.falsy; - this.branchTag.inner.update(branch.tag); + update(this.branchTag, branch.tag); return branch.value(); } diff --git a/packages/@ember/-internals/glimmer/lib/renderer.ts b/packages/@ember/-internals/glimmer/lib/renderer.ts index e58c95a2c14..b89d5e36c90 100644 --- a/packages/@ember/-internals/glimmer/lib/renderer.ts +++ b/packages/@ember/-internals/glimmer/lib/renderer.ts @@ -4,7 +4,7 @@ import { getViewElement, getViewId } from '@ember/-internals/views'; import { assert } from '@ember/debug'; import { backburner, getCurrentRunLoop } from '@ember/runloop'; import { Option, Simple } from '@glimmer/interfaces'; -import { CURRENT_TAG, VersionedPathReference } from '@glimmer/reference'; +import { CURRENT_TAG, validate, value, VersionedPathReference } from '@glimmer/reference'; import { clientBuilder, CurriedComponentDefinition, @@ -431,7 +431,7 @@ export abstract class Renderer { globalShouldReflush = globalShouldReflush || shouldReflush; } - this._lastRevision = CURRENT_TAG.value(); + this._lastRevision = value(CURRENT_TAG); } finally { env.commit(); } @@ -467,7 +467,7 @@ export abstract class Renderer { completedWithoutError = true; } finally { if (!completedWithoutError) { - this._lastRevision = CURRENT_TAG.value(); + this._lastRevision = value(CURRENT_TAG); if (this._env.inTransaction === true) { this._env.commit(); } @@ -498,7 +498,7 @@ export abstract class Renderer { } _isValid() { - return this._destroyed || this._roots.length === 0 || CURRENT_TAG.validate(this._lastRevision); + return this._destroyed || this._roots.length === 0 || validate(CURRENT_TAG, this._lastRevision); } _revalidate() { diff --git a/packages/@ember/-internals/glimmer/lib/utils/curly-component-state-bucket.ts b/packages/@ember/-internals/glimmer/lib/utils/curly-component-state-bucket.ts index d63156fd0bd..8cedbeeb202 100644 --- a/packages/@ember/-internals/glimmer/lib/utils/curly-component-state-bucket.ts +++ b/packages/@ember/-internals/glimmer/lib/utils/curly-component-state-bucket.ts @@ -1,5 +1,5 @@ import { clearElementView, clearViewElement, getViewElement } from '@ember/-internals/views'; -import { Revision, VersionedReference } from '@glimmer/reference'; +import { Revision, value, VersionedReference } from '@glimmer/reference'; import { CapturedNamedArguments } from '@glimmer/runtime'; import { Opaque } from '@glimmer/util'; import Environment from '../environment'; @@ -48,7 +48,7 @@ export default class ComponentStateBucket { public hasWrappedElement: boolean ) { this.classRef = null; - this.argsRevision = args === null ? 0 : args.tag.value(); + this.argsRevision = args === null ? 0 : value(args.tag); } destroy() { diff --git a/packages/@ember/-internals/glimmer/lib/utils/iterable.ts b/packages/@ember/-internals/glimmer/lib/utils/iterable.ts index 9c1ff036637..ea629935b2e 100644 --- a/packages/@ember/-internals/glimmer/lib/utils/iterable.ts +++ b/packages/@ember/-internals/glimmer/lib/utils/iterable.ts @@ -5,11 +5,11 @@ import { assert } from '@ember/debug'; import { AbstractIterable, combine, - CONSTANT_TAG, + createUpdatableTag, IterationItem, OpaqueIterator, Tag, - UpdatableTag, + update, VersionedReference, } from '@glimmer/reference'; import { Opaque, Option } from '@glimmer/util'; @@ -261,7 +261,7 @@ const EMPTY_ITERATOR: OpaqueIterator = { class EachInIterable implements EmberIterable { public tag: Tag; - private valueTag = UpdatableTag.create(CONSTANT_TAG); + private valueTag = createUpdatableTag(); constructor(private ref: VersionedReference, private keyPath: string) { this.tag = combine([ref.tag, this.valueTag]); @@ -279,7 +279,7 @@ class EachInIterable implements EmberIterable { iterable = _contentFor(iterable); } - valueTag.inner.update(tag); + update(valueTag, tag); if (!isIndexable(iterable)) { return EMPTY_ITERATOR; @@ -331,7 +331,7 @@ class EachInIterable implements EmberIterable { class EachIterable implements EmberIterable { public tag: Tag; - private valueTag = UpdatableTag.create(CONSTANT_TAG); + private valueTag = createUpdatableTag(); constructor(private ref: VersionedReference, private keyPath: string) { this.tag = combine([ref.tag, this.valueTag]); @@ -342,7 +342,7 @@ class EachIterable implements EmberIterable { let iterable = ref.value(); - valueTag.inner.update(tagForProperty(iterable, '[]')); + update(valueTag, tagForProperty(iterable, '[]')); if (iterable === null || typeof iterable !== 'object') { return EMPTY_ITERATOR; diff --git a/packages/@ember/-internals/glimmer/lib/utils/outlet.ts b/packages/@ember/-internals/glimmer/lib/utils/outlet.ts index e4e6cdfcf37..6c41134c855 100644 --- a/packages/@ember/-internals/glimmer/lib/utils/outlet.ts +++ b/packages/@ember/-internals/glimmer/lib/utils/outlet.ts @@ -1,6 +1,13 @@ import { Owner } from '@ember/-internals/owner'; import { Opaque } from '@glimmer/interfaces'; -import { combine, DirtyableTag, Reference, Tag, VersionedPathReference } from '@glimmer/reference'; +import { + combine, + createTag, + dirty, + Reference, + Tag, + VersionedPathReference, +} from '@glimmer/reference'; import { Factory as TemplateFactory, OwnedTemplate } from '../template'; export interface RenderState { @@ -63,7 +70,7 @@ export interface OutletState { * Represents the root outlet. */ export class RootOutletReference implements VersionedPathReference { - tag = DirtyableTag.create(); + tag = createTag(); constructor(public outletState: OutletState) {} @@ -77,7 +84,7 @@ export class RootOutletReference implements VersionedPathReference update(state: OutletState) { this.outletState.outlets.main = state; - this.tag.inner.dirty(); + dirty(this.tag); } } diff --git a/packages/@ember/-internals/glimmer/lib/utils/references.ts b/packages/@ember/-internals/glimmer/lib/utils/references.ts index 524bcdeafa8..b86470b1688 100644 --- a/packages/@ember/-internals/glimmer/lib/utils/references.ts +++ b/packages/@ember/-internals/glimmer/lib/utils/references.ts @@ -15,15 +15,21 @@ import { DEBUG } from '@glimmer/env'; import { Dict, Opaque } from '@glimmer/interfaces'; import { combine, - CONSTANT_TAG, + COMPUTE, ConstReference, + createTag, + createUpdatableTag, + dirty, DirtyableTag, isConst, Revision, - RevisionTag, Tag, - TagWrapper, UpdatableTag, + update, + validate, + VALIDATE, + value, + VALUE, VersionedPathReference, VersionedReference, } from '@glimmer/reference'; @@ -67,9 +73,9 @@ export abstract class CachedReference extends EmberPathReference { value(): Opaque { let { tag, lastRevision, lastValue } = this; - if (lastRevision === null || !tag.validate(lastRevision)) { + if (lastRevision === null || !validate(tag, lastRevision)) { lastValue = this.lastValue = this.compute(); - this.lastRevision = tag.value(); + this.lastRevision = value(tag); } return lastValue; @@ -100,26 +106,14 @@ export class RootReference extends ConstReference } } -interface ITwoWayFlushDetectionTag extends RevisionTag { - didCompute(parent: Opaque): void; -} - let TwoWayFlushDetectionTag: { - create( - tag: Tag, - key: string, - ref: VersionedPathReference - ): TagWrapper; + create(tag: Tag, key: string, ref: VersionedPathReference): Tag; }; if (DEBUG) { - TwoWayFlushDetectionTag = class TwoWayFlushDetectionTag implements ITwoWayFlushDetectionTag { - static create( - tag: Tag, - key: string, - ref: VersionedPathReference - ): TagWrapper { - return new TagWrapper((tag as any).type, new TwoWayFlushDetectionTag(tag, key, ref)); + TwoWayFlushDetectionTag = class TwoWayFlushDetectionTag { + static create(tag: Tag, key: string, ref: VersionedPathReference): Tag { + return (new TwoWayFlushDetectionTag(tag, key, ref) as unknown) as Tag; } private parent: Opaque = null; @@ -130,14 +124,18 @@ if (DEBUG) { private ref: VersionedPathReference ) {} - value(): Revision { - return this.tag.value(); + [VALUE](): Revision { + return value(this.tag); + } + + [COMPUTE](): Revision { + return this.tag[COMPUTE](); } - validate(ticket: Revision): boolean { + [VALIDATE](ticket: Revision): boolean { let { parent, key, ref } = this; - let isValid = this.tag.validate(ticket); + let isValid = validate(this.tag, ticket); if (isValid && parent) { didRender(parent, key, ref); @@ -172,15 +170,16 @@ export abstract class PropertyReference extends CachedReference { export class RootPropertyReference extends PropertyReference implements VersionedPathReference { public tag: Tag; - private propertyTag: TagWrapper; + private propertyTag: UpdatableTag; constructor(private parentValue: object, private propertyKey: string) { super(); if (EMBER_METAL_TRACKED_PROPERTIES) { - this.propertyTag = UpdatableTag.create(CONSTANT_TAG); + this.propertyTag = createUpdatableTag(); } else { - this.propertyTag = UpdatableTag.create(tagForProperty(parentValue, propertyKey)); + let tag = (this.propertyTag = createUpdatableTag()); + update(tag, tagForProperty(parentValue, propertyKey)); } if (DEBUG) { @@ -198,7 +197,7 @@ export class RootPropertyReference extends PropertyReference let { parentValue, propertyKey } = this; if (DEBUG) { - (this.tag.inner as ITwoWayFlushDetectionTag).didCompute(parentValue); + (this.tag as any).didCompute(parentValue); } let ret; @@ -209,7 +208,7 @@ export class RootPropertyReference extends PropertyReference }); consume(tag); - this.propertyTag.inner.update(tag); + update(this.propertyTag, tag); } else { ret = get(parentValue, propertyKey); } @@ -224,7 +223,7 @@ export class RootPropertyReference extends PropertyReference export class NestedPropertyReference extends PropertyReference { public tag: Tag; - private propertyTag: TagWrapper; + private propertyTag: UpdatableTag; constructor( private parentReference: VersionedPathReference, @@ -233,7 +232,7 @@ export class NestedPropertyReference extends PropertyReference { super(); let parentReferenceTag = parentReference.tag; - let propertyTag = (this.propertyTag = UpdatableTag.create(CONSTANT_TAG)); + let propertyTag = (this.propertyTag = createUpdatableTag()); if (DEBUG) { let tag = combine([parentReferenceTag, propertyTag]); @@ -261,7 +260,7 @@ export class NestedPropertyReference extends PropertyReference { } if (DEBUG) { - (this.tag.inner as ITwoWayFlushDetectionTag).didCompute(parentValue); + (this.tag as any).didCompute(parentValue); } let ret; @@ -273,10 +272,10 @@ export class NestedPropertyReference extends PropertyReference { consume(tag); - propertyTag.inner.update(tag); + update(propertyTag, tag); } else { ret = get(parentValue, propertyKey); - propertyTag.inner.update(tagForProperty(parentValue, propertyKey)); + update(propertyTag, tagForProperty(parentValue, propertyKey)); } return ret; @@ -295,13 +294,13 @@ export class NestedPropertyReference extends PropertyReference { } export class UpdatableReference extends EmberPathReference { - public tag: TagWrapper; + public tag: DirtyableTag; private _value: Opaque; constructor(value: Opaque) { super(); - this.tag = DirtyableTag.create(); + this.tag = createTag(); this._value = value; } @@ -313,7 +312,7 @@ export class UpdatableReference extends EmberPathReference { let { _value } = this; if (value !== _value) { - this.tag.inner.dirty(); + dirty(this.tag); this._value = value; } } @@ -321,7 +320,7 @@ export class UpdatableReference extends EmberPathReference { export class ConditionalReference extends GlimmerConditionalReference implements VersionedReference { - public objectTag: TagWrapper; + public objectTag: UpdatableTag; static create(reference: VersionedReference): VersionedReference { if (isConst(reference)) { let value = reference.value(); @@ -336,16 +335,16 @@ export class ConditionalReference extends GlimmerConditionalReference constructor(reference: VersionedReference) { super(reference); - this.objectTag = UpdatableTag.create(CONSTANT_TAG); + this.objectTag = createUpdatableTag(); this.tag = combine([reference.tag, this.objectTag]); } toBool(predicate: Opaque): boolean { if (isProxy(predicate)) { - this.objectTag.inner.update(tagForProperty(predicate, 'isTruthy')); + update(this.objectTag, tagForProperty(predicate, 'isTruthy')); return Boolean(get(predicate, 'isTruthy')); } else { - this.objectTag.inner.update(tagFor(predicate)); + update(this.objectTag, tagFor(predicate)); return emberToBool(predicate); } } diff --git a/packages/@ember/-internals/meta/lib/meta.ts b/packages/@ember/-internals/meta/lib/meta.ts index 40d88bf0c00..ba9c29bab76 100644 --- a/packages/@ember/-internals/meta/lib/meta.ts +++ b/packages/@ember/-internals/meta/lib/meta.ts @@ -1,7 +1,9 @@ import { lookupDescriptor, symbol, toString } from '@ember/-internals/utils'; import { assert } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; -import { Tag } from '@glimmer/reference'; +import { createUpdatableTag, UpdatableTag } from '@glimmer/reference'; + +type ObjMap = { [key: string]: T }; const objectPrototype = Object.prototype; @@ -98,10 +100,10 @@ export class Meta { _deps: any | undefined; _chainWatchers: any | undefined; _chains: any | undefined; - _tag: Tag | undefined; - _tags: any | undefined; + _tag: UpdatableTag | undefined; + _tags: ObjMap | undefined; _flags: MetaFlags; - _lazyChains: Map> | undefined; + _lazyChains: ObjMap> | undefined; source: object; proto: object | undefined; _parent: Meta | undefined | null; @@ -342,7 +344,7 @@ export class Meta { return this._tags; } - writableTag(create: (obj: object) => Tag) { + writableTag() { assert( this.isMetaDestroyed() ? `Cannot create a new tag for \`${toString(this.source)}\` after it has been destroyed.` @@ -351,7 +353,7 @@ export class Meta { ); let ret = this._tag; if (ret === undefined) { - ret = this._tag = create(this.source); + ret = this._tag = createUpdatableTag(); } return ret; } @@ -384,6 +386,8 @@ export class Meta { if (lazyChains !== undefined) { return lazyChains[key]; } + + return undefined; } writableChainWatchers(create: (source: object) => any) { diff --git a/packages/@ember/-internals/metal/index.ts b/packages/@ember/-internals/metal/index.ts index 7adecc8100d..a8f863741a8 100644 --- a/packages/@ember/-internals/metal/index.ts +++ b/packages/@ember/-internals/metal/index.ts @@ -59,13 +59,7 @@ export { default as expandProperties } from './lib/expand_properties'; export { addObserver, activateObserver, removeObserver, flushAsyncObservers } from './lib/observer'; export { Mixin, aliasMethod, mixin, observer, applyMixin } from './lib/mixin'; export { default as inject, DEBUG_INJECTION_FUNCTIONS } from './lib/injected_property'; -export { - tagForProperty, - tagFor, - markObjectAsDirty, - UNKNOWN_PROPERTY_TAG, - update, -} from './lib/tags'; +export { tagForProperty, tagFor, markObjectAsDirty, UNKNOWN_PROPERTY_TAG } from './lib/tags'; export { default as runInTransaction, didRender, assertNotRendered } from './lib/transaction'; export { consume, Tracker, tracked, track } from './lib/tracked'; diff --git a/packages/@ember/-internals/metal/lib/alias.ts b/packages/@ember/-internals/metal/lib/alias.ts index 82aeaec7f88..99f30047d38 100644 --- a/packages/@ember/-internals/metal/lib/alias.ts +++ b/packages/@ember/-internals/metal/lib/alias.ts @@ -3,7 +3,7 @@ import { inspect } from '@ember/-internals/utils'; import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import { assert } from '@ember/debug'; import EmberError from '@ember/error'; -import { combine } from '@glimmer/reference'; +import { combine, UpdatableTag, update, validate, value } from '@glimmer/reference'; import { finishLazyChains, getChainTagsForKey } from './chain-tags'; import { getCachedValueFor, @@ -23,7 +23,7 @@ import { descriptorForDecorator } from './descriptor_map'; import { defineProperty } from './properties'; import { get } from './property_get'; import { set } from './property_set'; -import { tagForProperty, update } from './tags'; +import { tagForProperty } from './tags'; import { consume, untrack } from './tracked'; const CONSUMED = Object.freeze({}); @@ -100,7 +100,7 @@ export class AliasedProperty extends ComputedDescriptor { let ret: any; if (EMBER_METAL_TRACKED_PROPERTIES) { - let propertyTag = tagForProperty(obj, keyName); + let propertyTag = tagForProperty(obj, keyName) as UpdatableTag; // We don't use the tag since CPs are not automatic, we just want to avoid // anything tracking while we get the altKey @@ -110,9 +110,9 @@ export class AliasedProperty extends ComputedDescriptor { let lastRevision = getLastRevisionFor(obj, keyName); - if (!propertyTag.validate(lastRevision)) { + if (!validate(propertyTag, lastRevision)) { update(propertyTag, combine(getChainTagsForKey(obj, this.altKey))); - setLastRevisionFor(obj, keyName, propertyTag.value()); + setLastRevisionFor(obj, keyName, value(propertyTag)); finishLazyChains(obj, keyName, ret); } diff --git a/packages/@ember/-internals/metal/lib/chain-tags.ts b/packages/@ember/-internals/metal/lib/chain-tags.ts index 63d34f46200..2cf4aa60b31 100644 --- a/packages/@ember/-internals/metal/lib/chain-tags.ts +++ b/packages/@ember/-internals/metal/lib/chain-tags.ts @@ -1,7 +1,7 @@ import { meta as metaFor, peekMeta } from '@ember/-internals/meta'; import { isEmberArray } from '@ember/-internals/utils'; import { assert } from '@ember/debug'; -import { combine, CONSTANT_TAG, Tag, UpdatableTag } from '@glimmer/reference'; +import { combine, createUpdatableTag, Tag, update, validate } from '@glimmer/reference'; import { getLastRevisionFor, peekCacheFor } from './computed_cache'; import { descriptorForProperty } from './descriptor_map'; import get from './property_get'; @@ -28,7 +28,7 @@ export function finishLazyChains(obj: any, key: string, value: any) { for (let path in lazyTags) { let tag = lazyTags[path]; - tag.inner.update(combine(getChainTagsForKey(value, path))); + update(tag, combine(getChainTagsForKey(value, path))); delete lazyTags[path]; } @@ -142,7 +142,7 @@ export function getChainTagsForKey(obj: any, path: string) { } else { let lastRevision = getLastRevisionFor(current, segment); - if (propertyTag.validate(lastRevision)) { + if (validate(propertyTag, lastRevision)) { if (typeof descriptor.altKey === 'string') { // it's an alias, so just get the altkey without tracking untrack(() => { @@ -159,7 +159,7 @@ export function getChainTagsForKey(obj: any, path: string) { let placeholderTag = lazyChains[rest]; if (placeholderTag === undefined) { - placeholderTag = lazyChains[rest] = UpdatableTag.create(CONSTANT_TAG); + placeholderTag = lazyChains[rest] = createUpdatableTag(); } chainTags.push(placeholderTag); diff --git a/packages/@ember/-internals/metal/lib/computed.ts b/packages/@ember/-internals/metal/lib/computed.ts index e694ee0226f..08405fd2c81 100644 --- a/packages/@ember/-internals/metal/lib/computed.ts +++ b/packages/@ember/-internals/metal/lib/computed.ts @@ -3,7 +3,14 @@ import { inspect, isEmberArray, toString } from '@ember/-internals/utils'; import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import { assert, deprecate, warn } from '@ember/debug'; import EmberError from '@ember/error'; -import { combine, Tag } from '@glimmer/reference'; +import { + combine, + Tag, + UpdatableTag, + update, + validate, + value as tagValue, +} from '@glimmer/reference'; import { finishLazyChains, getChainTagsForKeys } from './chain-tags'; import { getCachedValueFor, @@ -31,7 +38,7 @@ import { setObserverSuspended } from './observer'; import { defineProperty } from './properties'; import { beginPropertyChanges, endPropertyChanges, notifyPropertyChange } from './property_events'; import { set } from './property_set'; -import { tagForProperty, update } from './tags'; +import { tagForProperty } from './tags'; import { consume, track, untrack } from './tracked'; export type ComputedPropertyGetter = (keyName: string) => any; @@ -517,14 +524,12 @@ export class ComputedProperty extends ComputedDescriptor { } let cache = getCacheFor(obj); - let propertyTag: Tag; - if (EMBER_METAL_TRACKED_PROPERTIES) { - propertyTag = tagForProperty(obj, keyName); + let propertyTag = tagForProperty(obj, keyName) as UpdatableTag; let ret; - if (cache.has(keyName) && propertyTag.validate(getLastRevisionFor(obj, keyName))) { + if (cache.has(keyName) && validate(propertyTag, getLastRevisionFor(obj, keyName))) { ret = cache.get(keyName); } else { // For backwards compatibility, we only throw if the CP has any dependencies. CPs without dependencies @@ -559,7 +564,7 @@ export class ComputedProperty extends ComputedDescriptor { update(propertyTag!, upstreamTag); } - setLastRevisionFor(obj, keyName, propertyTag!.value()); + setLastRevisionFor(obj, keyName, tagValue(propertyTag)); } consume(propertyTag!); @@ -615,13 +620,13 @@ export class ComputedProperty extends ComputedDescriptor { finishLazyChains(obj, keyName, ret); - let propertyTag = tagForProperty(obj, keyName); + let propertyTag = tagForProperty(obj, keyName) as UpdatableTag; if (this._dependentKeys !== undefined) { update(propertyTag, combine(getChainTagsForKeys(obj, this._dependentKeys))); } - setLastRevisionFor(obj, keyName, propertyTag.value()); + setLastRevisionFor(obj, keyName, tagValue(propertyTag)); } finally { endPropertyChanges(); } diff --git a/packages/@ember/-internals/metal/lib/observer.ts b/packages/@ember/-internals/metal/lib/observer.ts index aa7dca33c70..e7aad4355d6 100644 --- a/packages/@ember/-internals/metal/lib/observer.ts +++ b/packages/@ember/-internals/metal/lib/observer.ts @@ -2,7 +2,7 @@ import { ENV } from '@ember/-internals/environment'; import { peekMeta } from '@ember/-internals/meta'; import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import { schedule } from '@ember/runloop'; -import { combine, CURRENT_TAG, Tag } from '@glimmer/reference'; +import { combine, CURRENT_TAG, Tag, validate, value } from '@glimmer/reference'; import { getChainTagsForKey } from './chain-tags'; import changeEvent from './change_event'; import { addListener, removeListener, sendEvent } from './events'; @@ -111,7 +111,7 @@ export function activateObserver(target: object, eventName: string, sync = false count: 1, path, tag, - lastRevision: tag.value(), + lastRevision: value(tag), suspended: false, }); } @@ -148,14 +148,14 @@ export function revalidateObservers(target: object) { if (ASYNC_OBSERVERS.has(target)) { ASYNC_OBSERVERS.get(target)!.forEach(observer => { observer.tag = combine(getChainTagsForKey(target, observer.path)); - observer.lastRevision = observer.tag.value(); + observer.lastRevision = value(observer.tag); }); } if (SYNC_OBSERVERS.has(target)) { SYNC_OBSERVERS.get(target)!.forEach(observer => { observer.tag = combine(getChainTagsForKey(target, observer.path)); - observer.lastRevision = observer.tag.value(); + observer.lastRevision = value(observer.tag); }); } } @@ -163,11 +163,11 @@ export function revalidateObservers(target: object) { let lastKnownRevision = 0; export function flushAsyncObservers() { - if (lastKnownRevision === CURRENT_TAG.value()) { + if (lastKnownRevision === value(CURRENT_TAG)) { return; } - lastKnownRevision = CURRENT_TAG.value(); + lastKnownRevision = value(CURRENT_TAG); ASYNC_OBSERVERS.forEach((activeObservers, target) => { let meta = peekMeta(target); @@ -178,13 +178,13 @@ export function flushAsyncObservers() { } activeObservers.forEach((observer, eventName) => { - if (!observer.tag.validate(observer.lastRevision)) { + if (!validate(observer.tag, observer.lastRevision)) { schedule('actions', () => { try { sendEvent(target, eventName, [target, observer.path]); } finally { observer.tag = combine(getChainTagsForKey(target, observer.path)); - observer.lastRevision = observer.tag.value(); + observer.lastRevision = value(observer.tag); } }); } @@ -206,14 +206,14 @@ export function flushSyncObservers() { } activeObservers.forEach((observer, eventName) => { - if (!observer.suspended && !observer.tag.validate(observer.lastRevision)) { + if (!observer.suspended && !validate(observer.tag, observer.lastRevision)) { try { observer.suspended = true; sendEvent(target, eventName, [target, observer.path]); } finally { observer.suspended = false; observer.tag = combine(getChainTagsForKey(target, observer.path)); - observer.lastRevision = observer.tag.value(); + observer.lastRevision = value(observer.tag); } } }); diff --git a/packages/@ember/-internals/metal/lib/tags.ts b/packages/@ember/-internals/metal/lib/tags.ts index 278e6ccf599..434dbf84ac7 100644 --- a/packages/@ember/-internals/metal/lib/tags.ts +++ b/packages/@ember/-internals/metal/lib/tags.ts @@ -3,21 +3,10 @@ import { isProxy, setupMandatorySetter, symbol } from '@ember/-internals/utils'; import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import { backburner } from '@ember/runloop'; import { DEBUG } from '@glimmer/env'; -import { - combine, - CONSTANT_TAG, - DirtyableTag, - Tag, - TagWrapper, - UpdatableTag, -} from '@glimmer/reference'; +import { CONSTANT_TAG, createTag, createUpdatableTag, dirty, Tag } from '@glimmer/reference'; export const UNKNOWN_PROPERTY_TAG = symbol('UNKNOWN_PROPERTY_TAG'); -function makeTag(): TagWrapper { - return DirtyableTag.create(); -} - export function tagForProperty(object: any, propertyKey: string | symbol, _meta?: Meta): Tag { let objectType = typeof object; if (objectType !== 'function' && (objectType !== 'object' || object === null)) { @@ -40,19 +29,19 @@ export function tagForProperty(object: any, propertyKey: string | symbol, _meta? } if (EMBER_METAL_TRACKED_PROPERTIES) { - let pair = combine([makeTag(), UpdatableTag.create(CONSTANT_TAG)]); + let newTag = createUpdatableTag(); if (DEBUG) { if (EMBER_METAL_TRACKED_PROPERTIES) { setupMandatorySetter!(object, propertyKey); } - (pair as any)._propertyKey = propertyKey; + (newTag as any)._propertyKey = propertyKey; } - return (tags[propertyKey] = pair); + return (tags[propertyKey] = newTag); } else { - return (tags[propertyKey] = makeTag()); + return (tags[propertyKey] = createTag()); } } @@ -61,41 +50,19 @@ export function tagFor(object: any | null, _meta?: Meta): Tag { let meta = _meta === undefined ? metaFor(object) : _meta; if (!meta.isMetaDestroyed()) { - return meta.writableTag(makeTag); + return meta.writableTag(); } } return CONSTANT_TAG; } -export let dirty: (tag: Tag) => void; -export let update: (outer: Tag, inner: Tag) => void; - -if (EMBER_METAL_TRACKED_PROPERTIES) { - dirty = tag => { - (tag.inner! as any).first.inner.dirty(); - }; - - update = (outer, inner) => { - (outer.inner! as any).lastChecked = 0; - (outer.inner! as any).second.inner.update(inner); - }; -} else { - dirty = tag => { - (tag.inner! as any).dirty(); - }; -} - export function markObjectAsDirty(obj: object, propertyKey: string, _meta?: Meta): void { let meta = _meta === undefined ? metaFor(obj) : _meta; let objectTag = meta.readableTag(); if (objectTag !== undefined) { - if (isProxy(obj)) { - (objectTag.inner! as any).first.inner.dirty(); - } else { - (objectTag.inner! as any).dirty(); - } + dirty(objectTag); } let tags = meta.readableTags(); diff --git a/packages/@ember/-internals/metal/lib/tracked.ts b/packages/@ember/-internals/metal/lib/tracked.ts index c70fac74e40..27fa79cbfa9 100644 --- a/packages/@ember/-internals/metal/lib/tracked.ts +++ b/packages/@ember/-internals/metal/lib/tracked.ts @@ -1,10 +1,10 @@ import { isEmberArray } from '@ember/-internals/utils'; import { assert } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; -import { combine, CONSTANT_TAG, Tag } from '@glimmer/reference'; +import { combine, CONSTANT_TAG, Tag, UpdatableTag, update } from '@glimmer/reference'; import { Decorator, DecoratorPropertyDescriptor, isElementDescriptor } from './decorator'; import { setClassicDecorator } from './descriptor_map'; -import { markObjectAsDirty, tagForProperty, update } from './tags'; +import { markObjectAsDirty, tagForProperty } from './tags'; type Option = T | null; @@ -190,7 +190,7 @@ function descriptorForField([_target, key, desc]: [ configurable: true, get(): any { - let propertyTag = tagForProperty(this, key); + let propertyTag = tagForProperty(this, key) as UpdatableTag; if (CURRENT_TRACKER) CURRENT_TRACKER.add(propertyTag); diff --git a/packages/@ember/-internals/metal/tests/alias_test.js b/packages/@ember/-internals/metal/tests/alias_test.js index 5d2eb2cdf94..4bea2f3f815 100644 --- a/packages/@ember/-internals/metal/tests/alias_test.js +++ b/packages/@ember/-internals/metal/tests/alias_test.js @@ -13,6 +13,7 @@ import { import { Object as EmberObject } from '@ember/-internals/runtime'; import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import { moduleFor, AbstractTestCase, runLoopSettled } from 'internal-test-helpers'; +import { value, validate } from '@glimmer/reference'; let obj, count; @@ -131,10 +132,10 @@ moduleFor( get(obj, 'bar'); let tag = EMBER_METAL_TRACKED_PROPERTIES ? tagForProperty(obj, 'bar') : tagFor(obj); - let tagValue = tag.value(); + let tagValue = value(tag); set(obj, 'foo.faz', 'BAR'); - assert.ok(!tag.validate(tagValue), 'setting the aliased key should dirty the object'); + assert.ok(!validate(tag, tagValue), 'setting the aliased key should dirty the object'); } ['@test setting alias on self should fail assertion']() { @@ -206,24 +207,20 @@ moduleFor( ['@test property tags are bumped when the source changes [GH#17243]'](assert) { function assertPropertyTagChanged(obj, keyName, callback) { let tag = tagForProperty(obj, keyName); - let before = tag.value(); + let before = value(tag); callback(); - let after = tag.value(); - - assert.notEqual(after, before, `tagForProperty ${keyName} should change`); + assert.notOk(validate(tag, before), `tagForProperty ${keyName} should change`); } function assertPropertyTagUnchanged(obj, keyName, callback) { let tag = tagForProperty(obj, keyName); - let before = tag.value(); + let before = value(tag); callback(); - let after = tag.value(); - - assert.equal(after, before, `tagForProperty ${keyName} should not change`); + assert.ok(validate(tag, before), `tagForProperty ${keyName} should not change`); } defineProperty(obj, 'bar', alias('foo.faz')); diff --git a/packages/@ember/-internals/metal/tests/tracked/classic_classes_test.js b/packages/@ember/-internals/metal/tests/tracked/classic_classes_test.js index 9c5b76da129..d6cfb955981 100644 --- a/packages/@ember/-internals/metal/tests/tracked/classic_classes_test.js +++ b/packages/@ember/-internals/metal/tests/tracked/classic_classes_test.js @@ -2,6 +2,7 @@ import { AbstractTestCase, moduleFor } from 'internal-test-helpers'; import { defineProperty, tracked, track, nativeDescDecorator } from '../..'; import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; +import { value, validate } from '@glimmer/reference'; if (EMBER_METAL_TRACKED_PROPERTIES) { moduleFor( @@ -36,24 +37,24 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { obj.last = 'Dale'; let tag = track(() => obj.full); - let snapshot = tag.value(); + let snapshot = value(tag); assert.equal(obj.full, 'Tom Dale', 'The full name starts correct'); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); - snapshot = tag.value(); - assert.equal(tag.validate(snapshot), true); + snapshot = value(tag); + assert.equal(validate(tag, snapshot), true); obj.full = 'Melanie Sumner'; - assert.equal(tag.validate(snapshot), false); + assert.equal(validate(tag, snapshot), false); assert.equal(obj.full, 'Melanie Sumner'); assert.equal(obj.first, 'Melanie'); assert.equal(obj.last, 'Sumner'); - snapshot = tag.value(); + snapshot = value(tag); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); } [`@test can pass a default value to the tracked decorator`](assert) { diff --git a/packages/@ember/-internals/metal/tests/tracked/validation_test.js b/packages/@ember/-internals/metal/tests/tracked/validation_test.js index fb9d8a3df4f..703e463f125 100644 --- a/packages/@ember/-internals/metal/tests/tracked/validation_test.js +++ b/packages/@ember/-internals/metal/tests/tracked/validation_test.js @@ -12,6 +12,7 @@ import { import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import { EMBER_ARRAY } from '@ember/-internals/utils'; import { AbstractTestCase, moduleFor } from 'internal-test-helpers'; +import { value, validate } from '@glimmer/reference'; if (EMBER_METAL_TRACKED_PROPERTIES) { moduleFor( @@ -28,22 +29,22 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { let obj = new Tracked('Tom', 'Dale'); let tag = track(() => obj.first); - let snapshot = tag.value(); + let snapshot = value(tag); assert.equal(obj.first, 'Tom', 'The full name starts correct'); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); - snapshot = tag.value(); - assert.equal(tag.validate(snapshot), true); + snapshot = value(tag); + assert.equal(validate(tag, snapshot), true); obj.first = 'Thomas'; - assert.equal(tag.validate(snapshot), false); + assert.equal(validate(tag, snapshot), false); assert.equal(obj.first, 'Thomas'); - snapshot = tag.value(); + snapshot = value(tag); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); } [`@test autotracking should work with native getters`](assert) { @@ -63,22 +64,22 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { let obj = new Tracked('Tom', 'Dale'); let tag = track(() => obj.full); - let snapshot = tag.value(); + let snapshot = value(tag); assert.equal(obj.full, 'Tom Dale', 'The full name starts correct'); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); - snapshot = tag.value(); - assert.equal(tag.validate(snapshot), true); + snapshot = value(tag); + assert.equal(validate(tag, snapshot), true); obj.first = 'Thomas'; - assert.equal(tag.validate(snapshot), false); + assert.equal(validate(tag, snapshot), false); assert.equal(obj.full, 'Thomas Dale'); - snapshot = tag.value(); + snapshot = value(tag); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); } [`@test autotracking should work with native setters`](assert) { @@ -105,24 +106,24 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { let obj = new Tracked('Tom', 'Dale'); let tag = track(() => obj.full); - let snapshot = tag.value(); + let snapshot = value(tag); assert.equal(obj.full, 'Tom Dale', 'The full name starts correct'); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); - snapshot = tag.value(); - assert.equal(tag.validate(snapshot), true); + snapshot = value(tag); + assert.equal(validate(tag, snapshot), true); obj.full = 'Melanie Sumner'; - assert.equal(tag.validate(snapshot), false); + assert.equal(validate(tag, snapshot), false); assert.equal(obj.full, 'Melanie Sumner'); assert.equal(obj.first, 'Melanie'); assert.equal(obj.last, 'Sumner'); - snapshot = tag.value(); + snapshot = value(tag); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); } [`@test interaction with Ember object model (tracked property depending on Ember property)`]( @@ -143,30 +144,30 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { let obj = new Tracked(tom); let tag = track(() => obj.full); - let snapshot = tag.value(); + let snapshot = value(tag); assert.equal(obj.full, 'Tom Dale'); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); - snapshot = tag.value(); - assert.equal(tag.validate(snapshot), true); + snapshot = value(tag); + assert.equal(validate(tag, snapshot), true); set(tom, 'first', 'Thomas'); - assert.equal(tag.validate(snapshot), false, 'invalid after setting with Ember set'); + assert.equal(validate(tag, snapshot), false, 'invalid after setting with Ember set'); assert.equal(obj.full, 'Thomas Dale'); - snapshot = tag.value(); + snapshot = value(tag); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); set(obj, 'name', { first: 'Ricardo', last: 'Mendes' }); - assert.equal(tag.validate(snapshot), false, 'invalid after setting with Ember set'); + assert.equal(validate(tag, snapshot), false, 'invalid after setting with Ember set'); assert.equal(obj.full, 'Ricardo Mendes'); - snapshot = tag.value(); + snapshot = value(tag); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); } [`@test interaction with Ember object model (Ember computed property depending on tracked property)`]( @@ -201,26 +202,26 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { let obj = new EmberObject(tom); let tag = tagForProperty(obj, 'full'); - let snapshot = tag.value(); + let snapshot = value(tag); let full = get(obj, 'full'); assert.equal(full, 'Tom Dale'); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); - snapshot = tag.value(); - assert.equal(tag.validate(snapshot), true); + snapshot = value(tag); + assert.equal(validate(tag, snapshot), true); tom.first = 'Thomas'; assert.equal( - tag.validate(snapshot), + validate(tag, snapshot), false, 'invalid after setting with tracked properties' ); assert.equal(get(obj, 'full'), 'Thomas Dale'); - snapshot = tag.value(); + snapshot = value(tag); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); } ['@test interaction with the Ember object model (paths going through tracked properties)']( @@ -265,29 +266,29 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { let obj = new EmberObject(contact); let tag = tagForProperty(obj, 'full'); - let snapshot = tag.value(); + let snapshot = value(tag); let full = get(obj, 'full'); assert.equal(full, 'Tom Dale'); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); - snapshot = tag.value(); - assert.equal(tag.validate(snapshot), true); + snapshot = value(tag); + assert.equal(validate(tag, snapshot), true); set(tom, 'first', 'Thomas'); - assert.equal(tag.validate(snapshot), false, 'invalid after setting with Ember.set'); + assert.equal(validate(tag, snapshot), false, 'invalid after setting with Ember.set'); assert.equal(get(obj, 'full'), 'Thomas Dale'); - snapshot = tag.value(); + snapshot = value(tag); tom = contact.name = new EmberName('T', 'Dale'); - assert.equal(tag.validate(snapshot), false, 'invalid after setting with Ember.set'); + assert.equal(validate(tag, snapshot), false, 'invalid after setting with Ember.set'); assert.equal(get(obj, 'full'), 'T Dale'); - snapshot = tag.value(); + snapshot = value(tag); set(tom, 'first', 'Tizzle'); - assert.equal(tag.validate(snapshot), false, 'invalid after setting with Ember.set'); + assert.equal(validate(tag, snapshot), false, 'invalid after setting with Ember.set'); assert.equal(get(obj, 'full'), 'Tizzle Dale'); } @@ -300,16 +301,16 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { let obj = new EmberObject(); let tag = tagForProperty(obj, 'array'); - let snapshot = tag.value(); + let snapshot = value(tag); let array = get(obj, 'array'); assert.deepEqual(array, []); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); array.push(1); notifyPropertyChange(array, '[]'); assert.equal( - tag.validate(snapshot), + validate(tag, snapshot), false, 'invalid after pushing an object and notifying on the array' ); @@ -325,14 +326,14 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { let obj = new EmberObject(); let tag = tagForProperty(obj, 'emberArray'); - let snapshot = tag.value(); + let snapshot = value(tag); let emberArray = get(obj, 'emberArray'); - assert.equal(tag.validate(snapshot), true); + assert.equal(validate(tag, snapshot), true); notifyPropertyChange(emberArray, '[]'); assert.equal( - tag.validate(snapshot), + validate(tag, snapshot), false, 'invalid after setting a property on the object' ); diff --git a/packages/@ember/-internals/runtime/lib/mixins/-proxy.js b/packages/@ember/-internals/runtime/lib/mixins/-proxy.js index 2ed537a9787..f0244f783cd 100644 --- a/packages/@ember/-internals/runtime/lib/mixins/-proxy.js +++ b/packages/@ember/-internals/runtime/lib/mixins/-proxy.js @@ -2,7 +2,6 @@ @module ember */ -import { combine, CONSTANT_TAG, DirtyableTag, UpdatableTag } from '@glimmer/reference'; import { meta } from '@ember/-internals/meta'; import { get, @@ -20,12 +19,13 @@ import { import { setProxy } from '@ember/-internals/utils'; import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import { assert } from '@ember/debug'; +import { combine, update } from '@glimmer/reference'; export function contentFor(proxy, m) { let content = get(proxy, 'content'); let tag = (m === undefined ? meta(proxy) : m).readableTag(); if (tag !== undefined) { - tag.inner.second.inner.update(tagFor(content)); + update(tag, tagFor(content)); } return content; } @@ -53,7 +53,7 @@ export default Mixin.create({ this._super(...arguments); setProxy(this); let m = meta(this); - m.writableTag(() => combine([DirtyableTag.create(), UpdatableTag.create(CONSTANT_TAG)])); + m.writableTag(); }, willDestroy() { diff --git a/packages/@ember/-internals/runtime/lib/system/array_proxy.js b/packages/@ember/-internals/runtime/lib/system/array_proxy.js index 2e33e2031a3..2c52936ec41 100644 --- a/packages/@ember/-internals/runtime/lib/system/array_proxy.js +++ b/packages/@ember/-internals/runtime/lib/system/array_proxy.js @@ -16,7 +16,7 @@ import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import EmberObject from './object'; import { isArray, MutableArray } from '../mixins/array'; import { assert } from '@ember/debug'; -import { combine } from '@glimmer/reference'; +import { combine, validate, value } from '@glimmer/reference'; const ARRAY_OBSERVER_MAPPING = { willChange: '_arrangedContentArrayWillChange', @@ -108,7 +108,7 @@ export default class ArrayProxy extends EmberObject { if (EMBER_METAL_TRACKED_PROPERTIES) { this._arrangedContentIsUpdating = false; this._arrangedContentTag = combine(getChainTagsForKey(this, 'arrangedContent')); - this._arrangedContentRevision = this._arrangedContentTag.value(); + this._arrangedContentRevision = value(this._arrangedContentTag); } this._addArrangedContentArrayObsever(); @@ -313,14 +313,14 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { _revalidate = function() { if ( !this._arrangedContentIsUpdating && - !this._arrangedContentTag.validate(this._arrangedContentRevision) + !validate(this._arrangedContentTag, this._arrangedContentRevision) ) { this._arrangedContentIsUpdating = true; this._updateArrangedContentArray(); this._arrangedContentIsUpdating = false; this._arrangedContentTag = combine(getChainTagsForKey(this, 'arrangedContent')); - this._arrangedContentRevision = this._arrangedContentTag.value(); + this._arrangedContentRevision = value(this._arrangedContentTag); } }; } diff --git a/packages/@ember/object/compat.ts b/packages/@ember/object/compat.ts index fe73e661022..9894c583ada 100644 --- a/packages/@ember/object/compat.ts +++ b/packages/@ember/object/compat.ts @@ -7,17 +7,17 @@ import { setClassicDecorator, tagForProperty, track, - update, } from '@ember/-internals/metal'; import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; import { assert } from '@ember/debug'; +import { UpdatableTag, update } from '@glimmer/reference'; let wrapGetterSetter = function(_target: object, key: string, desc: PropertyDescriptor) { let { get: originalGet } = desc; if (originalGet !== undefined) { desc.get = function() { - let propertyTag = tagForProperty(this, key); + let propertyTag = tagForProperty(this, key) as UpdatableTag; let ret; let tag = track(() => { diff --git a/yarn.lock b/yarn.lock index f80c6bab018..c327bb4a26e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -668,122 +668,122 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@glimmer/compiler@0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.38.5-alpha.1.tgz#bd34a40d167c0bd589f8b9084adf49d771466747" - integrity sha512-PqliDQUQkwIDsxzFfSKsgQUkLk6/rQ5BaF2cSI5i6D8T1J+ZUgzT0NaHNiDCVWUSsqd+SDaFe/NjG3cP/dplVw== +"@glimmer/compiler@0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.38.5-alpha.2.tgz#a133074450c0b75446ece387edfd0f0631e49b94" + integrity sha512-4tx4DkKooVwX2N7J52+W25RqAwPkl91bOgHo23bMXgQSjQgHNOTHDVuB0ov+nbf5OV6cebnGkvfwsoWINc9eew== dependencies: - "@glimmer/interfaces" "^0.38.5-alpha.1" - "@glimmer/syntax" "^0.38.5-alpha.1" - "@glimmer/util" "^0.38.5-alpha.1" - "@glimmer/wire-format" "^0.38.5-alpha.1" + "@glimmer/interfaces" "^0.38.5-alpha.2" + "@glimmer/syntax" "^0.38.5-alpha.2" + "@glimmer/util" "^0.38.5-alpha.2" + "@glimmer/wire-format" "^0.38.5-alpha.2" -"@glimmer/encoder@^0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.38.5-alpha.1.tgz#761bd2b45fcb48077a88ed69325b73102b3be02d" - integrity sha512-rw9SpDn5fZaZ0pqb6oEGp6MLgqqHGYpF9r7wi6v10Ky0//hl0aJL8rw1ZpCkqRQZ3awtKhZK6pBxNB9L3Dp8cw== +"@glimmer/encoder@^0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.38.5-alpha.2.tgz#e6dd9cf971cdb225273a62b66ca05fc70d8836a5" + integrity sha512-X5MUstqxsj5xsNyGuXxGXwy20rc3twUAdKOgots4YLJYzG/3Sjiw6zyoxue4bKNwZ/9iyTg1kNsCCfl/ep64Rg== dependencies: - "@glimmer/interfaces" "^0.38.5-alpha.1" - "@glimmer/vm" "^0.38.5-alpha.1" + "@glimmer/interfaces" "^0.38.5-alpha.2" + "@glimmer/vm" "^0.38.5-alpha.2" "@glimmer/env@^0.1.7": version "0.1.7" resolved "https://registry.yarnpkg.com/@glimmer/env/-/env-0.1.7.tgz#fd2d2b55a9029c6b37a6c935e8c8871ae70dfa07" integrity sha1-/S0rVakCnGs3psk16MiHGucN+gc= -"@glimmer/interfaces@0.38.5-alpha.1", "@glimmer/interfaces@^0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.38.5-alpha.1.tgz#c1bbb7604c272fa879cd00dcbb9191efb22204a2" - integrity sha512-Q38UPwaIzTNgqh00fjf7BqMxtlHL2tchOqf3wKYWK0csfMhR+NvmWGVP02sr7vbXxw0+rf1hg9iv+Ejburbgqw== +"@glimmer/interfaces@0.38.5-alpha.2", "@glimmer/interfaces@^0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.38.5-alpha.2.tgz#841370dc9112402a2aaf8add8bfefab83bc26793" + integrity sha512-7jsfMWFTNuA5ZObbAPPV7WelPAf2aW8YbjR1Dqsvwm/3ZJ7pbX6xTx7b4VeWx8k6oDF/xgQ4txoZ4YVYlgMOqw== dependencies: - "@glimmer/wire-format" "^0.38.5-alpha.1" + "@glimmer/wire-format" "^0.38.5-alpha.2" "@simple-dom/interface" "1.4.0" -"@glimmer/low-level@^0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/low-level/-/low-level-0.38.5-alpha.1.tgz#87d920cc3bbd4cff683a0d0f425b323804efa232" - integrity sha512-1wv8qR/t/OayqCW0S+mMGmpsQblRInR3pY8ueQrpUrTIqwTiZ7/u5k+4/H9fIbEHLe8Egt464QY5On0PNylqeQ== - -"@glimmer/node@0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.38.5-alpha.1.tgz#b48508bc6c8736cf06a6540da4f2697d1054f23f" - integrity sha512-yn4ll0xJXFNA993/Y4FNVnUY4BM+DGVYGBTODuHr8AXP0a4AqtsYhHpsk9u8RO+HaKHURYWJrTJNn4rwE8OLLA== - dependencies: - "@glimmer/interfaces" "^0.38.5-alpha.1" - "@glimmer/runtime" "^0.38.5-alpha.1" - -"@glimmer/opcode-compiler@0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/opcode-compiler/-/opcode-compiler-0.38.5-alpha.1.tgz#d51a564115d728efe32b286d46fb2ac17c235c6f" - integrity sha512-kSOnXxmZQkxP2h+IdxnwP9nxFjHISuEkyzqPRu0TP2+036NWtExLPjsapcDn4LqFXNz8Dkr1AKPKxBN5ldXCAA== - dependencies: - "@glimmer/encoder" "^0.38.5-alpha.1" - "@glimmer/interfaces" "^0.38.5-alpha.1" - "@glimmer/program" "^0.38.5-alpha.1" - "@glimmer/reference" "^0.38.5-alpha.1" - "@glimmer/util" "^0.38.5-alpha.1" - "@glimmer/vm" "^0.38.5-alpha.1" - "@glimmer/wire-format" "^0.38.5-alpha.1" - -"@glimmer/program@0.38.5-alpha.1", "@glimmer/program@^0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.38.5-alpha.1.tgz#559f2ccd8f0b49e5e150aed4100da3481165f628" - integrity sha512-4WcNGAGELB5+x2r9k4Fxtbvwr/8gkjQu2Tc5pRHIWCSaY2VaIvuh9PvSsZnFgWyG2i1MnKRGoiQANp0jtvIxqQ== - dependencies: - "@glimmer/encoder" "^0.38.5-alpha.1" - "@glimmer/interfaces" "^0.38.5-alpha.1" - "@glimmer/util" "^0.38.5-alpha.1" - -"@glimmer/reference@0.38.5-alpha.1", "@glimmer/reference@^0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.38.5-alpha.1.tgz#36b06ce7bdeb9fb6e7177837fc504e2576c0885c" - integrity sha512-C08ZG7FsLD8Ogu2mhoNPLAVKIlq6NQABo8mTHxZdNLFynfI3vVToDxWrGZwpAW3fbom1ldxErHNwcy2fHLgV/Q== - dependencies: - "@glimmer/util" "^0.38.5-alpha.1" - -"@glimmer/runtime@0.38.5-alpha.1", "@glimmer/runtime@^0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.38.5-alpha.1.tgz#870b6028cda8af5d9f3e7a8bd35c8e03848bb644" - integrity sha512-fPIDxAfq8WhJiXsZprHHvHK26n1+ENW0fGSrEmGBAEHWLxnhI1xHOZcj5/06IU7y/R/7c98iaAu6D+B23CMFsQ== - dependencies: - "@glimmer/interfaces" "^0.38.5-alpha.1" - "@glimmer/low-level" "^0.38.5-alpha.1" - "@glimmer/program" "^0.38.5-alpha.1" - "@glimmer/reference" "^0.38.5-alpha.1" - "@glimmer/util" "^0.38.5-alpha.1" - "@glimmer/vm" "^0.38.5-alpha.1" - "@glimmer/wire-format" "^0.38.5-alpha.1" +"@glimmer/low-level@^0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/low-level/-/low-level-0.38.5-alpha.2.tgz#0a8769fa7f4cce9a81e4d69ea76a7aaa817ba6db" + integrity sha512-GHZJ9AafVBtnWQRbEf56JCgptQm6isEdKuSD0sZUUNVkbXaxHDnHPDTDLmA7e4VZV6fKampKUgHv963Oug5dRw== + +"@glimmer/node@0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.38.5-alpha.2.tgz#7227de7ac22a94b2963a009953aa197575010ca7" + integrity sha512-4vo9uhIdbQlgfecHpFWf80fXr2q3uO3Ahe66Ab0E3SCe6VeaqrX6o4YUFF7hg05X567w9hcOcf1zp76xLBIYQw== + dependencies: + "@glimmer/interfaces" "^0.38.5-alpha.2" + "@glimmer/runtime" "^0.38.5-alpha.2" + +"@glimmer/opcode-compiler@0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/opcode-compiler/-/opcode-compiler-0.38.5-alpha.2.tgz#908ce6d198aff9430ec2c9511a02b5f63cea9b98" + integrity sha512-eXw45wB2cyOcvX6IP/LAkn9RBRNRKV9ISxMz2S3joZclo6/J5sXFK3rfJrJ5drKdRZI8iKekYGRKa2cnUkPTtg== + dependencies: + "@glimmer/encoder" "^0.38.5-alpha.2" + "@glimmer/interfaces" "^0.38.5-alpha.2" + "@glimmer/program" "^0.38.5-alpha.2" + "@glimmer/reference" "^0.38.5-alpha.2" + "@glimmer/util" "^0.38.5-alpha.2" + "@glimmer/vm" "^0.38.5-alpha.2" + "@glimmer/wire-format" "^0.38.5-alpha.2" + +"@glimmer/program@0.38.5-alpha.2", "@glimmer/program@^0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.38.5-alpha.2.tgz#df0e0a66c84410fa39c4b234fb37ad7b1da8dcda" + integrity sha512-2fHUg08rk0D4yWPV8ax7hqNW2mmWSLsEiXYcGH0ZQ7eZKgukO+pVJBvpSPIqBE8YN1iKXIi2m6xwoA4G14Cw9g== + dependencies: + "@glimmer/encoder" "^0.38.5-alpha.2" + "@glimmer/interfaces" "^0.38.5-alpha.2" + "@glimmer/util" "^0.38.5-alpha.2" + +"@glimmer/reference@0.38.5-alpha.2", "@glimmer/reference@^0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.38.5-alpha.2.tgz#116c29293f0b44c7cd4e289f68f1f164df0f0435" + integrity sha512-Av60bhB1RvQoSvC9nycpRE53+GgjkaxA369iFPilGeJ6KkyoZ0pAJ8s6TS6mCtykCvBqUWrj3JZyffqc8tmWxA== + dependencies: + "@glimmer/util" "^0.38.5-alpha.2" + +"@glimmer/runtime@0.38.5-alpha.2", "@glimmer/runtime@^0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.38.5-alpha.2.tgz#d01bd5077d406b0cb96bb082193b5368cd43e6ee" + integrity sha512-8/uRJ1p1G+ZmGD+IXyEyoRzvVMPUVRhvATNWz2JsOhsQnWTI8CzpZxewOvtGbSfkAfKWaY85W6CymphyZ5nLyA== + dependencies: + "@glimmer/interfaces" "^0.38.5-alpha.2" + "@glimmer/low-level" "^0.38.5-alpha.2" + "@glimmer/program" "^0.38.5-alpha.2" + "@glimmer/reference" "^0.38.5-alpha.2" + "@glimmer/util" "^0.38.5-alpha.2" + "@glimmer/vm" "^0.38.5-alpha.2" + "@glimmer/wire-format" "^0.38.5-alpha.2" "@simple-dom/interface" "^1.4.0" -"@glimmer/syntax@^0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.38.5-alpha.1.tgz#5b2c13aff088a39c326e142b465c57e7e3cf8ba9" - integrity sha512-VB5mQFqL2A9y8Sx9spALarokyZRfRzgClsmX+K3J19N+oLuXu8al9+5T9utDTLDZy33PQzFMkDYf/x91n3w7ow== +"@glimmer/syntax@^0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.38.5-alpha.2.tgz#cfdb27d351b741a6103d4994943d0b7c44b548eb" + integrity sha512-jKqhuNY/qyDLum/+93ycbblwflZyH0SuKrSnC2CMf5JBSNFmTrfVTzJyp7rzSJwcSfY3ul5qh8swH7KHCB7uDA== dependencies: - "@glimmer/interfaces" "^0.38.5-alpha.1" - "@glimmer/util" "^0.38.5-alpha.1" + "@glimmer/interfaces" "^0.38.5-alpha.2" + "@glimmer/util" "^0.38.5-alpha.2" handlebars "^4.0.6" - simple-html-tokenizer "^0.5.6" + simple-html-tokenizer "^0.5.8" -"@glimmer/util@^0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.38.5-alpha.1.tgz#2508e5015ab3a42262bf608d885233115488148e" - integrity sha512-JO7PDInhp0FepIx1V6XTPJ4q1xPlNtdS3B8j0uteNnhOPpkIMbpRLcJKPJbAHuFRORQBEDEeWzkZ6NAPpfVenQ== +"@glimmer/util@^0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.38.5-alpha.2.tgz#3f9c7be15e44746723d42558cfbd843943d11e33" + integrity sha512-uBqYFqwgl4x/socwx/RYsKG6NWrHtn5BQozX2vrGfcAQJ2U9DL1BwzxzNH8JNodECjdKCUyVwFjI3xWOmSYxRg== -"@glimmer/vm@^0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.38.5-alpha.1.tgz#20cad81985f58e512b95d5927230ac324c324e26" - integrity sha512-vLVLl+cYbJiUMsQe6PWWJtClrAZURSnvtUNSr1yIHto1ly7w1FDkNi3hbqkz9FPvWzw0L9ZE13uJgqX/2M5NGA== +"@glimmer/vm@^0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.38.5-alpha.2.tgz#de950abab4652cb043869222ecc9752ee7fac7ce" + integrity sha512-4Wypuu8cVE1eO17Zjp+SJWaIAZIoSAawNhJX0TA6d+qNBKPjzJLRPYUEKY5ti6hPl/lkIgCuVNGcTG34mr/sKw== dependencies: - "@glimmer/interfaces" "^0.38.5-alpha.1" - "@glimmer/util" "^0.38.5-alpha.1" + "@glimmer/interfaces" "^0.38.5-alpha.2" + "@glimmer/util" "^0.38.5-alpha.2" -"@glimmer/wire-format@^0.38.5-alpha.1": - version "0.38.5-alpha.1" - resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.38.5-alpha.1.tgz#f4b8476622cbe0b8cc0b0422677866d524aad2a1" - integrity sha512-BlgyY/11jaafWuK5DA13tvuwn1HOuso8MdW7PaFYqceFMYn/fhGrRXqcgeKiwT9p7U/LbNA1OZf678X2QYjzog== +"@glimmer/wire-format@^0.38.5-alpha.2": + version "0.38.5-alpha.2" + resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.38.5-alpha.2.tgz#9d699deaad4d2da2b67089e0d9eb733c14663b6c" + integrity sha512-NGmmqYdh+4bIffsaWZ6CVFOtoiahBfmLLr15++WYO2BIuKcLra7ZgvoBKciKu0y9x4Xd3Rt8lRS/CNdMvqzBLA== dependencies: - "@glimmer/util" "^0.38.5-alpha.1" + "@glimmer/util" "^0.38.5-alpha.2" "@simple-dom/document@^1.4.0": version "1.4.0" @@ -7413,10 +7413,10 @@ simple-dom@^1.4.0: "@simple-dom/serializer" "^1.4.0" "@simple-dom/void-map" "^1.4.0" -simple-html-tokenizer@^0.5.6: - version "0.5.6" - resolved "https://registry.yarnpkg.com/simple-html-tokenizer/-/simple-html-tokenizer-0.5.6.tgz#e1e442b14f5484bf9a7e2924f78f00855e6b3c14" - integrity sha512-WgtFeFTAzegTCs1/x096l79gscV43LS17fEXBjv1s26oqiu1qmTM0buaqba/HmlxHNfk4yJuKmSJoRDMWuQU6w== +simple-html-tokenizer@^0.5.8: + version "0.5.8" + resolved "https://registry.yarnpkg.com/simple-html-tokenizer/-/simple-html-tokenizer-0.5.8.tgz#3417382f75954ee34515cc4fd32d9918e693f173" + integrity sha512-0Sq4FvLlQEQODVA6PH2MIrc7tzYO0KT2HzzwvaVLYClWgIsuvaNUOrhrAvTi1pZHrcq7GDB4WiI3ukjqBMxcGQ== sinon@^1.17.6: version "1.17.7" From bd7f49282a489663cccdb7a2a948a60c62a51f29 Mon Sep 17 00:00:00 2001 From: Chris Garrett Date: Sun, 11 Aug 2019 15:50:28 -0700 Subject: [PATCH 3/5] Add test for 18253 --- .../glimmer/tests/integration/components/tracked-test.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js index 054d4f727b0..822e5be9961 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/tracked-test.js @@ -245,6 +245,10 @@ if (EMBER_METAL_TRACKED_PROPERTIES) { runTask(() => this.$('button').click()); this.assertText('1'); + + runTask(() => this.$('button').click()); + + this.assertText('2'); } '@test nested getters update when dependent properties are invalidated'() { From 546c30811da80f5903fe776136104d71d4920f2f Mon Sep 17 00:00:00 2001 From: Chris Garrett Date: Tue, 13 Aug 2019 09:08:44 -0700 Subject: [PATCH 4/5] [BUGFIX beta] Fixup typings and tag wrapper --- .../glimmer/lib/modifiers/action.ts | 6 +++--- .../glimmer/lib/utils/references.ts | 21 ------------------- .../@ember/-internals/metal/lib/chain-tags.ts | 1 + .../-internals/metal/tests/observer_test.js | 1 - 4 files changed, 4 insertions(+), 25 deletions(-) diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts index ef956ee4800..10d8b177b40 100644 --- a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts +++ b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts @@ -4,7 +4,7 @@ import { assert, deprecate } from '@ember/debug'; import { flaggedInstrument } from '@ember/instrumentation'; import { join } from '@ember/runloop'; import { Opaque, Simple } from '@glimmer/interfaces'; -import { RevisionTag, TagWrapper } from '@glimmer/reference'; +import { Tag } from '@glimmer/reference'; import { Arguments, CapturedNamedArguments, @@ -70,7 +70,7 @@ export class ActionState { public implicitTarget: any; public dom: any; public eventName: any; - public tag: TagWrapper; + public tag: Tag; constructor( element: Simple.Element, @@ -81,7 +81,7 @@ export class ActionState { positionalArgs: CapturedPositionalArguments, implicitTarget: any, dom: any, - tag: TagWrapper + tag: Tag ) { this.element = element; this.actionId = actionId; diff --git a/packages/@ember/-internals/glimmer/lib/utils/references.ts b/packages/@ember/-internals/glimmer/lib/utils/references.ts index b86470b1688..a1a84507dbf 100644 --- a/packages/@ember/-internals/glimmer/lib/utils/references.ts +++ b/packages/@ember/-internals/glimmer/lib/utils/references.ts @@ -27,9 +27,7 @@ import { UpdatableTag, update, validate, - VALIDATE, value, - VALUE, VersionedPathReference, VersionedReference, } from '@glimmer/reference'; @@ -116,36 +114,17 @@ if (DEBUG) { return (new TwoWayFlushDetectionTag(tag, key, ref) as unknown) as Tag; } - private parent: Opaque = null; - constructor( private tag: Tag, private key: string, private ref: VersionedPathReference ) {} - [VALUE](): Revision { - return value(this.tag); - } - [COMPUTE](): Revision { return this.tag[COMPUTE](); } - [VALIDATE](ticket: Revision): boolean { - let { parent, key, ref } = this; - - let isValid = validate(this.tag, ticket); - - if (isValid && parent) { - didRender(parent, key, ref); - } - - return isValid; - } - didCompute(parent: Opaque): void { - this.parent = parent; didRender(parent, this.key, this.ref); } }; diff --git a/packages/@ember/-internals/metal/lib/chain-tags.ts b/packages/@ember/-internals/metal/lib/chain-tags.ts index 2cf4aa60b31..1645c37d99a 100644 --- a/packages/@ember/-internals/metal/lib/chain-tags.ts +++ b/packages/@ember/-internals/metal/lib/chain-tags.ts @@ -53,6 +53,7 @@ export function getChainTagsForKey(obj: any, path: string) { // prevent closures let segment: string, descriptor: any; + // eslint-disable-next-line no-constant-condition while (true) { let currentType = typeof current; diff --git a/packages/@ember/-internals/metal/tests/observer_test.js b/packages/@ember/-internals/metal/tests/observer_test.js index 19a7c87817e..b66a576577c 100644 --- a/packages/@ember/-internals/metal/tests/observer_test.js +++ b/packages/@ember/-internals/metal/tests/observer_test.js @@ -15,7 +15,6 @@ import { changeProperties, get, set, - alias, } from '..'; import { moduleFor, AbstractTestCase, runLoopSettled } from 'internal-test-helpers'; import { FUNCTION_PROTOTYPE_EXTENSIONS } from '@ember/deprecated-features'; From 5bbd43e06a8afdcad13b13d596a01420a6fcea67 Mon Sep 17 00:00:00 2001 From: Chris Garrett Date: Tue, 13 Aug 2019 19:26:22 -0700 Subject: [PATCH 5/5] wtf Edge --- packages/internal-test-helpers/lib/ember-dev/assertion.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/internal-test-helpers/lib/ember-dev/assertion.ts b/packages/internal-test-helpers/lib/ember-dev/assertion.ts index 2f8f188d565..ae1025d7015 100644 --- a/packages/internal-test-helpers/lib/ember-dev/assertion.ts +++ b/packages/internal-test-helpers/lib/ember-dev/assertion.ts @@ -31,6 +31,8 @@ const BREAK = {}; disrupt the control flow. */ export function setupAssertionHelpers(hooks: NestedHooks, env: DebugEnv) { + let originalAssertFunc = env.getDebugFunction('assert'); + hooks.beforeEach(function(assert) { let expectAssertion: ExpectAssertionFunc = (func: () => void, expectedMessage: Message) => { if (!DEBUG) { @@ -70,6 +72,10 @@ export function setupAssertionHelpers(hooks: NestedHooks, env: DebugEnv) { }); hooks.afterEach(function() { + // Edge will occasionally not run finally blocks, so we have to be extra + // sure we restore the original assert function + env.setDebugFunction('assert', originalAssertFunc); + window.expectAssertion = null; window.ignoreAssertion = null; });