Skip to content

Commit

Permalink
Refactor template factory
Browse files Browse the repository at this point in the history
Per RFC #481, we want to align the factory signature between templates
and component managers. Since the factories for component managers are
just a function that takes the owner, we decided to move template
factories in the same direction here as well.

Co-authored-by: Robert Jackson <me@rwjblue.com>
  • Loading branch information
chancancode and rwjblue committed Jun 13, 2019
1 parent 319e3ce commit 5ece62b
Show file tree
Hide file tree
Showing 15 changed files with 224 additions and 225 deletions.
2 changes: 1 addition & 1 deletion packages/@ember/-internals/glimmer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@
*/

export { default as RootTemplate } from './lib/templates/root';
export { default as template } from './lib/template';
export { default as template, counters as templateCacheCounters, Factory as TemplateFactory, OwnedTemplate } from './lib/template';
export { default as Checkbox } from './lib/components/checkbox';
export { default as TextField } from './lib/components/text-field';
export { default as TextArea } from './lib/components/textarea';
Expand Down
45 changes: 22 additions & 23 deletions packages/@ember/-internals/glimmer/lib/component-managers/curly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function aliasIdToElementId(args: Arguments, props: any) {
}

function isTemplateFactory(template: OwnedTemplate | TemplateFactory): template is TemplateFactory {
return typeof (template as TemplateFactory).create === 'function';
return typeof template === 'function';
}

// We must traverse the attributeBindings in reverse keeping track of
Expand Down Expand Up @@ -119,41 +119,41 @@ export default class CurlyComponentManager
};
}

templateFor(component: Component, resolver: RuntimeResolver): OwnedTemplate {
let { layout, layoutName } = component;
templateFor(component: Component): OwnedTemplate {
let { layout: _layout, layoutName } = component;
let owner = getOwner(component);

if (layout !== undefined) {
// This needs to be cached by template.id
if (isTemplateFactory(layout)) {
return resolver.createTemplate(layout, getOwner(component));
} else {
// we were provided an instance already
return layout;
}
}
let layout: TemplateFactory;

if (layoutName) {
let template = owner.lookup<OwnedTemplate>('template:' + layoutName);
if (template) {
return template;
if (_layout === undefined) {
if (layoutName !== undefined) {
layout = owner.lookup<TemplateFactory>(`template:${layoutName}`);
assert(`Layout \`${layoutName}\` not found!`, layout !== undefined);
} else {
layout = owner.lookup(DEFAULT_LAYOUT);
}
} else if (isTemplateFactory(_layout)) {
layout = _layout;
} else {
// we were provided an instance already
return _layout;
}

return owner.lookup<OwnedTemplate>(DEFAULT_LAYOUT);
return layout(owner);
}

getDynamicLayout({ component }: ComponentStateBucket, resolver: RuntimeResolver): Invocation {
const template = this.templateFor(component, resolver);
const layout = template.asWrappedLayout();
getDynamicLayout({ component }: ComponentStateBucket): Invocation {
let template = this.templateFor(component);
let layout = template.asWrappedLayout();

return {
handle: layout.compile(),
symbolTable: layout.symbolTable,
};
}

getTagName(state: ComponentStateBucket): Option<string> {
const { component, hasWrappedElement } = state;
let { component, hasWrappedElement } = state;

if (!hasWrappedElement) {
return null;
Expand Down Expand Up @@ -574,7 +574,6 @@ export const CURLY_CAPABILITIES: ComponentCapabilities = {

const CURLY_COMPONENT_MANAGER = new CurlyComponentManager();
export class CurlyComponentDefinition implements ComponentDefinition {
public template: OwnedTemplate;
public args: CurriedArgs | undefined;
public state: DefinitionState;
public symbolTable: ProgramSymbolTable | undefined;
Expand All @@ -584,7 +583,7 @@ export class CurlyComponentDefinition implements ComponentDefinition {
public name: string,
public ComponentClass: any,
public handle: Option<VMHandle>,
template: OwnedTemplate,
public template?: OwnedTemplate,
args?: CurriedArgs
) {
const layout = template && template.asLayout();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { Destroyable, Opaque, Option } from '@glimmer/util';
import { Owner } from '@ember/-internals/owner';
import { generateControllerFactory } from '@ember/-internals/routing';
import { OwnedTemplateMeta } from '@ember/-internals/views';
import { TemplateFactory } from '../..';
import Environment from '../environment';
import RuntimeResolver from '../resolver';
import { OwnedTemplate } from '../template';
import { RootReference } from '../utils/references';
import AbstractManager from './abstract';

Expand Down Expand Up @@ -54,8 +54,10 @@ class MountManager
implements
WithDynamicLayout<EngineState | EngineWithModelState, OwnedTemplateMeta, RuntimeResolver> {
getDynamicLayout(state: EngineState, _: RuntimeResolver): Invocation {
let template = state.engine.lookup('template:application') as OwnedTemplate;
let templateFactory = state.engine.lookup('template:application') as TemplateFactory;
let template = templateFactory(state.engine);
let layout = template.asLayout();

return {
handle: layout.compile(),
symbolTable: layout.symbolTable,
Expand Down
12 changes: 6 additions & 6 deletions packages/@ember/-internals/glimmer/lib/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { BOUNDS } from './component';
import { createRootOutlet } from './component-managers/outlet';
import { RootComponentDefinition } from './component-managers/root';
import Environment from './environment';
import { OwnedTemplate } from './template';
import { Factory as TemplateFactory, OwnedTemplate } from './template';
import { Component } from './utils/curly-component-state-bucket';
import { OutletState } from './utils/outlet';
import { UnboundReference } from './utils/references';
Expand Down Expand Up @@ -246,7 +246,7 @@ interface ViewRegistry {

export abstract class Renderer {
private _env: Environment;
private _rootTemplate: any;
private _rootTemplate: OwnedTemplate;
private _viewRegistry: ViewRegistry;
private _destinedForDOM: boolean;
private _destroyed: boolean;
Expand All @@ -258,13 +258,13 @@ export abstract class Renderer {

constructor(
env: Environment,
rootTemplate: OwnedTemplate,
rootTemplate: TemplateFactory,
viewRegistry: ViewRegistry,
destinedForDOM = false,
builder = clientBuilder
) {
this._env = env;
this._rootTemplate = rootTemplate;
this._rootTemplate = rootTemplate(env.owner);
this._viewRegistry = viewRegistry;
this._destinedForDOM = destinedForDOM;
this._destroyed = false;
Expand Down Expand Up @@ -517,7 +517,7 @@ export class InertRenderer extends Renderer {
builder,
}: {
env: Environment;
rootTemplate: OwnedTemplate;
rootTemplate: TemplateFactory;
_viewRegistry: any;
builder: any;
}) {
Expand All @@ -539,7 +539,7 @@ export class InteractiveRenderer extends Renderer {
builder,
}: {
env: Environment;
rootTemplate: OwnedTemplate;
rootTemplate: TemplateFactory;
_viewRegistry: any;
builder: any;
}) {
Expand Down
60 changes: 14 additions & 46 deletions packages/@ember/-internals/glimmer/lib/resolver.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { privatize as P } from '@ember/-internals/container';
import { ENV } from '@ember/-internals/environment';
import { LookupOptions, Owner, setOwner } from '@ember/-internals/owner';
import { FactoryClass, LookupOptions, Owner } from '@ember/-internals/owner';
import { lookupComponent, lookupPartial, OwnedTemplateMeta } from '@ember/-internals/views';
import {
EMBER_GLIMMER_ANGLE_BRACKET_BUILT_INS,
Expand Down Expand Up @@ -49,7 +49,6 @@ import OnModifierManager from './modifiers/on';
import { populateMacros } from './syntax';
import { mountHelper } from './syntax/mount';
import { outletHelper } from './syntax/outlet';
import { Factory as TemplateFactory, Injections, OwnedTemplate } from './template';
import { getModifierManager } from './utils/custom-modifier-manager';
import { getManager } from './utils/managers';
import { ClassBasedHelperReference, SimpleHelperReference } from './utils/references';
Expand Down Expand Up @@ -114,13 +113,9 @@ export default class RuntimeResolver implements IRuntimeResolver<OwnedTemplateMe

private builtInModifiers: IBuiltInModifiers;

// supports directly imported late bound layouts on component.prototype.layout
private templateCache: Map<Owner, Map<TemplateFactory, OwnedTemplate>> = new Map();
private componentDefinitionCache: Map<object, ComponentDefinition | null> = new Map();
private customManagerCache: Map<string, ManagerDelegate<Opaque>> = new Map();

public templateCacheHits = 0;
public templateCacheMisses = 0;
public componentDefinitionCount = 0;
public helperDefinitionCount = 0;

Expand Down Expand Up @@ -213,34 +208,6 @@ export default class RuntimeResolver implements IRuntimeResolver<OwnedTemplateMe

// end CompileTimeLookup

/**
* Creates a template with injections from a directly imported template factory.
* @param templateFactory the directly imported template factory.
* @param owner the owner the template instance would belong to if resolved
*/
createTemplate(factory: TemplateFactory, owner: Owner): OwnedTemplate {
let cache = this.templateCache.get(owner);
let template;
if (cache === undefined) {
cache = new Map();
this.templateCache.set(owner, cache);
} else {
template = cache.get(factory);
}

if (template === undefined) {
const { compiler } = this;
const injections: Injections = { compiler };
setOwner(injections, owner);
template = factory.create(injections);
cache.set(factory, template);
this.templateCacheMisses++;
} else {
this.templateCacheHits++;
}
return template;
}

// needed for lazy compile time lookup
private handle(obj: Opaque) {
if (obj === undefined || obj === null) {
Expand Down Expand Up @@ -290,21 +257,18 @@ export default class RuntimeResolver implements IRuntimeResolver<OwnedTemplateMe
}

private _lookupPartial(name: string, meta: OwnedTemplateMeta): PartialDefinition {
const template = lookupPartial(name, meta.owner);
let templateFactory = lookupPartial(name, meta.owner);
let template = templateFactory(meta.owner);

if (template) {
return new PartialDefinition(name, template);
} else {
throw new Error(`${name} is not a partial`);
}
return new PartialDefinition(name, template);
}

private _lookupModifier(name: string, meta: OwnedTemplateMeta) {
let builtin = this.builtInModifiers[name];

if (builtin === undefined) {
let { owner } = meta;
let modifier = owner.factoryFor(`modifier:${name}`);
let modifier = owner.factoryFor<unknown, FactoryClass>(`modifier:${name}`);
if (modifier !== undefined) {
let managerFactory = getModifierManager<ModifierManagerDelegate<Opaque>>(modifier.class);
let manager = managerFactory!(owner);
Expand Down Expand Up @@ -367,13 +331,13 @@ export default class RuntimeResolver implements IRuntimeResolver<OwnedTemplateMe
let definition: Option<ComponentDefinition> = null;

if (layout !== undefined && component === undefined && ENV._TEMPLATE_ONLY_GLIMMER_COMPONENTS) {
definition = new TemplateOnlyComponentDefinition(layout);
definition = new TemplateOnlyComponentDefinition(layout(owner));
}

if (component !== undefined && component.class !== undefined) {
let wrapper = getManager(component.class);

if (wrapper && wrapper.type === 'component') {
if (wrapper !== null && wrapper.type === 'component') {
let { factory } = wrapper;

if (wrapper.internal) {
Expand All @@ -382,14 +346,18 @@ export default class RuntimeResolver implements IRuntimeResolver<OwnedTemplateMe
definition = new InternalComponentDefinition(
factory(owner) as InternalComponentManager<Opaque>,
component.class,
layout!
layout!(owner)
);
} else {
if (layout === undefined) {
layout = owner.lookup(P`template:components/-default`);
}

definition = new CustomManagerDefinition(
name,
component,
factory(owner) as ManagerDelegate<Opaque>,
layout || owner.lookup<OwnedTemplate>(P`template:components/-default`)
layout!(owner)
);
}
}
Expand All @@ -400,7 +368,7 @@ export default class RuntimeResolver implements IRuntimeResolver<OwnedTemplateMe
name,
component || owner.factoryFor(P`component:-default`),
null,
layout! // TODO fix type
layout !== undefined ? layout(owner) : undefined
);
}

Expand Down
12 changes: 6 additions & 6 deletions packages/@ember/-internals/glimmer/lib/setup-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function setupApplicationRegistry(registry: Registry) {
registry.injection('service:-dom-builder', 'bootOptions', '-environment:main');
registry.injection('renderer', 'builder', 'service:-dom-builder');

registry.register(P`template:-root`, RootTemplate);
registry.register(P`template:-root`, RootTemplate as any);
registry.injection('renderer', 'rootTemplate', P`template:-root`);

registry.register('renderer:-dom', InteractiveRenderer);
Expand All @@ -80,22 +80,22 @@ export function setupApplicationRegistry(registry: Registry) {
}

export function setupEngineRegistry(registry: Registry) {
registry.optionsForType('template', { instantiate: false });

registry.register('view:-outlet', OutletView);
registry.register('template:-outlet', OutletTemplate);
registry.register('template:-outlet', OutletTemplate as any);
registry.injection('view:-outlet', 'template', 'template:-outlet');

registry.injection('service:-dom-changes', 'document', 'service:-document');
registry.injection('service:-dom-tree-construction', 'document', 'service:-document');

registry.register(P`template:components/-default`, ComponentTemplate);
registry.register(P`template:components/-default`, ComponentTemplate as any);

registry.register('service:-glimmer-environment', Environment);

registry.register(P`template-compiler:main`, TemplateCompiler);
registry.injection(P`template-compiler:main`, 'environment', '-environment:main');

registry.injection('template', 'compiler', P`template-compiler:main`);

registry.optionsForType('helper', { instantiate: false });

registry.register('helper:loc', loc);
Expand All @@ -106,7 +106,7 @@ export function setupEngineRegistry(registry: Registry) {

if (EMBER_GLIMMER_ANGLE_BRACKET_BUILT_INS) {
registry.register('component:input', Input);
registry.register('template:components/input', InputTemplate);
registry.register('template:components/input', InputTemplate as any);

registry.register('component:textarea', TextArea);
} else {
Expand Down
Loading

0 comments on commit 5ece62b

Please sign in to comment.