From c8bf56326542479e9b5e7f7e2755342528e30712 Mon Sep 17 00:00:00 2001 From: Christopher Garrett Date: Thu, 4 Feb 2021 10:36:58 -0800 Subject: [PATCH] wip --- .../extension-support/lib/data_adapter.js | 141 +++++++++--------- 1 file changed, 70 insertions(+), 71 deletions(-) diff --git a/packages/@ember/-internals/extension-support/lib/data_adapter.js b/packages/@ember/-internals/extension-support/lib/data_adapter.js index 4c95da25460..6f66ed5a6e6 100644 --- a/packages/@ember/-internals/extension-support/lib/data_adapter.js +++ b/packages/@ember/-internals/extension-support/lib/data_adapter.js @@ -6,7 +6,7 @@ import { Namespace, Object as EmberObject, A as emberA } from '@ember/-internals import { consumeTag, createCache, getValue, tagFor, untrack } from '@glimmer/validator'; function iterate(arr, fn) { - if (Symbol.iterator in arr) { + if (typeof Symbol !== 'undefined' && Symbol.iterator in arr) { for (let item of arr) { fn(item); } @@ -18,67 +18,70 @@ function iterate(arr, fn) { class RecordsWatcher { recordCaches = new Map(); - constructor(records, recordsAdded, recordsUpdated, recordsRemoved, wrapRecord, release) { - let { recordCaches } = this; - - this.release = release; + added = []; + updated = []; + removed = []; - let added, updated, removed; + getCacheForItem(record) { + let recordCache = this.recordCaches.get(record); - this.recordArrayCache = createCache(() => { - let seen = new Set(); + if (!recordCache) { + let hasBeenAdded = false; - added = []; - updated = []; - removed = []; - - // Track `[]` for legacy support - consumeTag(tagFor(records, '[]')); + recordCache = createCache(() => { + if (!hasBeenAdded) { + this.added.push(this.wrapRecord(record)); + hasBeenAdded = true; + } else { + this.updated.push(this.wrapRecord(record)); + } + }); - iterate(records, (record) => { - let recordCache = recordCaches.get(record); + this.recordCaches.set(record, recordCache); + } - if (!recordCache) { - let hasBeenAdded = false; + return recordCache; + } - recordCache = createCache(() => { - if (!hasBeenAdded) { - added.push(wrapRecord(record)); - hasBeenAdded = true; - } else { - updated.push(wrapRecord(record)); - } - }); + constructor(records, recordsAdded, recordsUpdated, recordsRemoved, wrapRecord, release) { + this.release = release; + this.wrapRecord = wrapRecord; - recordCaches.set(record, recordCache); - } + this.recordArrayCache = createCache(() => { + let seen = new Set(); - getValue(recordCache); + // Track `[]` for legacy support + consumeTag(tagFor(records, '[]')); + iterate(records, record => { + getValue(this.getCacheForItem(record)); seen.add(record); }); // Untrack this operation because these records are being removed, they // should not be polled again in the future untrack(() => { - recordCaches.forEach((cache, record) => { + this.recordCaches.forEach((cache, record) => { if (!seen.has(record)) { - removed.push(wrapRecord(record)); - recordCaches.delete(record); + this.removed.push(wrapRecord(record)); + this.recordCaches.delete(record); } }); }); - if (added.length > 0) { - recordsAdded(added); + if (this.added.length > 0) { + recordsAdded(this.added); + this.added = []; } - if (updated.length > 0) { - recordsUpdated(updated); + if (this.updated.length > 0) { + recordsUpdated(this.updated); + this.updated = []; } - if (removed.length > 0) { - recordsRemoved(removed); + if (this.removed.length > 0) { + recordsRemoved(this.removed); + this.removed = []; } }); } @@ -165,7 +168,7 @@ export default EmberObject.extend({ this.releaseMethods = emberA(); this.recordsWatchers = new Map(); this.typeWatchers = new Map(); - this.flushWatchers = this.flushWatchers.bind(this); + this.flushWatchers = null; }, /** @@ -212,7 +215,6 @@ export default EmberObject.extend({ @property recordsWatchers @since 3.26.0 */ - recordsWatchers: null, /** Map from records arrays to TypeWatcher instances @@ -221,7 +223,6 @@ export default EmberObject.extend({ @property typeWatchers @since 3.26.0 */ - typeWatchers: null, /** Stores all methods that clear observers. @@ -231,7 +232,6 @@ export default EmberObject.extend({ @property releaseMethods @since 1.3.0 */ - releaseMethods: null, /** Specifies how records can be filtered. @@ -266,7 +266,7 @@ export default EmberObject.extend({ let releaseMethods = emberA(); let typesToSend; - typesToSend = modelTypes.map((type) => { + typesToSend = modelTypes.map(type => { let klass = type.klass; let wrapped = this.wrapModelType(klass, type.name); releaseMethods.push(this.observeModelType(type.name, typesUpdated)); @@ -276,7 +276,7 @@ export default EmberObject.extend({ typesAdded(typesToSend); let release = () => { - releaseMethods.forEach((fn) => fn()); + releaseMethods.forEach(fn => fn()); this.releaseMethods.removeObject(release); }; this.releaseMethods.pushObject(release); @@ -322,26 +322,20 @@ export default EmberObject.extend({ let recordsWatcher = recordsWatchers.get(records); if (!recordsWatcher) { - if (recordsWatchers.size === 0) { - backburner.on('end', this.flushWatchers); - } - recordsWatcher = new RecordsWatcher( records, recordsAdded, recordsUpdated, recordsRemoved, - (record) => this.wrapRecord(record), + record => this.wrapRecord(record), () => { - if (recordsWatchers.size === 1) { - backburner.off('end', this.flushWatchers); - } - recordsWatchers.delete(records); + this.updateFlushWatchers(); } ); recordsWatchers.set(records, recordsWatcher); + this.updateFlushWatchers(); recordsWatcher.revalidate(); } @@ -349,10 +343,21 @@ export default EmberObject.extend({ return recordsWatcher.release; }, - flushWatchers() { - this.typeWatchers.forEach((watcher) => watcher.revalidate()); - this.recordsWatchers.forEach((watcher) => watcher.revalidate()); - }, + updateFlushWatchers() { + if (this.flushWatchers === null) { + if (this.typeWatchers.size > 0 || this.recordsWatchers.size > 0) { + this.flushWatchers = () => { + this.typeWatchers.forEach(watcher => watcher.revalidate()); + this.recordsWatchers.forEach(watcher => watcher.revalidate()); + } + + backburner.on('end', this.flushWatchers); + } + } else if (this.typeWatchers.size === 0 && this.recordsWatchers.size === 0) { + backburner.off('end', this.flushWatchers); + this.flushWatchers = null; + } + } /** Clear all observers before destruction @@ -362,10 +367,10 @@ export default EmberObject.extend({ willDestroy() { this._super(...arguments); - this.typeWatchers.forEach((watcher) => watcher.release()); - this.recordsWatchers.forEach((watcher) => watcher.release()); + this.typeWatchers.forEach(watcher => watcher.release()); + this.recordsWatchers.forEach(watcher => watcher.release()); - this.releaseMethods.forEach((fn) => fn()); + this.releaseMethods.forEach(fn => fn()); }, /** @@ -418,19 +423,13 @@ export default EmberObject.extend({ let typeWatcher = typeWatchers.get(records); if (!typeWatcher) { - if (typeWatchers.size === 0) { - backburner.on('end', this.flushWatchers); - } - typeWatcher = new TypeWatcher(records, onChange, () => { - if (typeWatchers.size === 1) { - backburner.off('end', this.flushWatchers); - } - typeWatchers.delete(records); + this.updateFlushWatchers(); }); typeWatchers.set(records, typeWatcher); + this.updateFlushWatchers(); typeWatcher.revalidate(); } @@ -487,13 +486,13 @@ export default EmberObject.extend({ } // New adapters return strings instead of classes. - types = emberA(types).map((name) => { + types = emberA(types).map(name => { return { klass: this._nameToClass(name), name, }; }); - types = emberA(types).filter((type) => this.detect(type.klass)); + types = emberA(types).filter(type => this.detect(type.klass)); return emberA(types); }, @@ -510,7 +509,7 @@ export default EmberObject.extend({ let namespaces = emberA(Namespace.NAMESPACES); let types = emberA(); - namespaces.forEach((namespace) => { + namespaces.forEach(namespace => { for (let key in namespace) { if (!Object.prototype.hasOwnProperty.call(namespace, key)) { continue;