-
-
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
Future public @ember/engine types #19923
Conversation
ea75656
to
dd914f6
Compare
e34ab4a
to
cd198dd
Compare
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.
Will finish this review tomorrow, but WIP feedback!
@@ -143,7 +143,7 @@ export default class Container { | |||
@param {String} [options.source] The fullname of the request source (used for local lookup) | |||
@return {any} | |||
*/ | |||
lookup(fullName: string, options: LookupOptions): any { | |||
lookup<T>(fullName: string, options?: TypeOptions): T | undefined { |
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 should actually return unknown
, since it's impossible to infer from the arguments what the return type T
would actually be.
lookup<T>(fullName: string, options?: TypeOptions): T | undefined { | |
lookup(fullName: string, options?: TypeOptions): unknown { |
I know this matches the other implementations, but we should take care to move toward rather than away from safety with this work where our hands are not already tied in some way.
I expect you introduced this because there is client code which is relying on being able to freely cast because of the previous any
return type?
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 makes sense. I’ll give it a second look tomorrow.
readonly registrations: { [key: string]: object | undefined }; | ||
_localLookupCache: { [key: string]: object | undefined }; | ||
readonly _normalizeCache: { [key: string]: string | undefined }; | ||
readonly _options: { [key: string]: TypeOptions | undefined }; | ||
readonly _resolveCache: { [key: string]: object | undefined }; | ||
readonly _typeOptions: { [key: string]: TypeOptions | undefined }; |
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.
- Can we just use
Record<string, TypeOptions>
etc. here? - It looks like this as well as the
in
check below are both because we don't yet havenoUncheckedIndexAccess
enabled, so we're sort of pushing that safety in manually?
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.
We do have noUncheckedIndexAccess now. I’ll revisit this.
@@ -417,7 +417,7 @@ export default class Registry implements IRegistry { | |||
|
|||
getOptions(fullName: string): TypeOptions | undefined { | |||
let normalizedName = this.normalize(fullName); | |||
let options = this._options[normalizedName]; | |||
let options = normalizedName in this._options ? this._options[normalizedName] : undefined; |
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.
Hmm. This shouldn't be complaining about the access. 🤔 (See playground.) Since it's a string index, and given the type you wrote, it should correctly resolve it in either the Record
or the index type form. What error was TS giving you here?
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.
Not sure what was happening before but it seems ok now.
owner: Owner, | ||
options?: LookupOptions | ||
): Option<Factory<{}, {}>> { | ||
function componentFor(name: string, owner: Owner): Option<Factory<{}, {}>> { |
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 looks like an unrelated-to-types change – is this a dead code path or something?
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.
The type was incorrect. factoryFor
doesn't take options.
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.
Glad we caught it by doing this, then. Thanks! 😃
factoryFor<T, C>(fullName: string, options?: LookupOptions): Factory<T, C> | undefined; | ||
register<T, C>(fullName: string, factory: Factory<T, C>, options?: LookupOptions): void; | ||
hasRegistration(name: string, options?: LookupOptions): boolean; | ||
lookup<T>(fullName: string, options?: TypeOptions): T | undefined; |
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.
As before, I'm fine if we leave this for now, but we should start working to eliminate it. 😩
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'll fix it now.
} | ||
declare const ContainerProxy: Mixin; | ||
|
||
export { ContainerProxy as default }; |
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 believe the normal export default
form should work; does it not for some reason?
export { ContainerProxy as default }; | |
export default ContainerProxy; |
} | ||
declare const RegistryProxyMixin: Mixin; | ||
|
||
export { RegistryProxyMixin as default }; |
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.
export { RegistryProxyMixin as default }; | |
export default RegistryProxyMixin; |
cd198dd
to
47ff27b
Compare
47ff27b
to
b97e01a
Compare
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.
Guide:
Mark | Meaning |
---|---|
? | informational, non-blocking |
~ | not great, non-blocking |
X | blocking |
Spoilers: no X, so .
@@ -133,7 +133,7 @@ export default class CurlyComponentManager | |||
|
|||
if (layout === undefined) { | |||
if (layoutName !== undefined) { | |||
let _factory = owner.lookup<TemplateFactory>(`template:${layoutName}`); | |||
let _factory = owner.lookup(`template:${layoutName}`) as TemplateFactory; |
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.
?: Is this cast safe? If so, why? (I see that it was already here.)
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 don't know that it's safe, but it's how it was before so it probably is. I figure having as
is safer (as in we know we're doing something potentially risky) than the way it was before where it wasn't clear that there was risk!
if ((owner.lookup('-environment:main') as Environment)!.isInteractive) { | ||
this.__dispatcher = owner.lookup('event_dispatcher:main') as EventDispatcher; |
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.
~: Would be good to follow on with dev-time assertions instead of casting.
@@ -265,7 +265,7 @@ class ActionModifierManager implements InternalModifierManager<ActionState, obje | |||
} | |||
|
|||
ensureEventSetup(actionState: ActionState): void { | |||
let dispatcher = actionState.owner.lookup<EventDispatcher>('event_dispatcher:main'); | |||
let dispatcher = actionState.owner.lookup('event_dispatcher:main') as EventDispatcher; |
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.
?/~: as above re: casting and safety
let templateFullName = `template:components/${name}`; | ||
|
||
return owner.lookup(templateFullName, options) || null; | ||
return (owner.lookup(templateFullName, options) as Template) || null; |
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.
~: Could use a safety comment here in the future.
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.
Yeah, again I don't know that this is actually safe!
const factory = owner.factoryFor(`helper:${name}`) as | ||
| Factory<SimpleHelper, HelperFactory<SimpleHelper>> | ||
| Factory<HelperInstance, HelperFactory<HelperInstance>>; |
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.
?/~: as above on the cast.
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.
Yup, unsure this is safe, but it seems like it must be.
@@ -312,11 +312,11 @@ class EmberRouter<R extends Route = Route> extends EmberObject.extend(Evented) i | |||
this._resetQueuedQueryParameterChanges(); | |||
this.namespace = owner.lookup('application:main'); | |||
|
|||
let bucketCache: BucketCache | undefined = owner.lookup(P`-bucket-cache:main`); | |||
let bucketCache = owner.lookup(P`-bucket-cache:main`) as BucketCache | undefined; |
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.
~: as throughout.
@@ -44,7 +44,7 @@ interface View { | |||
@param {Object} owner | |||
*/ | |||
export function getRootViews(owner: Owner): View[] { | |||
let registry = owner.lookup<Dict<View>>('-view-registry:main')!; | |||
let registry = owner.lookup('-view-registry:main') as Dict<View>; |
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.
~: as throughout, for reference.
@@ -19,15 +23,14 @@ expectTypeOf( | |||
instance.register('service:store-singleton', Store, { singleton: true, instantiate: true }) | |||
).toEqualTypeOf<void>(); | |||
|
|||
expectTypeOf(instance.lookup<Store>('service:store')).toEqualTypeOf<Store | undefined>(); | |||
expectTypeOf(instance.lookup('service:store')).toEqualTypeOf<unknown>(); |
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.
If we add that registry, these will (happily!) flag it up for us as a case where it no longer equals that type. 🎉
@@ -20,7 +20,7 @@ import { expect } from '@glimmer/util'; | |||
@since 3.14.0 | |||
*/ | |||
export default function captureRenderTree(app: Owner): CapturedRenderNode[] { | |||
let renderer = expect(app.lookup<Renderer>('renderer:-dom'), `BUG: owner is missing renderer`); | |||
let renderer = expect(app.lookup('renderer:-dom') as Renderer, `BUG: owner is missing renderer`); |
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.
~: could use a better assertion to check that it's not just present but is the right/expected thing.
@@ -15,7 +16,7 @@ const ENGINE_PARENT = symbol('ENGINE_PARENT'); | |||
@static | |||
@private | |||
*/ | |||
export function getEngineParent(engine) { | |||
export function getEngineParent(engine: EngineInstance): EngineInstance | undefined { |
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.
💙
No description provided.