diff --git a/packages/-ember-data/tests/integration/relationships/promise-many-array-test.js b/packages/-ember-data/tests/integration/relationships/promise-many-array-test.js new file mode 100644 index 00000000000..7b58ab43340 --- /dev/null +++ b/packages/-ember-data/tests/integration/relationships/promise-many-array-test.js @@ -0,0 +1,39 @@ +import { A } from '@ember/array'; +import { w } from '@ember/string'; + +import { module, test } from 'qunit'; + +import { setupRenderingTest } from 'ember-qunit'; + +import Model, { attr, hasMany } from '@ember-data/model'; + +module('PromiseManyArray side-affected by EmberArray', (hooks) => { + setupRenderingTest(hooks); + + test('PromiseManyArray is not side-affected by EmberArray', async function (assert) { + const { owner } = this; + class Person extends Model { + @attr('string') name; + } + class Group extends Model { + @hasMany('person', { inverse: null }) members; + } + owner.register('model:person', Person); + owner.register('model:group', Group); + const store = owner.lookup('service:store'); + const members = w('Bob John Michael Larry Lucy').map((name) => store.createRecord('person', { name })); + const group = store.createRecord('group', { members }); + + const replaceFn = group.members.replace; + assert.strictEqual(group.members.length, 5, 'initial length is correct'); + + group.members.replace(0, 1); + assert.strictEqual(group.members.length, 4, 'updated length is correct'); + + A(group.members); + + assert.strictEqual(replaceFn, group.members.replace, 'we have the same function for replace'); + group.members.replace(0, 1); + assert.strictEqual(group.members.length, 3, 'updated length is correct'); + }); +}); diff --git a/packages/model/addon/-private/system/promise-many-array.ts b/packages/model/addon/-private/system/promise-many-array.ts index 6c0a6d58d38..69557348dfd 100644 --- a/packages/model/addon/-private/system/promise-many-array.ts +++ b/packages/model/addon/-private/system/promise-many-array.ts @@ -1,3 +1,4 @@ +import ArrayMixin from '@ember/array'; import { assert } from '@ember/debug'; import { dependentKeyCompat } from '@ember/object/compat'; import { tracked } from '@glimmer/tracking'; @@ -16,7 +17,7 @@ import { DEPRECATE_EVENTED_API_USAGE } from '@ember-data/private-build-infra/dep A PromiseManyArray is an array-like proxy that also proxies certain method calls to the underlying ManyArray in addition to being "promisified". - + Right now we proxy: * `reload()` @@ -41,6 +42,14 @@ export default class PromiseManyArray { this._update(promise, content); this.isDestroyed = false; this.isDestroying = false; + + const meta = Ember.meta(this); + meta.hasMixin = (mixin: Object) => { + if (mixin === ArrayMixin) { + return true; + } + return false; + }; } //---- Methods/Properties on ArrayProxy that we will keep as our API diff --git a/packages/store/types/ember/index.d.ts b/packages/store/types/ember/index.d.ts index 0cac9e5580b..bc7e03a32b9 100644 --- a/packages/store/types/ember/index.d.ts +++ b/packages/store/types/ember/index.d.ts @@ -2,3 +2,4 @@ export function run(callback: Function); export const ENV: { DS_WARN_ON_UNKNOWN_KEYS?: boolean; }; +export function meta(obj: Object): any;