-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce namespaced component and service invocation #16158
Introduce namespaced component and service invocation #16158
Conversation
@@ -278,7 +281,7 @@ function isFactoryInstance(container, fullName, { instantiate, singleton }) { | |||
} | |||
|
|||
function instantiateFactory(container, fullName, options) { | |||
let factoryManager = EMBER_MODULE_UNIFICATION && options && options.source ? container.factoryFor(fullName, options) : container.factoryFor(fullName); | |||
let factoryManager = EMBER_MODULE_UNIFICATION && options ? container.factoryFor(fullName, options) : container.factoryFor(fullName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can just pass container.factoryFor(fullName, options)
all the time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out some tests related to local lookup fail if we remove this.
@@ -440,3 +446,42 @@ class FactoryManager { | |||
return instance; | |||
} | |||
} | |||
|
|||
export function parseInjectionString(injectionString) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
document this
} | ||
} | ||
|
||
export function lookupWithRawString(container, type, rawString) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
document this
packages/container/lib/container.js
Outdated
} | ||
} | ||
|
||
export function factoryForWithRawString(container, type, rawString) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
document this
packages/container/lib/index.js
Outdated
@@ -9,4 +9,7 @@ export { default as Registry, privatize } from './registry'; | |||
export { | |||
default as Container, | |||
FACTORY_FOR, | |||
factoryForWithRawString, | |||
lookupWithRawString, | |||
RAW_STRING_OPTION_KEY as _RAW_STRING_OPTION_KEY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirm these don't become public API
packages/container/lib/registry.js
Outdated
import { DEBUG } from 'ember-env-flags'; | ||
import { ENV } from 'ember-environment'; | ||
|
||
const VALID_FULL_NAME_REGEXP = /^[^:]+:[^:]+$/; | ||
const missingResolverFunctionsDeprecation = 'Passing a `resolver` function into a Registry is deprecated. Please pass in a Resolver object with a `resolve` method.'; | ||
|
||
let missingResolverFunctionsDeprecation = 'Passing a `resolver` function into a Registry is deprecated. Please pass in a Resolver object with a `resolve` method.'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line should remain whatever it was in master.
packages/container/lib/registry.js
Outdated
if(EMBER_MODULE_UNIFICATION) { | ||
/* With a rawString, the fullName doesn't need to contain a : */ | ||
if (options && options[RAW_STRING_OPTION_KEY] && fullName) { | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs review with @rwjblue @dgeb I'm not quite sure what to do here. The gist is that previously we required type:name
but this check happens at low levels and now type
alone is permitted (the name ends up in the rawString). Perhaps we should move this check out of the deep parts of the container instead of removing it in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mixonic I believe type alone is no longer permitted so we can remove this.
@mixonic FYI I tested this with the latest |
specifier: type, | ||
rawString: rawString | ||
specifier, | ||
targetNamespace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could just be namespace
, I don't think target
is useful to discern it from anything else?
6a6c7b7
to
0aed89a
Compare
4dc4587
to
e6b3cbb
Compare
@mixonic and @dgeb We should clarify how we expect the "main" service of an addon to work. In my end-to-end test, If I have an addon called If I try to inject a service called |
e6b3cbb
to
6f4ea49
Compare
This commit adds support for invoking a component or injecting a service from a module unification namespace. It does so in a very targetted manner, and specifically *avoids* adding support for namespaces to lower-level APIs like lookup or factoryFor. Ember itself doesn't perform any resolution steps for a lookup. Instead, it defers resolution to a resolver class provided to the application at runtime. For example this invocation: ```hbs {{! app/templates/index.hbs }} {{app-component}} ``` Causes a resolver invocation of: ``js resolve( 'template:components/app-component', // a "fullName" formatted type:name. 'app/templates/index' // a referrer for this lookup ); ``` The resolver API has already been changed behind the module unification feature flag to pass the second argument of "referrer" when appropriate. A component from another namespace is invoked by putting the namespace before a :: delemiter. For example an invocation: ```hbs {{! src/ui/components/app-component/template.hbs }} {{my-addon::addon-component}} ``` In order to resolve this namespace the resolver must be passed `my-addon` is some form or another. The current Ember container APIs are coupled heavily to the idea of a "fullName". This is a string formatted as `type:name`, and expected to resolve something. I'm hesitant to expand that syntax to something like `type:optional-namespace::name`, especially since we would like to replace the strings there with "specifiers" from the glimmer-di project as we adopt more of that project. Additionally we want existing implementions of the resolver API to *not* be passed the namespace in the first argument. If they were, they may resolve certain lookups in ways that don't mesh our goals for the `::` syntax. For example a custom resolver in someone's app may be splitting on `:` an expecting a syntax in the string that matches `type:name`. It is ok to break those resolvers for namespaced lookups, and we would rather they fail in some way than resolve something that is wrong. Instead, we've made an *additive* change to the resolver API. The "rawString", the string invoking the lookup, is passed in the third position: ```hbs {{! src/ui/components/app-component/template.hbs }} {{my-addon::addon-component}} ``` Resolves with: ```js resolve( 'template:components/', 'src/ui/components/app-component/template', 'my-addon::addon-component' ); resolve( 'component', 'src/ui/components/app-component/template', 'my-addon::addon-component' ); ``` Similarly service injections pass their "rawString": ```hbs Ember.inject.service('my-addon::addon-service'); ``` Resolves with: ```js resolve( 'service', undefined, 'my-addon::addon-service' ); ``` The resolver is expected to parse the invocation string.
- Still TODO cleanup rename rawString to targetNamespace
6f4ea49
to
5c460a9
Compare
Closing this in favor of #16319 |
This commit adds support for invoking a component or injecting a service from a module unification namespace. It does so in a very targeted manner, and specifically avoids adding support for namespaces to lower-level APIs like lookup or factoryFor.
Ember itself doesn't perform any resolution steps for a lookup. Instead, it defers resolution to a resolver class provided to the application at runtime. For example this invocation:
Causes a resolver invocation of:
The resolver API has already been changed behind the module unification feature flag to pass the second argument of "referrer" when appropriate.
A component from another namespace is invoked by putting the namespace before a
::
delemiter. For example an invocation:In order to resolve this namespace the resolver must be passed
my-addon
is some form or another.The current Ember container APIs are coupled heavily to the idea of a "fullName". This is a string formatted as
type:name
, and expected to resolve something. I'm hesitant to expand that syntax to something liketype:optional-namespace::name
, especially since we would like to replace the strings there with "specifiers" from the glimmer-di project as we adopt more of that project.Additionally we want existing implementions of the resolver API to not be passed the namespace in the first argument. If they were, they may resolve certain lookups in ways that don't mesh our goals for the
::
syntax. For example a custom resolver in someone's app may be splitting on:
an expecting a syntax in the string that matchestype:name
. It is ok to break those resolvers for namespaced lookups, and we would rather they fail in some way than resolve something that is wrong.Instead, we've made an additive change to the resolver API. The "rawString", the string invoking the lookup, is passed in the third position:
Resolves with:
Similarly service injections pass their "rawString":
Resolves with:
The resolver is expected to parse the invocation string.
TODO:
main
lookups of services.store: Ember.inject.service('ember-data')
and the addonssrc/services/main.js
would be resolved.moduleName
is on a template and what it should be.