Skip to content

Commit

Permalink
Share more stuff between custom managers
Browse files Browse the repository at this point in the history
  • Loading branch information
chadhietala committed Oct 22, 2018
1 parent 64eadfe commit 8bc9483
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 95 deletions.
1 change: 1 addition & 0 deletions packages/@ember/-internals/glimmer/index.ts
Expand Up @@ -307,4 +307,5 @@ export { default as OutletView } from './lib/views/outlet';
export { capabilities } from './lib/component-managers/custom';
export { setComponentManager, getComponentManager } from './lib/utils/custom-component-manager';
export { setModifierManager, getModifierManager } from './lib/utils/custom-modifier-manager';
export { capabilities as modifierCapabilties } from './lib/modifiers/custom';
export { isSerializationFirstNode } from './lib/utils/serialization-first-node-helpers';
Expand Up @@ -22,6 +22,7 @@ import { Destroyable } from '@glimmer/util';
import Environment from '../environment';
import RuntimeResolver from '../resolver';
import { OwnedTemplate } from '../template';
import { ManagerArgs, valueForCapturedArgs } from '../utils/managers';
import { RootReference } from '../utils/references';
import AbstractComponentManager from './abstract';

Expand Down Expand Up @@ -64,15 +65,10 @@ export interface Capabilities {
destructor: boolean;
}

export interface CustomComponentManagerArgs {
named: Dict<Opaque>;
positional: Opaque[];
}

export interface ManagerDelegate<ComponentInstance> {
capabilities: Capabilities;
createComponent(factory: Opaque, args: CustomComponentManagerArgs): ComponentInstance;
updateComponent(instance: ComponentInstance, args: CustomComponentManagerArgs): void;
createComponent(factory: Opaque, args: ManagerArgs): ComponentInstance;
updateComponent(instance: ComponentInstance, args: ManagerArgs): void;
getContext(instance: ComponentInstance): Opaque;
}

Expand Down Expand Up @@ -104,12 +100,6 @@ export interface ComponentArguments {
named: Dict<Opaque>;
}

function valueForCapturedArgs(args: CapturedArguments): CustomComponentManagerArgs {
return {
named: args.named.value(),
positional: args.positional.value(),
};
}
/**
The CustomComponentManager allows addons to provide custom component
implementations that integrate seamlessly into Ember. This is accomplished
Expand Down
34 changes: 11 additions & 23 deletions packages/@ember/-internals/glimmer/lib/modifiers/custom.ts
@@ -1,16 +1,19 @@
import { Factory } from '@ember/-internals/owner';
import { Dict, Opaque } from '@glimmer/interfaces';
import { Opaque } from '@glimmer/interfaces';
import { Tag } from '@glimmer/reference';
import { Arguments, CapturedArguments, ModifierManager } from '@glimmer/runtime';
import { ManagerArgs, valueForCapturedArgs } from '../utils/managers';

export interface CustomModifierDefinitionState<ModifierInstance> {
ModifierClass: Factory<ModifierInstance>;
name: string;
delegate: ModifierManagerDelegate<ModifierInstance>;
}

export interface Capabilities {}

// Currently there are no capabilities for modifiers
export function capabilities() {
export function capabilities(_managerAPI: string, _optionalFeatures?: {}): Capabilities {
return {};
}

Expand All @@ -19,7 +22,7 @@ export class CustomModifierDefinition<ModifierInstance> {
public manager = CUSTOM_MODIFIER_MANAGER;
constructor(
public name: string,
ModifierClass: Factory<ModifierInstance>,
public ModifierClass: Factory<ModifierInstance>,
public delegate: ModifierManagerDelegate<ModifierInstance>
) {
this.state = {
Expand All @@ -45,27 +48,12 @@ export class CustomModifierState<ModifierInstance> {
}
}

export interface CustomModifierManagerArgs {
named: Dict<Opaque>;
positional: Opaque[];
}

export interface ModifierManagerDelegate<ModifierInstance> {
createModifier(factory: Opaque, args: CustomModifierManagerArgs): ModifierInstance;
installModifier(
instance: ModifierInstance,
element: Element,
args: CustomModifierManagerArgs
): void;
updateModifier(instance: ModifierInstance, args: CustomModifierManagerArgs): void;
destroyModifier(instance: ModifierInstance, args: CustomModifierManagerArgs): void;
}

function valueForCapturedArgs(args: CapturedArguments): CustomModifierManagerArgs {
return {
named: args.named.value(),
positional: args.positional.value(),
};
capabilities: Capabilities;
createModifier(factory: Opaque, args: ManagerArgs): ModifierInstance;
installModifier(instance: ModifierInstance, element: Element, args: ManagerArgs): void;
updateModifier(instance: ModifierInstance, args: ManagerArgs): void;
destroyModifier(instance: ModifierInstance, args: ManagerArgs): void;
}

class CustomModifierManager<ModifierInstance>
Expand Down
25 changes: 6 additions & 19 deletions packages/@ember/-internals/glimmer/lib/resolver.ts
Expand Up @@ -41,7 +41,7 @@ import { default as queryParams } from './helpers/query-param';
import { default as readonly } from './helpers/readonly';
import { default as unbound } from './helpers/unbound';
import ActionModifierManager from './modifiers/action';
import { CustomModifierDefinition } from './modifiers/custom';
import { CustomModifierDefinition, ModifierManagerDelegate } from './modifiers/custom';
import { populateMacros } from './syntax';
import { mountHelper } from './syntax/mount';
import { outletHelper } from './syntax/outlet';
Expand Down Expand Up @@ -285,14 +285,7 @@ export default class RuntimeResolver implements IRuntimeResolver<OwnedTemplateMe
let { owner } = meta;
let modifier = owner.factoryFor(`modifier:${name}`);
if (modifier !== undefined) {
let managerFactory = getModifierManager(modifier.class);
assert(
`Could not find custom modifier manager for '${name}' which was specified by ${
modifier.class
}`,
!!managerFactory
);

let managerFactory = getModifierManager<ModifierManagerDelegate<Opaque>>(modifier.class);
let manager = managerFactory!(owner);

return new CustomModifierDefinition(name, modifier, manager);
Expand Down Expand Up @@ -352,20 +345,14 @@ export default class RuntimeResolver implements IRuntimeResolver<OwnedTemplateMe
}

if (GLIMMER_CUSTOM_COMPONENT_MANAGER && component && component.class) {
let managerId = getComponentManager(component.class);
if (managerId) {
let manager = this._lookupComponentManager(meta.owner, managerId);
assert(
`Could not find custom component manager '${managerId}' which was specified by ${
component.class
}`,
!!manager
);
let managerFactory = getComponentManager<ManagerDelegate<Opaque>>(component.class);
if (managerFactory) {
let delegate = managerFactory(meta.owner);

let definition = new CustomManagerDefinition(
name,
component,
manager,
delegate,
layout || meta.owner.lookup<OwnedTemplate>(P`template:components/-default`)
);
finalizer();
Expand Down
@@ -1,27 +1,24 @@
import { Owner } from '@ember/-internals/owner';
import { GLIMMER_CUSTOM_COMPONENT_MANAGER } from '@ember/canary-features';
import { Opaque } from '@glimmer/interfaces';
import { getManager, ManagerFactory, setManager } from './managers';

const getPrototypeOf = Object.getPrototypeOf;
const MANAGERS: WeakMap<any, string> = new WeakMap();

export function setComponentManager(managerId: string, obj: any) {
MANAGERS.set(obj, managerId);

return obj;
export function setComponentManager(stringOrFunction: string | ManagerFactory<Opaque>, obj: any) {
let factory;
if (typeof stringOrFunction === 'string') {
factory = function(owner: Owner) {
return owner.lookup(`component-manager:${stringOrFunction}`);
};
} else {
factory = stringOrFunction;
}
return setManager(factory, obj);
}

export function getComponentManager(obj: any): string | undefined {
export function getComponentManager<T>(obj: any): undefined | ManagerFactory<T> {
if (!GLIMMER_CUSTOM_COMPONENT_MANAGER) {
return;
}

let pointer = obj;
while (pointer !== undefined && pointer !== null) {
if (MANAGERS.has(pointer)) {
return MANAGERS.get(pointer);
}

pointer = getPrototypeOf(pointer);
}

return;
return getManager(obj);
}
@@ -1,32 +1,15 @@
import { Owner } from '@ember/-internals/owner';
import { GLIMMER_MODIFIER_MANAGER } from '@ember/canary-features';
import { Opaque } from '@glimmer/util';
import { ModifierManagerDelegate } from '../modifiers/custom';
import { getManager, ManagerFactory, setManager } from './managers';

const getPrototypeOf = Object.getPrototypeOf;

export type ModifierManagerFactory = (owner: Owner) => ModifierManagerDelegate<Opaque>;

const MANAGERS: WeakMap<any, ModifierManagerFactory> = new WeakMap();

export function setModifierManager(factory: ModifierManagerFactory, obj: any) {
MANAGERS.set(obj, factory);
return obj;
export function setModifierManager(factory: ManagerFactory<Opaque>, obj: any) {
return setManager(factory, obj);
}

export function getModifierManager(obj: any): undefined | ModifierManagerFactory {
export function getModifierManager<T>(obj: any): undefined | ManagerFactory<T> {
if (!GLIMMER_MODIFIER_MANAGER) {
return;
}

let pointer = obj;
while (pointer !== undefined && pointer !== null) {
if (MANAGERS.has(pointer)) {
return MANAGERS.get(pointer);
}

pointer = getPrototypeOf(pointer);
}

return;
return getManager(obj);
}
39 changes: 39 additions & 0 deletions packages/@ember/-internals/glimmer/lib/utils/managers.ts
@@ -0,0 +1,39 @@
import { Owner } from '@ember/-internals/owner';
import { Dict, Opaque } from '@glimmer/interfaces';
import { CapturedArguments } from '@glimmer/runtime';

const MANAGERS: WeakMap<any, ManagerFactory<Opaque>> = new WeakMap();

const getPrototypeOf = Object.getPrototypeOf;

export type ManagerFactory<ManagerDelegate> = (owner: Owner) => ManagerDelegate;

export function setManager<ManagerDelegate>(factory: ManagerFactory<ManagerDelegate>, obj: any) {
MANAGERS.set(obj, factory);
return obj;
}

export function getManager<T>(obj: any): undefined | ManagerFactory<T> {
let pointer = obj;
while (pointer !== undefined && pointer !== null) {
if (MANAGERS.has(pointer)) {
return MANAGERS.get(pointer) as ManagerFactory<T>;
}

pointer = getPrototypeOf(pointer);
}

return;
}

export function valueForCapturedArgs(args: CapturedArguments): ManagerArgs {
return {
named: args.named.value(),
positional: args.positional.value(),
};
}

export interface ManagerArgs {
named: Dict<Opaque>;
positional: Opaque[];
}

0 comments on commit 8bc9483

Please sign in to comment.