From 21a288e27247069b6782fd985579b2170b9eae3e Mon Sep 17 00:00:00 2001 From: Chris Garrett Date: Thu, 4 Apr 2019 11:01:51 -0700 Subject: [PATCH 1/2] [FEATURE beta] Passes the owner through to classic classes --- .../runtime/lib/system/core_object.js | 46 +++++++++++++++---- .../runtime/tests/system/core_object_test.js | 25 ++++++++++ 2 files changed, 61 insertions(+), 10 deletions(-) diff --git a/packages/@ember/-internals/runtime/lib/system/core_object.js b/packages/@ember/-internals/runtime/lib/system/core_object.js index b7e9fcc14b0..58d2c7cff98 100644 --- a/packages/@ember/-internals/runtime/lib/system/core_object.js +++ b/packages/@ember/-internals/runtime/lib/system/core_object.js @@ -4,6 +4,7 @@ import { FACTORY_FOR } from '@ember/-internals/container'; import { assign, _WeakSet as WeakSet } from '@ember/polyfills'; +import { getOwner, setOwner } from '@ember/-internals/owner'; import { guidFor, getName, @@ -40,12 +41,14 @@ const factoryMap = new WeakMap(); const prototypeMixinMap = new WeakMap(); -let PASSED_FROM_CREATE; +let OWNER_PLACEHOLDER; +let passedFromCreate; let initCalled; // only used in debug builds to enable the proxy trap // using DEBUG here to avoid the extraneous variable when not needed if (DEBUG) { - PASSED_FROM_CREATE = Symbol(); + OWNER_PLACEHOLDER = Object.freeze({}); + passedFromCreate = new WeakSet(); initCalled = new WeakSet(); } @@ -215,7 +218,7 @@ class CoreObject { factoryMap.set(this, factory); } - constructor(properties) { + constructor(owner) { // pluck off factory let initFactory = factoryMap.get(this.constructor); if (initFactory !== undefined) { @@ -284,12 +287,20 @@ class CoreObject { m.setInitializing(); - assert( - `An EmberObject based class, ${ - this.constructor - }, was not instantiated correctly. You may have either used \`new\` instead of \`.create()\`, or not passed arguments to your call to super in the constructor: \`super(...arguments)\`. If you are trying to use \`new\`, consider using native classes without extending from EmberObject.`, - properties[PASSED_FROM_CREATE] - ); + if (DEBUG) { + assert( + `An EmberObject based class, ${ + this.constructor + }, was not instantiated correctly. You may have either used \`new\` instead of \`.create()\`, or not passed arguments to your call to super in the constructor: \`super(...arguments)\`. If you are trying to use \`new\`, consider using native classes without extending from EmberObject.`, + passedFromCreate.has(owner) || owner === OWNER_PLACEHOLDER + ); + + if (owner !== OWNER_PLACEHOLDER) { + setOwner(this, owner); + } + } else { + setOwner(this, owner); + } // only return when in debug builds and `self` is the proxy created above if (DEBUG && self !== this) { @@ -764,7 +775,22 @@ class CoreObject { */ static create(props, extra) { let C = this; - let instance = DEBUG ? new C(Object.freeze({ [PASSED_FROM_CREATE]: true })) : new C(); + + let owner = typeof props === 'object' && props !== null ? getOwner(props) : undefined; + + if (DEBUG) { + if (owner) { + passedFromCreate.add(owner); + } else { + owner = OWNER_PLACEHOLDER; + } + } + + let instance = new C(owner); + + if (DEBUG) { + passedFromCreate.delete(owner); + } if (extra === undefined) { initialize(instance, props); diff --git a/packages/@ember/-internals/runtime/tests/system/core_object_test.js b/packages/@ember/-internals/runtime/tests/system/core_object_test.js index 0f809a78234..b7ac98691a0 100644 --- a/packages/@ember/-internals/runtime/tests/system/core_object_test.js +++ b/packages/@ember/-internals/runtime/tests/system/core_object_test.js @@ -29,6 +29,31 @@ moduleFor( }, /You may have either used `new` instead of `.create\(\)`/); } + ['@test tunnels the owner through to the base constructor'](assert) { + assert.expect(2); + + let owner = {}; + let props = { + someOtherProp: 'foo', + }; + + setOwner(props, owner); + + class Route extends CoreObject { + constructor() { + super(...arguments); + assert.equal( + getOwner(this), + owner, + 'owner was assigned properly in the root constructor' + ); + assert.equal(this.someOtherProp, undefined, 'other props were not yet assigned'); + } + } + + Route.create(props); + } + ['@test toString should be not be added as a property when calling toString()'](assert) { let obj = CoreObject.create({ firstName: 'Foo', From 0b47cd296924163b3bb3f5f1cbab862c15bd4daa Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Thu, 2 May 2019 17:11:52 -0400 Subject: [PATCH 2/2] Refactor implementation of owner tunnel to limit to framework classes. --- .../-internals/glimmer/lib/component.ts | 7 +- .../@ember/-internals/glimmer/lib/helper.ts | 7 +- .../components/curly-components-test.js | 24 +++++ .../integration/helpers/custom-helper-test.js | 26 +++++- .../routing/lib/system/generate_controller.ts | 6 +- .../-internals/routing/lib/system/route.ts | 6 ++ packages/@ember/-internals/runtime/index.d.ts | 1 + packages/@ember/-internals/runtime/index.js | 2 +- .../runtime/lib/system/core_object.js | 92 +++++++++++-------- .../-internals/runtime/lib/system/object.js | 25 ++++- .../@ember/-internals/runtime/lib/type-of.js | 6 +- .../runtime/tests/system/core_object_test.js | 25 ----- .../tests/system/object/framework_test.js | 35 +++++++ packages/@ember/canary-features/index.ts | 4 + packages/@ember/controller/index.js | 9 +- packages/@ember/service/index.js | 9 +- packages/ember/index.js | 7 +- 17 files changed, 212 insertions(+), 79 deletions(-) create mode 100644 packages/@ember/-internals/runtime/tests/system/object/framework_test.js diff --git a/packages/@ember/-internals/glimmer/lib/component.ts b/packages/@ember/-internals/glimmer/lib/component.ts index f5d4ac8bff5..df918c285c1 100644 --- a/packages/@ember/-internals/glimmer/lib/component.ts +++ b/packages/@ember/-internals/glimmer/lib/component.ts @@ -1,6 +1,6 @@ import { get, PROPERTY_DID_CHANGE } from '@ember/-internals/metal'; import { getOwner } from '@ember/-internals/owner'; -import { TargetActionSupport } from '@ember/-internals/runtime'; +import { setFrameworkClass, TargetActionSupport } from '@ember/-internals/runtime'; import { symbol } from '@ember/-internals/utils'; import { ActionSupport, @@ -16,6 +16,7 @@ import { DEBUG } from '@glimmer/env'; import { DirtyableTag } from '@glimmer/reference'; import { normalizeProperty, SVG_NAMESPACE } from '@glimmer/runtime'; +import { EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT } from '@ember/canary-features'; import { RootReference, UPDATE } from './utils/references'; export const DIRTY_TAG = symbol('DIRTY_TAG'); @@ -1086,4 +1087,8 @@ Component.reopenClass({ positionalParams: [], }); +if (EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT) { + setFrameworkClass(Component); +} + export default Component; diff --git a/packages/@ember/-internals/glimmer/lib/helper.ts b/packages/@ember/-internals/glimmer/lib/helper.ts index 70d72b27080..dcbd65a9a7c 100644 --- a/packages/@ember/-internals/glimmer/lib/helper.ts +++ b/packages/@ember/-internals/glimmer/lib/helper.ts @@ -3,8 +3,9 @@ */ import { Factory } from '@ember/-internals/owner'; -import { FrameworkObject } from '@ember/-internals/runtime'; +import { FrameworkObject, setFrameworkClass } from '@ember/-internals/runtime'; import { symbol } from '@ember/-internals/utils'; +import { EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT } from '@ember/canary-features'; import { Dict, Opaque } from '@glimmer/interfaces'; import { DirtyableTag } from '@glimmer/reference'; @@ -131,6 +132,10 @@ let Helper = FrameworkObject.extend({ Helper.isHelperFactory = true; +if (EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT) { + setFrameworkClass(Helper); +} + class Wrapper implements HelperFactory { isHelperFactory: true = true; diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js index 50db70bf830..e164309535a 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/curly-components-test.js @@ -3594,6 +3594,30 @@ moduleFor( this.assertText('[third][]'); } + + ['@feature(EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT) it can render a basic component in native ES class syntax']( + assert + ) { + let testContext = this; + this.registerComponent('foo-bar', { + ComponentClass: class extends Component { + constructor(owner) { + super(owner); + + assert.equal(owner, testContext.owner, 'owner was passed as a constructor argument'); + } + }, + template: 'hello', + }); + + this.render('{{foo-bar}}'); + + this.assertComponentElement(this.firstChild, { content: 'hello' }); + + runTask(() => this.rerender()); + + this.assertComponentElement(this.firstChild, { content: 'hello' }); + } } ); diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/custom-helper-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/custom-helper-test.js index 78e678abb11..b68dcee9e57 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/custom-helper-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/custom-helper-test.js @@ -1,7 +1,7 @@ /* globals EmberDev */ import { RenderingTestCase, moduleFor, runDestroy, runTask } from 'internal-test-helpers'; - +import { Helper } from '@ember/-internals/glimmer'; import { set } from '@ember/-internals/metal'; moduleFor( @@ -599,6 +599,30 @@ moduleFor( assert.equal(typeof instance.compute, 'function', 'expected instance.compute to be present'); assert.equal(instance.compute(), 'lolol', 'can invoke `.compute`'); } + + ['@feature(EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT) class-based helper in native ES syntax receives owner']( + assert + ) { + let testContext = this; + this.add( + 'helper:hello-world', + class extends Helper { + constructor(owner) { + super(owner); + + assert.equal(owner, testContext.owner, 'owner was passed as a constructor argument'); + } + + compute() { + return 'huzza!'; + } + } + ); + + this.render('{{hello-world}}'); + + this.assertText('huzza!'); + } } ); diff --git a/packages/@ember/-internals/routing/lib/system/generate_controller.ts b/packages/@ember/-internals/routing/lib/system/generate_controller.ts index 982bd09731d..6b711f87491 100644 --- a/packages/@ember/-internals/routing/lib/system/generate_controller.ts +++ b/packages/@ember/-internals/routing/lib/system/generate_controller.ts @@ -1,5 +1,5 @@ import { get } from '@ember/-internals/metal'; -import { Owner } from '@ember/-internals/owner'; +import { Factory, Owner } from '@ember/-internals/owner'; import { info } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; /** @@ -14,7 +14,7 @@ import { DEBUG } from '@glimmer/env'; @private */ -export function generateControllerFactory(owner: Owner, controllerName: string) { +export function generateControllerFactory(owner: Owner, controllerName: string): Factory<{}> { let Factory = owner.factoryFor('controller:basic')!.class!; Factory = Factory.extend({ @@ -27,7 +27,7 @@ export function generateControllerFactory(owner: Owner, controllerName: string) owner.register(fullName, Factory); - return Factory; + return owner.factoryFor(fullName) as Factory<{}>; } /** diff --git a/packages/@ember/-internals/routing/lib/system/route.ts b/packages/@ember/-internals/routing/lib/system/route.ts index af8ded76420..c2fa3e0790f 100644 --- a/packages/@ember/-internals/routing/lib/system/route.ts +++ b/packages/@ember/-internals/routing/lib/system/route.ts @@ -14,9 +14,11 @@ import { ActionHandler, Evented, Object as EmberObject, + setFrameworkClass, typeOf, } from '@ember/-internals/runtime'; import { + EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT, EMBER_METAL_TRACKED_PROPERTIES, EMBER_ROUTING_BUILD_ROUTEINFO_METADATA, } from '@ember/canary-features'; @@ -2627,4 +2629,8 @@ if (EMBER_ROUTING_BUILD_ROUTEINFO_METADATA) { }); } +if (EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT) { + setFrameworkClass(Route); +} + export default Route; diff --git a/packages/@ember/-internals/runtime/index.d.ts b/packages/@ember/-internals/runtime/index.d.ts index b3a044c855c..94519e464f3 100644 --- a/packages/@ember/-internals/runtime/index.d.ts +++ b/packages/@ember/-internals/runtime/index.d.ts @@ -11,6 +11,7 @@ export function deprecatingAlias( ): any; export const FrameworkObject: any; +export function setFrameworkClass(klass: new () => T): void; export const Object: any; export function _contentFor(proxy: any): any; diff --git a/packages/@ember/-internals/runtime/index.js b/packages/@ember/-internals/runtime/index.js index 6558895952b..52d7202269c 100644 --- a/packages/@ember/-internals/runtime/index.js +++ b/packages/@ember/-internals/runtime/index.js @@ -17,7 +17,7 @@ export { default as Comparable } from './lib/mixins/comparable'; export { default as Namespace } from './lib/system/namespace'; export { default as ArrayProxy } from './lib/system/array_proxy'; export { default as ObjectProxy } from './lib/system/object_proxy'; -export { default as CoreObject } from './lib/system/core_object'; +export { default as CoreObject, setFrameworkClass } from './lib/system/core_object'; export { default as ActionHandler } from './lib/mixins/action_handler'; export { default as Copyable } from './lib/mixins/copyable'; export { default as Enumerable } from './lib/mixins/enumerable'; diff --git a/packages/@ember/-internals/runtime/lib/system/core_object.js b/packages/@ember/-internals/runtime/lib/system/core_object.js index 58d2c7cff98..1b1fb7ab1d6 100644 --- a/packages/@ember/-internals/runtime/lib/system/core_object.js +++ b/packages/@ember/-internals/runtime/lib/system/core_object.js @@ -3,17 +3,21 @@ */ import { FACTORY_FOR } from '@ember/-internals/container'; +import { getOwner } from '@ember/-internals/owner'; import { assign, _WeakSet as WeakSet } from '@ember/polyfills'; -import { getOwner, setOwner } from '@ember/-internals/owner'; import { guidFor, getName, setName, + symbol, makeArray, HAS_NATIVE_PROXY, isInternalSymbol, } from '@ember/-internals/utils'; -import { EMBER_METAL_TRACKED_PROPERTIES } from '@ember/canary-features'; +import { + EMBER_METAL_TRACKED_PROPERTIES, + EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT, +} from '@ember/canary-features'; import { schedule } from '@ember/runloop'; import { meta, peekMeta, deleteMeta } from '@ember/-internals/meta'; import { @@ -41,15 +45,15 @@ const factoryMap = new WeakMap(); const prototypeMixinMap = new WeakMap(); -let OWNER_PLACEHOLDER; -let passedFromCreate; -let initCalled; // only used in debug builds to enable the proxy trap +const initCalled = DEBUG ? new WeakSet() : undefined; // only used in debug builds to enable the proxy trap +const PASSED_FROM_CREATE = DEBUG ? symbol('PASSED_FROM_CREATE') : undefined; -// using DEBUG here to avoid the extraneous variable when not needed -if (DEBUG) { - OWNER_PLACEHOLDER = Object.freeze({}); - passedFromCreate = new WeakSet(); - initCalled = new WeakSet(); +const FRAMEWORK_CLASSES = EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT + ? symbol('FRAMEWORK_CLASS') + : undefined; + +export function setFrameworkClass(klass) { + klass[FRAMEWORK_CLASSES] = true; } function initialize(obj, properties) { @@ -218,7 +222,7 @@ class CoreObject { factoryMap.set(this, factory); } - constructor(owner) { + constructor(passedFromCreate) { // pluck off factory let initFactory = factoryMap.get(this.constructor); if (initFactory !== undefined) { @@ -287,20 +291,30 @@ class CoreObject { m.setInitializing(); - if (DEBUG) { - assert( - `An EmberObject based class, ${ - this.constructor - }, was not instantiated correctly. You may have either used \`new\` instead of \`.create()\`, or not passed arguments to your call to super in the constructor: \`super(...arguments)\`. If you are trying to use \`new\`, consider using native classes without extending from EmberObject.`, - passedFromCreate.has(owner) || owner === OWNER_PLACEHOLDER - ); + assert( + `An EmberObject based class, ${ + this.constructor + }, was not instantiated correctly. You may have either used \`new\` instead of \`.create()\`, or not passed arguments to your call to super in the constructor: \`super(...arguments)\`. If you are trying to use \`new\`, consider using native classes without extending from EmberObject.`, + (() => { + if (passedFromCreate === PASSED_FROM_CREATE) { + return true; + } - if (owner !== OWNER_PLACEHOLDER) { - setOwner(this, owner); - } - } else { - setOwner(this, owner); - } + if (!EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT) { + return false; + } + + if (initFactory === undefined) { + return false; + } + + if (passedFromCreate === initFactory.owner) { + return true; + } + + return false; + })() + ); // only return when in debug builds and `self` is the proxy created above if (DEBUG && self !== this) { @@ -775,21 +789,27 @@ class CoreObject { */ static create(props, extra) { let C = this; - - let owner = typeof props === 'object' && props !== null ? getOwner(props) : undefined; - - if (DEBUG) { - if (owner) { - passedFromCreate.add(owner); - } else { - owner = OWNER_PLACEHOLDER; + let instance; + + if (EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT && this[FRAMEWORK_CLASSES]) { + let initFactory = factoryMap.get(this); + let owner; + if (initFactory !== undefined) { + owner = initFactory.owner; + } else if (props !== undefined) { + owner = getOwner(props); } - } - let instance = new C(owner); + if (owner === undefined) { + // fallback to passing the special PASSED_FROM_CREATE symbol + // to avoid an error when folks call things like Controller.extend().create() + // we should do a subsequent deprecation pass to ensure this isn't allowed + owner = PASSED_FROM_CREATE; + } - if (DEBUG) { - passedFromCreate.delete(owner); + instance = new C(owner); + } else { + instance = DEBUG ? new C(PASSED_FROM_CREATE) : new C(); } if (extra === undefined) { diff --git a/packages/@ember/-internals/runtime/lib/system/object.js b/packages/@ember/-internals/runtime/lib/system/object.js index 8b34319abaa..a7a9ed98717 100644 --- a/packages/@ember/-internals/runtime/lib/system/object.js +++ b/packages/@ember/-internals/runtime/lib/system/object.js @@ -3,9 +3,10 @@ */ import { FACTORY_FOR } from '@ember/-internals/container'; -import { OWNER } from '@ember/-internals/owner'; +import { OWNER, setOwner } from '@ember/-internals/owner'; import { symbol, setName } from '@ember/-internals/utils'; import { addListener } from '@ember/-internals/metal'; +import { EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT } from '@ember/canary-features'; import CoreObject from './core_object'; import Observable from '../mixins/observable'; import { assert } from '@ember/debug'; @@ -49,13 +50,31 @@ setName(EmberObject, 'Ember.Object'); Observable.apply(EmberObject.prototype); -export let FrameworkObject = EmberObject; +export let FrameworkObject; + +if (EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT) { + FrameworkObject = class FrameworkObject extends CoreObject { + get _debugContainerKey() { + let factory = FACTORY_FOR.get(this); + return factory !== undefined && factory.fullName; + } + + constructor(owner) { + super(); + + setOwner(this, owner); + } + }; + Observable.apply(FrameworkObject.prototype); +} else { + FrameworkObject = class FrameworkObject extends EmberObject {}; +} if (DEBUG) { let INIT_WAS_CALLED = symbol('INIT_WAS_CALLED'); let ASSERT_INIT_WAS_CALLED = symbol('ASSERT_INIT_WAS_CALLED'); - FrameworkObject = class FrameworkObject extends EmberObject { + FrameworkObject = class DebugFrameworkObject extends EmberObject { init() { super.init(...arguments); this[INIT_WAS_CALLED] = true; diff --git a/packages/@ember/-internals/runtime/lib/type-of.js b/packages/@ember/-internals/runtime/lib/type-of.js index f2922dd12ca..c58ae66782c 100644 --- a/packages/@ember/-internals/runtime/lib/type-of.js +++ b/packages/@ember/-internals/runtime/lib/type-of.js @@ -1,4 +1,4 @@ -import EmberObject from './system/object'; +import CoreObject from './system/core_object'; // ........................................ // TYPING & ARRAY MESSAGING @@ -90,13 +90,13 @@ export function typeOf(item) { let ret = TYPE_MAP[toString.call(item)] || 'object'; if (ret === 'function') { - if (EmberObject.detect(item)) { + if (CoreObject.detect(item)) { ret = 'class'; } } else if (ret === 'object') { if (item instanceof Error) { ret = 'error'; - } else if (item instanceof EmberObject) { + } else if (item instanceof CoreObject) { ret = 'instance'; } else if (item instanceof Date) { ret = 'date'; diff --git a/packages/@ember/-internals/runtime/tests/system/core_object_test.js b/packages/@ember/-internals/runtime/tests/system/core_object_test.js index b7ac98691a0..0f809a78234 100644 --- a/packages/@ember/-internals/runtime/tests/system/core_object_test.js +++ b/packages/@ember/-internals/runtime/tests/system/core_object_test.js @@ -29,31 +29,6 @@ moduleFor( }, /You may have either used `new` instead of `.create\(\)`/); } - ['@test tunnels the owner through to the base constructor'](assert) { - assert.expect(2); - - let owner = {}; - let props = { - someOtherProp: 'foo', - }; - - setOwner(props, owner); - - class Route extends CoreObject { - constructor() { - super(...arguments); - assert.equal( - getOwner(this), - owner, - 'owner was assigned properly in the root constructor' - ); - assert.equal(this.someOtherProp, undefined, 'other props were not yet assigned'); - } - } - - Route.create(props); - } - ['@test toString should be not be added as a property when calling toString()'](assert) { let obj = CoreObject.create({ firstName: 'Foo', diff --git a/packages/@ember/-internals/runtime/tests/system/object/framework_test.js b/packages/@ember/-internals/runtime/tests/system/object/framework_test.js new file mode 100644 index 00000000000..01998eafe8b --- /dev/null +++ b/packages/@ember/-internals/runtime/tests/system/object/framework_test.js @@ -0,0 +1,35 @@ +import { EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT } from '@ember/canary-features'; +import { getOwner } from '@ember/-internals/owner'; +import { FrameworkObject } from '../../../index'; +import { moduleFor, AbstractRenderingTestCase } from 'internal-test-helpers'; +import { setFrameworkClass } from '../../../lib/system/core_object'; + +if (EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT) { + moduleFor( + 'FrameworkObject', + class extends AbstractRenderingTestCase { + ['@test tunnels the owner through to the base constructor for framework classes'](assert) { + assert.expect(2); + + let testContext = this; + class Model extends FrameworkObject { + constructor(owner) { + super(owner); + + assert.equal( + getOwner(this), + testContext.owner, + 'owner was assigned properly in the root constructor' + ); + + assert.equal(owner, testContext.owner, 'owner was passed properly to the constructor'); + } + } + setFrameworkClass(Model); + this.owner.register('model:blah', Model); + + this.owner.factoryFor('model:blah').create(); + } + } + ); +} diff --git a/packages/@ember/canary-features/index.ts b/packages/@ember/canary-features/index.ts index 973f83e465f..bf2afc30479 100644 --- a/packages/@ember/canary-features/index.ts +++ b/packages/@ember/canary-features/index.ts @@ -25,6 +25,7 @@ export const DEFAULT_FEATURES = { EMBER_GLIMMER_FN_HELPER: true, EMBER_CUSTOM_COMPONENT_ARG_PROXY: null, EMBER_GLIMMER_ON_MODIFIER: null, + EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT: null, }; /** @@ -96,3 +97,6 @@ export const EMBER_CUSTOM_COMPONENT_ARG_PROXY = featureValue( FEATURES.EMBER_CUSTOM_COMPONENT_ARG_PROXY ); export const EMBER_GLIMMER_ON_MODIFIER = featureValue(FEATURES.EMBER_GLIMMER_ON_MODIFIER); +export const EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT = featureValue( + FEATURES.EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT +); diff --git a/packages/@ember/controller/index.js b/packages/@ember/controller/index.js index 78dc0047499..d2acb7168e3 100644 --- a/packages/@ember/controller/index.js +++ b/packages/@ember/controller/index.js @@ -1,5 +1,6 @@ -import { Object as EmberObject } from '@ember/-internals/runtime'; +import { FrameworkObject, setFrameworkClass } from '@ember/-internals/runtime'; import { inject as metalInject } from '@ember/-internals/metal'; +import { EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT } from '@ember/canary-features'; import ControllerMixin from './lib/controller_mixin'; /** @@ -12,7 +13,11 @@ import ControllerMixin from './lib/controller_mixin'; @uses Ember.ControllerMixin @public */ -const Controller = EmberObject.extend(ControllerMixin); +const Controller = FrameworkObject.extend(ControllerMixin); + +if (EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT) { + setFrameworkClass(Controller); +} /** Creates a property that lazily looks up another controller in the container. diff --git a/packages/@ember/service/index.js b/packages/@ember/service/index.js index 665e0c41514..95f5d5b1cda 100644 --- a/packages/@ember/service/index.js +++ b/packages/@ember/service/index.js @@ -1,4 +1,5 @@ -import { Object as EmberObject } from '@ember/-internals/runtime'; +import { EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT } from '@ember/canary-features'; +import { FrameworkObject, setFrameworkClass } from '@ember/-internals/runtime'; import { inject as metalInject } from '@ember/-internals/metal'; /** @@ -63,10 +64,14 @@ export function inject() { @since 1.10.0 @public */ -const Service = EmberObject.extend(); +const Service = FrameworkObject.extend(); Service.reopenClass({ isServiceFactory: true, }); +if (EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT) { + setFrameworkClass(Service); +} + export default Service; diff --git a/packages/ember/index.js b/packages/ember/index.js index 129a9eed37b..43a449d5f1f 100644 --- a/packages/ember/index.js +++ b/packages/ember/index.js @@ -7,7 +7,7 @@ import { Registry, Container } from '@ember/-internals/container'; import * as instrumentation from '@ember/instrumentation'; import { deleteMeta, meta } from '@ember/-internals/meta'; import * as metal from '@ember/-internals/metal'; -import { FEATURES, isEnabled } from '@ember/canary-features'; +import { FEATURES, isEnabled, EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT } from '@ember/canary-features'; import * as EmberDebug from '@ember/debug'; import { assert, deprecate } from '@ember/debug'; import Backburner from 'backburner'; @@ -91,6 +91,7 @@ import { CoreObject, NativeArray, A, + setFrameworkClass, } from '@ember/-internals/runtime'; import { Checkbox, @@ -401,6 +402,10 @@ Ember.compare = compare; Ember.copy = copy; Ember.isEqual = isEqual; +if (EMBER_FRAMEWORK_OBJECT_OWNER_ARGUMENT) { + Ember._setFrameworkClass = setFrameworkClass; +} + /** @module ember */