@ember-data/store 5.3.0-alpha.9 → 5.4.0-alpha.0
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.
- package/addon/-private.js +1 -1
- package/addon/index.js +1 -1
- package/addon/index.js.map +1 -1
- package/addon/{store-service-845a5162.js → store-service-0a03d2a4.js} +365 -319
- package/addon/store-service-0a03d2a4.js.map +1 -0
- package/package.json +17 -17
- package/addon/store-service-845a5162.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { macroCondition, getOwnConfig } from '@embroider/macros';
|
|
2
2
|
import { getOwner } from '@ember/application';
|
|
3
|
-
import { assert, warn } from '@ember/debug';
|
|
3
|
+
import { assert, deprecate, warn } from '@ember/debug';
|
|
4
4
|
import EmberObject from '@ember/object';
|
|
5
5
|
import { _backburner } from '@ember/runloop';
|
|
6
6
|
import { tracked } from '@glimmer/tracking';
|
|
@@ -354,50 +354,63 @@ function copyDocumentProperties(target, source) {
|
|
|
354
354
|
}
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
-
/**
|
|
358
|
-
@module @ember-data/store
|
|
359
|
-
*/
|
|
360
|
-
|
|
361
357
|
// Used by the store to normalize IDs entering the store. Despite the fact
|
|
362
358
|
// that developers may provide IDs as numbers (e.g., `store.findRecord('person', 1)`),
|
|
363
359
|
// it is important that internally we use strings, since IDs may be serialized
|
|
364
360
|
// and lose type information. For example, Ember's router may put a record's
|
|
365
361
|
// ID into the URL, and if we later try to deserialize that URL and find the
|
|
366
362
|
// corresponding record, we will not know if it is a string or a number.
|
|
367
|
-
|
|
368
363
|
function coerceId(id) {
|
|
369
|
-
if (
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
364
|
+
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_NON_STRICT_ID)) {
|
|
365
|
+
let normalized;
|
|
366
|
+
if (id === null || id === undefined || id === '') {
|
|
367
|
+
normalized = null;
|
|
368
|
+
} else {
|
|
369
|
+
normalized = String(id);
|
|
370
|
+
}
|
|
371
|
+
deprecate(`The resource id '<${typeof id}> ${String(id)} ' is not normalized. Update your application code to use '${JSON.stringify(normalized)}' instead.`, normalized === id, {
|
|
372
|
+
id: 'ember-data:deprecate-non-strict-id',
|
|
373
|
+
until: '6.0',
|
|
374
|
+
for: 'ember-data',
|
|
375
|
+
since: {
|
|
376
|
+
available: '5.3',
|
|
377
|
+
enabled: '5.3'
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
return normalized;
|
|
377
381
|
}
|
|
378
|
-
|
|
382
|
+
assert(`Resource IDs must be a non-empty string or null. Received '${String(id)}'.`, id === null || typeof id === 'string' && id.length > 0);
|
|
383
|
+
return id;
|
|
379
384
|
}
|
|
380
385
|
function ensureStringId(id) {
|
|
381
386
|
let normalized = null;
|
|
382
387
|
if (typeof id === 'string') {
|
|
383
388
|
normalized = id.length > 0 ? id : null;
|
|
384
389
|
} else if (typeof id === 'number' && !isNaN(id)) {
|
|
385
|
-
normalized =
|
|
386
|
-
}
|
|
387
|
-
if (normalized === null) {
|
|
388
|
-
throw new Error(`Expected id to be a string or number, received ${String(id)}`);
|
|
390
|
+
normalized = String(id);
|
|
389
391
|
}
|
|
392
|
+
assert(`Expected id to be a string or number, received ${String(id)}`, normalized !== null);
|
|
390
393
|
return normalized;
|
|
391
394
|
}
|
|
392
395
|
|
|
393
396
|
// provided for additional debuggability
|
|
394
397
|
const DEBUG_CLIENT_ORIGINATED = Symbol('record-originated-on-client');
|
|
395
398
|
const DEBUG_IDENTIFIER_BUCKET = Symbol('identifier-bucket');
|
|
396
|
-
function
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
399
|
+
function normalizeModelName(type) {
|
|
400
|
+
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_NON_STRICT_TYPES)) {
|
|
401
|
+
const result = dasherize(type);
|
|
402
|
+
deprecate(`The resource type '${type}' is not normalized. Update your application code to use '${result}' instead of '${type}'.`, result === type, {
|
|
403
|
+
id: 'ember-data:deprecate-non-strict-types',
|
|
404
|
+
until: '6.0',
|
|
405
|
+
for: 'ember-data',
|
|
406
|
+
since: {
|
|
407
|
+
available: '5.3',
|
|
408
|
+
enabled: '5.3'
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
return result;
|
|
412
|
+
}
|
|
413
|
+
return type;
|
|
401
414
|
}
|
|
402
415
|
|
|
403
416
|
/**
|
|
@@ -441,6 +454,21 @@ function installPolyfill() {
|
|
|
441
454
|
};
|
|
442
455
|
}
|
|
443
456
|
}
|
|
457
|
+
function isResource(resource) {
|
|
458
|
+
return Boolean(resource && typeof resource === 'object');
|
|
459
|
+
}
|
|
460
|
+
function hasProp(resource, prop) {
|
|
461
|
+
return Boolean(isResource(resource) && prop in resource && typeof resource[prop] === 'string' && resource[prop].length);
|
|
462
|
+
}
|
|
463
|
+
function hasLid(resource) {
|
|
464
|
+
return hasProp(resource, 'lid');
|
|
465
|
+
}
|
|
466
|
+
function hasId(resource) {
|
|
467
|
+
return hasProp(resource, 'id') || Boolean(isResource(resource) && 'id' in resource && typeof resource.id === 'number');
|
|
468
|
+
}
|
|
469
|
+
function hasType(resource) {
|
|
470
|
+
return hasProp(resource, 'type');
|
|
471
|
+
}
|
|
444
472
|
|
|
445
473
|
/**
|
|
446
474
|
@module @ember-data/store
|
|
@@ -459,7 +487,7 @@ if (macroCondition(getOwnConfig().polyfillUUID)) {
|
|
|
459
487
|
installPolyfill();
|
|
460
488
|
}
|
|
461
489
|
function uuidv4() {
|
|
462
|
-
assert('crypto.randomUUID needs to be avaliable. Some browsers incorrectly disallow it in insecure contexts. You maybe want to enable the polyfill: https://github.com/emberjs/data#randomuuid-polyfill', _crypto.randomUUID);
|
|
490
|
+
assert('crypto.randomUUID needs to be avaliable. Some browsers incorrectly disallow it in insecure contexts. You maybe want to enable the polyfill: https://github.com/emberjs/data#randomuuid-polyfill', typeof _crypto.randomUUID === 'function');
|
|
463
491
|
return _crypto.randomUUID();
|
|
464
492
|
}
|
|
465
493
|
function freeze(obj) {
|
|
@@ -468,6 +496,9 @@ function freeze(obj) {
|
|
|
468
496
|
}
|
|
469
497
|
return obj;
|
|
470
498
|
}
|
|
499
|
+
|
|
500
|
+
// type IdentifierTypeLookup = { all: Set<StableRecordIdentifier>; id: Map<string, StableRecordIdentifier> };
|
|
501
|
+
// type IdentifiersByType = Map<string, IdentifierTypeLookup>;
|
|
471
502
|
let configuredForgetMethod;
|
|
472
503
|
let configuredGenerationMethod;
|
|
473
504
|
let configuredResetMethod;
|
|
@@ -484,20 +515,46 @@ function setIdentifierForgetMethod(method) {
|
|
|
484
515
|
function setIdentifierResetMethod(method) {
|
|
485
516
|
configuredResetMethod = method;
|
|
486
517
|
}
|
|
518
|
+
|
|
519
|
+
// Map<type, Map<id, lid>>
|
|
520
|
+
|
|
521
|
+
const NEW_IDENTIFIERS = new Map();
|
|
522
|
+
function updateTypeIdMapping(typeMap, identifier, id) {
|
|
523
|
+
let idMap = typeMap.get(identifier.type);
|
|
524
|
+
if (!idMap) {
|
|
525
|
+
idMap = new Map();
|
|
526
|
+
typeMap.set(identifier.type, idMap);
|
|
527
|
+
}
|
|
528
|
+
idMap.set(id, identifier.lid);
|
|
529
|
+
}
|
|
530
|
+
function defaultUpdateMethod(identifier, data, bucket) {
|
|
531
|
+
if (bucket === 'record') {
|
|
532
|
+
assert(`Expected identifier to be a StableRecordIdentifier`, isStableIdentifier(identifier));
|
|
533
|
+
if (!identifier.id && hasId(data)) {
|
|
534
|
+
updateTypeIdMapping(NEW_IDENTIFIERS, identifier, data.id);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
function defaultKeyInfoMethod(resource, known) {
|
|
539
|
+
// TODO RFC something to make this configurable
|
|
540
|
+
const id = hasId(resource) ? coerceId(resource.id) : null;
|
|
541
|
+
const type = hasType(resource) ? normalizeModelName(resource.type) : known ? known.type : null;
|
|
542
|
+
assert(`Expected keyInfoForResource to provide a type for the resource`, type);
|
|
543
|
+
return {
|
|
544
|
+
type,
|
|
545
|
+
id
|
|
546
|
+
};
|
|
547
|
+
}
|
|
487
548
|
function defaultGenerationMethod(data, bucket) {
|
|
488
549
|
if (bucket === 'record') {
|
|
489
|
-
if (
|
|
550
|
+
if (hasLid(data)) {
|
|
490
551
|
return data.lid;
|
|
491
552
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
// TODO: add test for id not a string
|
|
498
|
-
if (isNonEmptyString(coerceId(id))) {
|
|
499
|
-
return `@lid:${normalizeModelName(type)}-${id}`;
|
|
500
|
-
}
|
|
553
|
+
assert(`Cannot generate an identifier for a resource without a type`, hasType(data));
|
|
554
|
+
if (hasId(data)) {
|
|
555
|
+
const type = normalizeModelName(data.type);
|
|
556
|
+
const lid = NEW_IDENTIFIERS.get(type)?.get(data.id);
|
|
557
|
+
return lid || `@lid:${type}-${data.id}`;
|
|
501
558
|
}
|
|
502
559
|
return uuidv4();
|
|
503
560
|
} else if (bucket === 'document') {
|
|
@@ -512,6 +569,9 @@ function defaultGenerationMethod(data, bucket) {
|
|
|
512
569
|
assert(`Unknown bucket ${bucket}`, false);
|
|
513
570
|
}
|
|
514
571
|
function defaultEmptyCallback(...args) {}
|
|
572
|
+
function defaultMergeMethod(a, _b, _c) {
|
|
573
|
+
return a;
|
|
574
|
+
}
|
|
515
575
|
let DEBUG_MAP;
|
|
516
576
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
517
577
|
DEBUG_MAP = new WeakMap();
|
|
@@ -532,19 +592,20 @@ if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
|
532
592
|
*/
|
|
533
593
|
class IdentifierCache {
|
|
534
594
|
constructor() {
|
|
535
|
-
this._cache = {
|
|
536
|
-
lids: new Map(),
|
|
537
|
-
types: Object.create(null),
|
|
538
|
-
documents: new Map()
|
|
539
|
-
};
|
|
540
595
|
// we cache the user configuredGenerationMethod at init because it must
|
|
541
596
|
// be configured prior and is not allowed to be changed
|
|
542
597
|
this._generate = configuredGenerationMethod || defaultGenerationMethod;
|
|
543
|
-
this._update = configuredUpdateMethod ||
|
|
598
|
+
this._update = configuredUpdateMethod || defaultUpdateMethod;
|
|
544
599
|
this._forget = configuredForgetMethod || defaultEmptyCallback;
|
|
545
600
|
this._reset = configuredResetMethod || defaultEmptyCallback;
|
|
546
|
-
this._merge =
|
|
601
|
+
this._merge = defaultMergeMethod;
|
|
602
|
+
this._keyInfoForResource = defaultKeyInfoMethod;
|
|
547
603
|
this._isDefaultConfig = !configuredGenerationMethod;
|
|
604
|
+
this._cache = {
|
|
605
|
+
resources: new Map(),
|
|
606
|
+
resourcesByType: Object.create(null),
|
|
607
|
+
documents: new Map()
|
|
608
|
+
};
|
|
548
609
|
}
|
|
549
610
|
|
|
550
611
|
/**
|
|
@@ -557,7 +618,10 @@ class IdentifierCache {
|
|
|
557
618
|
* @private
|
|
558
619
|
*/
|
|
559
620
|
__configureMerge(method) {
|
|
560
|
-
this._merge = method ||
|
|
621
|
+
this._merge = method || defaultMergeMethod;
|
|
622
|
+
}
|
|
623
|
+
upgradeIdentifier(resource) {
|
|
624
|
+
return this._getRecordIdentifier(resource, 2);
|
|
561
625
|
}
|
|
562
626
|
|
|
563
627
|
/**
|
|
@@ -565,130 +629,62 @@ class IdentifierCache {
|
|
|
565
629
|
* @private
|
|
566
630
|
*/
|
|
567
631
|
|
|
568
|
-
_getRecordIdentifier(resource, shouldGenerate
|
|
632
|
+
_getRecordIdentifier(resource, shouldGenerate) {
|
|
633
|
+
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
634
|
+
// eslint-disable-next-line no-console
|
|
635
|
+
console.groupCollapsed(`Identifiers: ${shouldGenerate ? 'Generating' : 'Peeking'} Identifier`, resource);
|
|
636
|
+
}
|
|
569
637
|
// short circuit if we're already the stable version
|
|
570
638
|
if (isStableIdentifier(resource)) {
|
|
571
639
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
572
640
|
// TODO should we instead just treat this case as a new generation skipping the short circuit?
|
|
573
|
-
if (!this._cache.
|
|
574
|
-
throw new Error(`The supplied identifier ${resource} does not belong to this store instance`);
|
|
641
|
+
if (!this._cache.resources.has(resource.lid) || this._cache.resources.get(resource.lid) !== resource) {
|
|
642
|
+
throw new Error(`The supplied identifier ${JSON.stringify(resource)} does not belong to this store instance`);
|
|
575
643
|
}
|
|
576
644
|
}
|
|
577
645
|
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
578
646
|
// eslint-disable-next-line no-console
|
|
579
|
-
console.log(`Identifiers:
|
|
647
|
+
console.log(`Identifiers: cache HIT - Stable ${resource.lid}`);
|
|
648
|
+
// eslint-disable-next-line no-console
|
|
649
|
+
console.groupEnd();
|
|
580
650
|
}
|
|
581
651
|
return resource;
|
|
582
652
|
}
|
|
583
|
-
|
|
584
|
-
|
|
653
|
+
|
|
654
|
+
// the resource is unknown, ask the application to identify this data for us
|
|
655
|
+
const lid = this._generate(resource, 'record');
|
|
656
|
+
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
657
|
+
// eslint-disable-next-line no-console
|
|
658
|
+
console.log(`Identifiers: ${lid ? 'no ' : ''}lid ${lid ? lid + ' ' : ''}determined for resource`, resource);
|
|
659
|
+
}
|
|
660
|
+
let identifier = /*#__NOINLINE__*/getIdentifierFromLid(this._cache, lid, resource);
|
|
585
661
|
if (identifier !== undefined) {
|
|
586
662
|
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
587
663
|
// eslint-disable-next-line no-console
|
|
588
|
-
console.
|
|
664
|
+
console.groupEnd();
|
|
589
665
|
}
|
|
590
666
|
return identifier;
|
|
591
667
|
}
|
|
592
|
-
if (
|
|
593
|
-
// eslint-disable-next-line no-console
|
|
594
|
-
console.groupCollapsed(`Identifiers: ${shouldGenerate ? 'Generating' : 'Peeking'} Identifier`, resource);
|
|
595
|
-
}
|
|
596
|
-
if (shouldGenerate === false) {
|
|
597
|
-
if (!resource.type || !resource.id) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
// `type` must always be present
|
|
603
|
-
assert('resource.type needs to be a string', 'type' in resource && isNonEmptyString(resource.type));
|
|
604
|
-
let type = resource.type && normalizeModelName(resource.type);
|
|
605
|
-
let id = coerceId(resource.id);
|
|
606
|
-
let keyOptions = getTypeIndex(this._cache.types, type);
|
|
607
|
-
|
|
608
|
-
// go straight for the stable RecordIdentifier key'd to `lid`
|
|
609
|
-
if (lid !== null) {
|
|
610
|
-
identifier = keyOptions.lid.get(lid);
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// we may have not seen this resource before
|
|
614
|
-
// but just in case we check our own secondary lookup (`id`)
|
|
615
|
-
if (identifier === undefined && id !== null) {
|
|
616
|
-
identifier = keyOptions.id.get(id);
|
|
617
|
-
}
|
|
618
|
-
if (identifier === undefined) {
|
|
619
|
-
// we have definitely not seen this resource before
|
|
620
|
-
// so we allow the user configured `GenerationMethod` to tell us
|
|
621
|
-
let newLid = this._generate(resource, 'record');
|
|
668
|
+
if (shouldGenerate === 0) {
|
|
622
669
|
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
623
670
|
// eslint-disable-next-line no-console
|
|
624
|
-
console.
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
// we do this _even_ when `lid` is present because secondary lookups
|
|
628
|
-
// may need to be populated, but we enforce not giving us something
|
|
629
|
-
// different than expected
|
|
630
|
-
if (lid !== null && newLid !== lid) {
|
|
631
|
-
throw new Error(`You should not change the <lid> of a RecordIdentifier`);
|
|
632
|
-
} else if (lid === null && !this._isDefaultConfig) {
|
|
633
|
-
// allow configuration to tell us that we have
|
|
634
|
-
// seen this `lid` before. E.g. a secondary lookup
|
|
635
|
-
// connects this resource to a previously seen
|
|
636
|
-
// resource.
|
|
637
|
-
identifier = keyOptions.lid.get(newLid);
|
|
638
|
-
}
|
|
639
|
-
if (shouldGenerate === true) {
|
|
640
|
-
if (identifier === undefined) {
|
|
641
|
-
// if we still don't have an identifier, time to generate one
|
|
642
|
-
identifier = makeStableRecordIdentifier(id, type, newLid, 'record', false);
|
|
643
|
-
|
|
644
|
-
// populate our unique table
|
|
645
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
646
|
-
// realistically if you hit this it means you changed `type` :/
|
|
647
|
-
// TODO consider how to handle type change assertions more gracefully
|
|
648
|
-
if (this._cache.lids.has(identifier.lid)) {
|
|
649
|
-
throw new Error(`You should not change the <type> of a RecordIdentifier`);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
this._cache.lids.set(identifier.lid, identifier);
|
|
653
|
-
|
|
654
|
-
// populate our primary lookup table
|
|
655
|
-
// TODO consider having the `lid` cache be
|
|
656
|
-
// one level up
|
|
657
|
-
keyOptions.lid.set(identifier.lid, identifier);
|
|
658
|
-
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
659
|
-
if (shouldGenerate) {
|
|
660
|
-
// eslint-disable-next-line no-console
|
|
661
|
-
console.log(`Identifiers: generated ${String(identifier)} for`, resource);
|
|
662
|
-
if (resource[DEBUG_IDENTIFIER_BUCKET]) {
|
|
663
|
-
// eslint-disable-next-line no-console
|
|
664
|
-
console.trace(`[WARNING] Identifiers: generated a new identifier from a previously used identifier. This is likely a bug.`);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
// populate our own secondary lookup table
|
|
671
|
-
// even for the "successful" secondary lookup
|
|
672
|
-
// by `_generate()`, since we missed the cache
|
|
673
|
-
// previously
|
|
674
|
-
// we use identifier.id instead of id here
|
|
675
|
-
// because they may not match and we prefer
|
|
676
|
-
// what we've set via resource data
|
|
677
|
-
if (identifier.id !== null) {
|
|
678
|
-
keyOptions.id.set(identifier.id, identifier);
|
|
679
|
-
|
|
680
|
-
// TODO allow filling out of `id` here
|
|
681
|
-
// for the `username` non-client created
|
|
682
|
-
// case.
|
|
683
|
-
}
|
|
671
|
+
console.groupEnd();
|
|
684
672
|
}
|
|
673
|
+
return;
|
|
685
674
|
}
|
|
686
675
|
|
|
676
|
+
// if we still don't have an identifier, time to generate one
|
|
677
|
+
if (shouldGenerate === 2) {
|
|
678
|
+
resource.lid = lid;
|
|
679
|
+
identifier = /*#__NOINLINE__*/makeStableRecordIdentifier(resource, 'record', false);
|
|
680
|
+
} else {
|
|
681
|
+
// we lie a bit here as a memory optimization
|
|
682
|
+
const keyInfo = this._keyInfoForResource(resource, null);
|
|
683
|
+
keyInfo.lid = lid;
|
|
684
|
+
identifier = /*#__NOINLINE__*/makeStableRecordIdentifier(keyInfo, 'record', false);
|
|
685
|
+
}
|
|
686
|
+
addResourceToCache(this._cache, identifier);
|
|
687
687
|
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
688
|
-
if (!identifier && !shouldGenerate) {
|
|
689
|
-
// eslint-disable-next-line no-console
|
|
690
|
-
console.log(`Identifiers: cache MISS`, resource);
|
|
691
|
-
}
|
|
692
688
|
// eslint-disable-next-line no-console
|
|
693
689
|
console.groupEnd();
|
|
694
690
|
}
|
|
@@ -706,7 +702,7 @@ class IdentifierCache {
|
|
|
706
702
|
* @private
|
|
707
703
|
*/
|
|
708
704
|
peekRecordIdentifier(resource) {
|
|
709
|
-
return this._getRecordIdentifier(resource,
|
|
705
|
+
return this._getRecordIdentifier(resource, 0);
|
|
710
706
|
}
|
|
711
707
|
|
|
712
708
|
/**
|
|
@@ -751,9 +747,8 @@ class IdentifierCache {
|
|
|
751
747
|
@returns {StableRecordIdentifier}
|
|
752
748
|
@public
|
|
753
749
|
*/
|
|
754
|
-
|
|
755
750
|
getOrCreateRecordIdentifier(resource) {
|
|
756
|
-
return this._getRecordIdentifier(resource,
|
|
751
|
+
return this._getRecordIdentifier(resource, 1);
|
|
757
752
|
}
|
|
758
753
|
|
|
759
754
|
/**
|
|
@@ -769,22 +764,21 @@ class IdentifierCache {
|
|
|
769
764
|
*/
|
|
770
765
|
createIdentifierForNewRecord(data) {
|
|
771
766
|
let newLid = this._generate(data, 'record');
|
|
772
|
-
let identifier = makeStableRecordIdentifier(
|
|
773
|
-
|
|
767
|
+
let identifier = /*#__NOINLINE__*/makeStableRecordIdentifier({
|
|
768
|
+
id: data.id || null,
|
|
769
|
+
type: data.type,
|
|
770
|
+
lid: newLid
|
|
771
|
+
}, 'record', true);
|
|
774
772
|
|
|
775
773
|
// populate our unique table
|
|
776
774
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
777
|
-
if (this._cache.
|
|
775
|
+
if (this._cache.resources.has(identifier.lid)) {
|
|
778
776
|
throw new Error(`The lid generated for the new record is not unique as it matches an existing identifier`);
|
|
779
777
|
}
|
|
780
778
|
}
|
|
781
|
-
this._cache.lids.set(identifier.lid, identifier);
|
|
782
779
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
if (data.id) {
|
|
786
|
-
keyOptions.id.set(data.id, identifier);
|
|
787
|
-
}
|
|
780
|
+
/*#__NOINLINE__*/
|
|
781
|
+
addResourceToCache(this._cache, identifier);
|
|
788
782
|
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
789
783
|
// eslint-disable-next-line no-console
|
|
790
784
|
console.log(`Identifiers: created identifier ${String(identifier)} for newly generated resource`, data);
|
|
@@ -812,43 +806,49 @@ class IdentifierCache {
|
|
|
812
806
|
*/
|
|
813
807
|
updateRecordIdentifier(identifierObject, data) {
|
|
814
808
|
let identifier = this.getOrCreateRecordIdentifier(identifierObject);
|
|
815
|
-
|
|
816
|
-
let existingIdentifier = detectMerge(this._cache
|
|
809
|
+
const keyInfo = this._keyInfoForResource(data, identifier);
|
|
810
|
+
let existingIdentifier = /*#__NOINLINE__*/detectMerge(this._cache, keyInfo, identifier, data);
|
|
811
|
+
const hadLid = hasLid(data);
|
|
817
812
|
if (!existingIdentifier) {
|
|
818
813
|
// If the incoming type does not match the identifier type, we need to create an identifier for the incoming
|
|
819
814
|
// data so we can merge the incoming data with the existing identifier, see #7325 and #7363
|
|
820
|
-
if (
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
existingIdentifier = this.getOrCreateRecordIdentifier(incomingDataResource);
|
|
815
|
+
if (identifier.type !== keyInfo.type) {
|
|
816
|
+
if (hadLid) {
|
|
817
|
+
// Strip the lid to ensure we force a new identifier creation
|
|
818
|
+
delete data.lid;
|
|
819
|
+
}
|
|
820
|
+
existingIdentifier = this.getOrCreateRecordIdentifier(data);
|
|
827
821
|
}
|
|
828
822
|
}
|
|
829
823
|
if (existingIdentifier) {
|
|
830
|
-
let keyOptions = getTypeIndex(this._cache.types, identifier.type);
|
|
831
824
|
let generatedIdentifier = identifier;
|
|
832
|
-
identifier = this._mergeRecordIdentifiers(
|
|
825
|
+
identifier = this._mergeRecordIdentifiers(keyInfo, generatedIdentifier, existingIdentifier, data);
|
|
826
|
+
|
|
827
|
+
// make sure that the `lid` on the data we are processing matches the lid we kept
|
|
828
|
+
if (hadLid) {
|
|
829
|
+
data.lid = identifier.lid;
|
|
830
|
+
}
|
|
833
831
|
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
834
832
|
// eslint-disable-next-line no-console
|
|
835
833
|
console.log(`Identifiers: merged identifiers ${generatedIdentifier.lid} and ${existingIdentifier.lid} for resource into ${identifier.lid}`, data);
|
|
836
834
|
}
|
|
837
835
|
}
|
|
838
836
|
let id = identifier.id;
|
|
839
|
-
|
|
840
|
-
|
|
837
|
+
/*#__NOINLINE__*/
|
|
838
|
+
performRecordIdentifierUpdate(identifier, keyInfo, data, this._update);
|
|
839
|
+
const newId = identifier.id;
|
|
841
840
|
|
|
842
841
|
// add to our own secondary lookup table
|
|
843
842
|
if (id !== newId && newId !== null) {
|
|
844
843
|
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
845
844
|
// eslint-disable-next-line no-console
|
|
846
|
-
console.log(`Identifiers: updated id for identifier ${identifier.lid} from '${id}' to '${newId}' for resource`, data);
|
|
845
|
+
console.log(`Identifiers: updated id for identifier ${identifier.lid} from '${String(id)}' to '${String(newId)}' for resource`, data);
|
|
847
846
|
}
|
|
848
|
-
|
|
849
|
-
|
|
847
|
+
const typeSet = this._cache.resourcesByType[identifier.type];
|
|
848
|
+
assert(`Expected to find a typeSet for ${identifier.type}`, typeSet);
|
|
849
|
+
typeSet.id.set(newId, identifier);
|
|
850
850
|
if (id !== null) {
|
|
851
|
-
|
|
851
|
+
typeSet.id.delete(id);
|
|
852
852
|
}
|
|
853
853
|
} else if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
854
854
|
// eslint-disable-next-line no-console
|
|
@@ -861,22 +861,22 @@ class IdentifierCache {
|
|
|
861
861
|
* @method _mergeRecordIdentifiers
|
|
862
862
|
* @private
|
|
863
863
|
*/
|
|
864
|
-
_mergeRecordIdentifiers(
|
|
864
|
+
_mergeRecordIdentifiers(keyInfo, identifier, existingIdentifier, data) {
|
|
865
|
+
assert(`Expected keyInfo to contain an id`, hasId(keyInfo));
|
|
865
866
|
// delegate determining which identifier to keep to the configured MergeMethod
|
|
866
|
-
|
|
867
|
-
|
|
867
|
+
const kept = this._merge(identifier, existingIdentifier, data);
|
|
868
|
+
const abandoned = kept === identifier ? existingIdentifier : identifier;
|
|
868
869
|
|
|
869
870
|
// cleanup the identifier we no longer need
|
|
870
871
|
this.forgetRecordIdentifier(abandoned);
|
|
871
872
|
|
|
872
873
|
// ensure a secondary cache entry for this id for the identifier we do keep
|
|
873
|
-
keyOptions.id.set(newId, kept);
|
|
874
|
+
// keyOptions.id.set(newId, kept);
|
|
875
|
+
|
|
874
876
|
// ensure a secondary cache entry for this id for the abandoned identifier's type we do keep
|
|
875
|
-
let baseKeyOptions = getTypeIndex(this._cache.
|
|
876
|
-
baseKeyOptions.id.set(newId, kept);
|
|
877
|
+
// let baseKeyOptions = getTypeIndex(this._cache.resourcesByType, existingIdentifier.type);
|
|
878
|
+
// baseKeyOptions.id.set(newId, kept);
|
|
877
879
|
|
|
878
|
-
// make sure that the `lid` on the data we are processing matches the lid we kept
|
|
879
|
-
data.lid = kept.lid;
|
|
880
880
|
return kept;
|
|
881
881
|
}
|
|
882
882
|
|
|
@@ -891,14 +891,15 @@ class IdentifierCache {
|
|
|
891
891
|
@public
|
|
892
892
|
*/
|
|
893
893
|
forgetRecordIdentifier(identifierObject) {
|
|
894
|
-
|
|
895
|
-
|
|
894
|
+
const identifier = this.getOrCreateRecordIdentifier(identifierObject);
|
|
895
|
+
const typeSet = this._cache.resourcesByType[identifier.type];
|
|
896
|
+
assert(`Expected to find a typeSet for ${identifier.type}`, typeSet);
|
|
896
897
|
if (identifier.id !== null) {
|
|
897
|
-
|
|
898
|
+
typeSet.id.delete(identifier.id);
|
|
898
899
|
}
|
|
899
|
-
this._cache.
|
|
900
|
-
|
|
901
|
-
IDENTIFIERS.delete(
|
|
900
|
+
this._cache.resources.delete(identifier.lid);
|
|
901
|
+
typeSet.lid.delete(identifier.lid);
|
|
902
|
+
IDENTIFIERS.delete(identifier);
|
|
902
903
|
this._forget(identifier, 'record');
|
|
903
904
|
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
904
905
|
// eslint-disable-next-line no-console
|
|
@@ -906,29 +907,14 @@ class IdentifierCache {
|
|
|
906
907
|
}
|
|
907
908
|
}
|
|
908
909
|
destroy() {
|
|
910
|
+
NEW_IDENTIFIERS.clear();
|
|
909
911
|
this._cache.documents.forEach(identifier => {
|
|
910
912
|
DOCUMENTS.delete(identifier);
|
|
911
913
|
});
|
|
912
914
|
this._reset();
|
|
913
915
|
}
|
|
914
916
|
}
|
|
915
|
-
function
|
|
916
|
-
let typeIndex = typeMap[type];
|
|
917
|
-
if (typeIndex === undefined) {
|
|
918
|
-
typeIndex = {
|
|
919
|
-
lid: new Map(),
|
|
920
|
-
id: new Map()
|
|
921
|
-
};
|
|
922
|
-
typeMap[type] = typeIndex;
|
|
923
|
-
}
|
|
924
|
-
return typeIndex;
|
|
925
|
-
}
|
|
926
|
-
function makeStableRecordIdentifier(id, type, lid, bucket, clientOriginated = false) {
|
|
927
|
-
let recordIdentifier = {
|
|
928
|
-
lid,
|
|
929
|
-
id,
|
|
930
|
-
type
|
|
931
|
-
};
|
|
917
|
+
function makeStableRecordIdentifier(recordIdentifier, bucket, clientOriginated) {
|
|
932
918
|
IDENTIFIERS.add(recordIdentifier);
|
|
933
919
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
934
920
|
// we enforce immutability in dev
|
|
@@ -944,15 +930,15 @@ function makeStableRecordIdentifier(id, type, lid, bucket, clientOriginated = fa
|
|
|
944
930
|
return recordIdentifier.type;
|
|
945
931
|
},
|
|
946
932
|
toString() {
|
|
947
|
-
|
|
933
|
+
const {
|
|
948
934
|
type,
|
|
949
935
|
id,
|
|
950
936
|
lid
|
|
951
937
|
} = recordIdentifier;
|
|
952
|
-
return `${clientOriginated ? '[CLIENT_ORIGINATED] ' : ''}${type}:${id} (${lid})`;
|
|
938
|
+
return `${clientOriginated ? '[CLIENT_ORIGINATED] ' : ''}${String(type)}:${String(id)} (${lid})`;
|
|
953
939
|
},
|
|
954
940
|
toJSON() {
|
|
955
|
-
|
|
941
|
+
const {
|
|
956
942
|
type,
|
|
957
943
|
id,
|
|
958
944
|
lid
|
|
@@ -973,37 +959,33 @@ function makeStableRecordIdentifier(id, type, lid, bucket, clientOriginated = fa
|
|
|
973
959
|
}
|
|
974
960
|
return recordIdentifier;
|
|
975
961
|
}
|
|
976
|
-
function performRecordIdentifierUpdate(identifier, data, updateFn) {
|
|
962
|
+
function performRecordIdentifierUpdate(identifier, keyInfo, data, updateFn) {
|
|
977
963
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
let type = 'type' in data && data.type && normalizeModelName(data.type);
|
|
964
|
+
const {
|
|
965
|
+
id,
|
|
966
|
+
type
|
|
967
|
+
} = keyInfo;
|
|
983
968
|
|
|
984
969
|
// get the mutable instance behind our proxy wrapper
|
|
985
970
|
let wrapper = identifier;
|
|
986
971
|
identifier = DEBUG_MAP.get(wrapper);
|
|
987
|
-
if (
|
|
988
|
-
|
|
989
|
-
if (
|
|
990
|
-
throw new Error(`The 'lid' for a RecordIdentifier cannot be updated once it has been created. Attempted to set lid for '${wrapper}' to '${lid}'.`);
|
|
972
|
+
if (hasLid(data)) {
|
|
973
|
+
const lid = data.lid;
|
|
974
|
+
if (lid !== identifier.lid) {
|
|
975
|
+
throw new Error(`The 'lid' for a RecordIdentifier cannot be updated once it has been created. Attempted to set lid for '${wrapper.lid}' to '${lid}'.`);
|
|
991
976
|
}
|
|
992
977
|
}
|
|
993
|
-
if (id !==
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
id: 'ember-data:multiple-ids-for-identifier'
|
|
1000
|
-
});
|
|
1001
|
-
}
|
|
978
|
+
if (id && identifier.id !== null && identifier.id !== id) {
|
|
979
|
+
// here we warn and ignore, as this may be a mistake, but we allow the user
|
|
980
|
+
// to have multiple cache-keys pointing at a single lid so we cannot error
|
|
981
|
+
warn(`The 'id' for a RecordIdentifier should not be updated once it has been set. Attempted to set id for '${wrapper.lid}' to '${id}'.`, false, {
|
|
982
|
+
id: 'ember-data:multiple-ids-for-identifier'
|
|
983
|
+
});
|
|
1002
984
|
}
|
|
1003
985
|
|
|
1004
986
|
// TODO consider just ignoring here to allow flexible polymorphic support
|
|
1005
987
|
if (type && type !== identifier.type) {
|
|
1006
|
-
throw new Error(`The 'type' for a RecordIdentifier cannot be updated once it has been set. Attempted to set type for '${wrapper}' to '${type}'.`);
|
|
988
|
+
throw new Error(`The 'type' for a RecordIdentifier cannot be updated once it has been set. Attempted to set type for '${wrapper.lid}' to '${type}'.`);
|
|
1007
989
|
}
|
|
1008
990
|
updateFn(wrapper, data, 'record');
|
|
1009
991
|
} else {
|
|
@@ -1018,32 +1000,62 @@ function performRecordIdentifierUpdate(identifier, data, updateFn) {
|
|
|
1018
1000
|
identifier.id = coerceId(data.id);
|
|
1019
1001
|
}
|
|
1020
1002
|
}
|
|
1021
|
-
function detectMerge(
|
|
1003
|
+
function detectMerge(cache, keyInfo, identifier, data) {
|
|
1004
|
+
const newId = keyInfo.id;
|
|
1022
1005
|
const {
|
|
1023
1006
|
id,
|
|
1024
1007
|
type,
|
|
1025
1008
|
lid
|
|
1026
1009
|
} = identifier;
|
|
1010
|
+
const typeSet = cache.resourcesByType[identifier.type];
|
|
1011
|
+
|
|
1012
|
+
// if the IDs are present but do not match
|
|
1013
|
+
// then check if we have an existing identifier
|
|
1014
|
+
// for the newer ID.
|
|
1027
1015
|
if (id !== null && id !== newId && newId !== null) {
|
|
1028
|
-
|
|
1029
|
-
let existingIdentifier = keyOptions.id.get(newId);
|
|
1016
|
+
const existingIdentifier = typeSet && typeSet.id.get(newId);
|
|
1030
1017
|
return existingIdentifier !== undefined ? existingIdentifier : false;
|
|
1031
1018
|
} else {
|
|
1032
|
-
|
|
1019
|
+
const newType = keyInfo.type;
|
|
1033
1020
|
|
|
1034
1021
|
// If the ids and type are the same but lid is not the same, we should trigger a merge of the identifiers
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1022
|
+
// we trigger a merge of the identifiers
|
|
1023
|
+
// though probably we should just throw an error here
|
|
1024
|
+
if (id !== null && id === newId && newType === type && hasLid(data) && data.lid !== lid) {
|
|
1025
|
+
return cache.resources.get(data.lid) || false;
|
|
1026
|
+
|
|
1038
1027
|
// If the lids are the same, and ids are the same, but types are different we should trigger a merge of the identifiers
|
|
1039
|
-
} else if (id !== null && id === newId && newType && newType !== type && data
|
|
1040
|
-
|
|
1041
|
-
|
|
1028
|
+
} else if (id !== null && id === newId && newType && newType !== type && hasLid(data) && data.lid === lid) {
|
|
1029
|
+
const newTypeSet = cache.resourcesByType[newType];
|
|
1030
|
+
const existingIdentifier = newTypeSet && newTypeSet.id.get(newId);
|
|
1042
1031
|
return existingIdentifier !== undefined ? existingIdentifier : false;
|
|
1043
1032
|
}
|
|
1044
1033
|
}
|
|
1045
1034
|
return false;
|
|
1046
1035
|
}
|
|
1036
|
+
function getIdentifierFromLid(cache, lid, resource) {
|
|
1037
|
+
const identifier = cache.resources.get(lid);
|
|
1038
|
+
if (macroCondition(getOwnConfig().debug.LOG_IDENTIFIERS)) {
|
|
1039
|
+
// eslint-disable-next-line no-console
|
|
1040
|
+
console.log(`Identifiers: cache ${identifier ? 'HIT' : 'MISS'} - Non-Stable ${lid}`, resource);
|
|
1041
|
+
}
|
|
1042
|
+
return identifier;
|
|
1043
|
+
}
|
|
1044
|
+
function addResourceToCache(cache, identifier) {
|
|
1045
|
+
cache.resources.set(identifier.lid, identifier);
|
|
1046
|
+
let typeSet = cache.resourcesByType[identifier.type];
|
|
1047
|
+
if (!typeSet) {
|
|
1048
|
+
typeSet = {
|
|
1049
|
+
lid: new Map(),
|
|
1050
|
+
id: new Map()
|
|
1051
|
+
};
|
|
1052
|
+
cache.resourcesByType[identifier.type] = typeSet;
|
|
1053
|
+
}
|
|
1054
|
+
typeSet.lid.set(identifier.lid, identifier);
|
|
1055
|
+
if (identifier.id) {
|
|
1056
|
+
typeSet.id.set(identifier.id, identifier);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1047
1059
|
var _class$1, _descriptor$1;
|
|
1048
1060
|
|
|
1049
1061
|
/**
|
|
@@ -1402,9 +1414,12 @@ class InstanceCache {
|
|
|
1402
1414
|
store.identifierCache.__configureMerge((identifier, matchedIdentifier, resourceData) => {
|
|
1403
1415
|
let keptIdentifier = identifier;
|
|
1404
1416
|
if (identifier.id !== matchedIdentifier.id) {
|
|
1417
|
+
// @ts-expect-error TODO this needs to be fixed
|
|
1405
1418
|
keptIdentifier = 'id' in resourceData && identifier.id === resourceData.id ? identifier : matchedIdentifier;
|
|
1406
1419
|
} else if (identifier.type !== matchedIdentifier.type) {
|
|
1407
|
-
keptIdentifier =
|
|
1420
|
+
keptIdentifier =
|
|
1421
|
+
// @ts-expect-error TODO this needs to be fixed
|
|
1422
|
+
'type' in resourceData && identifier.type === resourceData.type ? identifier : matchedIdentifier;
|
|
1408
1423
|
}
|
|
1409
1424
|
let staleIdentifier = identifier === keptIdentifier ? matchedIdentifier : identifier;
|
|
1410
1425
|
|
|
@@ -1419,6 +1434,7 @@ class InstanceCache {
|
|
|
1419
1434
|
// we can probably just "swap" what data source the abandoned
|
|
1420
1435
|
// record points at so long as
|
|
1421
1436
|
// it itself is not retained by the store in any way.
|
|
1437
|
+
// @ts-expect-error TODO this needs to be fixed
|
|
1422
1438
|
if ('id' in resourceData) {
|
|
1423
1439
|
throw new Error(`Failed to update the 'id' for the RecordIdentifier '${identifier.type}:${String(identifier.id)} (${identifier.lid})' to '${String(resourceData.id)}', because that id is already in use by '${matchedIdentifier.type}:${String(matchedIdentifier.id)} (${matchedIdentifier.lid})'`);
|
|
1424
1440
|
}
|
|
@@ -1557,11 +1573,11 @@ class InstanceCache {
|
|
|
1557
1573
|
if (type === undefined) {
|
|
1558
1574
|
// it would be cool if we could just de-ref cache here
|
|
1559
1575
|
// but probably would require WeakRef models to do so.
|
|
1560
|
-
cache.
|
|
1576
|
+
cache.resources.forEach(identifier => {
|
|
1561
1577
|
this.unloadRecord(identifier);
|
|
1562
1578
|
});
|
|
1563
1579
|
} else {
|
|
1564
|
-
const typeCache = cache.
|
|
1580
|
+
const typeCache = cache.resourcesByType;
|
|
1565
1581
|
let identifiers = typeCache[type]?.lid;
|
|
1566
1582
|
if (identifiers) {
|
|
1567
1583
|
identifiers.forEach(identifier => {
|
|
@@ -1683,7 +1699,7 @@ function _convertPreloadRelationshipToJSON(value, type) {
|
|
|
1683
1699
|
if (typeof value === 'string' || typeof value === 'number') {
|
|
1684
1700
|
return {
|
|
1685
1701
|
type,
|
|
1686
|
-
id: value
|
|
1702
|
+
id: ensureStringId(value)
|
|
1687
1703
|
};
|
|
1688
1704
|
}
|
|
1689
1705
|
// TODO if not a record instance assert it's an identifier
|
|
@@ -1712,7 +1728,7 @@ function getShimClass(store, modelName) {
|
|
|
1712
1728
|
return shim;
|
|
1713
1729
|
}
|
|
1714
1730
|
function mapFromHash(hash) {
|
|
1715
|
-
|
|
1731
|
+
const map = new Map();
|
|
1716
1732
|
for (let i in hash) {
|
|
1717
1733
|
if (Object.prototype.hasOwnProperty.call(hash, i)) {
|
|
1718
1734
|
map.set(i, hash[i]);
|
|
@@ -1721,7 +1737,7 @@ function mapFromHash(hash) {
|
|
|
1721
1737
|
return map;
|
|
1722
1738
|
}
|
|
1723
1739
|
|
|
1724
|
-
// Mimics the static apis of
|
|
1740
|
+
// Mimics the static apis of @ember-data/model
|
|
1725
1741
|
class ShimModelClass {
|
|
1726
1742
|
constructor(store, modelName) {
|
|
1727
1743
|
this.__store = store;
|
|
@@ -2561,13 +2577,13 @@ let IdentifierArray = (_class3 = class IdentifierArray {
|
|
|
2561
2577
|
@type Store
|
|
2562
2578
|
*/
|
|
2563
2579
|
|
|
2564
|
-
destroy() {
|
|
2565
|
-
this.isDestroying =
|
|
2580
|
+
destroy(clear) {
|
|
2581
|
+
this.isDestroying = !clear;
|
|
2566
2582
|
// changing the reference breaks the Proxy
|
|
2567
2583
|
// this[SOURCE] = [];
|
|
2568
2584
|
this[SOURCE].length = 0;
|
|
2569
2585
|
this[NOTIFY]();
|
|
2570
|
-
this.isDestroyed =
|
|
2586
|
+
this.isDestroyed = !clear;
|
|
2571
2587
|
}
|
|
2572
2588
|
|
|
2573
2589
|
// length must be on self for proxied methods to work properly
|
|
@@ -2872,8 +2888,8 @@ class Collection extends IdentifierArray {
|
|
|
2872
2888
|
});
|
|
2873
2889
|
return promise;
|
|
2874
2890
|
}
|
|
2875
|
-
destroy() {
|
|
2876
|
-
super.destroy();
|
|
2891
|
+
destroy(clear) {
|
|
2892
|
+
super.destroy(clear);
|
|
2877
2893
|
this._manager._managed.delete(this);
|
|
2878
2894
|
this._manager._pending.delete(this);
|
|
2879
2895
|
}
|
|
@@ -2971,10 +2987,14 @@ class RecordArrayManager {
|
|
|
2971
2987
|
this._staged = new Map();
|
|
2972
2988
|
this._keyedArrays = new Map();
|
|
2973
2989
|
this._identifiers = new Map();
|
|
2990
|
+
this._set = new Map();
|
|
2991
|
+
this._visibilitySet = new Map();
|
|
2974
2992
|
this._subscription = this.store.notifications.subscribe('resource', (identifier, type) => {
|
|
2975
2993
|
if (type === 'added') {
|
|
2994
|
+
this._visibilitySet.set(identifier, true);
|
|
2976
2995
|
this.identifierAdded(identifier);
|
|
2977
2996
|
} else if (type === 'removed') {
|
|
2997
|
+
this._visibilitySet.set(identifier, false);
|
|
2978
2998
|
this.identifierRemoved(identifier);
|
|
2979
2999
|
} else if (type === 'state') {
|
|
2980
3000
|
this.identifierChanged(identifier);
|
|
@@ -2986,7 +3006,7 @@ class RecordArrayManager {
|
|
|
2986
3006
|
if (!pending || this.isDestroying || this.isDestroyed) {
|
|
2987
3007
|
return;
|
|
2988
3008
|
}
|
|
2989
|
-
sync(array, pending);
|
|
3009
|
+
sync(array, pending, this._set.get(array));
|
|
2990
3010
|
this._pending.delete(array);
|
|
2991
3011
|
}
|
|
2992
3012
|
|
|
@@ -3019,6 +3039,7 @@ class RecordArrayManager {
|
|
|
3019
3039
|
manager: this
|
|
3020
3040
|
});
|
|
3021
3041
|
this._live.set(type, array);
|
|
3042
|
+
this._set.set(array, new Set(identifiers));
|
|
3022
3043
|
}
|
|
3023
3044
|
return array;
|
|
3024
3045
|
}
|
|
@@ -3036,6 +3057,7 @@ class RecordArrayManager {
|
|
|
3036
3057
|
};
|
|
3037
3058
|
let array = new Collection(options);
|
|
3038
3059
|
this._managed.add(array);
|
|
3060
|
+
this._set.set(array, new Set(options.identifiers || []));
|
|
3039
3061
|
if (config.identifiers) {
|
|
3040
3062
|
associate(this._identifiers, array, config.identifiers);
|
|
3041
3063
|
}
|
|
@@ -3107,6 +3129,7 @@ class RecordArrayManager {
|
|
|
3107
3129
|
const old = source.slice();
|
|
3108
3130
|
source.length = 0;
|
|
3109
3131
|
fastPush(source, identifiers);
|
|
3132
|
+
this._set.set(array, new Set(identifiers));
|
|
3110
3133
|
notifyArray(array);
|
|
3111
3134
|
array.meta = payload.meta || null;
|
|
3112
3135
|
array.links = payload.links || null;
|
|
@@ -3144,21 +3167,30 @@ class RecordArrayManager {
|
|
|
3144
3167
|
}
|
|
3145
3168
|
identifierChanged(identifier) {
|
|
3146
3169
|
let newState = this.store._instanceCache.recordIsLoaded(identifier, true);
|
|
3170
|
+
|
|
3171
|
+
// if the change matches the most recent direct added/removed
|
|
3172
|
+
// state, then we can ignore it
|
|
3173
|
+
if (this._visibilitySet.get(identifier) === newState) {
|
|
3174
|
+
return;
|
|
3175
|
+
}
|
|
3147
3176
|
if (newState) {
|
|
3148
3177
|
this.identifierAdded(identifier);
|
|
3149
3178
|
} else {
|
|
3150
3179
|
this.identifierRemoved(identifier);
|
|
3151
3180
|
}
|
|
3152
3181
|
}
|
|
3153
|
-
clear() {
|
|
3154
|
-
this._live.forEach(array => array.destroy());
|
|
3155
|
-
this._managed.forEach(array => array.destroy());
|
|
3182
|
+
clear(isClear = true) {
|
|
3183
|
+
this._live.forEach(array => array.destroy(isClear));
|
|
3184
|
+
this._managed.forEach(array => array.destroy(isClear));
|
|
3156
3185
|
this._managed.clear();
|
|
3157
3186
|
this._identifiers.clear();
|
|
3187
|
+
this._pending.clear();
|
|
3188
|
+
this._set.forEach(set => set.clear());
|
|
3189
|
+
this._visibilitySet.clear();
|
|
3158
3190
|
}
|
|
3159
3191
|
destroy() {
|
|
3160
3192
|
this.isDestroying = true;
|
|
3161
|
-
this.clear();
|
|
3193
|
+
this.clear(false);
|
|
3162
3194
|
this._live.clear();
|
|
3163
3195
|
this.isDestroyed = true;
|
|
3164
3196
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
@@ -3187,19 +3219,20 @@ function disassociateIdentifier(ArraysCache, array, identifier) {
|
|
|
3187
3219
|
cache.delete(array);
|
|
3188
3220
|
}
|
|
3189
3221
|
}
|
|
3190
|
-
function sync(array, changes) {
|
|
3222
|
+
function sync(array, changes, arraySet) {
|
|
3191
3223
|
let state = array[SOURCE];
|
|
3192
3224
|
const adds = [];
|
|
3193
3225
|
const removes = [];
|
|
3194
3226
|
changes.forEach((value, key) => {
|
|
3195
3227
|
if (value === 'add') {
|
|
3196
3228
|
// likely we want to keep a Set along-side
|
|
3197
|
-
if (
|
|
3229
|
+
if (arraySet.has(key)) {
|
|
3198
3230
|
return;
|
|
3199
3231
|
}
|
|
3200
3232
|
adds.push(key);
|
|
3233
|
+
arraySet.add(key);
|
|
3201
3234
|
} else {
|
|
3202
|
-
if (
|
|
3235
|
+
if (arraySet.has(key)) {
|
|
3203
3236
|
removes.push(key);
|
|
3204
3237
|
}
|
|
3205
3238
|
}
|
|
@@ -3207,6 +3240,7 @@ function sync(array, changes) {
|
|
|
3207
3240
|
if (removes.length) {
|
|
3208
3241
|
if (removes.length === state.length) {
|
|
3209
3242
|
state.length = 0;
|
|
3243
|
+
arraySet.clear();
|
|
3210
3244
|
// changing the reference breaks the Proxy
|
|
3211
3245
|
// state = array[SOURCE] = [];
|
|
3212
3246
|
} else {
|
|
@@ -3214,6 +3248,7 @@ function sync(array, changes) {
|
|
|
3214
3248
|
const index = state.indexOf(i);
|
|
3215
3249
|
if (index !== -1) {
|
|
3216
3250
|
state.splice(index, 1);
|
|
3251
|
+
arraySet.delete(i);
|
|
3217
3252
|
}
|
|
3218
3253
|
});
|
|
3219
3254
|
}
|
|
@@ -3232,11 +3267,9 @@ function sync(array, changes) {
|
|
|
3232
3267
|
}
|
|
3233
3268
|
}
|
|
3234
3269
|
|
|
3235
|
-
/**
|
|
3236
|
-
* @module @ember-data/store
|
|
3237
|
-
*/
|
|
3238
3270
|
const Touching = Symbol('touching');
|
|
3239
3271
|
const RequestPromise = Symbol('promise');
|
|
3272
|
+
const EMPTY_ARR = macroCondition(getOwnConfig().env.DEBUG) ? Object.freeze([]) : [];
|
|
3240
3273
|
function hasRecordIdentifier(op) {
|
|
3241
3274
|
return 'recordIdentifier' in op;
|
|
3242
3275
|
}
|
|
@@ -3250,9 +3283,9 @@ function hasRecordIdentifier(op) {
|
|
|
3250
3283
|
*/
|
|
3251
3284
|
class RequestStateService {
|
|
3252
3285
|
constructor(store) {
|
|
3253
|
-
this._pending =
|
|
3286
|
+
this._pending = new Map();
|
|
3254
3287
|
this._done = new Map();
|
|
3255
|
-
this._subscriptions =
|
|
3288
|
+
this._subscriptions = new Map();
|
|
3256
3289
|
this._toFlush = [];
|
|
3257
3290
|
this._store = void 0;
|
|
3258
3291
|
this._store = store;
|
|
@@ -3263,10 +3296,10 @@ class RequestStateService {
|
|
|
3263
3296
|
_enqueue(promise, queryRequest) {
|
|
3264
3297
|
let query = queryRequest.data[0];
|
|
3265
3298
|
if (hasRecordIdentifier(query)) {
|
|
3266
|
-
|
|
3299
|
+
const identifier = query.recordIdentifier;
|
|
3267
3300
|
let type = query.op === 'saveRecord' ? 'mutation' : 'query';
|
|
3268
|
-
if (!this._pending
|
|
3269
|
-
this._pending
|
|
3301
|
+
if (!this._pending.has(identifier)) {
|
|
3302
|
+
this._pending.set(identifier, []);
|
|
3270
3303
|
}
|
|
3271
3304
|
let request = {
|
|
3272
3305
|
state: 'pending',
|
|
@@ -3275,10 +3308,10 @@ class RequestStateService {
|
|
|
3275
3308
|
};
|
|
3276
3309
|
request[Touching] = [query.recordIdentifier];
|
|
3277
3310
|
request[RequestPromise] = promise;
|
|
3278
|
-
this._pending
|
|
3311
|
+
this._pending.get(identifier).push(request);
|
|
3279
3312
|
this._triggerSubscriptions(request);
|
|
3280
3313
|
return promise.then(result => {
|
|
3281
|
-
this._dequeue(
|
|
3314
|
+
this._dequeue(identifier, request);
|
|
3282
3315
|
let finalizedRequest = {
|
|
3283
3316
|
state: 'fulfilled',
|
|
3284
3317
|
request: queryRequest,
|
|
@@ -3292,7 +3325,7 @@ class RequestStateService {
|
|
|
3292
3325
|
this._triggerSubscriptions(finalizedRequest);
|
|
3293
3326
|
return result;
|
|
3294
3327
|
}, error => {
|
|
3295
|
-
this._dequeue(
|
|
3328
|
+
this._dequeue(identifier, request);
|
|
3296
3329
|
let finalizedRequest = {
|
|
3297
3330
|
state: 'rejected',
|
|
3298
3331
|
request: queryRequest,
|
|
@@ -3329,13 +3362,15 @@ class RequestStateService {
|
|
|
3329
3362
|
}
|
|
3330
3363
|
_flushRequest(req) {
|
|
3331
3364
|
req[Touching].forEach(identifier => {
|
|
3332
|
-
|
|
3333
|
-
|
|
3365
|
+
const subscriptions = this._subscriptions.get(identifier);
|
|
3366
|
+
if (subscriptions) {
|
|
3367
|
+
subscriptions.forEach(callback => callback(req));
|
|
3334
3368
|
}
|
|
3335
3369
|
});
|
|
3336
3370
|
}
|
|
3337
|
-
_dequeue(
|
|
3338
|
-
|
|
3371
|
+
_dequeue(identifier, request) {
|
|
3372
|
+
const pending = this._pending.get(identifier);
|
|
3373
|
+
this._pending.set(identifier, pending.filter(req => req !== request));
|
|
3339
3374
|
}
|
|
3340
3375
|
_addDone(request) {
|
|
3341
3376
|
request[Touching].forEach(identifier => {
|
|
@@ -3346,7 +3381,7 @@ class RequestStateService {
|
|
|
3346
3381
|
requests = requests.filter(req => {
|
|
3347
3382
|
// TODO add support for multiple
|
|
3348
3383
|
let data;
|
|
3349
|
-
if (req.request.data
|
|
3384
|
+
if (Array.isArray(req.request.data)) {
|
|
3350
3385
|
data = req.request.data[0];
|
|
3351
3386
|
} else {
|
|
3352
3387
|
data = req.request.data;
|
|
@@ -3390,10 +3425,12 @@ class RequestStateService {
|
|
|
3390
3425
|
* @param {(state: RequestState) => void} callback
|
|
3391
3426
|
*/
|
|
3392
3427
|
subscribeForRecord(identifier, callback) {
|
|
3393
|
-
|
|
3394
|
-
|
|
3428
|
+
let subscriptions = this._subscriptions.get(identifier);
|
|
3429
|
+
if (!subscriptions) {
|
|
3430
|
+
subscriptions = [];
|
|
3431
|
+
this._subscriptions.set(identifier, subscriptions);
|
|
3395
3432
|
}
|
|
3396
|
-
|
|
3433
|
+
subscriptions.push(callback);
|
|
3397
3434
|
}
|
|
3398
3435
|
|
|
3399
3436
|
/**
|
|
@@ -3405,10 +3442,7 @@ class RequestStateService {
|
|
|
3405
3442
|
* @returns {RequestState[]} an array of request states for any pending requests for the given identifier
|
|
3406
3443
|
*/
|
|
3407
3444
|
getPendingRequestsForRecord(identifier) {
|
|
3408
|
-
|
|
3409
|
-
return this._pending[identifier.lid];
|
|
3410
|
-
}
|
|
3411
|
-
return [];
|
|
3445
|
+
return this._pending.get(identifier) || EMPTY_ARR;
|
|
3412
3446
|
}
|
|
3413
3447
|
|
|
3414
3448
|
/**
|
|
@@ -3427,6 +3461,9 @@ class RequestStateService {
|
|
|
3427
3461
|
return null;
|
|
3428
3462
|
}
|
|
3429
3463
|
}
|
|
3464
|
+
function isNonEmptyString(str) {
|
|
3465
|
+
return Boolean(str && typeof str === 'string');
|
|
3466
|
+
}
|
|
3430
3467
|
function constructResource(type, id, lid) {
|
|
3431
3468
|
if (typeof type === 'object' && type !== null) {
|
|
3432
3469
|
let resource = type;
|
|
@@ -3623,17 +3660,34 @@ class Store extends EmberObject {
|
|
|
3623
3660
|
_run(cb) {
|
|
3624
3661
|
assert(`EmberData should never encounter a nested run`, !this._cbs);
|
|
3625
3662
|
const _cbs = this._cbs = {};
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3663
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
3664
|
+
try {
|
|
3665
|
+
cb();
|
|
3666
|
+
if (_cbs.coalesce) {
|
|
3667
|
+
_cbs.coalesce();
|
|
3668
|
+
}
|
|
3669
|
+
if (_cbs.sync) {
|
|
3670
|
+
_cbs.sync();
|
|
3671
|
+
}
|
|
3672
|
+
if (_cbs.notify) {
|
|
3673
|
+
_cbs.notify();
|
|
3674
|
+
}
|
|
3675
|
+
} finally {
|
|
3676
|
+
this._cbs = null;
|
|
3677
|
+
}
|
|
3678
|
+
} else {
|
|
3679
|
+
cb();
|
|
3680
|
+
if (_cbs.coalesce) {
|
|
3681
|
+
_cbs.coalesce();
|
|
3682
|
+
}
|
|
3683
|
+
if (_cbs.sync) {
|
|
3684
|
+
_cbs.sync();
|
|
3685
|
+
}
|
|
3686
|
+
if (_cbs.notify) {
|
|
3687
|
+
_cbs.notify();
|
|
3688
|
+
}
|
|
3689
|
+
this._cbs = null;
|
|
3635
3690
|
}
|
|
3636
|
-
this._cbs = null;
|
|
3637
3691
|
}
|
|
3638
3692
|
_join(cb) {
|
|
3639
3693
|
if (this._cbs) {
|
|
@@ -3666,9 +3720,8 @@ class Store extends EmberObject {
|
|
|
3666
3720
|
if (macroCondition(getOwnConfig().env.TESTING)) {
|
|
3667
3721
|
const all = [];
|
|
3668
3722
|
const pending = this._requestCache._pending;
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
all.push(...pending[lid].map(v => v[RequestPromise]));
|
|
3723
|
+
pending.forEach(requests => {
|
|
3724
|
+
all.push(...requests.map(v => v[RequestPromise]));
|
|
3672
3725
|
});
|
|
3673
3726
|
this.requestManager._pending.forEach(v => all.push(v));
|
|
3674
3727
|
const promise = Promise.allSettled(all);
|
|
@@ -3994,7 +4047,7 @@ class Store extends EmberObject {
|
|
|
3994
4047
|
};
|
|
3995
4048
|
if (resource.id) {
|
|
3996
4049
|
const identifier = this.identifierCache.peekRecordIdentifier(resource);
|
|
3997
|
-
assert(`The id ${properties.id} has already been used with another '${normalizedModelName}' record.`, !identifier);
|
|
4050
|
+
assert(`The id ${String(properties.id)} has already been used with another '${normalizedModelName}' record.`, !identifier);
|
|
3998
4051
|
}
|
|
3999
4052
|
const identifier = this.identifierCache.createIdentifierForNewRecord(resource);
|
|
4000
4053
|
const cache = this.cache;
|
|
@@ -4476,7 +4529,7 @@ class Store extends EmberObject {
|
|
|
4476
4529
|
assertDestroyingStore(this, 'peekRecord');
|
|
4477
4530
|
}
|
|
4478
4531
|
assert(`You need to pass a model name to the store's peekRecord method`, identifier);
|
|
4479
|
-
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${identifier}`, typeof identifier === 'string');
|
|
4532
|
+
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${String(identifier)}`, typeof identifier === 'string');
|
|
4480
4533
|
const type = normalizeModelName(identifier);
|
|
4481
4534
|
const normalizedId = ensureStringId(id);
|
|
4482
4535
|
const resource = {
|
|
@@ -4864,7 +4917,7 @@ class Store extends EmberObject {
|
|
|
4864
4917
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
4865
4918
|
assertDestroyedStoreOnly(this, 'unloadAll');
|
|
4866
4919
|
}
|
|
4867
|
-
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, !modelName || typeof modelName === 'string');
|
|
4920
|
+
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${String(modelName)}`, !modelName || typeof modelName === 'string');
|
|
4868
4921
|
this._join(() => {
|
|
4869
4922
|
if (modelName === undefined) {
|
|
4870
4923
|
// destroy the graph before unloadAll
|
|
@@ -5032,7 +5085,7 @@ class Store extends EmberObject {
|
|
|
5032
5085
|
@method _push
|
|
5033
5086
|
@private
|
|
5034
5087
|
@param {Object} jsonApiDoc
|
|
5035
|
-
@return {StableRecordIdentifier|Array<StableRecordIdentifier
|
|
5088
|
+
@return {StableRecordIdentifier|Array<StableRecordIdentifier>|null} identifiers for the primary records that had data loaded
|
|
5036
5089
|
*/
|
|
5037
5090
|
_push(jsonApiDoc, asyncFlush) {
|
|
5038
5091
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
@@ -5058,7 +5111,7 @@ class Store extends EmberObject {
|
|
|
5058
5111
|
});
|
|
5059
5112
|
});
|
|
5060
5113
|
this._enableAsyncFlush = null;
|
|
5061
|
-
return ret.data;
|
|
5114
|
+
return 'data' in ret ? ret.data : null;
|
|
5062
5115
|
}
|
|
5063
5116
|
|
|
5064
5117
|
/**
|
|
@@ -5109,19 +5162,10 @@ class Store extends EmberObject {
|
|
|
5109
5162
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
5110
5163
|
assertDestroyingStore(this, 'pushPayload');
|
|
5111
5164
|
}
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
serializer = this.serializerFor('application');
|
|
5117
|
-
assert(`You cannot use 'store#pushPayload' without a modelName unless your default serializer defines 'pushPayload'`, typeof serializer.pushPayload === 'function');
|
|
5118
|
-
} else {
|
|
5119
|
-
payload = inputPayload;
|
|
5120
|
-
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string');
|
|
5121
|
-
let normalizedModelName = normalizeModelName(modelName);
|
|
5122
|
-
serializer = this.serializerFor(normalizedModelName);
|
|
5123
|
-
}
|
|
5124
|
-
assert(`You must define a pushPayload method in your serializer in order to call store.pushPayload`, serializer.pushPayload);
|
|
5165
|
+
const payload = inputPayload || modelName;
|
|
5166
|
+
const normalizedModelName = inputPayload ? normalizeModelName(modelName) : 'application';
|
|
5167
|
+
const serializer = this.serializerFor(normalizedModelName);
|
|
5168
|
+
assert(`You cannot use 'store.pushPayload(<type>, <payload>)' unless the serializer for '${normalizedModelName}' defines 'pushPayload'`, serializer && typeof serializer.pushPayload === 'function');
|
|
5125
5169
|
serializer.pushPayload(this, payload);
|
|
5126
5170
|
}
|
|
5127
5171
|
|
|
@@ -5147,7 +5191,7 @@ class Store extends EmberObject {
|
|
|
5147
5191
|
return Promise.reject(`Record Is Disconnected`);
|
|
5148
5192
|
}
|
|
5149
5193
|
// TODO we used to check if the record was destroyed here
|
|
5150
|
-
assert(`Cannot initiate a save request for an unloaded record: ${identifier}`, this._instanceCache.recordIsLoaded(identifier));
|
|
5194
|
+
assert(`Cannot initiate a save request for an unloaded record: ${identifier.lid}`, this._instanceCache.recordIsLoaded(identifier));
|
|
5151
5195
|
if (resourceIsFullyDeleted(this._instanceCache, identifier)) {
|
|
5152
5196
|
return Promise.resolve(record);
|
|
5153
5197
|
}
|
|
@@ -5235,11 +5279,11 @@ class Store extends EmberObject {
|
|
|
5235
5279
|
}
|
|
5236
5280
|
assert(`You need to pass a model name to the store's normalize method`, modelName);
|
|
5237
5281
|
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${typeof modelName}`, typeof modelName === 'string');
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
assert(`You must define a normalize method in your serializer in order to call store.normalize`, serializer?.normalize);
|
|
5242
|
-
return serializer.normalize(
|
|
5282
|
+
const normalizedModelName = normalizeModelName(modelName);
|
|
5283
|
+
const serializer = this.serializerFor(normalizedModelName);
|
|
5284
|
+
const schema = this.modelFor(normalizedModelName);
|
|
5285
|
+
assert(`You must define a normalize method in your serializer in order to call store.normalize`, typeof serializer?.normalize === 'function');
|
|
5286
|
+
return serializer.normalize(schema, payload);
|
|
5243
5287
|
}
|
|
5244
5288
|
|
|
5245
5289
|
/**
|
|
@@ -5268,7 +5312,7 @@ class Store extends EmberObject {
|
|
|
5268
5312
|
if (adapter) {
|
|
5269
5313
|
return adapter;
|
|
5270
5314
|
}
|
|
5271
|
-
|
|
5315
|
+
const owner = getOwner(this);
|
|
5272
5316
|
|
|
5273
5317
|
// name specific adapter
|
|
5274
5318
|
adapter = owner.lookup(`adapter:${normalizedModelName}`);
|
|
@@ -5315,9 +5359,9 @@ class Store extends EmberObject {
|
|
|
5315
5359
|
if (serializer) {
|
|
5316
5360
|
return serializer;
|
|
5317
5361
|
}
|
|
5318
|
-
let owner = getOwner(this);
|
|
5319
5362
|
|
|
5320
5363
|
// by name
|
|
5364
|
+
const owner = getOwner(this);
|
|
5321
5365
|
serializer = owner.lookup(`serializer:${normalizedModelName}`);
|
|
5322
5366
|
if (serializer !== undefined) {
|
|
5323
5367
|
_serializerCache[normalizedModelName] = serializer;
|
|
@@ -5369,9 +5413,11 @@ class Store extends EmberObject {
|
|
|
5369
5413
|
let assertDestroyingStore;
|
|
5370
5414
|
let assertDestroyedStoreOnly;
|
|
5371
5415
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
5372
|
-
|
|
5416
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
5417
|
+
assertDestroyingStore = function assertDestroyingStore(store, method) {
|
|
5373
5418
|
assert(`Attempted to call store.${method}(), but the store instance has already been destroyed.`, !(store.isDestroying || store.isDestroyed));
|
|
5374
5419
|
};
|
|
5420
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
5375
5421
|
assertDestroyedStoreOnly = function assertDestroyedStoreOnly(store, method) {
|
|
5376
5422
|
assert(`Attempted to call store.${method}(), but the store instance has already been destroyed.`, !store.isDestroyed);
|
|
5377
5423
|
};
|