Skip to content

Commit

Permalink
Merge pull request #19923 from wagenet/ember-engine-types
Browse files Browse the repository at this point in the history
Future public @ember/engine types
  • Loading branch information
wagenet authored Feb 10, 2022
2 parents f6a6b00 + b97e01a commit a94cf49
Show file tree
Hide file tree
Showing 26 changed files with 247 additions and 114 deletions.
29 changes: 17 additions & 12 deletions packages/@ember/-internals/container/lib/container.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Factory, LookupOptions, Owner, setOwner } from '@ember/-internals/owner';
import { Factory, FactoryClass, Owner, setOwner } from '@ember/-internals/owner';
import { dictionary, symbol } from '@ember/-internals/utils';
import { assert } from '@ember/debug';
import { DEBUG } from '@glimmer/env';
import Registry, { DebugRegistry } from './registry';
import Registry, { DebugRegistry, TypeOptions } from './registry';

interface LeakTracking {
hasContainers(): boolean;
Expand Down Expand Up @@ -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(fullName: string, options?: TypeOptions): unknown {
if (this.isDestroyed) {
throw new Error(`Cannot call \`.lookup\` after the owner has been destroyed`);
}
Expand Down Expand Up @@ -206,19 +206,19 @@ export default class Container {
@public
@method factoryFor
@param {String} fullName
@param {Object} [options]
@param {String} [options.source] The fullname of the request source (used for local lookup)
@return {any}
*/
factoryFor<T, C>(fullName: string): Factory<T, C> | undefined {
factoryFor(fullName: string): Factory<unknown> | undefined {
if (this.isDestroyed) {
throw new Error(`Cannot call \`.factoryFor\` after the owner has been destroyed`);
}
let normalizedName = this.registry.normalize(fullName);

assert('fullName must be a proper full name', this.registry.isValidFullName(normalizedName));

return factoryFor<T, C>(this, normalizedName, fullName) as Factory<T, C> | undefined;
// TODO: This needs to return a Factory to be compatible with Owner.
// We should correctly the types so that this cast is not necessary.
return factoryFor(this, normalizedName, fullName) as Factory<unknown>;
}
}

Expand Down Expand Up @@ -261,7 +261,7 @@ function isInstantiatable(container: Container, fullName: string) {
return container.registry.getOption(fullName, 'instantiate') !== false;
}

function lookup(container: Container, fullName: string, options: LookupOptions = {}) {
function lookup(container: Container, fullName: string, options: TypeOptions = {}) {
let normalizedName = fullName;

if (
Expand All @@ -277,14 +277,18 @@ function lookup(container: Container, fullName: string, options: LookupOptions =
return instantiateFactory(container, normalizedName, fullName, options);
}

function factoryFor<T, C>(container: Container, normalizedName: string, fullName: string) {
function factoryFor(
container: Container,
normalizedName: string,
fullName: string
): FactoryManager<unknown> | undefined {
let cached = container.factoryManagerCache[normalizedName];

if (cached !== undefined) {
return cached;
}

let factory = container.registry.resolve(normalizedName) as DebugFactory<T, C> | undefined;
let factory = container.registry.resolve(normalizedName) as DebugFactory<unknown> | undefined;

if (factory === undefined) {
return;
Expand Down Expand Up @@ -442,7 +446,8 @@ export interface LazyInjection {
specifier: string;
}

declare interface DebugFactory<T, C> extends Factory<T, C> {
declare interface DebugFactory<T, C extends FactoryClass | object = FactoryClass>
extends Factory<T, C> {
_onLookup?: (fullName: string) => void;
_initFactory?: (factoryManager: FactoryManager<T, C>) => void;
_lazyInjections(): { [key: string]: LazyInjection };
Expand All @@ -458,7 +463,7 @@ export function setFactoryFor(obj: any, factory: FactoryManager<any, any>): void
obj[INIT_FACTORY] = factory;
}

export class FactoryManager<T, C> {
export class FactoryManager<T, C extends FactoryClass | object = FactoryClass> {
readonly container: Container;
readonly owner: Owner | null;
readonly class: Factory<T, C> & DebugFactory<T, C>;
Expand Down
14 changes: 7 additions & 7 deletions packages/@ember/-internals/container/lib/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ export default class Registry implements IRegistry {
readonly _failSet: Set<string>;
resolver: Resolver | (Resolve & NotResolver) | null;
readonly fallback: IRegistry | null;
readonly registrations: { [key: string]: object };
_localLookupCache: { [key: string]: object };
readonly _normalizeCache: { [key: string]: string };
readonly _options: { [key: string]: TypeOptions };
readonly _resolveCache: { [key: string]: object };
readonly _typeOptions: { [key: string]: TypeOptions };
readonly registrations: Record<string, object>;
_localLookupCache: Record<string, object>;
readonly _normalizeCache: Record<string, string>;
readonly _options: Record<string, TypeOptions>;
readonly _resolveCache: Record<string, object>;
readonly _typeOptions: Record<string, TypeOptions>;

constructor(options: RegistryOptions = {}) {
this.fallback = options.fallback || null;
Expand Down Expand Up @@ -182,7 +182,7 @@ export default class Registry implements IRegistry {
@param {Function} factory
@param {Object} options
*/
register<T, C>(fullName: string, factory: Factory<T, C>, options: object = {}): void {
register(fullName: string, factory: Factory<unknown>, options: TypeOptions = {}): void {
assert('fullName must be a proper full name', this.isValidFullName(fullName));
assert(`Attempting to register an unknown factory: '${fullName}'`, factory !== undefined);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
assert(`Layout \`${layoutName}\` not found!`, _factory !== undefined);
factory = _factory;
} else {
Expand Down
4 changes: 2 additions & 2 deletions packages/@ember/-internals/glimmer/lib/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -710,8 +710,8 @@ const Component = CoreView.extend(
let owner = getOwner(this);
assert('Component is unexpectedly missing an owner', owner);

if (owner.lookup<Environment>('-environment:main')!.isInteractive) {
this.__dispatcher = owner.lookup<EventDispatcher>('event_dispatcher:main');
if ((owner.lookup('-environment:main') as Environment)!.isInteractive) {
this.__dispatcher = owner.lookup('event_dispatcher:main') as EventDispatcher;
} else {
// In FastBoot we have no EventDispatcher. Set to null to not try again to look it up.
this.__dispatcher = null;
Expand Down
3 changes: 2 additions & 1 deletion packages/@ember/-internals/glimmer/lib/components/link-to.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { Owner } from '@ember/-internals/owner';
import { Route, RouterState, RoutingService } from '@ember/-internals/routing';
import { isSimpleClick } from '@ember/-internals/views';
import { assert, debugFreeze, inspect, warn } from '@ember/debug';
import { EngineInstance, getEngineParent } from '@ember/engine';
import { getEngineParent } from '@ember/engine';
import EngineInstance from '@ember/engine/instance';
import { flaggedInstrument } from '@ember/instrumentation';
import { action } from '@ember/object';
import { service } from '@ember/service';
Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/-internals/glimmer/lib/modifiers/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
dispatcher?.setupHandlerForEmberEvent(actionState.eventName);
}

Expand Down
32 changes: 14 additions & 18 deletions packages/@ember/-internals/glimmer/lib/resolver.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { privatize as P } from '@ember/-internals/container';
import { TypeOptions } from '@ember/-internals/container/lib/registry';
import { ENV } from '@ember/-internals/environment';
import { Factory, FactoryClass, LookupOptions, Owner } from '@ember/-internals/owner';
import { Factory, Owner } from '@ember/-internals/owner';
import { assert } from '@ember/debug';
import { _instrumentStart } from '@ember/instrumentation';
import { DEBUG } from '@glimmer/env';
Expand Down Expand Up @@ -56,28 +57,24 @@ function instrumentationPayload(name: string) {
return { object: `component:${name}` };
}

function componentFor(
name: string,
owner: Owner,
options?: LookupOptions
): Option<Factory<{}, {}>> {
function componentFor(name: string, owner: Owner): Option<Factory<unknown>> {
let fullName = `component:${name}`;
return owner.factoryFor(fullName, options) || null;
return owner.factoryFor(fullName) || null;
}

function layoutFor(name: string, owner: Owner, options?: LookupOptions): Option<Template> {
function layoutFor(name: string, owner: Owner, options?: TypeOptions): Option<Template> {
let templateFullName = `template:components/${name}`;

return owner.lookup(templateFullName, options) || null;
return (owner.lookup(templateFullName, options) as Template) || null;
}

type LookupResult =
| {
component: Factory<{}, {}>;
component: Factory<unknown>;
layout: TemplateFactory;
}
| {
component: Factory<{}, {}>;
component: Factory<unknown>;
layout: null;
}
| {
Expand All @@ -88,9 +85,9 @@ type LookupResult =
function lookupComponentPair(
owner: Owner,
name: string,
options?: LookupOptions
options?: TypeOptions
): Option<LookupResult> {
let component = componentFor(name, owner, options);
let component = componentFor(name, owner);

if (component !== null && component.class !== undefined) {
let layout = getComponentTemplate(component.class);
Expand Down Expand Up @@ -176,10 +173,9 @@ export default class ResolverImpl implements RuntimeResolver<Owner>, CompileTime
return helper;
}

const factory = owner.factoryFor<
SimpleHelper | HelperInstance,
HelperFactory<SimpleHelper | HelperInstance>
>(`helper:${name}`);
const factory = owner.factoryFor(`helper:${name}`) as
| Factory<SimpleHelper, HelperFactory<SimpleHelper>>
| Factory<HelperInstance, HelperFactory<HelperInstance>>;

if (factory === undefined) {
return null;
Expand Down Expand Up @@ -224,7 +220,7 @@ export default class ResolverImpl implements RuntimeResolver<Owner>, CompileTime
return builtin;
}

let modifier = owner.factoryFor<unknown, FactoryClass>(`modifier:${name}`);
let modifier = owner.factoryFor(`modifier:${name}`);

if (modifier === undefined) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ if (ENV._DEBUG_RENDER_TREE) {
Resolver = ModuleBasedTestResolver;

init() {
super.init(...arguments);
super.init();
this.register(
'template:application',
compileTemplate(
Expand Down Expand Up @@ -234,7 +234,7 @@ if (ENV._DEBUG_RENDER_TREE) {
Resolver = ModuleBasedTestResolver;

init() {
super.init(...arguments);
super.init();
this.register(
'template:application',
compileTemplate(
Expand Down Expand Up @@ -579,7 +579,7 @@ if (ENV._DEBUG_RENDER_TREE) {
Resolver = ModuleBasedTestResolver;

init() {
super.init(...arguments);
super.init();
this.register(
'template:application',
compileTemplate(
Expand Down Expand Up @@ -670,7 +670,7 @@ if (ENV._DEBUG_RENDER_TREE) {
]);

runTask(() => {
let controller = instance!.lookup<Controller>('controller:application')!;
let controller = (instance!.lookup('controller:application') as Controller)!;
controller.set('message', 'World');
});

Expand Down Expand Up @@ -716,7 +716,7 @@ if (ENV._DEBUG_RENDER_TREE) {
]);

runTask(() => {
let controller = instance!.lookup<Controller>('controller:application')!;
let controller = (instance!.lookup('controller:application') as Controller)!;
controller.set('message', undefined);
});

Expand Down
14 changes: 5 additions & 9 deletions packages/@ember/-internals/owner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ import { getOwner as glimmerGetOwner, setOwner as glimmerSetOwner } from '@glimm
@module @ember/application
*/

export interface LookupOptions {
singleton?: boolean;
instantiate?: boolean;
}

export interface FactoryClass {
positionalParams?: string | string[] | undefined | null;
}
Expand All @@ -27,11 +22,12 @@ export interface EngineInstanceOptions {
}

import EngineInstance from '@ember/engine/instance';
import { TypeOptions } from '../container/lib/registry';
export interface Owner {
lookup<T>(fullName: string, options?: LookupOptions): T | undefined;
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(fullName: string, options?: TypeOptions): unknown;
factoryFor(fullName: string): Factory<unknown> | undefined;
register(fullName: string, factory: Factory<unknown>, options?: TypeOptions): void;
hasRegistration(name: string): boolean;

/** @internal */
mountPoint?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export default class AutoLocation extends EmberObject implements EmberLocation {

let owner = getOwner(this);
assert('AutoLocation is unexpectedly missing an owner', owner);
let concrete = owner.lookup<EmberLocation>(`location:${implementation}`);
let concrete = owner.lookup(`location:${implementation}`) as EmberLocation;
assert(`Could not find location '${implementation}'.`, concrete !== undefined);

set(concrete, 'rootURL', rootURL);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Container } from '@ember/-internals/container';
import { LookupOptions } from '@ember/-internals/owner';
import { TypeOptions } from '@ember/-internals/container/lib/registry';
/**
@module ember
*/
Expand All @@ -14,7 +14,7 @@ import { LookupOptions } from '@ember/-internals/owner';
export default function controllerFor(
container: Container,
controllerName: string,
lookupOptions: LookupOptions
lookupOptions: TypeOptions
) {
return container.lookup(`controller:${controllerName}`, lookupOptions);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { DEBUG } from '@glimmer/env';
*/

export function generateControllerFactory(owner: Owner, controllerName: string): Factory<{}> {
let Factory = owner.factoryFor<any, any>('controller:basic')!.class;
let Factory = (owner.factoryFor('controller:basic') as Factory<any, any>).class;

Factory = Factory.extend({
toString() {
Expand Down Expand Up @@ -44,7 +44,7 @@ export default function generateController(owner: Owner, controllerName: string)
generateControllerFactory(owner, controllerName);

let fullName = `controller:${controllerName}`;
let instance = owner.lookup<Controller>(fullName)!;
let instance = (owner.lookup(fullName) as Controller)!;

if (DEBUG) {
if (get(instance, 'namespace.LOG_ACTIVE_GENERATION')) {
Expand Down
Loading

0 comments on commit a94cf49

Please sign in to comment.