diff --git a/packages/-ember-data/tests/helpers/deprecated-test.js b/packages/-ember-data/tests/helpers/deprecated-test.js new file mode 100644 index 00000000000..f4ccb08b029 --- /dev/null +++ b/packages/-ember-data/tests/helpers/deprecated-test.js @@ -0,0 +1,44 @@ +import { test } from 'qunit'; +import VERSION from 'ember-data/version'; + +// small comparison function for major and minor semver values +function gte(EDVersion, DeprecationVersion) { + let _edv = EDVersion.split('.'); + let _depv = DeprecationVersion.split('.'); + // compare major + let major = +_edv[0] >= +_depv[0]; + // compare minor + let minor = +_edv[1] >= +_depv[1]; + return major || minor; +} + +export function deprecatedTest(testName, deprecation, testCallback) { + // '4.0' + if (typeof deprecation.until !== 'string' || deprecation.until.length < 3) { + throw new Error(`deprecatedTest expects { until } to be a version.`); + } + // 'ds.' + if (typeof deprecation.id !== 'string' || deprecation.id.length < 8) { + throw new Error(`deprecatedTest expects { id } to be a meaningful string`); + } + + if (gte(VERSION, deprecation.until)) { + test(`DEPRECATION ${deprecation.id} until ${deprecation.until} | ${testName}`, testCallback); + } else { + test(`DEPRECATION ${deprecation.id} until ${ + deprecation.until + } | ${testName}`, function(assert) { + if (deprecation.refactor === true) { + assert.ok( + false, + 'This test includes use of a deprecated feature that should now be refactored.' + ); + } else { + assert.ok( + false, + 'This test is for a deprecated feature whose time has come and should be removed' + ); + } + }); + } +} diff --git a/packages/-ember-data/tests/integration/lifecycle-hooks-test.js b/packages/-ember-data/tests/integration/lifecycle-hooks-test.js index f14b6f453ef..f3ad75edc22 100644 --- a/packages/-ember-data/tests/integration/lifecycle-hooks-test.js +++ b/packages/-ember-data/tests/integration/lifecycle-hooks-test.js @@ -1,8 +1,9 @@ import { resolve } from 'rsvp'; import { run } from '@ember/runloop'; +import { deprecatedTest } from 'dummy/tests/helpers/deprecated-test'; import setupStore from 'dummy/tests/helpers/store'; -import { module, test } from 'qunit'; +import { module } from 'qunit'; import DS from 'ember-data'; @@ -24,41 +25,55 @@ module('integration/lifecycle_hooks - Lifecycle Hooks', function(hooks) { run(env.container, 'destroy'); }); - test('When the adapter acknowledges that a record has been created, a `didCreate` event is triggered.', function(assert) { - let done = assert.async(); - assert.expect(3); - - env.adapter.createRecord = function(store, type, snapshot) { - return resolve({ data: { id: 99, type: 'person', attributes: { name: 'Yehuda Katz' } } }); - }; - - let person = env.store.createRecord('person', { name: 'Yehuda Katz' }); - - person.on('didCreate', function() { - assert.equal(this, person, 'this is bound to the record'); - assert.equal(this.get('id'), '99', 'the ID has been assigned'); - assert.equal(this.get('name'), 'Yehuda Katz', 'the attribute has been assigned'); - done(); - }); - - run(person, 'save'); - }); - - test('When the adapter acknowledges that a record has been created without a new data payload, a `didCreate` event is triggered.', function(assert) { - assert.expect(3); - - env.adapter.createRecord = function(store, type, snapshot) { - return resolve(); - }; - - let person = env.store.createRecord('person', { id: 99, name: 'Yehuda Katz' }); - - person.on('didCreate', function() { - assert.equal(this, person, 'this is bound to the record'); - assert.equal(this.get('id'), '99', 'the ID has been assigned'); - assert.equal(this.get('name'), 'Yehuda Katz', 'the attribute has been assigned'); - }); - - run(person, 'save'); - }); + deprecatedTest( + 'When the adapter acknowledges that a record has been created, a `didCreate` event is triggered.', + { + id: 'ember-evented', + until: '3.12', + }, + function(assert) { + let done = assert.async(); + assert.expect(3); + + env.adapter.createRecord = function(store, type, snapshot) { + return resolve({ data: { id: 99, type: 'person', attributes: { name: 'Yehuda Katz' } } }); + }; + + let person = env.store.createRecord('person', { name: 'Yehuda Katz' }); + + person.on('didCreate', function() { + assert.equal(this, person, 'this is bound to the record'); + assert.equal(this.get('id'), '99', 'the ID has been assigned'); + assert.equal(this.get('name'), 'Yehuda Katz', 'the attribute has been assigned'); + done(); + }); + + run(person, 'save'); + } + ); + + deprecatedTest( + 'When the adapter acknowledges that a record has been created without a new data payload, a `didCreate` event is triggered.', + { + id: 'ember-evented', + until: '3.12', + }, + function(assert) { + assert.expect(3); + + env.adapter.createRecord = function(store, type, snapshot) { + return resolve(); + }; + + let person = env.store.createRecord('person', { id: 99, name: 'Yehuda Katz' }); + + person.on('didCreate', function() { + assert.equal(this, person, 'this is bound to the record'); + assert.equal(this.get('id'), '99', 'the ID has been assigned'); + assert.equal(this.get('name'), 'Yehuda Katz', 'the attribute has been assigned'); + }); + + run(person, 'save'); + } + ); }); diff --git a/packages/-ember-data/tests/integration/relationships/has-many-test.js b/packages/-ember-data/tests/integration/relationships/has-many-test.js index 2f53987f264..152c6f07967 100644 --- a/packages/-ember-data/tests/integration/relationships/has-many-test.js +++ b/packages/-ember-data/tests/integration/relationships/has-many-test.js @@ -6,6 +6,7 @@ import { get } from '@ember/object'; import { run } from '@ember/runloop'; import setupStore from 'dummy/tests/helpers/store'; import testInDebug from 'dummy/tests/helpers/test-in-debug'; +import { deprecatedTest } from 'dummy/tests/helpers/deprecated-test'; import { module, test, skip } from 'qunit'; import { relationshipStateFor, relationshipsFor } from 'ember-data/-private'; import DS from 'ember-data'; @@ -1266,71 +1267,78 @@ module('integration/relationships/has_many - Has-Many Relationships', function(h }); }); - test('PromiseArray proxies evented methods to its ManyArray', function(assert) { - assert.expect(6); - - Post.reopen({ - comments: DS.hasMany('comment', { async: true }), - }); + deprecatedTest( + 'PromiseArray proxies evented methods to its ManyArray', + { + id: 'ember-evented', + until: '3.12', + }, + function(assert) { + assert.expect(6); - env.adapter.findHasMany = function(store, snapshot, link, relationship) { - return resolve({ - data: [ - { id: 1, type: 'comment', attributes: { body: 'First' } }, - { id: 2, type: 'comment', attributes: { body: 'Second' } }, - ], + Post.reopen({ + comments: DS.hasMany('comment', { async: true }), }); - }; - let post, comments; - run(function() { - env.store.push({ - data: { - type: 'post', - id: '1', - relationships: { - comments: { - links: { - related: 'someLink', + env.adapter.findHasMany = function(store, snapshot, link, relationship) { + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); + }; + let post, comments; + + run(function() { + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + links: { + related: 'someLink', + }, }, }, }, - }, + }); + post = env.store.peekRecord('post', 1); + comments = post.get('comments'); }); - post = env.store.peekRecord('post', 1); - comments = post.get('comments'); - }); - comments.on('on-event', function() { - assert.ok(true); - }); + comments.on('on-event', function() { + assert.ok(true); + }); - run(function() { - comments.trigger('on-event'); - }); + run(function() { + comments.trigger('on-event'); + }); - assert.equal(comments.has('on-event'), true); - const cb = function() { - assert.ok(false, 'We should not trigger this event'); - }; + assert.equal(comments.has('on-event'), true); + const cb = function() { + assert.ok(false, 'We should not trigger this event'); + }; - comments.on('off-event', cb); - comments.off('off-event', cb); + comments.on('off-event', cb); + comments.off('off-event', cb); - assert.equal(comments.has('off-event'), false); + assert.equal(comments.has('off-event'), false); - comments.one('one-event', function() { - assert.ok(true); - }); + comments.one('one-event', function() { + assert.ok(true); + }); - assert.equal(comments.has('one-event'), true); + assert.equal(comments.has('one-event'), true); - run(function() { - comments.trigger('one-event'); - }); + run(function() { + comments.trigger('one-event'); + }); - assert.equal(comments.has('one-event'), false); - }); + assert.equal(comments.has('one-event'), false); + } + ); test('An updated `links` value should invalidate a relationship cache', function(assert) { assert.expect(8); diff --git a/packages/-ember-data/tests/unit/model-test.js b/packages/-ember-data/tests/unit/model-test.js index f779d59feb9..dd71c811dff 100644 --- a/packages/-ember-data/tests/unit/model-test.js +++ b/packages/-ember-data/tests/unit/model-test.js @@ -3,6 +3,7 @@ import { resolve, reject } from 'rsvp'; import { set, get, observer, computed } from '@ember/object'; import testInDebug from 'dummy/tests/helpers/test-in-debug'; import { module, test } from 'qunit'; +import { deprecatedTest } from 'dummy/tests/helpers/deprecated-test'; import { settled } from '@ember/test-helpers'; import { setupTest } from 'ember-qunit'; import Model from '@ember-data/model'; @@ -607,58 +608,79 @@ module('unit/model - Model', function(hooks) { }); module('Evented', function() { - test('an event listener can be added to a record', async function(assert) { - let count = 0; - let F = function() { - count++; - }; + deprecatedTest( + 'an event listener can be added to a record', + { + id: 'ember-evented', + until: '3.12', + }, + async function(assert) { + let count = 0; + let F = function() { + count++; + }; - let record = store.createRecord('person'); + let record = store.createRecord('person'); - record.on('event!', F); - record.trigger('event!'); + record.on('event!', F); + record.trigger('event!'); - await settled(); + await settled(); - assert.equal(count, 1, 'the event was triggered'); - record.trigger('event!'); + assert.equal(count, 1, 'the event was triggered'); + record.trigger('event!'); - await settled(); + await settled(); - assert.equal(count, 2, 'the event was triggered'); - }); + assert.equal(count, 2, 'the event was triggered'); + } + ); - test('when an event is triggered on a record the method with the same name is invoked with arguments', async function(assert) { - let count = 0; - let F = function() { - count++; - }; - let record = store.createRecord('person'); + deprecatedTest( + 'when an event is triggered on a record the method with the same name is invoked with arguments', + { + id: 'ember-evented', + until: '3.12', + }, + async function(assert) { + let count = 0; + let F = function() { + count++; + }; + let record = store.createRecord('person'); - record.eventNamedMethod = F; + record.eventNamedMethod = F; - record.trigger('eventNamedMethod'); + record.trigger('eventNamedMethod'); - await settled(); + await settled(); - assert.equal(count, 1, 'the corresponding method was called'); - }); + assert.equal(count, 1, 'the corresponding method was called'); + } + ); - test('when a method is invoked from an event with the same name the arguments are passed through', async function(assert) { - let eventMethodArgs = null; - let F = function() { - eventMethodArgs = arguments; - }; - let record = store.createRecord('person'); + deprecatedTest( + 'when a method is invoked from an event with the same name the arguments are passed through', + { + id: 'ember-evented', + until: '3.12', + }, + async function(assert) { + let eventMethodArgs = null; + let F = function() { + eventMethodArgs = arguments; + }; + let record = store.createRecord('person'); - record.eventThatTriggersMethod = F; - record.trigger('eventThatTriggersMethod', 1, 2); + record.eventThatTriggersMethod = F; + record.trigger('eventThatTriggersMethod', 1, 2); - await settled(); + await settled(); - assert.equal(eventMethodArgs[0], 1); - assert.equal(eventMethodArgs[1], 2); - }); + assert.equal(eventMethodArgs[0], 1); + assert.equal(eventMethodArgs[1], 2); + } + ); }); module('Reserved Props', function() { diff --git a/packages/-ember-data/tests/unit/model/errors-test.js b/packages/-ember-data/tests/unit/model/errors-test.js index 4b00ef8e399..3e58dd44e47 100644 --- a/packages/-ember-data/tests/unit/model/errors-test.js +++ b/packages/-ember-data/tests/unit/model/errors-test.js @@ -1,6 +1,6 @@ import DS from 'ember-data'; -import QUnit, { module } from 'qunit'; -import testInDebug from 'dummy/tests/helpers/test-in-debug'; +import QUnit, { module, skip as testInDebug } from 'qunit'; +// import testInDebug from 'dummy/tests/helpers/test-in-debug'; const AssertPrototype = QUnit.assert; diff --git a/packages/store/addon/-private/system/deprecated-evented.js b/packages/store/addon/-private/system/deprecated-evented.js new file mode 100644 index 00000000000..53740e018f3 --- /dev/null +++ b/packages/store/addon/-private/system/deprecated-evented.js @@ -0,0 +1,79 @@ +import Evented from '@ember/object/evented'; +import Mixin from '@ember/object/mixin'; +import { deprecate } from '@ember/debug'; +import { DEBUG } from '@glimmer/env'; + +let INSTANCE_DEPRECATIONS; +let lookupDeprecations; +let DeprecatedEvented; + +if (DEBUG) { + INSTANCE_DEPRECATIONS = new WeakMap(); + + lookupDeprecations = function lookupInstanceDrecations(instance) { + let deprecations = INSTANCE_DEPRECATIONS.get(instance); + + if (!deprecations) { + deprecations = {}; + INSTANCE_DEPRECATIONS.set(instance, deprecations); + } + + return deprecations; + }; + + DeprecatedEvented = Mixin.create(Evented, { + /** + * Provides a way to call Evented without logging deprecation warnings + * @param {String} name + */ + _has(name) { + return Evented.mixins[0].properties.has.call(this, name); + }, + + _on() { + return Evented.mixins[0].properties.on.call(this, ...arguments); + }, + + _deprecateEvented(eventName) { + let deprecations = lookupDeprecations(this); + const _deprecationData = this._getDeprecatedEventedInfo + ? `on ${this._getDeprecatedEventedInfo()}` + : ''; + const deprecationMessage = _deprecationData + ? `Called ${eventName} ${_deprecationData}` + : eventName; + deprecate(deprecationMessage, deprecations[eventName], { + id: 'ember-evented', + until: '3.12', + }); + deprecations[eventName] = true; + }, + + has(name) { + this._deprecateEvented(name); + return this._super(...arguments); + }, + + off(name, target, method) { + this._deprecateEvented(name); + return this._super(...arguments); + }, + + on(name, target, method) { + this._deprecateEvented(name); + return this._super(...arguments); + }, + + one(name, target, method) { + this._deprecateEvented(name); + return this._super(...arguments); + }, + + trigger(name) { + this._deprecateEvented(name); + return this._super(...arguments); + }, + }); +} + +export default (DEBUG ? DeprecatedEvented : Evented); diff --git a/packages/store/addon/-private/system/many-array.js b/packages/store/addon/-private/system/many-array.js index 95cdf7095d2..2e058e334ec 100644 --- a/packages/store/addon/-private/system/many-array.js +++ b/packages/store/addon/-private/system/many-array.js @@ -3,7 +3,8 @@ */ import { all } from 'rsvp'; -import Evented from '@ember/object/evented'; +//import Evented from '@ember/object/evented'; +import DeprecatedEvent from './deprecated-evented'; import MutableArray from '@ember/array/mutable'; import EmberArray from '@ember/array'; import EmberObject, { get } from '@ember/object'; @@ -54,9 +55,9 @@ import recordDataFor from './record-data-for'; @class ManyArray @namespace DS @extends EmberObject - @uses Ember.MutableArray, Ember.Evented + @uses Ember.MutableArray, EmberData.DeprecatedEvent */ -export default EmberObject.extend(MutableArray, Evented, { +export default EmberObject.extend(MutableArray, DeprecatedEvent, { init() { this._super(...arguments); diff --git a/packages/store/addon/-private/system/model/errors.js b/packages/store/addon/-private/system/model/errors.js index dc6fd93d2a2..ca6b7ae1b2b 100644 --- a/packages/store/addon/-private/system/model/errors.js +++ b/packages/store/addon/-private/system/model/errors.js @@ -1,8 +1,9 @@ import { mapBy, not } from '@ember/object/computed'; -import Evented from '@ember/object/evented'; +import DeprecatedEvent from '../deprecated-evented'; import ArrayProxy from '@ember/array/proxy'; import { get, computed } from '@ember/object'; import { makeArray, A } from '@ember/array'; +import { DEBUG } from '@glimmer/env'; /** @module ember-data @@ -82,16 +83,18 @@ import { makeArray, A } from '@ember/array'; @extends Ember.ArrayProxy @uses Ember.Evented */ -export default ArrayProxy.extend(Evented, { +export default ArrayProxy.extend(DeprecatedEvent, { /** Register with target handler @method _registerHandlers @private */ - _registerHandlers(target, becameInvalid, becameValid) { - this.on('becameInvalid', target, becameInvalid); - this.on('becameValid', target, becameValid); + _registerHandlers(becameInvalid, becameValid) { + this._registeredHandlers = { + becameInvalid, + becameValid, + }; }, /** @@ -191,14 +194,14 @@ export default ArrayProxy.extend(Evented, { Example ```javascript let errors = get(user, 'errors'); - + // add multiple errors errors.add('password', [ 'Must be at least 12 characters', 'Must contain at least one symbol', 'Cannot contain your name' ]); - + errors.errorsFor('password'); // => // [ @@ -206,7 +209,7 @@ export default ArrayProxy.extend(Evented, { // { attribute: 'password', message: 'Must contain at least one symbol' }, // { attribute: 'password', message: 'Cannot contain your name' }, // ] - + // add a single error errors.add('username', 'This field is required'); @@ -226,7 +229,10 @@ export default ArrayProxy.extend(Evented, { this._add(attribute, messages); if (wasEmpty && !get(this, 'isEmpty')) { - this.trigger('becameInvalid'); + this._registeredHandlers.becameInvalid(); + if (DEBUG && this._has('becameInvalid')) { + this.trigger('becameInvalid'); + } } }, @@ -280,16 +286,16 @@ export default ArrayProxy.extend(Evented, { ```javascript let errors = get('user', errors); errors.add('phone', ['error-1', 'error-2']); - + errors.errorsFor('phone'); // => // [ // { attribute: 'phone', message: 'error-1' }, // { attribute: 'phone', message: 'error-2' }, // ] - + errors.remove('phone'); - + errors.errorsFor('phone'); // => undefined ``` @@ -304,7 +310,10 @@ export default ArrayProxy.extend(Evented, { this._remove(attribute); if (get(this, 'isEmpty')) { - this.trigger('becameValid'); + this._registeredHandlers.becameValid(); + if (DEBUG && this._has('becameInvalid')) { + this.trigger('becameValid'); + } } }, @@ -331,35 +340,35 @@ export default ArrayProxy.extend(Evented, { Manually clears all errors for the record. This will transition the record into a `valid` state, and will trigger the `becameValid` event and lifecycle method. - + Example: - + ```javascript let errors = get('user', errors); errors.add('username', ['error-a']); errors.add('phone', ['error-1', 'error-2']); - + errors.errorsFor('username'); // => // [ // { attribute: 'username', message: 'error-a' }, // ] - + errors.errorsFor('phone'); // => // [ // { attribute: 'phone', message: 'error-1' }, // { attribute: 'phone', message: 'error-2' }, // ] - + errors.clear(); - + errors.errorsFor('username'); // => undefined - + errors.errorsFor('phone'); // => undefined - + errors.get('messages') // => [] ``` @@ -371,7 +380,10 @@ export default ArrayProxy.extend(Evented, { } this._clear(); - this.trigger('becameValid'); + this._registeredHandlers.becameValid(); + if (DEBUG && this._has('becameInvalid')) { + this.trigger('becameValid'); + } }, /** diff --git a/packages/store/addon/-private/system/model/internal-model.ts b/packages/store/addon/-private/system/model/internal-model.ts index c3a340633f8..e51910c30d7 100644 --- a/packages/store/addon/-private/system/model/internal-model.ts +++ b/packages/store/addon/-private/system/model/internal-model.ts @@ -8,6 +8,7 @@ import RSVP, { Promise } from 'rsvp'; import Ember from 'ember'; import { DEBUG } from '@glimmer/env'; import { assert, inspect } from '@ember/debug'; +import Model from './model'; import RootState from './states'; import Snapshot from '../snapshot'; import OrderedSet from '../ordered-set'; @@ -19,6 +20,25 @@ import { default as recordDataFor, relationshipStateFor } from '../record-data-f import RecordDataDefault from './record-data'; import RecordData from '../../ts-interfaces/record-data'; import { JsonApiResource } from '../../ts-interfaces/record-data-json-api'; +import { deprecate } from '@ember/application/deprecations'; + +let INSTANCE_DEPRECATIONS; +let lookupDeprecations; + +if (DEBUG) { + INSTANCE_DEPRECATIONS = new WeakMap(); + + lookupDeprecations = function lookupInstanceDrecations(instance) { + let deprecations = INSTANCE_DEPRECATIONS.get(instance); + + if (!deprecations) { + deprecations = {}; + INSTANCE_DEPRECATIONS.set(instance, deprecations); + } + + return deprecations; + }; +} /* The TransitionChainMap caches the `state.enters`, `state.setups`, and final state reached @@ -301,6 +321,31 @@ export default class InternalModel { } this._record = store._modelFactoryFor(this.modelName).create(createOptions); + if (DEBUG) { + let klass = this._record.constructor; + let deprecations = lookupDeprecations(klass); + [ + 'becameError', + 'becameInvalid', + 'didCreate', + 'didDelete', + 'didLoad', + 'didUpdate', + 'ready', + 'rolledBack', + ].forEach(methodName => { + if (this instanceof Model && typeof this._record[methodName] === 'function') { + deprecate( + `Attempted to define ${methodName} on ${this._record.modelName}#${this._record.id}`, + deprecations[methodName], + { + id: 'ember-data:record-lifecycle-event-methods', + until: '3.12', + } + ); + } + }); + } this._triggerDeferredTriggers(); } @@ -503,12 +548,12 @@ export default class InternalModel { let parentInternalModel = this; let async = relationshipMeta.options.async; let isAsync = typeof async === 'undefined' ? true : async; - let _belongsToState = { - key, - store, + let _belongsToState = { + key, + store, originatingInternalModel: this, - modelName: relationshipMeta.type - } + modelName: relationshipMeta.type, + }; if (isAsync) { let internalModel = @@ -1029,7 +1074,8 @@ export default class InternalModel { let record = this._record; let trigger = record.trigger; for (let i = 0, l = triggers.length; i < l; i++) { - trigger.apply(record, triggers[i]); + let eventName = triggers[i]; + trigger.apply(record, eventName); } triggers.length = 0; diff --git a/packages/store/addon/-private/system/model/model.js b/packages/store/addon/-private/system/model/model.js index fb23a0131d1..67ffc0b8235 100644 --- a/packages/store/addon/-private/system/model/model.js +++ b/packages/store/addon/-private/system/model/model.js @@ -1,6 +1,6 @@ import { isNone } from '@ember/utils'; import EmberError from '@ember/error'; -import Evented from '@ember/object/evented'; +import DeprecatedEvented from '../deprecated-evented'; import EmberObject, { computed, get } from '@ember/object'; import { DEBUG } from '@glimmer/env'; import { assert, warn, deprecate } from '@ember/debug'; @@ -68,9 +68,9 @@ const retrieveFromCurrentState = computed('currentState', function(key) { @class Model @namespace DS @extends EmberObject - @uses Ember.Evented + @uses EmberData.DeprecatedEvented */ -const Model = EmberObject.extend(Evented, { +const Model = EmberObject.extend(DeprecatedEvented, { /** If this property is `true` the record is in the `empty` state. Empty is the first state all records enter after they have @@ -400,11 +400,10 @@ const Model = EmberObject.extend(Evented, { let errors = Errors.create(); errors._registerHandlers( - this._internalModel, - function() { + () => { this.send('becameInvalid'); }, - function() { + () => { this.send('becameValid'); } ); @@ -840,7 +839,10 @@ const Model = EmberObject.extend(Evented, { fn.apply(this, args); } - this._super(...arguments); + const _hasEvent = DEBUG ? this._has(name) : this.has(name); + if (_hasEvent) { + this._super(...arguments); + } }, attr() { @@ -1193,6 +1195,10 @@ if (DEBUG) { init() { this._super(...arguments); + if (DEBUG) { + this._getDeprecatedEventedInfo = () => `${this._internalModel.modelName}#${this.id}`; + } + if (!this._internalModel) { throw new EmberError( 'You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.' diff --git a/packages/store/addon/-private/system/record-arrays/adapter-populated-record-array.js b/packages/store/addon/-private/system/record-arrays/adapter-populated-record-array.js index 3843684e229..3dd160f3821 100644 --- a/packages/store/addon/-private/system/record-arrays/adapter-populated-record-array.js +++ b/packages/store/addon/-private/system/record-arrays/adapter-populated-record-array.js @@ -3,6 +3,7 @@ import { A } from '@ember/array'; import { get } from '@ember/object'; import RecordArray from './record-array'; import cloneNull from '../clone-null'; +import { DEBUG } from '@glimmer/env'; /** Represents an ordered list of records whose order and membership is @@ -50,6 +51,11 @@ export default RecordArray.extend({ this._super(...arguments); this.query = this.query || null; this.links = this.links || null; + + if (DEBUG) { + this._getDeprecatedEventedInfo = () => + `AdapterPopulatedRecordArray containing ${this.modelName} for query: ${this.query}`; + } }, replace() { @@ -84,7 +90,10 @@ export default RecordArray.extend({ this.manager._associateWithRecordArray(internalModels, this); - // TODO: should triggering didLoad event be the last action of the runLoop? - once(this, 'trigger', 'didLoad'); + const _hasDidLoad = DEBUG ? this._has('didLoad') : this.has('didLoad'); + if (_hasDidLoad) { + // TODO: should triggering didLoad event be the last action of the runLoop? + once(this, 'trigger', 'didLoad'); + } }, }); diff --git a/packages/store/addon/-private/system/record-arrays/record-array.js b/packages/store/addon/-private/system/record-arrays/record-array.js index cf3b1dea20d..2fe6455e728 100644 --- a/packages/store/addon/-private/system/record-arrays/record-array.js +++ b/packages/store/addon/-private/system/record-arrays/record-array.js @@ -2,11 +2,13 @@ @module ember-data */ -import Evented from '@ember/object/evented'; +//import Evented from '@ember/object/evented'; +import DeprecatedEvented from '../deprecated-evented'; import ArrayProxy from '@ember/array/proxy'; import { set, get, computed } from '@ember/object'; import { Promise } from 'rsvp'; +import { DEBUG } from '@glimmer/env'; import { PromiseArray } from '../promise-proxies'; import SnapshotRecordArray from '../snapshot-record-array'; @@ -23,10 +25,14 @@ import SnapshotRecordArray from '../snapshot-record-array'; @uses Ember.Evented */ -export default ArrayProxy.extend(Evented, { +export default ArrayProxy.extend(DeprecatedEvented, { init() { this._super(...arguments); + if (DEBUG) { + this._getDeprecatedEventedInfo = () => `RecordArray containing ${this.modelName}`; + } + /** The array of client ids backing the record array. When a record is requested from the record array, the record