dist/globals/ember-data.prod.js in ember-data-source-3.0.0 vs dist/globals/ember-data.prod.js in ember-data-source-3.0.1

- old
+ new

@@ -4,11 +4,11 @@ /*! * @overview Ember Data * @copyright Copyright 2011-2017 Tilde Inc. and contributors. * Portions Copyright 2011 LivingSocial Inc. * @license Licensed under MIT license (see license.js) - * @version 3.0.0 + * @version 3.0.1 */ var loader, define, requireModule, require, requirejs; (function (global) { @@ -2654,16 +2654,28 @@ } } return true; } + // Handle dematerialization for relationship `rel`. In all cases, notify the + // relatinoship of the dematerialization: this is done so the relationship can + // notify its inverse which needs to update state + // + // If the inverse is sync, unloading this record is treated as a client-side + // delete, so we remove the inverse records from this relationship to + // disconnect the graph. Because it's not async, we don't need to keep around + // the internalModel as an id-wrapper for references and because the graph is + // disconnected we can actually destroy the internalModel when checking for + // orphaned models. function destroyRelationship(rel) { - if (rel._inverseIsAsync()) { - rel.removeInternalModelFromInverse(rel.inverseInternalModel); - rel.removeInverseRelationships(); - } else { - rel.removeCompletelyFromInverse(); + rel.internalModelDidDematerialize(); + + if (rel._inverseIsSync()) { + // disconnect the graph so that the sync inverse relationship does not + // prevent us from cleaning up during `_cleanupOrphanedInternalModels` + rel.removeAllInternalModelsFromOwn(); + rel.removeAllCanonicalInternalModelsFromOwn(); } } // this (and all heimdall instrumentation) will be stripped by a babel transform // https://github.com/heimdalljs/babel5-plugin-strip-heimdall @@ -2876,10 +2888,11 @@ }); }; InternalModel.prototype._directlyRelatedInternalModels = function _directlyRelatedInternalModels() { var array = []; + this._relationships.forEach(function (name, rel) { array = array.concat(rel.members.list, rel.canonicalMembers.list); }); return array; }; @@ -3267,14 +3280,11 @@ var implicitRelationships = this._implicitRelationships; this.__implicitRelationships = null; Object.keys(implicitRelationships).forEach(function (key) { var rel = implicitRelationships[key]; - destroyRelationship(rel); - - rel.destroy(); }); }; InternalModel.prototype.preloadData = function preloadData(preload) { var _this = this; @@ -8476,10 +8486,11 @@ this.canonicalState = internalModel; _Relationship.prototype.addCanonicalInternalModel.call(this, internalModel); }; BelongsToRelationship.prototype.inverseDidDematerialize = function inverseDidDematerialize() { + _Relationship.prototype.inverseDidDematerialize.call(this, this.inverseInternalModel); this.notifyBelongsToChanged(); }; BelongsToRelationship.prototype.removeCompletelyFromOwn = function removeCompletelyFromOwn(internalModel) { _Relationship.prototype.removeCompletelyFromOwn.call(this, internalModel); @@ -8492,10 +8503,16 @@ this.inverseInternalModel = null; this.notifyBelongsToChanged(); } }; + BelongsToRelationship.prototype.removeCompletelyFromInverse = function removeCompletelyFromInverse() { + _Relationship.prototype.removeCompletelyFromInverse.call(this); + + this.inverseInternalModel = null; + }; + BelongsToRelationship.prototype.flushCanonical = function flushCanonical() { //temporary fix to not remove newly created records if server returned null. //TODO remove once we have proper diffing if (this.inverseInternalModel && this.inverseInternalModel.isNew() && !this.canonicalState) { return; @@ -8536,10 +8553,16 @@ this.inverseInternalModel = null; _Relationship.prototype.removeInternalModelFromOwn.call(this, internalModel); this.notifyBelongsToChanged(); }; + BelongsToRelationship.prototype.removeAllInternalModelsFromOwn = function removeAllInternalModelsFromOwn() { + _Relationship.prototype.removeAllInternalModelsFromOwn.call(this); + this.inverseInternalModel = null; + this.notifyBelongsToChanged(); + }; + BelongsToRelationship.prototype.notifyBelongsToChanged = function notifyBelongsToChanged() { this.internalModel.notifyBelongsToChanged(this.key); }; BelongsToRelationship.prototype.removeCanonicalInternalModelFromOwn = function removeCanonicalInternalModelFromOwn(internalModel) { @@ -8548,10 +8571,15 @@ } this.canonicalState = null; _Relationship.prototype.removeCanonicalInternalModelFromOwn.call(this, internalModel); }; + BelongsToRelationship.prototype.removeAllCanonicalInternalModelsFromOwn = function removeAllCanonicalInternalModelsFromOwn() { + _Relationship.prototype.removeAllCanonicalInternalModelsFromOwn.call(this); + this.canonicalState = null; + }; + BelongsToRelationship.prototype.findRecord = function findRecord() { if (this.inverseInternalModel) { return this.store._findByInternalModel(this.inverseInternalModel); } else { return EmberPromise.resolve(null); @@ -8808,11 +8836,16 @@ var _this = _possibleConstructorReturn(this, _Relationship.call(this, store, internalModel, inverseKey, relationshipMeta)); _this.belongsToType = relationshipMeta.type; _this.canonicalState = []; _this.isPolymorphic = relationshipMeta.options.polymorphic; + // The ManyArray for this relationship _this._manyArray = null; + // The previous ManyArray for this relationship. It will be destroyed when + // we create a new many array, but in the interim it will be updated if + // inverse internal models are unloaded. + _this._retainedManyArray = null; _this.__loadingPromise = null; return _this; } ManyRelationship.prototype._updateLoadingPromise = function _updateLoadingPromise(promise, content) { @@ -8860,14 +8893,18 @@ this.canonicalState.push(internalModel); } _Relationship.prototype.addCanonicalInternalModel.call(this, internalModel, idx); }; - ManyRelationship.prototype.inverseDidDematerialize = function inverseDidDematerialize() { - if (this._manyArray) { - this._manyArray.destroy(); - this._manyArray = null; + ManyRelationship.prototype.inverseDidDematerialize = function inverseDidDematerialize(inverseInternalModel) { + _Relationship.prototype.inverseDidDematerialize.call(this, inverseInternalModel); + if (this.isAsync) { + if (this._manyArray) { + this._retainedManyArray = this._manyArray; + this._manyArray = null; + } + this._removeInternalModelFromManyArray(this._retainedManyArray, inverseInternalModel); } this.notifyHasManyChanged(); }; ManyRelationship.prototype.addInternalModel = function addInternalModel(internalModel, idx) { @@ -8892,10 +8929,16 @@ this.canonicalState.splice(i, 1); } _Relationship.prototype.removeCanonicalInternalModelFromOwn.call(this, internalModel, idx); }; + ManyRelationship.prototype.removeAllCanonicalInternalModelsFromOwn = function removeAllCanonicalInternalModelsFromOwn() { + _Relationship.prototype.removeAllCanonicalInternalModelsFromOwn.call(this); + this.canonicalMembers.clear(); + this.canonicalState.splice(0, this.canonicalState.length); + }; + ManyRelationship.prototype.removeCompletelyFromOwn = function removeCompletelyFromOwn(internalModel) { _Relationship.prototype.removeCompletelyFromOwn.call(this, internalModel); var canonicalIndex = this.canonicalState.indexOf(internalModel); @@ -8924,11 +8967,37 @@ ManyRelationship.prototype.removeInternalModelFromOwn = function removeInternalModelFromOwn(internalModel, idx) { if (!this.members.has(internalModel)) { return; } _Relationship.prototype.removeInternalModelFromOwn.call(this, internalModel, idx); - var manyArray = this.manyArray; + // note that ensuring the many array is created, via `this.manyArray` + // (instead of `this._manyArray`) is intentional. + // + // Because we're removing from local, and not canonical, state, it is + // important that the many array is initialized now with those changes, + // otherwise it will be initialized with canonical state and we'll have + // lost the fact that this internalModel was removed. + this._removeInternalModelFromManyArray(this.manyArray, internalModel, idx); + this._removeInternalModelFromManyArray(this._retainedManyArray, internalModel, idx); + }; + + ManyRelationship.prototype.removeAllInternalModelsFromOwn = function removeAllInternalModelsFromOwn() { + _Relationship.prototype.removeAllInternalModelsFromOwn.call(this); + // as with removeInternalModelFromOwn, we make sure the many array is + // instantiated, or we'll lose local removals, as we're not updating + // canonical state here. + this.manyArray.clear(); + if (this._retainedManyArray) { + this._retainedManyArray.clear(); + } + }; + + ManyRelationship.prototype._removeInternalModelFromManyArray = function _removeInternalModelFromManyArray(manyArray, internalModel, idx) { + if (manyArray === null) { + return; + } + if (idx !== undefined) { //TODO(Igor) not used currently, fix manyArray.currentState.removeAt(idx); } else { manyArray._removeInternalModels([internalModel]); @@ -9086,16 +9155,18 @@ ManyRelationship.prototype.destroy = function destroy() { _Relationship.prototype.destroy.call(this); var manyArray = this._manyArray; if (manyArray) { manyArray.destroy(); + this._manyArray = null; } var proxy = this.__loadingPromise; if (proxy) { proxy.destroy(); + this.__loadingPromise = null; } }; _createClass(ManyRelationship, [{ key: '_loadingPromise', @@ -9103,21 +9174,30 @@ return this.__loadingPromise; } }, { key: 'manyArray', get: function () { + (false && Ember.assert('Error: relationship ' + this.parentType + ':' + this.key + ' has both many array and retained many array', this._manyArray === null || this._retainedManyArray === null)); + + if (!this._manyArray) { this._manyArray = _manyArray.default.create({ canonicalState: this.canonicalState, store: this.store, relationship: this, type: this.store.modelFor(this.belongsToType), record: this.internalModel, meta: this.meta, isPolymorphic: this.isPolymorphic }); + + if (this._retainedManyArray !== null) { + this._retainedManyArray.destroy(); + this._retainedManyArray = null; + } } + return this._manyArray; } }]); return ManyRelationship; @@ -9166,10 +9246,11 @@ return Constructor; }; }(); var guidFor = Ember.guidFor; + var get = Ember.get; var Relationship = function () { function Relationship(store, internalModel, inverseKey, relationshipMeta) { var async = relationshipMeta.options.async; var polymorphic = relationshipMeta.options.polymorphic; @@ -9187,38 +9268,56 @@ this.inverseKeyForImplicit = this.internalModel.modelName + this.key; this.linkPromise = null; this.meta = null; this.hasData = false; this.hasLoaded = false; + this.__inverseMeta = undefined; } Relationship.prototype._inverseIsAsync = function _inverseIsAsync() { - if (!this.inverseKey || !this.inverseInternalModel) { + var inverseMeta = this._inverseMeta; + if (!inverseMeta) { return false; } - return this.inverseInternalModel._relationships.get(this.inverseKey).isAsync; + + var inverseAsync = inverseMeta.options.async; + return typeof inverseAsync === 'undefined' ? true : inverseAsync; }; - Relationship.prototype.removeInverseRelationships = function removeInverseRelationships() { + Relationship.prototype._inverseIsSync = function _inverseIsSync() { + var inverseMeta = this._inverseMeta; + if (!inverseMeta) { + return false; + } + + var inverseAsync = inverseMeta.options.async; + return typeof inverseAsync === 'undefined' ? false : !inverseAsync; + }; + + Relationship.prototype.internalModelDidDematerialize = function internalModelDidDematerialize() { + var _this = this; + if (!this.inverseKey) { return; } - var allMembers = - // we actually want a union of members and canonicalMembers - // they should be disjoint but currently are not due to a bug - this.members.list.concat(this.canonicalMembers.list); + this.forAllMembers(function (inverseInternalModel) { + var relationship = inverseInternalModel._relationships.get(_this.inverseKey); + relationship.inverseDidDematerialize(_this.internalModel); + }); + }; - for (var i = 0; i < allMembers.length; i++) { - var inverseInternalModel = allMembers[i]; - var relationship = inverseInternalModel._relationships.get(this.inverseKey); - relationship.inverseDidDematerialize(); + Relationship.prototype.inverseDidDematerialize = function inverseDidDematerialize(inverseInternalModel) { + if (!this.isAsync) { + // unloading inverse of a sync relationship is treated as a client-side + // delete, so actually remove the models don't merely invalidate the cp + // cache. + this.removeInternalModelFromOwn(inverseInternalModel); + this.removeCanonicalInternalModelFromOwn(inverseInternalModel); } }; - Relationship.prototype.inverseDidDematerialize = function inverseDidDematerialize() {}; - Relationship.prototype.updateMeta = function updateMeta(meta) { this.meta = meta; }; Relationship.prototype.clear = function clear() { @@ -9234,23 +9333,33 @@ var _member = canonicalMembers[0]; this.removeCanonicalInternalModel(_member); } }; + Relationship.prototype.removeAllInternalModelsFromOwn = function removeAllInternalModelsFromOwn() { + this.members.clear(); + this.internalModel.updateRecordArrays(); + }; + + Relationship.prototype.removeAllCanonicalInternalModelsFromOwn = function removeAllCanonicalInternalModelsFromOwn() { + this.canonicalMembers.clear(); + this.flushCanonicalLater(); + }; + Relationship.prototype.removeInternalModels = function removeInternalModels(internalModels) { - var _this = this; + var _this2 = this; internalModels.forEach(function (internalModel) { - return _this.removeInternalModel(internalModel); + return _this2.removeInternalModel(internalModel); }); }; Relationship.prototype.addInternalModels = function addInternalModels(internalModels, idx) { - var _this2 = this; + var _this3 = this; internalModels.forEach(function (internalModel) { - _this2.addInternalModel(internalModel, idx); + _this3.addInternalModel(internalModel, idx); if (idx !== undefined) { idx++; } }); }; @@ -9289,11 +9398,11 @@ } } else { var _relationships = internalModel._implicitRelationships; var _relationship = _relationships[this.inverseKeyForImplicit]; if (!_relationship) { - _relationship = _relationships[this.inverseKeyForImplicit] = new Relationship(this.store, internalModel, this.key, { options: { async: this.isAsync } }); + _relationship = _relationships[this.inverseKeyForImplicit] = new Relationship(this.store, internalModel, this.key, { options: { async: this.isAsync }, type: this.parentType }); } _relationship.addCanonicalInternalModel(this.internalModel); } }; @@ -9327,11 +9436,11 @@ this.notifyRecordRelationshipAdded(internalModel, idx); if (this.inverseKey) { internalModel._relationships.get(this.inverseKey).addInternalModel(this.internalModel); } else { if (!internalModel._implicitRelationships[this.inverseKeyForImplicit]) { - internalModel._implicitRelationships[this.inverseKeyForImplicit] = new Relationship(this.store, internalModel, this.key, { options: { async: this.isAsync } }); + internalModel._implicitRelationships[this.inverseKeyForImplicit] = new Relationship(this.store, internalModel, this.key, { options: { async: this.isAsync }, type: this.parentType }); } internalModel._implicitRelationships[this.inverseKeyForImplicit].addInternalModel(this.internalModel); } this.internalModel.updateRecordArrays(); } @@ -9376,11 +9485,11 @@ this.canonicalMembers.delete(internalModel); this.flushCanonicalLater(); }; Relationship.prototype.removeCompletelyFromInverse = function removeCompletelyFromInverse() { - var _this3 = this; + var _this4 = this; if (!this.inverseKey) { return; } @@ -9391,20 +9500,46 @@ var unload = function (inverseInternalModel) { var id = guidFor(inverseInternalModel); if (seen[id] === undefined) { - var relationship = inverseInternalModel._relationships.get(_this3.inverseKey); + var relationship = inverseInternalModel._relationships.get(_this4.inverseKey); relationship.removeCompletelyFromOwn(internalModel); seen[id] = true; } }; this.members.forEach(unload); this.canonicalMembers.forEach(unload); + + if (!this.isAsync) { + this.clear(); + } }; + Relationship.prototype.forAllMembers = function forAllMembers(callback) { + var seen = Object.create(null); + + for (var i = 0; i < this.members.list.length; i++) { + var inverseInternalModel = this.members.list[i]; + var id = guidFor(inverseInternalModel); + if (!seen[id]) { + seen[id] = true; + callback(inverseInternalModel); + } + } + + for (var _i = 0; _i < this.canonicalMembers.list.length; _i++) { + var _inverseInternalModel = this.canonicalMembers.list[_i]; + var _id = guidFor(_inverseInternalModel); + if (!seen[_id]) { + seen[_id] = true; + callback(_inverseInternalModel); + } + } + }; + Relationship.prototype.removeCompletelyFromOwn = function removeCompletelyFromOwn(internalModel) { this.canonicalMembers.delete(internalModel); this.members.delete(internalModel); this.internalModel.updateRecordArrays(); }; @@ -9421,12 +9556,12 @@ } } //TODO(Igor) make this less abysmally slow this.members = this.canonicalMembers.copy(); - for (var _i = 0; _i < newInternalModels.length; _i++) { - this.members.add(newInternalModels[_i]); + for (var _i2 = 0; _i2 < newInternalModels.length; _i2++) { + this.members.add(newInternalModels[_i2]); } }; Relationship.prototype.flushCanonicalLater = function flushCanonicalLater() { if (this.willSync) { @@ -9523,10 +9658,27 @@ Relationship.prototype.updateData = function updateData() {}; Relationship.prototype.destroy = function destroy() {}; _createClass(Relationship, [{ + key: '_inverseMeta', + get: function () { + if (this.__inverseMeta === undefined) { + var inverseMeta = null; + + if (this.inverseKey) { + var inverseModelClass = this.store.modelFor(this.relationshipMeta.type); + var inverseRelationships = get(inverseModelClass, 'relationshipsByName'); + inverseMeta = inverseRelationships.get(this.inverseKey); + } + + this.__inverseMeta = inverseMeta; + } + + return this.__inverseMeta; + } + }, { key: 'parentType', get: function () { return this.internalModel.modelName; } }]); @@ -17928,10 +18080,10 @@ }); define("ember-data/version", ["exports"], function (exports) { "use strict"; exports.__esModule = true; - exports.default = "3.0.0"; + exports.default = "3.0.1"; }); define("ember-inflector", ["module", "exports", "ember-inflector/lib/system", "ember-inflector/lib/ext/string"], function (module, exports, _system) { "use strict"; exports.__esModule = true;