@ember-data/store 4.0.0-beta.3 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,20 @@
1
1
  import { deprecate } from '@ember/debug';
2
+ import { dependentKeyCompat } from '@ember/object/compat';
3
+ import { cached, tracked } from '@glimmer/tracking';
2
4
 
3
5
  import { resolve } from 'rsvp';
4
6
 
7
+ import { CUSTOM_MODEL_CLASS } from '@ember-data/canary-features';
5
8
  import { DEPRECATE_BELONGS_TO_REFERENCE_PUSH } from '@ember-data/private-build-infra/deprecations';
9
+ import type { BelongsToRelationship } from '@ember-data/record-data/-private';
6
10
  import { assertPolymorphicType } from '@ember-data/store/-debug';
7
11
 
12
+ import { SingleResourceDocument } from '../../ts-interfaces/ember-data-json-api';
13
+ import { StableRecordIdentifier } from '../../ts-interfaces/identifier';
14
+ import CoreStore from '../core-store';
15
+ import { NotificationType, unsubscribe } from '../record-notification-manager';
8
16
  import { internalModelFactoryFor, peekRecordIdentifier, recordIdentifierFor } from '../store/internal-model-factory';
17
+ import RecordReference from './record';
9
18
  import Reference from './reference';
10
19
 
11
20
  /**
@@ -22,17 +31,81 @@ import Reference from './reference';
22
31
  @extends Reference
23
32
  */
24
33
  export default class BelongsToReference extends Reference {
25
- constructor(store, parentIMOrIdentifier, belongsToRelationship, key) {
26
- super(store, parentIMOrIdentifier);
34
+ declare key: string;
35
+ declare belongsToRelationship: BelongsToRelationship;
36
+ declare type: string;
37
+ declare parent: RecordReference;
38
+ declare parentIdentifier: StableRecordIdentifier;
39
+
40
+ // unsubscribe tokens given to us by the notification manager
41
+ #token!: Object;
42
+ #relatedToken: Object | null = null;
43
+
44
+ @tracked _ref = 0;
45
+
46
+ constructor(
47
+ store: CoreStore,
48
+ parentIdentifier: StableRecordIdentifier,
49
+ belongsToRelationship: BelongsToRelationship,
50
+ key: string
51
+ ) {
52
+ super(store, parentIdentifier);
27
53
  this.key = key;
28
54
  this.belongsToRelationship = belongsToRelationship;
29
55
  this.type = belongsToRelationship.definition.type;
30
- this.parent = internalModelFactoryFor(store).peek(parentIMOrIdentifier).recordReference;
31
- this.parentIdentifier = parentIMOrIdentifier;
56
+ const parent = internalModelFactoryFor(store).peek(parentIdentifier);
57
+ this.parent = parent!.recordReference;
58
+ this.parentIdentifier = parentIdentifier;
59
+
60
+ if (CUSTOM_MODEL_CLASS) {
61
+ this.#token = store._notificationManager.subscribe(
62
+ parentIdentifier,
63
+ (_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
64
+ if ((bucket === 'relationships' || bucket === 'property') && notifiedKey === key) {
65
+ this._ref++;
66
+ }
67
+ }
68
+ );
69
+ }
32
70
 
33
71
  // TODO inverse
34
72
  }
35
73
 
74
+ destroy() {
75
+ if (CUSTOM_MODEL_CLASS) {
76
+ unsubscribe(this.#token);
77
+ if (this.#relatedToken) {
78
+ unsubscribe(this.#relatedToken);
79
+ }
80
+ }
81
+ }
82
+
83
+ @cached
84
+ @dependentKeyCompat
85
+ get _relatedIdentifier(): StableRecordIdentifier | null {
86
+ this._ref; // consume the tracked prop
87
+ if (this.#relatedToken) {
88
+ unsubscribe(this.#relatedToken);
89
+ }
90
+
91
+ let resource = this._resource();
92
+ if (resource && resource.data) {
93
+ const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resource.data);
94
+ this.#relatedToken = this.store._notificationManager.subscribe(
95
+ identifier,
96
+ (_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
97
+ if (bucket === 'identity' || ((bucket === 'attributes' || bucket === 'property') && notifiedKey === 'id')) {
98
+ this._ref++;
99
+ }
100
+ }
101
+ );
102
+
103
+ return identifier;
104
+ }
105
+
106
+ return null;
107
+ }
108
+
36
109
  /**
37
110
  The `id` of the record that this reference refers to. Together, the
38
111
  `type()` and `id()` methods form a composite key for the identity
@@ -73,13 +146,18 @@ export default class BelongsToReference extends Reference {
73
146
  @public
74
147
  @return {String} The id of the record in this belongsTo relationship.
75
148
  */
76
- id() {
77
- let id = null;
149
+ id(): string | null {
150
+ if (CUSTOM_MODEL_CLASS) {
151
+ return this._relatedIdentifier?.id || null;
152
+ }
78
153
  let resource = this._resource();
79
154
  if (resource && resource.data) {
80
- id = resource.data.id;
155
+ const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resource.data);
156
+
157
+ return identifier.id;
81
158
  }
82
- return id;
159
+
160
+ return null;
83
161
  }
84
162
 
85
163
  _resource() {
@@ -132,10 +210,10 @@ export default class BelongsToReference extends Reference {
132
210
  @param {Object|Promise} objectOrPromise a promise that resolves to a JSONAPI document object describing the new value of this relationship.
133
211
  @return {Promise<record>} A promise that resolves with the new value in this belongs-to relationship.
134
212
  */
135
- push(objectOrPromise) {
213
+ async push(objectOrPromise: Object | SingleResourceDocument): Promise<Object> {
136
214
  // TODO deprecate thenable support
137
215
  return resolve(objectOrPromise).then((data) => {
138
- let record;
216
+ let record: Object;
139
217
 
140
218
  if (DEPRECATE_BELONGS_TO_REFERENCE_PUSH && peekRecordIdentifier(data)) {
141
219
  deprecate('Pushing a record into a BelongsToReference is deprecated', false, {
@@ -147,15 +225,16 @@ export default class BelongsToReference extends Reference {
147
225
  enabled: '3.16',
148
226
  },
149
227
  });
150
- record = data;
228
+ record = data as Object;
151
229
  } else {
152
- record = this.store.push(data);
230
+ record = this.store.push(data as SingleResourceDocument);
153
231
  }
154
232
 
233
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
155
234
  assertPolymorphicType(
156
235
  this.belongsToRelationship.identifier,
157
236
  this.belongsToRelationship.definition,
158
- record._internalModel.identifier,
237
+ recordIdentifierFor(record),
159
238
  this.store
160
239
  );
161
240
 
@@ -223,7 +302,7 @@ export default class BelongsToReference extends Reference {
223
302
  @public
224
303
  @return {Model} the record in this relationship
225
304
  */
226
- value() {
305
+ value(): Object | null {
227
306
  let resource = this._resource();
228
307
  if (resource && resource.data) {
229
308
  let inverseInternalModel = this.store._internalModelForResource(resource.data);
@@ -299,7 +378,7 @@ export default class BelongsToReference extends Reference {
299
378
  */
300
379
  load(options) {
301
380
  let parentInternalModel = internalModelFactoryFor(this.store).peek(this.parentIdentifier);
302
- return parentInternalModel.getBelongsTo(this.key, options);
381
+ return parentInternalModel!.getBelongsTo(this.key, options);
303
382
  }
304
383
 
305
384
  /**
@@ -354,7 +433,7 @@ export default class BelongsToReference extends Reference {
354
433
  */
355
434
  reload(options) {
356
435
  let parentInternalModel = internalModelFactoryFor(this.store).peek(this.parentIdentifier);
357
- return parentInternalModel.reloadBelongsTo(this.key, options).then((internalModel) => {
436
+ return parentInternalModel!.reloadBelongsTo(this.key, options).then((internalModel) => {
358
437
  return this.value();
359
438
  });
360
439
  }
@@ -1,10 +1,23 @@
1
+ import { dependentKeyCompat } from '@ember/object/compat';
1
2
  import { DEBUG } from '@glimmer/env';
3
+ import { cached, tracked } from '@glimmer/tracking';
2
4
 
3
5
  import { resolve } from 'rsvp';
4
6
 
7
+ import { CUSTOM_MODEL_CLASS } from '@ember-data/canary-features';
8
+ import type { ManyRelationship } from '@ember-data/record-data/-private';
5
9
  import { assertPolymorphicType } from '@ember-data/store/-debug';
6
10
 
11
+ import {
12
+ CollectionResourceDocument,
13
+ ExistingResourceObject,
14
+ SingleResourceDocument,
15
+ } from '../../ts-interfaces/ember-data-json-api';
16
+ import { StableRecordIdentifier } from '../../ts-interfaces/identifier';
17
+ import CoreStore from '../core-store';
18
+ import { NotificationType, unsubscribe } from '../record-notification-manager';
7
19
  import { internalModelFactoryFor, recordIdentifierFor } from '../store/internal-model-factory';
20
+ import RecordReference from './record';
8
21
  import Reference, { internalModelForReference } from './reference';
9
22
 
10
23
  /**
@@ -20,17 +33,88 @@ import Reference, { internalModelForReference } from './reference';
20
33
  @extends Reference
21
34
  */
22
35
  export default class HasManyReference extends Reference {
23
- constructor(store, parentIMOrIdentifier, hasManyRelationship, key) {
24
- super(store, parentIMOrIdentifier);
36
+ declare key: string;
37
+ declare hasManyRelationship: ManyRelationship;
38
+ declare type: string;
39
+ declare parent: RecordReference;
40
+ declare parentIdentifier: StableRecordIdentifier;
41
+
42
+ // unsubscribe tokens given to us by the notification manager
43
+ #token!: Object;
44
+ #relatedTokenMap!: Map<StableRecordIdentifier, Object>;
45
+
46
+ @tracked _ref = 0;
47
+
48
+ constructor(
49
+ store: CoreStore,
50
+ parentIdentifier: StableRecordIdentifier,
51
+ hasManyRelationship: ManyRelationship,
52
+ key: string
53
+ ) {
54
+ super(store, parentIdentifier);
25
55
  this.key = key;
26
56
  this.hasManyRelationship = hasManyRelationship;
27
57
  this.type = hasManyRelationship.definition.type;
28
58
 
29
- this.parent = internalModelFactoryFor(store).peek(parentIMOrIdentifier).recordReference;
59
+ this.parent = internalModelFactoryFor(store).peek(parentIdentifier)!.recordReference;
30
60
 
61
+ if (CUSTOM_MODEL_CLASS) {
62
+ this.#token = store._notificationManager.subscribe(
63
+ parentIdentifier,
64
+ (_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
65
+ if ((bucket === 'relationships' || bucket === 'property') && notifiedKey === key) {
66
+ this._ref++;
67
+ }
68
+ }
69
+ );
70
+ this.#relatedTokenMap = new Map();
71
+ }
31
72
  // TODO inverse
32
73
  }
33
74
 
75
+ destroy() {
76
+ if (CUSTOM_MODEL_CLASS) {
77
+ unsubscribe(this.#token);
78
+ this.#relatedTokenMap.forEach((token) => {
79
+ unsubscribe(token);
80
+ });
81
+ this.#relatedTokenMap.clear();
82
+ }
83
+ }
84
+
85
+ @cached
86
+ @dependentKeyCompat
87
+ get _relatedIdentifiers(): StableRecordIdentifier[] {
88
+ this._ref; // consume the tracked prop
89
+
90
+ let resource = this._resource();
91
+
92
+ this.#relatedTokenMap.forEach((token) => {
93
+ unsubscribe(token);
94
+ });
95
+ this.#relatedTokenMap.clear();
96
+
97
+ if (resource && resource.data) {
98
+ return resource.data.map((resourceIdentifier) => {
99
+ const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resourceIdentifier);
100
+ const token = this.store._notificationManager.subscribe(
101
+ identifier,
102
+ (_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
103
+ if (bucket === 'identity' || ((bucket === 'attributes' || bucket === 'property') && notifiedKey === 'id')) {
104
+ this._ref++;
105
+ }
106
+ }
107
+ );
108
+
109
+ this.#relatedTokenMap.set(identifier, token);
110
+
111
+ return identifier;
112
+ });
113
+ }
114
+
115
+ return [];
116
+ }
117
+
34
118
  _resource() {
35
119
  return this.recordData.getHasMany(this.key);
36
120
  }
@@ -77,7 +161,7 @@ export default class HasManyReference extends Reference {
77
161
  @public
78
162
  @return {String} The name of the remote type. This should either be `link` or `ids`
79
163
  */
80
- remoteType() {
164
+ remoteType(): 'link' | 'ids' {
81
165
  let value = this._resource();
82
166
  if (value && value.links && value.links.related) {
83
167
  return 'link';
@@ -121,15 +205,22 @@ export default class HasManyReference extends Reference {
121
205
  @public
122
206
  @return {Array} The ids in this has-many relationship
123
207
  */
124
- ids() {
208
+ ids(): Array<string | null> {
209
+ if (CUSTOM_MODEL_CLASS) {
210
+ return this._relatedIdentifiers.map((identifier) => identifier.id);
211
+ }
212
+
125
213
  let resource = this._resource();
126
214
 
127
- let ids = [];
128
- if (resource.data) {
129
- ids = resource.data.map((data) => data.id);
215
+ if (resource && resource.data) {
216
+ return resource.data.map((resourceIdentifier) => {
217
+ const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resourceIdentifier);
218
+
219
+ return identifier.id;
220
+ });
130
221
  }
131
222
 
132
- return ids;
223
+ return [];
133
224
  }
134
225
 
135
226
  /**
@@ -177,45 +268,50 @@ export default class HasManyReference extends Reference {
177
268
  @param {Array|Promise} objectOrPromise a promise that resolves to a JSONAPI document object describing the new value of this relationship.
178
269
  @return {ManyArray}
179
270
  */
180
- push(objectOrPromise) {
181
- return resolve(objectOrPromise).then((payload) => {
182
- let array = payload;
183
-
184
- if (typeof payload === 'object' && payload.data) {
185
- array = payload.data;
186
- }
271
+ async push(
272
+ objectOrPromise: ExistingResourceObject[] | CollectionResourceDocument | { data: SingleResourceDocument[] }
273
+ ): Promise<any> {
274
+ const payload = await resolve(objectOrPromise);
275
+ let array: Array<ExistingResourceObject | SingleResourceDocument>;
276
+
277
+ if (!Array.isArray(payload) && typeof payload === 'object' && Array.isArray(payload.data)) {
278
+ array = payload.data;
279
+ } else {
280
+ array = payload as ExistingResourceObject[];
281
+ }
187
282
 
188
- let internalModel = internalModelForReference(this);
283
+ const internalModel = internalModelForReference(this)!;
284
+ const { store } = this;
189
285
 
190
- let identifiers = array.map((obj) => {
191
- let record = this.store.push(obj);
286
+ let identifiers = array.map((obj) => {
287
+ let record;
288
+ if ('data' in obj) {
289
+ // TODO deprecate pushing non-valid JSON:API here
290
+ record = store.push(obj);
291
+ } else {
292
+ record = store.push({ data: obj });
293
+ }
192
294
 
193
- if (DEBUG) {
194
- let relationshipMeta = this.hasManyRelationship.definition;
195
- assertPolymorphicType(
196
- internalModel.identifier,
197
- relationshipMeta,
198
- record._internalModel.identifier,
199
- this.store
200
- );
201
- }
202
- return recordIdentifierFor(record);
203
- });
295
+ if (DEBUG) {
296
+ let relationshipMeta = this.hasManyRelationship.definition;
297
+ let identifier = this.hasManyRelationship.identifier;
298
+ assertPolymorphicType(identifier, relationshipMeta, recordIdentifierFor(record), store);
299
+ }
300
+ return recordIdentifierFor(record);
301
+ });
204
302
 
205
- const { graph, identifier } = this.hasManyRelationship;
206
- this.store._backburner.join(() => {
207
- graph.push({
208
- op: 'replaceRelatedRecords',
209
- record: identifier,
210
- field: this.key,
211
- value: identifiers,
212
- });
303
+ const { graph, identifier } = this.hasManyRelationship;
304
+ store._backburner.join(() => {
305
+ graph.push({
306
+ op: 'replaceRelatedRecords',
307
+ record: identifier,
308
+ field: this.key,
309
+ value: identifiers,
213
310
  });
214
-
215
- return internalModel.getHasMany(this.key);
216
- // TODO IGOR it seems wrong that we were returning the many array here
217
- //return this.hasManyRelationship.manyArray;
218
311
  });
312
+
313
+ // TODO IGOR it seems wrong that we were returning the many array here
314
+ return internalModel.getHasMany(this.key);
219
315
  }
220
316
 
221
317
  _isLoaded() {
@@ -275,7 +371,7 @@ export default class HasManyReference extends Reference {
275
371
  @return {ManyArray}
276
372
  */
277
373
  value() {
278
- let internalModel = internalModelForReference(this);
374
+ let internalModel = internalModelForReference(this)!;
279
375
  if (this._isLoaded()) {
280
376
  return internalModel.getManyArray(this.key);
281
377
  }
@@ -348,7 +444,7 @@ export default class HasManyReference extends Reference {
348
444
  this has-many relationship.
349
445
  */
350
446
  load(options) {
351
- let internalModel = internalModelForReference(this);
447
+ let internalModel = internalModelForReference(this)!;
352
448
  return internalModel.getHasMany(this.key, options);
353
449
  }
354
450
 
@@ -403,7 +499,7 @@ export default class HasManyReference extends Reference {
403
499
  @return {Promise} a promise that resolves with the ManyArray in this has-many relationship.
404
500
  */
405
501
  reload(options) {
406
- let internalModel = internalModelForReference(this);
502
+ let internalModel = internalModelForReference(this)!;
407
503
  return internalModel.reloadHasMany(this.key, options);
408
504
  }
409
505
  }
@@ -1,8 +1,15 @@
1
+ import { dependentKeyCompat } from '@ember/object/compat';
2
+ import { cached, tracked } from '@glimmer/tracking';
3
+
1
4
  import RSVP, { resolve } from 'rsvp';
2
5
 
6
+ import { CUSTOM_MODEL_CLASS } from '@ember-data/canary-features';
7
+
3
8
  import type { SingleResourceDocument } from '../../ts-interfaces/ember-data-json-api';
4
9
  import type { StableRecordIdentifier } from '../../ts-interfaces/identifier';
5
10
  import type { RecordInstance } from '../../ts-interfaces/record-instance';
11
+ import type CoreStore from '../core-store';
12
+ import { NotificationType, unsubscribe } from '../record-notification-manager';
6
13
  import Reference, { internalModelForReference, REFERENCE_CACHE } from './reference';
7
14
 
8
15
  /**
@@ -18,11 +25,39 @@ import Reference, { internalModelForReference, REFERENCE_CACHE } from './referen
18
25
  @extends Reference
19
26
  */
20
27
  export default class RecordReference extends Reference {
28
+ // unsubscribe token given to us by the notification manager
29
+ #token!: Object;
30
+
31
+ @tracked _ref = 0;
32
+
33
+ constructor(public store: CoreStore, identifier: StableRecordIdentifier) {
34
+ super(store, identifier);
35
+ if (CUSTOM_MODEL_CLASS) {
36
+ this.#token = store._notificationManager.subscribe(
37
+ identifier,
38
+ (_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
39
+ if (bucket === 'identity' || ((bucket === 'attributes' || bucket === 'property') && notifiedKey === 'id')) {
40
+ this._ref++;
41
+ }
42
+ }
43
+ );
44
+ }
45
+ }
46
+
47
+ destroy() {
48
+ if (CUSTOM_MODEL_CLASS) {
49
+ unsubscribe(this.#token);
50
+ }
51
+ }
52
+
21
53
  public get type(): string {
22
54
  return this.identifier().type;
23
55
  }
24
56
 
57
+ @cached
58
+ @dependentKeyCompat
25
59
  private get _id(): string | null {
60
+ this._ref; // consume the tracked prop
26
61
  let identifier = this.identifier();
27
62
  if (identifier) {
28
63
  return identifier.id;
@@ -50,7 +85,15 @@ export default class RecordReference extends Reference {
50
85
  @return {String} The id of the record.
51
86
  */
52
87
  id() {
53
- return this._id;
88
+ if (CUSTOM_MODEL_CLASS) {
89
+ return this._id;
90
+ }
91
+ let identifier = this.identifier();
92
+ if (identifier) {
93
+ return identifier.id;
94
+ }
95
+
96
+ return null;
54
97
  }
55
98
 
56
99
  /**
@@ -92,7 +135,7 @@ export default class RecordReference extends Reference {
92
135
  @public
93
136
  @return {String} 'identity'
94
137
  */
95
- remoteType(): 'link' | 'id' | 'identity' {
138
+ remoteType(): 'identity' {
96
139
  return 'identity';
97
140
  }
98
141
 
@@ -159,7 +202,7 @@ export default class RecordReference extends Reference {
159
202
  @return {Model} the record for this RecordReference
160
203
  */
161
204
  value(): RecordInstance | null {
162
- if (this._id !== null) {
205
+ if (this.id() !== null) {
163
206
  let internalModel = internalModelForReference(this);
164
207
  if (internalModel && internalModel.currentState.isLoaded) {
165
208
  return internalModel.getRecord();
@@ -186,8 +229,9 @@ export default class RecordReference extends Reference {
186
229
  @return {Promise<record>} the record for this RecordReference
187
230
  */
188
231
  load() {
189
- if (this._id !== null) {
190
- return this.store.findRecord(this.type, this._id);
232
+ const id = this.id();
233
+ if (id !== null) {
234
+ return this.store.findRecord(this.type, id);
191
235
  }
192
236
  throw new Error(`Unable to fetch record of type ${this.type} without an id`);
193
237
  }
@@ -210,8 +254,9 @@ export default class RecordReference extends Reference {
210
254
  @return {Promise<record>} the record for this RecordReference
211
255
  */
212
256
  reload() {
213
- if (this._id !== null) {
214
- return this.store.findRecord(this.type, this._id, { reload: true });
257
+ const id = this.id();
258
+ if (id !== null) {
259
+ return this.store.findRecord(this.type, id, { reload: true });
215
260
  }
216
261
  throw new Error(`Unable to fetch record of type ${this.type} without an id`);
217
262
  }
@@ -98,7 +98,7 @@ abstract class Reference {
98
98
  @public
99
99
  @return {String} The name of the remote type. This should either be "link" or "ids"
100
100
  */
101
- remoteType(): 'link' | 'id' | 'identity' {
101
+ remoteType(): 'link' | 'id' | 'ids' | 'identity' {
102
102
  let value = this._resource();
103
103
  if (isResourceIdentiferWithRelatedLinks(value)) {
104
104
  return 'link';
@@ -7,10 +7,9 @@ import type {
7
7
  } from '../ts-interfaces/fetch-manager';
8
8
  import { RequestStateEnum } from '../ts-interfaces/fetch-manager';
9
9
  import type { RecordIdentifier } from '../ts-interfaces/identifier';
10
- import { addSymbol, symbol } from '../utils/symbol';
11
10
 
12
- const Touching: unique symbol = symbol('touching');
13
- export const RequestPromise: unique symbol = symbol('promise');
11
+ const Touching: unique symbol = Symbol('touching');
12
+ export const RequestPromise: unique symbol = Symbol('promise');
14
13
 
15
14
  interface InternalRequest extends RequestState {
16
15
  [Touching]: RecordIdentifier[];
@@ -41,8 +40,8 @@ export default class RequestCache {
41
40
  request: queryRequest,
42
41
  type,
43
42
  } as InternalRequest;
44
- addSymbol(request, Touching, [query.recordIdentifier]);
45
- addSymbol(request, RequestPromise, promise);
43
+ request[Touching] = [query.recordIdentifier];
44
+ request[RequestPromise] = promise;
46
45
  this._pending[lid].push(request);
47
46
  this._triggerSubscriptions(request);
48
47
  promise.then(
@@ -54,7 +53,7 @@ export default class RequestCache {
54
53
  type,
55
54
  response: { data: result },
56
55
  } as InternalRequest;
57
- addSymbol(finalizedRequest, Touching, request[Touching]);
56
+ finalizedRequest[Touching] = request[Touching];
58
57
  this._addDone(finalizedRequest);
59
58
  this._triggerSubscriptions(finalizedRequest);
60
59
  },
@@ -66,7 +65,7 @@ export default class RequestCache {
66
65
  type,
67
66
  response: { data: error && error.error },
68
67
  } as InternalRequest;
69
- addSymbol(finalizedRequest, Touching, request[Touching]);
68
+ finalizedRequest[Touching] = request[Touching];
70
69
  this._addDone(finalizedRequest);
71
70
  this._triggerSubscriptions(finalizedRequest);
72
71
  }
@@ -3,7 +3,6 @@
3
3
  */
4
4
  import { assert } from '@ember/debug';
5
5
  import { get } from '@ember/object';
6
- import { assign } from '@ember/polyfills';
7
6
 
8
7
  import { CUSTOM_MODEL_CLASS } from '@ember-data/canary-features';
9
8
  import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
@@ -234,7 +233,7 @@ export default class Snapshot implements Snapshot {
234
233
  @public
235
234
  */
236
235
  attributes(): Dict<unknown> {
237
- return assign({}, this._attributes);
236
+ return { ...this._attributes };
238
237
  }
239
238
 
240
239
  /**
@@ -1,5 +1,4 @@
1
1
  import { assert, deprecate, warn } from '@ember/debug';
2
- import { assign } from '@ember/polyfills';
3
2
  import { DEBUG } from '@glimmer/env';
4
3
 
5
4
  import { Promise } from 'rsvp';
@@ -274,18 +273,12 @@ function fixRelationshipData(relationshipData, relationshipKind, { id, modelName
274
273
  if (relationshipKind === 'hasMany') {
275
274
  payload = relationshipData || [];
276
275
  if (relationshipData) {
277
- // IE11 does not support array.find
278
276
  // these arrays could be massive so this is better than filter
279
277
  // Note: this is potentially problematic if type/id are not in the
280
278
  // same state of normalization.
281
- let found = false;
282
- for (let i = 0; i < relationshipData.length; i++) {
283
- let v = relationshipData[i];
284
- if (v.type === parentRelationshipData.type && v.id === parentRelationshipData.id) {
285
- found = true;
286
- break;
287
- }
288
- }
279
+ let found = relationshipData.find((v) => {
280
+ return v.type === parentRelationshipData.type && v.id === parentRelationshipData.id;
281
+ });
289
282
  if (!found) {
290
283
  payload.push(parentRelationshipData);
291
284
  }
@@ -294,7 +287,7 @@ function fixRelationshipData(relationshipData, relationshipKind, { id, modelName
294
287
  }
295
288
  } else {
296
289
  payload = relationshipData || {};
297
- assign(payload, parentRelationshipData);
290
+ Object.assign(payload, parentRelationshipData);
298
291
  }
299
292
 
300
293
  return payload;
@@ -17,6 +17,7 @@ export interface DSModel extends RecordInstance, EmberObject {
17
17
  isDeleted: boolean;
18
18
  deleteRecord(): void;
19
19
  unloadRecord(): void;
20
+ errors: any;
20
21
  }
21
22
 
22
23
  // Implemented by both ShimModelClass and DSModel