From 258fc30e77813c185c3b15c5a9ea719feb47b332 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sat, 19 Dec 2015 10:25:42 -0500 Subject: [PATCH] [BUGFIX beta] Ensure `container` can still be provided to `.create`. In Ember versions until 2.3.0 it was common to provide a `container` property (if needed) when creating instances of a factory manually. This might look like: ``` let Foo = container.lookupFactory('model:foo'); let instance = Foo.create({ container }); ``` Many addons did this (examples include ember-cp-validations and ember-data). Our initial implementation of the deprecated `container` property on extendable factories used `Object.defineProperty` to ensure calling `instance.container` returned the correct value. Unfortunately, we only defined a getter which means calling `Foo.create({ container });` triggers the following error: ``` Cannot set property container of [object Object] which has only a getter ``` This change adds a setter (with an appropriate deprecation) to prevent triggering an error. --- packages/container/lib/container.js | 18 +++++++++++++++++- packages/container/tests/container_test.js | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/packages/container/lib/container.js b/packages/container/lib/container.js index 7e7cecc1abe..40d363f7c9c 100644 --- a/packages/container/lib/container.js +++ b/packages/container/lib/container.js @@ -4,6 +4,9 @@ import dictionary from 'ember-metal/dictionary'; import isEnabled from 'ember-metal/features'; import { setOwner, OWNER } from './owner'; import { buildFakeContainerWithDeprecations } from 'ember-runtime/mixins/container_proxy'; +import symbol from 'ember-metal/symbol'; + +const CONTAINER_OVERRIDE = symbol('CONTAINER_OVERRIDE'); /** A container used to instantiate and cache objects. @@ -27,6 +30,7 @@ function Container(registry, options) { if (isEnabled('ember-container-inject-owner')) { this._fakeContainerToInject = buildFakeContainerWithDeprecations(this); + this[CONTAINER_OVERRIDE] = undefined; } } @@ -404,7 +408,19 @@ function injectDeprecatedContainer(object, container) { deprecate('Using the injected `container` is deprecated. Please use the `getOwner` helper instead to access the owner of this object.', false, { id: 'ember-application.injected-container', until: '3.0.0', url: 'http://emberjs.com/deprecations/v2.x#toc_injected-container-access' }); - return container; + return this[CONTAINER_OVERRIDE] || container; + }, + + set(value) { + deprecate( + `Providing the \`container\` property to ${this} is deprecated. Please use \`Ember.setOwner\` or \`owner.ownerInjection()\` instead to provide an owner to the instance being created.`, + false, + { id: 'ember-application.injected-container', until: '3.0.0', url: 'http://emberjs.com/deprecations/v2.x#toc_injected-container-access' } + ); + + this[CONTAINER_OVERRIDE] = value; + + return value; } }); } diff --git a/packages/container/tests/container_test.js b/packages/container/tests/container_test.js index 8049ca1df56..02cd2c25478 100644 --- a/packages/container/tests/container_test.js +++ b/packages/container/tests/container_test.js @@ -642,6 +642,28 @@ if (isEnabled('ember-container-inject-owner')) { equal(otherController.container, 'foo', 'container was not added'); }); + + QUnit.test('An extendable factory can provide `container` upon create, with a deprecation', function(assert) { + let registry = new Registry(); + let container = registry.container(); + + registry.register('controller:post', factory()); + + let PostController = container.lookupFactory('controller:post'); + + let postController; + + expectDeprecation(function() { + postController = PostController.create({ + container: 'foo' + }); + }, /Providing the \`container\` property to .+ is deprecated. Please use \`Ember.setOwner\` or \`owner.ownerInjection\(\)\` instead to provide an owner to the instance being created/); + + expectDeprecation(function() { + let c = postController.container; + assert.equal(c, 'foo', 'the `container` provided to `.create`was used'); + }, 'Using the injected `container` is deprecated. Please use the `getOwner` helper instead to access the owner of this object.'); + }); } else { QUnit.test('A `container` property is appended to every instantiated object', function() { let registry = new Registry();