diff --git a/broccoli/packages.js b/broccoli/packages.js index e8d97866e0a..db25d4d7712 100644 --- a/broccoli/packages.js +++ b/broccoli/packages.js @@ -273,6 +273,9 @@ module.exports.glimmerES = function glimmerES(environment) { let glimmerEntries = [ '@glimmer/node', '@simple-dom/document', + '@glimmer/manager', + '@glimmer/destroyable', + '@glimmer/owner', '@glimmer/opcode-compiler', '@glimmer/runtime', ]; diff --git a/package.json b/package.json index 19d4aa53742..0b31bdcd78f 100644 --- a/package.json +++ b/package.json @@ -74,16 +74,19 @@ }, "devDependencies": { "@babel/preset-env": "^7.9.5", - "@glimmer/compiler": "0.67.0", + "@glimmer/compiler": "0.68.0", "@glimmer/env": "^0.1.7", - "@glimmer/global-context": "0.67.0", - "@glimmer/interfaces": "0.67.0", - "@glimmer/node": "0.67.0", - "@glimmer/opcode-compiler": "0.67.0", - "@glimmer/program": "0.67.0", - "@glimmer/reference": "0.67.0", - "@glimmer/runtime": "0.67.0", - "@glimmer/validator": "0.67.0", + "@glimmer/global-context": "0.68.0", + "@glimmer/interfaces": "0.68.0", + "@glimmer/manager": "0.68.0", + "@glimmer/destroyable": "0.68.0", + "@glimmer/owner": "0.68.0", + "@glimmer/node": "0.68.0", + "@glimmer/opcode-compiler": "0.68.0", + "@glimmer/program": "0.68.0", + "@glimmer/reference": "0.68.0", + "@glimmer/runtime": "0.68.0", + "@glimmer/validator": "0.68.0", "@simple-dom/document": "^1.4.0", "@types/qunit": "^2.9.1", "@types/rsvp": "^4.0.3", diff --git a/packages/@ember/-internals/glimmer/index.ts b/packages/@ember/-internals/glimmer/index.ts index bfc142eedbb..7729ebecc57 100644 --- a/packages/@ember/-internals/glimmer/index.ts +++ b/packages/@ember/-internals/glimmer/index.ts @@ -361,7 +361,6 @@ */ export { templateFactory as template, templateCacheCounters } from '@glimmer/opcode-compiler'; -export { setComponentTemplate, getComponentTemplate } from '@glimmer/runtime'; export { default as RootTemplate } from './lib/templates/root'; export { default as Checkbox } from './lib/components/checkbox'; @@ -393,10 +392,8 @@ export { DOMChanges, NodeDOMTreeConstruction, DOMTreeConstruction } from './lib/ // a lot of these are testing how a problem was solved // rather than the problem was solved export { INVOKE } from './lib/helpers/action'; +export { default as on } from './lib/modifiers/on'; export { default as OutletView } from './lib/views/outlet'; export { OutletState } from './lib/utils/outlet'; export { setComponentManager } from './lib/utils/managers'; -export { capabilities } from './lib/component-managers/custom'; -export { capabilities as modifierCapabilities } from './lib/modifiers/custom'; -export { helperCapabilities, invokeHelper } from './lib/helpers/custom'; export { isSerializationFirstNode } from './lib/utils/serialization-first-node-helpers'; diff --git a/packages/@ember/-internals/glimmer/lib/compile-time-lookup.ts b/packages/@ember/-internals/glimmer/lib/compile-time-lookup.ts deleted file mode 100644 index e62cf9ec0e5..00000000000 --- a/packages/@ember/-internals/glimmer/lib/compile-time-lookup.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Owner } from '@ember/-internals/owner'; -import { - CompileTimeComponent, - CompileTimeResolver, - ComponentDefinition, - InternalComponentCapabilities, - InternalComponentManager, - Option, - WithStaticLayout, -} from '@glimmer/interfaces'; -import { unwrapTemplate } from '@glimmer/util'; -import RuntimeResolver from './resolver'; - -interface StaticComponentManager - extends WithStaticLayout, - InternalComponentManager {} - -function isStaticComponentManager( - _manager: InternalComponentManager, - capabilities: InternalComponentCapabilities -): _manager is StaticComponentManager { - return !capabilities.dynamicLayout; -} - -export default class CompileTimeResolverImpl implements CompileTimeResolver { - constructor(private resolver: RuntimeResolver) {} - - lookupHelper(name: string, owner: Owner): Option { - return this.resolver.lookupHelper(name, owner); - } - - lookupModifier(name: string, owner: Owner): Option { - return this.resolver.lookupModifier(name, owner); - } - - lookupComponent(name: string, owner: Owner): Option { - let definitionHandle = this.resolver.lookupComponentHandle(name, owner); - - if (definitionHandle === null) { - return null; - } - - const { manager, state } = this.resolver.resolve>( - definitionHandle - ); - const capabilities = manager.getCapabilities(state); - - if (!isStaticComponentManager(manager, capabilities)) { - return { - handle: definitionHandle, - capabilities, - compilable: null, - }; - } - - let template = unwrapTemplate(manager.getStaticLayout(state)); - let layout = capabilities.wrapped ? template.asWrappedLayout() : template.asLayout(); - - return { - handle: definitionHandle, - capabilities, - compilable: layout, - }; - } - - lookupPartial(name: string, owner: Owner): Option { - return this.resolver.lookupPartial(name, owner); - } - - resolve(): null { - return null; - } -} diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts b/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts index 2bffb2280dd..05ec993483d 100644 --- a/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts +++ b/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts @@ -1,6 +1,5 @@ -import { privatize as P } from '@ember/-internals/container'; -import { getOwner } from '@ember/-internals/owner'; -import { guidFor } from '@ember/-internals/utils'; +import { Factory, getOwner } from '@ember/-internals/owner'; +import { enumerableSymbol, guidFor, symbol } from '@ember/-internals/utils'; import { addChildView, setElementView, setViewElement } from '@ember/-internals/views'; import { assert, debugFreeze } from '@ember/debug'; import { EMBER_COMPONENT_IS_VISIBLE } from '@ember/deprecated-features'; @@ -9,16 +8,16 @@ import { assign } from '@ember/polyfills'; import { DEBUG } from '@glimmer/env'; import { Bounds, - ComponentDefinition, + CompilableProgram, Destroyable, ElementOperations, Environment, InternalComponentCapabilities, Option, PreparedArguments, - Template, TemplateFactory, VMArguments, + WithCreateInstance, WithDynamicLayout, WithDynamicTagName, } from '@glimmer/interfaces'; @@ -29,8 +28,8 @@ import { Reference, valueForRef, } from '@glimmer/reference'; -import { BaseInternalComponentManager, reifyPositional } from '@glimmer/runtime'; -import { EMPTY_ARRAY } from '@glimmer/util'; +import { reifyPositional } from '@glimmer/runtime'; +import { EMPTY_ARRAY, unwrapTemplate } from '@glimmer/util'; import { beginTrackFrame, beginUntrackFrame, @@ -41,7 +40,6 @@ import { valueForTag, } from '@glimmer/validator'; import { SimpleElement } from '@simple-dom/interface'; -import { BOUNDS, DIRTY_TAG, HAS_BLOCK, IS_DISPATCHING_ATTRS } from '../component'; import { DynamicScope } from '../renderer'; import RuntimeResolver from '../resolver'; import { isTemplateFactory } from '../template'; @@ -55,7 +53,13 @@ import { import ComponentStateBucket, { Component } from '../utils/curly-component-state-bucket'; import { processComponentArgs } from '../utils/process-args'; -import DefinitionState from './definition-state'; + +export const ARGS = enumerableSymbol('ARGS'); +export const HAS_BLOCK = enumerableSymbol('HAS_BLOCK'); + +export const DIRTY_TAG = symbol('DIRTY_TAG'); +export const IS_DISPATCHING_ATTRS = symbol('IS_DISPATCHING_ATTRS'); +export const BOUNDS = symbol('BOUNDS'); const EMBER_VIEW_REF = createPrimitiveRef('ember-view'); @@ -109,17 +113,25 @@ function applyAttributeBindings( } } -const DEFAULT_LAYOUT = P`template:components/-default`; const EMPTY_POSITIONAL_ARGS: Reference[] = []; debugFreeze(EMPTY_POSITIONAL_ARGS); +type ComponentFactory = Factory< + Component, + { + create(props?: any): Component; + positionalParams: string | string[] | undefined | null; + name: string; + } +>; + export default class CurlyComponentManager - extends BaseInternalComponentManager implements + WithCreateInstance, WithDynamicLayout, WithDynamicTagName { - protected templateFor(component: Component): Template { + protected templateFor(component: Component): CompilableProgram | null { let { layout, layoutName } = component; let owner = getOwner(component); @@ -129,21 +141,21 @@ export default class CurlyComponentManager if (layoutName !== undefined) { let _factory = owner.lookup(`template:${layoutName}`); assert(`Layout \`${layoutName}\` not found!`, _factory !== undefined); - factory = _factory!; + factory = _factory; } else { - factory = owner.lookup(DEFAULT_LAYOUT)!; + return null; } } else if (isTemplateFactory(layout)) { factory = layout; } else { - // we were provided an instance already - return layout; + // no layout was found, use the default layout + return null; } - return factory(owner); + return unwrapTemplate(factory(owner)).asWrappedLayout(); } - getDynamicLayout(bucket: ComponentStateBucket): Template { + getDynamicLayout(bucket: ComponentStateBucket): CompilableProgram | null { return this.templateFor(bucket.component); } @@ -157,11 +169,11 @@ export default class CurlyComponentManager return (component && component.tagName) || 'div'; } - getCapabilities(state: DefinitionState): InternalComponentCapabilities { - return state.capabilities; + getCapabilities(): InternalComponentCapabilities { + return CURLY_CAPABILITIES; } - prepareArgs(state: DefinitionState, args: VMArguments): Option { + prepareArgs(ComponentClass: ComponentFactory, args: VMArguments): Option { if (args.named.has('__ARGS__')) { let { __ARGS__, ...rest } = args.named.capture(); @@ -176,7 +188,7 @@ export default class CurlyComponentManager return prepared; } - const { positionalParams } = state.ComponentClass.class!; + const { positionalParams } = ComponentClass.class!; // early exits if ( @@ -236,7 +248,7 @@ export default class CurlyComponentManager */ create( environment: Environment, - state: DefinitionState, + ComponentClass: ComponentFactory, args: VMArguments, dynamicScope: DynamicScope, callerSelfRef: Reference, @@ -246,9 +258,6 @@ export default class CurlyComponentManager // components will be skipped. let parentView = dynamicScope.view; - // Get the Ember.Component subclass to instantiate for this component. - let factory = state.ComponentClass; - // Capture the arguments, which tells Glimmer to give us our own, stable // copy of the Arguments object that is safe to hold on to between renders. let capturedArgs = args.named.capture(); @@ -273,11 +282,6 @@ export default class CurlyComponentManager // `_target`, so bubbled actions are routed to the right place. props._target = valueForRef(callerSelfRef); - // static layout asserts CurriedDefinition - if (state.template) { - props.layout = state.template; - } - // caller: // // @@ -287,7 +291,7 @@ export default class CurlyComponentManager // Now that we've built up all of the properties to set on the component instance, // actually create it. beginUntrackFrame(); - let component = factory.create(props); + let component = ComponentClass.create(props); let finalizer = _instrumentStart('render.component', initialRenderInstrumentDetails, component); @@ -350,8 +354,8 @@ export default class CurlyComponentManager return bucket; } - getDebugName({ name }: DefinitionState): string { - return name; + getDebugName(definition: ComponentFactory): string { + return definition.fullName || definition.normalizedName || definition.class!.name; } getSelf({ rootRef }: ComponentStateBucket): Reference { @@ -471,42 +475,7 @@ export default class CurlyComponentManager } } -export function validatePositionalParameters( - named: { has(name: string): boolean }, - positional: { length: number }, - positionalParamsDefinition: any -) { - if (DEBUG) { - if (!named || !positional || !positional.length) { - return; - } - - let paramType = typeof positionalParamsDefinition; - - if (paramType === 'string') { - // tslint:disable-next-line:max-line-length - assert( - `You cannot specify positional parameters and the hash argument \`${positionalParamsDefinition}\`.`, - !named.has(positionalParamsDefinition) - ); - } else { - if (positional.length < positionalParamsDefinition.length) { - positionalParamsDefinition = positionalParamsDefinition.slice(0, positional.length); - } - - for (let i = 0; i < positionalParamsDefinition.length; i++) { - let name = positionalParamsDefinition[i]; - - assert( - `You cannot specify both a positional param (at position ${i}) and the hash argument \`${name}\`.`, - !named.has(name) - ); - } - } - } -} - -export function processComponentInitializationAssertions(component: Component, props: any) { +export function processComponentInitializationAssertions(component: Component, props: any): void { assert( `classNameBindings must be non-empty strings: ${component}`, (() => { @@ -566,14 +535,6 @@ export function rerenderInstrumentDetails(component: any): any { return component.instrumentDetails({ initialRender: false }); } -// This is not any of glimmer-vm's proper Argument types because we -// don't have sufficient public constructors to conveniently -// reassemble one after we mangle the various arguments. -interface CurriedArgs { - positional: any[]; - named: any; -} - export const CURLY_CAPABILITIES: InternalComponentCapabilities = { dynamicLayout: true, dynamicTag: true, @@ -589,22 +550,4 @@ export const CURLY_CAPABILITIES: InternalComponentCapabilities = { willDestroy: true, }; -const CURLY_COMPONENT_MANAGER = new CurlyComponentManager(); -export class CurlyComponentDefinition implements ComponentDefinition { - public state: DefinitionState; - public manager: CurlyComponentManager = CURLY_COMPONENT_MANAGER; - - constructor( - public name: string, - public ComponentClass: any, - public template?: Template, - public args?: CurriedArgs - ) { - this.state = { - name, - ComponentClass, - template, - capabilities: CURLY_CAPABILITIES, - }; - } -} +export const CURLY_COMPONENT_MANAGER = new CurlyComponentManager(); diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/custom.ts b/packages/@ember/-internals/glimmer/lib/component-managers/custom.ts deleted file mode 100644 index f55e5c03c9c..00000000000 --- a/packages/@ember/-internals/glimmer/lib/component-managers/custom.ts +++ /dev/null @@ -1,242 +0,0 @@ -import { Factory } from '@ember/-internals/owner'; -import { assert } from '@ember/debug'; -import { DEBUG } from '@glimmer/env'; -import { - Arguments, - ComponentCapabilities, - ComponentCapabilitiesVersions, - ComponentDefinition, - ComponentManager, - ComponentManagerWithAsyncLifeCycleCallbacks, - ComponentManagerWithAsyncUpdateHook, - ComponentManagerWithDestructors, - ComponentManagerWithUpdateHook, - Destroyable, - Environment, - InternalComponentCapabilities, - Option, - Template, - VMArguments, - WithStaticLayout, -} from '@glimmer/interfaces'; -import { createConstRef, Reference } from '@glimmer/reference'; -import { - BaseInternalComponentManager, - buildCapabilities, - registerDestructor, -} from '@glimmer/runtime'; -import { deprecateMutationsInTrackingTransaction } from '@glimmer/validator'; -import { argsProxyFor } from '../utils/args-proxy'; - -const CAPABILITIES = { - dynamicLayout: false, - dynamicTag: false, - prepareArgs: false, - createArgs: true, - attributeHook: false, - elementHook: false, - createCaller: false, - dynamicScope: true, - updateHook: true, - createInstance: true, - wrapped: false, - willDestroy: false, -}; - -export function capabilities( - managerAPI: Version, - options: ComponentCapabilitiesVersions[Version] = {} -): ComponentCapabilities { - assert( - 'Invalid component manager compatibility specified', - managerAPI === '3.4' || managerAPI === '3.13' - ); - - let updateHook = true; - - if (managerAPI === '3.13') { - updateHook = Boolean((options as ComponentCapabilitiesVersions['3.13']).updateHook); - } - - return buildCapabilities({ - asyncLifeCycleCallbacks: Boolean(options.asyncLifecycleCallbacks), - destructor: Boolean(options.destructor), - updateHook, - }); -} - -export interface DefinitionState { - name: string; - ComponentClass: Factory; - template: Template; -} - -export function hasAsyncLifeCycleCallbacks( - delegate: ComponentManager -): delegate is ComponentManagerWithAsyncLifeCycleCallbacks { - return delegate.capabilities.asyncLifeCycleCallbacks; -} - -export function hasUpdateHook( - delegate: ComponentManager -): delegate is ComponentManagerWithUpdateHook { - return delegate.capabilities.updateHook; -} - -export function hasAsyncUpdateHook( - delegate: ComponentManager -): delegate is ComponentManagerWithAsyncUpdateHook { - return hasAsyncLifeCycleCallbacks(delegate) && hasUpdateHook(delegate); -} - -export function hasDestructors( - delegate: ComponentManager -): delegate is ComponentManagerWithDestructors { - return delegate.capabilities.destructor; -} - -/** - The CustomComponentManager allows addons to provide custom component - implementations that integrate seamlessly into Ember. This is accomplished - through a delegate, registered with the custom component manager, which - implements a set of hooks that determine component behavior. - - To create a custom component manager, instantiate a new CustomComponentManager - class and pass the delegate as the first argument: - - ```js - let manager = new CustomComponentManager({ - // ...delegate implementation... - }); - ``` - - ## Delegate Hooks - - Throughout the lifecycle of a component, the component manager will invoke - delegate hooks that are responsible for surfacing those lifecycle changes to - the end developer. - - * `create()` - invoked when a new instance of a component should be created - * `update()` - invoked when the arguments passed to a component change - * `getContext()` - returns the object that should be -*/ -export default class CustomComponentManager - extends BaseInternalComponentManager< - CustomComponentState, - CustomComponentDefinitionState - > - implements - WithStaticLayout< - CustomComponentState, - CustomComponentDefinitionState - > { - create( - env: Environment, - definition: CustomComponentDefinitionState, - vmArgs: VMArguments - ): CustomComponentState { - let { delegate } = definition; - let args = argsProxyFor(vmArgs.capture(), 'component'); - - let component; - - if (DEBUG && deprecateMutationsInTrackingTransaction !== undefined) { - deprecateMutationsInTrackingTransaction(() => { - component = delegate.createComponent(definition.ComponentClass.class!, args); - }); - } else { - component = delegate.createComponent(definition.ComponentClass.class!, args); - } - - let bucket = new CustomComponentState(delegate, component, args, env); - - return bucket as CustomComponentState; - } - - getDebugName({ name }: CustomComponentDefinitionState): string { - return name; - } - - update(bucket: CustomComponentState): void { - if (hasUpdateHook(bucket.delegate)) { - let { delegate, component, args } = bucket; - - delegate.updateComponent(component, args); - } - } - - didCreate({ delegate, component }: CustomComponentState): void { - if (hasAsyncLifeCycleCallbacks(delegate)) { - delegate.didCreateComponent(component); - } - } - - didUpdate({ delegate, component }: CustomComponentState): void { - if (hasAsyncUpdateHook(delegate)) { - delegate.didUpdateComponent(component); - } - } - - didRenderLayout(): void {} - - didUpdateLayout(): void {} - - getSelf({ delegate, component }: CustomComponentState): Reference { - return createConstRef(delegate.getContext(component), 'this'); - } - - getDestroyable(bucket: CustomComponentState): Option { - return bucket; - } - - getCapabilities(): InternalComponentCapabilities { - return CAPABILITIES; - } - - getStaticLayout(state: DefinitionState): Template { - return state.template; - } -} -const CUSTOM_COMPONENT_MANAGER = new CustomComponentManager(); - -/** - * Stores internal state about a component instance after it's been created. - */ -export class CustomComponentState { - constructor( - public delegate: ComponentManager, - public component: ComponentInstance, - public args: Arguments, - public env: Environment - ) { - if (hasDestructors(delegate)) { - registerDestructor(this, () => delegate.destroyComponent(component)); - } - } -} - -export interface CustomComponentDefinitionState - extends DefinitionState { - delegate: ComponentManager; -} - -export class CustomManagerDefinition implements ComponentDefinition { - public state: CustomComponentDefinitionState; - public manager: CustomComponentManager< - ComponentInstance - > = CUSTOM_COMPONENT_MANAGER as CustomComponentManager; - - constructor( - public name: string, - public ComponentClass: Factory, - public delegate: ComponentManager, - public template: Template - ) { - this.state = { - name, - ComponentClass, - template, - delegate, - }; - } -} diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/definition-state.ts b/packages/@ember/-internals/glimmer/lib/component-managers/definition-state.ts deleted file mode 100644 index 156fee126d9..00000000000 --- a/packages/@ember/-internals/glimmer/lib/component-managers/definition-state.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Factory } from '@ember/-internals/owner'; -import { InternalComponentCapabilities, Template } from '@glimmer/interfaces'; -import { Component } from '../utils/curly-component-state-bucket'; - -export default interface DefinitionState { - capabilities: InternalComponentCapabilities; - name: string; - ComponentClass: Factory< - Component, - { create(props?: any): Component; positionalParams: string | string[] | undefined | null } - >; - template?: Template; -} diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/internal.ts b/packages/@ember/-internals/glimmer/lib/component-managers/internal.ts index b56161631c6..aa30f4f9e5c 100644 --- a/packages/@ember/-internals/glimmer/lib/component-managers/internal.ts +++ b/packages/@ember/-internals/glimmer/lib/component-managers/internal.ts @@ -1,19 +1,16 @@ import { Owner } from '@ember/-internals/owner'; import { assert } from '@ember/debug'; import { - ComponentDefinition, + CapturedNamedArguments, Destroyable, DynamicScope, Environment, InternalComponentCapabilities, InternalComponentManager, - Template, VMArguments, - WithStaticLayout, + WithCreateInstance, } from '@glimmer/interfaces'; import { createConstRef, isConstRef, Reference, valueForRef } from '@glimmer/reference'; -import { BaseInternalComponentManager } from '@glimmer/runtime'; -import InternalComponent from '../components/internal'; const CAPABILITIES: InternalComponentCapabilities = { dynamicLayout: false, @@ -30,40 +27,24 @@ const CAPABILITIES: InternalComponentCapabilities = { willDestroy: false, }; -export interface InternalDefinitionState { - ComponentClass: typeof InternalComponent; - layout: Template; -} - export interface InternalComponentState { env: Environment; instance: Destroyable; } -export class InternalComponentDefinition - implements - ComponentDefinition { - public state: InternalDefinitionState; - - constructor( - public manager: InternalComponentManager, - ComponentClass: typeof InternalComponent, - layout: Template - ) { - this.state = { ComponentClass, layout }; - } +export interface EmberInternalComponentConstructor { + new (owner: Owner, args: CapturedNamedArguments, caller: unknown): Destroyable; } export default class InternalManager - extends BaseInternalComponentManager - implements WithStaticLayout { + implements + InternalComponentManager, + WithCreateInstance { static for(name: string): (owner: Owner) => InternalManager { return (owner: Owner) => new InternalManager(owner, name); } - constructor(private owner: Owner, private name: string) { - super(); - } + constructor(private owner: Owner, private name: string) {} getCapabilities(): InternalComponentCapabilities { return CAPABILITIES; @@ -71,7 +52,7 @@ export default class InternalManager create( env: Environment, - { ComponentClass }: InternalDefinitionState, + ComponentClass: EmberInternalComponentConstructor, args: VMArguments, _dynamicScope: DynamicScope, caller: Reference @@ -90,6 +71,12 @@ export default class InternalManager return state; } + didCreate(): void {} + didUpdate(): void {} + + didRenderLayout(): void {} + didUpdateLayout(): void {} + getDebugName(): string { return this.name; } @@ -101,8 +88,4 @@ export default class InternalManager getDestroyable(state: InternalComponentState): Destroyable { return state.instance; } - - getStaticLayout({ layout: template }: InternalDefinitionState): Template { - return template; - } } diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/mount.ts b/packages/@ember/-internals/glimmer/lib/component-managers/mount.ts index 9d5e3a97a48..cf526e4ccd9 100644 --- a/packages/@ember/-internals/glimmer/lib/component-managers/mount.ts +++ b/packages/@ember/-internals/glimmer/lib/component-managers/mount.ts @@ -1,6 +1,7 @@ import { Owner } from '@ember/-internals/owner'; import { generateControllerFactory } from '@ember/-internals/routing'; import EngineInstance from '@ember/engine/instance'; +import { associateDestroyableChild } from '@glimmer/destroyable'; import { CapturedArguments, ComponentDefinition, @@ -9,14 +10,15 @@ import { Environment, InternalComponentCapabilities, Option, - Template, TemplateFactory, VMArguments, + WithCreateInstance, WithCustomDebugRenderTree, WithDynamicLayout, } from '@glimmer/interfaces'; +import { capabilityFlagsFrom } from '@glimmer/manager'; import { createConstRef, Reference, valueForRef } from '@glimmer/reference'; -import { associateDestroyableChild, BaseInternalComponentManager } from '@glimmer/runtime'; +import { unwrapTemplate } from '@glimmer/util'; import RuntimeResolver from '../resolver'; interface EngineState { @@ -46,13 +48,13 @@ const CAPABILITIES = { }; class MountManager - extends BaseInternalComponentManager implements + WithCreateInstance, WithDynamicLayout, WithCustomDebugRenderTree { getDynamicLayout(state: EngineState) { let templateFactory = state.engine.lookup('template:application') as TemplateFactory; - return templateFactory(state.engine); + return unwrapTemplate(templateFactory(state.engine)).asLayout(); } getCapabilities(): InternalComponentCapabilities { @@ -106,7 +108,7 @@ class MountManager definition: EngineDefinitionState, state: EngineState, args: CapturedArguments, - template?: Template + templateModuleName?: string ): CustomRenderNode[] { return [ { @@ -122,7 +124,7 @@ class MountManager type: 'route-template', name: 'application', args, - template, + template: templateModuleName, }, ]; } @@ -135,7 +137,11 @@ class MountManager return bucket.engine; } + didCreate() {} + didUpdate() {} + didRenderLayout(): void {} + didUpdateLayout(): void {} update(bucket: EngineState): void { let { controller, modelRef } = bucket; @@ -144,17 +150,20 @@ class MountManager controller.set('model', valueForRef(modelRef!)); } } - - didUpdateLayout(): void {} } const MOUNT_MANAGER = new MountManager(); export class MountDefinition implements ComponentDefinition { + // handle is not used by this custom definition + public handle = -1; + public state: EngineDefinitionState; public manager = MOUNT_MANAGER; + public compilable = null; + public capabilities = capabilityFlagsFrom(CAPABILITIES); - constructor(name: string) { - this.state = { name }; + constructor(public resolvedName: string) { + this.state = { name: resolvedName }; } } diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/outlet.ts b/packages/@ember/-internals/glimmer/lib/component-managers/outlet.ts index c0f53fb409e..abdee7e3517 100644 --- a/packages/@ember/-internals/glimmer/lib/component-managers/outlet.ts +++ b/packages/@ember/-internals/glimmer/lib/component-managers/outlet.ts @@ -6,20 +6,24 @@ import { _instrumentStart } from '@ember/instrumentation'; import { assign } from '@ember/polyfills'; import { CapturedArguments, + CompilableProgram, ComponentDefinition, CustomRenderNode, Destroyable, Environment, InternalComponentCapabilities, + InternalComponentCapability, Option, Template, VMArguments, + WithCreateInstance, WithCustomDebugRenderTree, WithDynamicTagName, - WithStaticLayout, } from '@glimmer/interfaces'; +import { capabilityFlagsFrom } from '@glimmer/manager'; import { createConstRef, Reference, valueForRef } from '@glimmer/reference'; -import { BaseInternalComponentManager, EMPTY_ARGS } from '@glimmer/runtime'; +import { EMPTY_ARGS } from '@glimmer/runtime'; +import { unwrapTemplate } from '@glimmer/util'; import { SimpleElement } from '@simple-dom/interface'; import { DynamicScope } from '../renderer'; @@ -63,9 +67,8 @@ const CAPABILITIES: InternalComponentCapabilities = { }; class OutletComponentManager - extends BaseInternalComponentManager implements - WithStaticLayout, + WithCreateInstance, WithCustomDebugRenderTree { create( env: Environment, @@ -144,17 +147,12 @@ class OutletComponentManager name: definition.name, args: args, instance: definition.controller, - template: definition.template, + template: unwrapTemplate(definition.template).moduleName, }); return nodes; } - getStaticLayout({ template }: OutletDefinitionState) { - // The router has already resolved the template - return template; - } - getCapabilities(): InternalComponentCapabilities { return CAPABILITIES; } @@ -163,10 +161,15 @@ class OutletComponentManager return self; } + didCreate() {} + didUpdate() {} + didRenderLayout(state: OutletInstanceState): void { state.finalize(); } + didUpdateLayout() {} + getDestroyable(): Option { return null; } @@ -177,10 +180,24 @@ const OUTLET_MANAGER = new OutletComponentManager(); export class OutletComponentDefinition implements ComponentDefinition { + // handle is not used by this custom definition + public handle = -1; + + public resolvedName: string; + public compilable: CompilableProgram; + public capabilities: InternalComponentCapability; + constructor( public state: OutletDefinitionState, public manager: OutletComponentManager = OUTLET_MANAGER - ) {} + ) { + let capabilities = manager.getCapabilities(); + this.capabilities = capabilityFlagsFrom(capabilities); + this.compilable = capabilities.wrapped + ? unwrapTemplate(state.template).asWrappedLayout() + : unwrapTemplate(state.template).asLayout(); + this.resolvedName = state.name; + } } export function createRootOutlet(outletView: OutletView): OutletComponentDefinition { @@ -198,11 +215,6 @@ export function createRootOutlet(outletView: OutletView): OutletComponentDefinit return 'div'; } - getStaticLayout({ template }: OutletDefinitionState) { - // The router has already resolved the template - return template; - } - getCapabilities(): InternalComponentCapabilities { return WRAPPED_CAPABILITIES; } diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/root.ts b/packages/@ember/-internals/glimmer/lib/component-managers/root.ts index d8ae5774223..bf829e89786 100644 --- a/packages/@ember/-internals/glimmer/lib/component-managers/root.ts +++ b/packages/@ember/-internals/glimmer/lib/component-managers/root.ts @@ -1,5 +1,4 @@ import { getFactoryFor } from '@ember/-internals/container'; -import { Factory } from '@ember/-internals/owner'; import { _instrumentStart } from '@ember/instrumentation'; import { DEBUG } from '@glimmer/env'; import { @@ -7,18 +6,17 @@ import { Environment, InternalComponentCapabilities, Option, - Template, VMArguments, } from '@glimmer/interfaces'; +import { capabilityFlagsFrom } from '@glimmer/manager'; import { CONSTANT_TAG, consumeTag } from '@glimmer/validator'; -import { DIRTY_TAG } from '../component'; import { DynamicScope } from '../renderer'; import ComponentStateBucket, { Component } from '../utils/curly-component-state-bucket'; import CurlyComponentManager, { + DIRTY_TAG, initialRenderInstrumentDetails, processComponentInitializationAssertions, } from './curly'; -import DefinitionState from './definition-state'; class RootComponentManager extends CurlyComponentManager { component: Component; @@ -28,13 +26,9 @@ class RootComponentManager extends CurlyComponentManager { this.component = component; } - getStaticLayout(): Template { - return this.templateFor(this.component); - } - create( environment: Environment, - _state: DefinitionState, + _state: unknown, _args: Option, dynamicScope: DynamicScope ) { @@ -81,7 +75,7 @@ class RootComponentManager extends CurlyComponentManager { // ROOT is the top-level template it has nothing but one yield. // it is supposed to have a dummy element export const ROOT_CAPABILITIES: InternalComponentCapabilities = { - dynamicLayout: false, + dynamicLayout: true, dynamicTag: true, prepareArgs: false, createArgs: false, @@ -96,17 +90,17 @@ export const ROOT_CAPABILITIES: InternalComponentCapabilities = { }; export class RootComponentDefinition implements ComponentDefinition { - state: DefinitionState; + // handle is not used by this custom definition + handle = -1; + + resolvedName = '-top-level'; + state: object; manager: RootComponentManager; + capabilities = capabilityFlagsFrom(ROOT_CAPABILITIES); + compilable = null; - constructor(public component: Component) { - let manager = new RootComponentManager(component); - this.manager = manager; - let factory = getFactoryFor(component); - this.state = { - name: factory!.fullName.slice(10), - capabilities: ROOT_CAPABILITIES, - ComponentClass: factory as Factory, - }; + constructor(component: Component) { + this.manager = new RootComponentManager(component); + this.state = getFactoryFor(component); } } diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/template-only.ts b/packages/@ember/-internals/glimmer/lib/component-managers/template-only.ts deleted file mode 100644 index 9aa36c1dd1e..00000000000 --- a/packages/@ember/-internals/glimmer/lib/component-managers/template-only.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { - ComponentDefinition, - Environment, - InternalComponentCapabilities, - Option, - Template, - WithStaticLayout, -} from '@glimmer/interfaces'; -import { NULL_REFERENCE, Reference } from '@glimmer/reference'; - -const CAPABILITIES: InternalComponentCapabilities = { - dynamicLayout: false, - dynamicTag: false, - prepareArgs: false, - createArgs: false, - attributeHook: false, - elementHook: false, - createCaller: false, - dynamicScope: false, - updateHook: false, - createInstance: false, - wrapped: false, - willDestroy: false, -}; - -export interface DebugStateBucket { - environment: Environment; -} - -export default class TemplateOnlyComponentManager - implements WithStaticLayout, TemplateOnlyComponentDefinitionState> { - getStaticLayout({ template }: TemplateOnlyComponentDefinitionState): Template { - return template; - } - - getCapabilities(): InternalComponentCapabilities { - return CAPABILITIES; - } - - getDebugName({ name }: TemplateOnlyComponentDefinitionState): string { - return name; - } - - getSelf(): Reference { - return NULL_REFERENCE; - } - - getDestroyable(): null { - return null; - } -} - -const MANAGER = new TemplateOnlyComponentManager(); - -export interface TemplateOnlyComponentDefinitionState { - name: string; - template: Template; -} - -export class TemplateOnlyComponentDefinition - implements - TemplateOnlyComponentDefinitionState, - ComponentDefinition< - TemplateOnlyComponentDefinitionState, - Option, - TemplateOnlyComponentManager - > { - manager = MANAGER; - constructor(public name: string, public template: Template) {} - - get state(): TemplateOnlyComponentDefinitionState { - return this; - } -} diff --git a/packages/@ember/-internals/glimmer/lib/component.ts b/packages/@ember/-internals/glimmer/lib/component.ts index abe9d409e95..49e2b50189e 100644 --- a/packages/@ember/-internals/glimmer/lib/component.ts +++ b/packages/@ember/-internals/glimmer/lib/component.ts @@ -1,7 +1,6 @@ import { get, PROPERTY_DID_CHANGE } from '@ember/-internals/metal'; import { getOwner } from '@ember/-internals/owner'; import { TargetActionSupport } from '@ember/-internals/runtime'; -import { enumerableSymbol, symbol } from '@ember/-internals/utils'; import { ActionSupport, ChildViewsSupport, @@ -13,17 +12,18 @@ import { } from '@ember/-internals/views'; import { assert, deprecate } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; +import { setInternalComponentManager } from '@glimmer/manager'; import { isUpdatableRef, updateRef } from '@glimmer/reference'; import { normalizeProperty } from '@glimmer/runtime'; import { createTag, dirtyTag } from '@glimmer/validator'; import { Namespace } from '@simple-dom/interface'; - -export const ARGS = enumerableSymbol('ARGS'); -export const HAS_BLOCK = enumerableSymbol('HAS_BLOCK'); - -export const DIRTY_TAG = symbol('DIRTY_TAG'); -export const IS_DISPATCHING_ATTRS = symbol('IS_DISPATCHING_ATTRS'); -export const BOUNDS = symbol('BOUNDS'); +import { + ARGS, + BOUNDS, + CURLY_COMPONENT_MANAGER, + DIRTY_TAG, + IS_DISPATCHING_ATTRS, +} from './component-managers/curly'; /** @module @ember/component @@ -1128,4 +1128,6 @@ Component.reopenClass({ positionalParams: [], }); +setInternalComponentManager(() => CURLY_COMPONENT_MANAGER, Component); + export default Component; diff --git a/packages/@ember/-internals/glimmer/lib/components/input.ts b/packages/@ember/-internals/glimmer/lib/components/input.ts index c74e0e6545d..e56943537dc 100644 --- a/packages/@ember/-internals/glimmer/lib/components/input.ts +++ b/packages/@ember/-internals/glimmer/lib/components/input.ts @@ -1,7 +1,7 @@ /** @module @ember/component */ -import { setComponentManager } from '@glimmer/runtime'; +import { setInternalComponentManager } from '@glimmer/manager'; import InternalManager from '../component-managers/internal'; import InternalComponent from './internal'; @@ -117,6 +117,6 @@ export default class Input extends InternalComponent { } } -setComponentManager(InternalManager.for('input'), Input); +setInternalComponentManager(InternalManager.for('input'), Input); Input.toString = () => '@ember/component/input'; diff --git a/packages/@ember/-internals/glimmer/lib/components/link-to.ts b/packages/@ember/-internals/glimmer/lib/components/link-to.ts index b3442b0473a..1ca712aac1c 100644 --- a/packages/@ember/-internals/glimmer/lib/components/link-to.ts +++ b/packages/@ember/-internals/glimmer/lib/components/link-to.ts @@ -11,7 +11,8 @@ import { EngineInstance, getEngineParent } from '@ember/engine'; import { flaggedInstrument } from '@ember/instrumentation'; import { inject as injectService } from '@ember/service'; import { DEBUG } from '@glimmer/env'; -import EmberComponent, { HAS_BLOCK } from '../component'; +import EmberComponent from '../component'; +import { HAS_BLOCK } from '../component-managers/curly'; import layout from '../templates/link-to'; /** diff --git a/packages/@ember/-internals/glimmer/lib/helper.ts b/packages/@ember/-internals/glimmer/lib/helper.ts index a35978fefa6..215aa20882f 100644 --- a/packages/@ember/-internals/glimmer/lib/helper.ts +++ b/packages/@ember/-internals/glimmer/lib/helper.ts @@ -8,15 +8,13 @@ import { getDebugName, symbol } from '@ember/-internals/utils'; import { join } from '@ember/runloop'; import { DEBUG } from '@glimmer/env'; import { Arguments, Dict, HelperManager } from '@glimmer/interfaces'; -import { setHelperManager } from '@glimmer/runtime'; -import { _WeakSet as WeakSet } from '@glimmer/util'; +import { helperCapabilities, setHelperManager } from '@glimmer/manager'; import { consumeTag, createTag, deprecateMutationsInTrackingTransaction, dirtyTag, } from '@glimmer/validator'; -import { helperCapabilities } from './helpers/custom'; export const RECOMPUTE_TAG = symbol('RECOMPUTE_TAG'); @@ -39,12 +37,6 @@ export interface SimpleHelper { compute: HelperFunction; } -const CLASSIC_HELPER_MANAGERS = new WeakSet(); - -export function isClassicHelperManager(obj: object) { - return CLASSIC_HELPER_MANAGERS.has(obj); -} - /** Ember Helpers are functions that can compute values, and are used in templates. For example, this code calls a helper named `format-currency`: @@ -139,7 +131,14 @@ let Helper = FrameworkObject.extend({ */ }); +const IS_CLASSIC_HELPER = symbol('IS_CLASSIC_HELPER'); + Helper.isHelperFactory = true; +Helper[IS_CLASSIC_HELPER] = true; + +export function isClassicHelper(obj: object): boolean { + return obj[IS_CLASSIC_HELPER] === true; +} interface ClassicHelperStateBucket { instance: HelperInstance; @@ -155,13 +154,12 @@ class ClassicHelperManager implements HelperManager { private ownerInjection: object; constructor(owner: Owner | undefined) { - CLASSIC_HELPER_MANAGERS.add(this); let ownerInjection = {}; setOwner(ownerInjection, owner!); this.ownerInjection = ownerInjection; } - createHelper(definition: ClassHelperFactory | typeof Helper, args: Arguments) { + createHelper(definition: typeof Helper, args: Arguments) { let instance = definition.class === undefined ? definition.create(this.ownerInjection) : definition.create(); @@ -197,7 +195,11 @@ class ClassicHelperManager implements HelperManager { } } -setHelperManager((owner: Owner | undefined) => new ClassicHelperManager(owner), Helper); +export const CLASSIC_HELPER_MANAGER_FACTORY = (owner: Owner | undefined): ClassicHelperManager => { + return new ClassicHelperManager(owner); +}; + +setHelperManager(CLASSIC_HELPER_MANAGER_FACTORY, Helper); /////////// diff --git a/packages/@ember/-internals/glimmer/lib/helpers/-assert-implicit-component-helper-argument.ts b/packages/@ember/-internals/glimmer/lib/helpers/-assert-implicit-component-helper-argument.ts index ad86606eb6e..b7879daa2c5 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/-assert-implicit-component-helper-argument.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/-assert-implicit-component-helper-argument.ts @@ -2,6 +2,7 @@ import { assert } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; import { Helper, VMArguments } from '@glimmer/interfaces'; import { createComputeRef, valueForRef } from '@glimmer/reference'; +import { internalHelper } from './internal-helper'; let helper: Helper; @@ -22,4 +23,4 @@ if (DEBUG) { helper = (args: VMArguments) => args.positional.at(0); } -export default helper; +export default internalHelper(helper); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/-in-element-null-check.ts b/packages/@ember/-internals/glimmer/lib/helpers/-in-element-null-check.ts index 111c8099a71..97cd913abe3 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/-in-element-null-check.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/-in-element-null-check.ts @@ -2,6 +2,7 @@ import { assert } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; import { Helper, VMArguments } from '@glimmer/interfaces'; import { createComputeRef, valueForRef } from '@glimmer/reference'; +import { internalHelper } from './internal-helper'; let helper: Helper; @@ -24,4 +25,4 @@ if (DEBUG) { helper = (args: VMArguments) => args.positional.at(0); } -export default helper; +export default internalHelper(helper); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/-normalize-class.ts b/packages/@ember/-internals/glimmer/lib/helpers/-normalize-class.ts index 0aa1bde5a6b..940524cf7fb 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/-normalize-class.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/-normalize-class.ts @@ -1,8 +1,9 @@ import { dasherize } from '@ember/string'; import { VMArguments } from '@glimmer/interfaces'; import { createComputeRef, valueForRef } from '@glimmer/reference'; +import { internalHelper } from './internal-helper'; -export default function (args: VMArguments) { +export default internalHelper((args: VMArguments) => { let positional = args.positional.capture(); return createComputeRef(() => { @@ -18,4 +19,4 @@ export default function (args: VMArguments) { return String(value); } }); -} +}); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/-track-array.ts b/packages/@ember/-internals/glimmer/lib/helpers/-track-array.ts index 04c444ca6c1..f91c576259b 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/-track-array.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/-track-array.ts @@ -6,13 +6,14 @@ import { isObject } from '@ember/-internals/utils'; import { VMArguments } from '@glimmer/interfaces'; import { createComputeRef, valueForRef } from '@glimmer/reference'; import { consumeTag } from '@glimmer/validator'; +import { internalHelper } from './internal-helper'; /** This reference is used to get the `[]` tag of iterables, so we can trigger updates to `{{each}}` when it changes. It is put into place by a template transform at build time, similar to the (-each-in) helper */ -export default function trackArray(args: VMArguments) { +export default internalHelper((args: VMArguments) => { let inner = args.positional.at(0); return createComputeRef(() => { @@ -24,4 +25,4 @@ export default function trackArray(args: VMArguments) { return iterable; }); -} +}); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/action.ts b/packages/@ember/-internals/glimmer/lib/helpers/action.ts index 5f7aa791e94..d5e9d59a248 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/action.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/action.ts @@ -16,6 +16,7 @@ import { valueForRef, } from '@glimmer/reference'; import { _WeakSet } from '@glimmer/util'; +import { internalHelper } from './internal-helper'; export const ACTIONS = new _WeakSet(); export const INVOKE: unique symbol = symbol('INVOKE') as any; @@ -283,40 +284,48 @@ export const INVOKE: unique symbol = symbol('INVOKE') as any; @for Ember.Templates.helpers @public */ -export default function (args: VMArguments): Reference { - let { named, positional } = args; +export default internalHelper( + (args: VMArguments): Reference => { + let { named, positional } = args; - let capturedArgs = positional.capture(); + let capturedArgs = positional.capture(); - // The first two argument slots are reserved. - // pos[0] is the context (or `this`) - // pos[1] is the action name or function - // Anything else is an action argument. - let [context, action, ...restArgs] = capturedArgs; + // The first two argument slots are reserved. + // pos[0] is the context (or `this`) + // pos[1] is the action name or function + // Anything else is an action argument. + let [context, action, ...restArgs] = capturedArgs; - let debugKey: string = action.debugLabel!; + let debugKey: string = action.debugLabel!; - let target = named.has('target') ? named.get('target') : context; - let processArgs = makeArgsProcessor(named.has('value') && named.get('value'), restArgs); + let target = named.has('target') ? named.get('target') : context; + let processArgs = makeArgsProcessor(named.has('value') && named.get('value'), restArgs); - let fn: Function; + let fn: Function; - if (isInvokableRef(action)) { - fn = makeClosureAction(action, action as MaybeActionHandler, invokeRef, processArgs, debugKey); - } else { - fn = makeDynamicClosureAction( - valueForRef(context) as object, - target, - action, - processArgs, - debugKey - ); - } + if (isInvokableRef(action)) { + fn = makeClosureAction( + action, + action as MaybeActionHandler, + invokeRef, + processArgs, + debugKey + ); + } else { + fn = makeDynamicClosureAction( + valueForRef(context) as object, + target, + action, + processArgs, + debugKey + ); + } - ACTIONS.add(fn); + ACTIONS.add(fn); - return createUnboundRef(fn, '(result of an `action` helper)'); -} + return createUnboundRef(fn, '(result of an `action` helper)'); + } +); function NOOP(args: unknown[]) { return args; diff --git a/packages/@ember/-internals/glimmer/lib/helpers/array.ts b/packages/@ember/-internals/glimmer/lib/helpers/array.ts index 80a1cc6e57e..1805777fb7d 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/array.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/array.ts @@ -1,6 +1,7 @@ import { VMArguments } from '@glimmer/interfaces'; import { createComputeRef, Reference } from '@glimmer/reference'; import { reifyPositional } from '@glimmer/runtime'; +import { internalHelper } from './internal-helper'; /** @module ember @@ -42,8 +43,10 @@ import { reifyPositional } from '@glimmer/runtime'; @public */ -export default function (args: VMArguments): Reference { - let captured = args.positional.capture(); +export default internalHelper( + (args: VMArguments): Reference => { + let captured = args.positional.capture(); - return createComputeRef(() => reifyPositional(captured), null, 'array'); -} + return createComputeRef(() => reifyPositional(captured), null, 'array'); + } +); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/concat.ts b/packages/@ember/-internals/glimmer/lib/helpers/concat.ts index e21cfe8c25b..7af9ef8b5c3 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/concat.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/concat.ts @@ -1,12 +1,13 @@ import { VMArguments } from '@glimmer/interfaces'; import { createComputeRef } from '@glimmer/reference'; import { reifyPositional } from '@glimmer/runtime'; +import { internalHelper } from './internal-helper'; -const isEmpty = (value: any): boolean => { - return value === null || value === undefined || typeof value.toString !== 'function'; +const isEmpty = (value: unknown): boolean => { + return value === null || value === undefined || typeof (value as object).toString !== 'function'; }; -const normalizeTextValue = (value: any): string => { +const normalizeTextValue = (value: unknown): string => { if (isEmpty(value)) { return ''; } @@ -39,7 +40,7 @@ const normalizeTextValue = (value: any): string => { @for Ember.Templates.helpers @since 1.13.0 */ -export default function (args: VMArguments) { +export default internalHelper((args: VMArguments) => { let captured = args.positional.capture(); return createComputeRef( @@ -47,4 +48,4 @@ export default function (args: VMArguments) { null, 'concat' ); -} +}); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/each-in.ts b/packages/@ember/-internals/glimmer/lib/helpers/each-in.ts index 98505a89cb0..64143fa99c4 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/each-in.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/each-in.ts @@ -7,6 +7,7 @@ import { isProxy } from '@ember/-internals/utils'; import { VMArguments } from '@glimmer/interfaces'; import { createComputeRef, valueForRef } from '@glimmer/reference'; import { consumeTag } from '@glimmer/validator'; +import { internalHelper } from './internal-helper'; /** The `{{#each}}` helper loops over elements in a collection. It is an extension @@ -158,7 +159,7 @@ export class EachInWrapper { constructor(public inner: unknown) {} } -export default function (args: VMArguments) { +export default internalHelper((args: VMArguments) => { let inner = args.positional.at(0); return createComputeRef(() => { @@ -174,4 +175,4 @@ export default function (args: VMArguments) { return new EachInWrapper(iterable); }); -} +}); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/fn.ts b/packages/@ember/-internals/glimmer/lib/helpers/fn.ts index 7c4dca12077..46a67a70f94 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/fn.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/fn.ts @@ -10,6 +10,7 @@ import { } from '@glimmer/reference'; import { reifyPositional } from '@glimmer/runtime'; import buildUntouchableThis from '../utils/untouchable-this'; +import { internalHelper } from './internal-helper'; const context = buildUntouchableThis('`fn` helper'); @@ -84,7 +85,7 @@ const context = buildUntouchableThis('`fn` helper'); @public @since 3.11.0 */ -export default function (args: VMArguments) { +export default internalHelper((args: VMArguments) => { let positional = args.positional.capture(); let callbackRef = positional[0]; @@ -108,7 +109,7 @@ export default function (args: VMArguments) { null, 'fn' ); -} +}); function assertCallbackIsFn(callbackRef: Reference) { assert( diff --git a/packages/@ember/-internals/glimmer/lib/helpers/get.ts b/packages/@ember/-internals/glimmer/lib/helpers/get.ts index 163533acc96..26131c7cfd3 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/get.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/get.ts @@ -9,6 +9,7 @@ import { NULL_REFERENCE, valueForRef, } from '@glimmer/reference'; +import { internalHelper } from './internal-helper'; /** @module ember @@ -94,7 +95,7 @@ import { @for Ember.Templates.helpers @since 2.1.0 */ -export default function (args: VMArguments) { +export default internalHelper((args: VMArguments) => { let sourceRef = args.positional.at(0); let pathRef = args.positional.at(1); @@ -130,4 +131,4 @@ export default function (args: VMArguments) { 'get' ); } -} +}); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/hash.ts b/packages/@ember/-internals/glimmer/lib/helpers/hash.ts index 1ce8fbb6893..2de7eecc059 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/hash.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/hash.ts @@ -1,6 +1,7 @@ import { Dict, VMArguments } from '@glimmer/interfaces'; import { createComputeRef, Reference } from '@glimmer/reference'; import { reifyNamed } from '@glimmer/runtime'; +import { internalHelper } from './internal-helper'; /** @module ember @@ -44,8 +45,10 @@ import { reifyNamed } from '@glimmer/runtime'; @since 2.3.0 @public */ -export default function (args: VMArguments): Reference> { - let positional = args.named.capture(); +export default internalHelper( + (args: VMArguments): Reference> => { + let positional = args.named.capture(); - return createComputeRef(() => reifyNamed(positional), null, 'hash'); -} + return createComputeRef(() => reifyNamed(positional), null, 'hash'); + } +); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/if-unless.ts b/packages/@ember/-internals/glimmer/lib/helpers/if-unless.ts index 70ddb97980a..47ac572ffc9 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/if-unless.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/if-unless.ts @@ -6,6 +6,7 @@ import { assert } from '@ember/debug'; import { toBool } from '@glimmer/global-context'; import { VMArguments } from '@glimmer/interfaces'; import { createComputeRef, valueForRef } from '@glimmer/reference'; +import { internalHelper } from './internal-helper'; /** The `if` helper allows you to conditionally render one of two branches, @@ -98,7 +99,7 @@ import { createComputeRef, valueForRef } from '@glimmer/reference'; @for Ember.Templates.helpers @public */ -export function inlineIf(args: VMArguments) { +export const inlineIf = internalHelper((args: VMArguments) => { let positional = args.positional.capture(); return createComputeRef( @@ -119,7 +120,7 @@ export function inlineIf(args: VMArguments) { null, 'if' ); -} +}); /** The `unless` helper is the inverse of the `if` helper. It displays if a value @@ -206,7 +207,7 @@ export function inlineIf(args: VMArguments) { @for Ember.Templates.helpers @public */ -export function inlineUnless(args: VMArguments) { +export const inlineUnless = internalHelper((args: VMArguments) => { let positional = args.positional.capture(); return createComputeRef( @@ -227,4 +228,4 @@ export function inlineUnless(args: VMArguments) { null, 'unless' ); -} +}); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/internal-helper.ts b/packages/@ember/-internals/glimmer/lib/helpers/internal-helper.ts new file mode 100644 index 00000000000..1152a6bf541 --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/helpers/internal-helper.ts @@ -0,0 +1,6 @@ +import { Helper, HelperDefinitionState } from '@glimmer/interfaces'; +import { setInternalHelperManager } from '@glimmer/manager'; + +export function internalHelper(helper: Helper): HelperDefinitionState { + return setInternalHelperManager(() => helper, {}); +} diff --git a/packages/@ember/-internals/glimmer/lib/helpers/log.ts b/packages/@ember/-internals/glimmer/lib/helpers/log.ts index 3e3cf2a2031..758b298be2c 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/log.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/log.ts @@ -1,6 +1,7 @@ import { VMArguments } from '@glimmer/interfaces'; import { createComputeRef } from '@glimmer/reference'; import { reifyPositional } from '@glimmer/runtime'; +import { internalHelper } from './internal-helper'; /** @module ember @@ -19,7 +20,7 @@ import { reifyPositional } from '@glimmer/runtime'; @param {Array} params @public */ -export default function (args: VMArguments) { +export default internalHelper((args: VMArguments) => { let positional = args.positional.capture(); return createComputeRef(() => { @@ -27,4 +28,4 @@ export default function (args: VMArguments) { console.log(...reifyPositional(positional)); /* eslint-enable no-console */ }); -} +}); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/mut.ts b/packages/@ember/-internals/glimmer/lib/helpers/mut.ts index 63dd959b60b..b7c7c2a9fee 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/mut.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/mut.ts @@ -4,6 +4,7 @@ import { assert } from '@ember/debug'; import { VMArguments } from '@glimmer/interfaces'; import { createInvokableRef, isUpdatableRef } from '@glimmer/reference'; +import { internalHelper } from './internal-helper'; /** The `mut` helper lets you __clearly specify__ that a child `Component` can update the @@ -79,7 +80,7 @@ import { createInvokableRef, isUpdatableRef } from '@glimmer/reference'; @public */ -export default function (args: VMArguments) { +export default internalHelper((args: VMArguments) => { let ref = args.positional.at(0); // TODO: Improve this error message. This covers at least two distinct @@ -97,4 +98,4 @@ export default function (args: VMArguments) { assert('You can only pass a path to mut', isUpdatableRef(ref)); return createInvokableRef(ref); -} +}); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/query-param.ts b/packages/@ember/-internals/glimmer/lib/helpers/query-param.ts index 291c8c935be..a13b7efee16 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/query-param.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/query-param.ts @@ -7,6 +7,7 @@ import { assign } from '@ember/polyfills'; import { VMArguments } from '@glimmer/interfaces'; import { createComputeRef } from '@glimmer/reference'; import { reifyNamed } from '@glimmer/runtime'; +import { internalHelper } from './internal-helper'; /** This is a helper to be used in conjunction with the link-to helper. @@ -29,7 +30,7 @@ import { reifyNamed } from '@glimmer/runtime'; @return {Object} A `QueryParams` object for `{{link-to}}` @public */ -export default function (args: VMArguments) { +export default internalHelper((args: VMArguments) => { let { positional, named } = args.capture(); return createComputeRef(() => { @@ -40,4 +41,4 @@ export default function (args: VMArguments) { return new QueryParams(assign({}, reifyNamed(named) as any)); }); -} +}); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/readonly.ts b/packages/@ember/-internals/glimmer/lib/helpers/readonly.ts index 85229007796..f2f6b53b333 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/readonly.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/readonly.ts @@ -3,6 +3,7 @@ */ import { VMArguments } from '@glimmer/interfaces'; import { createReadOnlyRef } from '@glimmer/reference'; +import { internalHelper } from './internal-helper'; /** The `readonly` helper let's you specify that a binding is one-way only, @@ -119,6 +120,6 @@ import { createReadOnlyRef } from '@glimmer/reference'; @for Ember.Templates.helpers @private */ -export default function (args: VMArguments) { +export default internalHelper((args: VMArguments) => { return createReadOnlyRef(args.positional.at(0)); -} +}); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/unbound.ts b/packages/@ember/-internals/glimmer/lib/helpers/unbound.ts index b02e4959feb..474c39b1f00 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/unbound.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/unbound.ts @@ -5,6 +5,7 @@ import { assert } from '@ember/debug'; import { VMArguments } from '@glimmer/interfaces'; import { createUnboundRef, valueForRef } from '@glimmer/reference'; +import { internalHelper } from './internal-helper'; /** The `{{unbound}}` helper disconnects the one-way binding of a property, @@ -34,11 +35,11 @@ import { createUnboundRef, valueForRef } from '@glimmer/reference'; @public */ -export default function (args: VMArguments) { +export default internalHelper((args: VMArguments) => { assert( 'unbound helper cannot be called with multiple params or hash params', args.positional.length === 1 && args.named.length === 0 ); return createUnboundRef(valueForRef(args.positional.at(0)), '(resurt of an `unbound` helper)'); -} +}); diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts index 81fb377262c..dfb67e406d2 100644 --- a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts +++ b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts @@ -3,6 +3,7 @@ import { ActionManager, isSimpleClick } from '@ember/-internals/views'; import { assert, deprecate } from '@ember/debug'; import { flaggedInstrument } from '@ember/instrumentation'; import { join } from '@ember/runloop'; +import { registerDestructor } from '@glimmer/destroyable'; import { DEBUG } from '@glimmer/env'; import { CapturedNamedArguments, @@ -12,8 +13,8 @@ import { InternalModifierManager, VMArguments, } from '@glimmer/interfaces'; +import { setInternalModifierManager } from '@glimmer/manager'; import { isInvokableRef, updateRef, valueForRef } from '@glimmer/reference'; -import { registerDestructor } from '@glimmer/runtime'; import { createUpdatableTag, UpdatableTag } from '@glimmer/validator'; import { SimpleElement } from '@simple-dom/interface'; import { INVOKE } from '../helpers/action'; @@ -201,12 +202,10 @@ export class ActionState { } } -// implements ModifierManager -export default class ActionModifierManager - implements InternalModifierManager { +class ActionModifierManager implements InternalModifierManager { create( element: SimpleElement, - _state: unknown, + _state: object, args: VMArguments, _dynamicScope: DynamicScope, dom: GlimmerTreeChanges @@ -310,3 +309,7 @@ export default class ActionModifierManager return actionState; } } + +const ACTION_MODIFIER_MANAGER = new ActionModifierManager(); + +export default setInternalModifierManager(() => ACTION_MODIFIER_MANAGER, {}); diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/custom.ts b/packages/@ember/-internals/glimmer/lib/modifiers/custom.ts deleted file mode 100644 index 9ba2a1154e1..00000000000 --- a/packages/@ember/-internals/glimmer/lib/modifiers/custom.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { Factory } from '@ember/-internals/owner'; -import { assert } from '@ember/debug'; -import { DEBUG } from '@glimmer/env'; -import { - Arguments, - InternalModifierManager, - ModifierCapabilities, - ModifierCapabilitiesVersions, - ModifierManager, - VMArguments, -} from '@glimmer/interfaces'; -import { buildCapabilities, registerDestructor, reifyArgs } from '@glimmer/runtime'; -import { - createUpdatableTag, - deprecateMutationsInTrackingTransaction, - untrack, - UpdatableTag, -} from '@glimmer/validator'; -import { SimpleElement } from '@simple-dom/interface'; -import { argsProxyFor } from '../utils/args-proxy'; - -export interface CustomModifierDefinitionState { - ModifierClass: Factory; - name: string; - delegate: ModifierManager; -} - -export function capabilities( - managerAPI: Version, - optionalFeatures: ModifierCapabilitiesVersions[Version] = {} -): ModifierCapabilities { - assert( - 'Invalid modifier manager compatibility specified', - managerAPI === '3.13' || managerAPI === '3.22' - ); - - return buildCapabilities({ - disableAutoTracking: Boolean(optionalFeatures.disableAutoTracking), - useArgsProxy: managerAPI === '3.13' ? false : true, - passFactoryToCreate: managerAPI === '3.13', - }); -} - -export class CustomModifierDefinition { - public state: CustomModifierDefinitionState; - public manager: InternalModifierManager< - unknown | null, - CustomModifierDefinitionState - >; - - constructor( - public name: string, - public ModifierClass: Factory, - public delegate: ModifierManager, - isInteractive: boolean - ) { - this.state = { - ModifierClass, - name, - delegate, - }; - - this.manager = isInteractive - ? CUSTOM_INTERACTIVE_MODIFIER_MANAGER - : CUSTOM_NON_INTERACTIVE_MODIFIER_MANAGER; - } -} - -export interface CustomModifierState { - tag: UpdatableTag; - element: SimpleElement; - delegate: ModifierManager; - modifier: ModifierInstance; - args: Arguments; - debugName?: string; -} - -/** - The CustomModifierManager allows addons to provide custom modifier - implementations that integrate seamlessly into Ember. This is accomplished - through a delegate, registered with the custom modifier manager, which - implements a set of hooks that determine modifier behavior. - To create a custom modifier manager, instantiate a new CustomModifierManager - class and pass the delegate as the first argument: - - ```js - let manager = new CustomModifierManager({ - // ...delegate implementation... - }); - ``` - - ## Delegate Hooks - - Throughout the lifecycle of a modifier, the modifier manager will invoke - delegate hooks that are responsible for surfacing those lifecycle changes to - the end developer. - * `createModifier()` - invoked when a new instance of a modifier should be created - * `installModifier()` - invoked when the modifier is installed on the element - * `updateModifier()` - invoked when the arguments passed to a modifier change - * `destroyModifier()` - invoked when the modifier is about to be destroyed -*/ -class InteractiveCustomModifierManager - implements - InternalModifierManager< - CustomModifierState, - CustomModifierDefinitionState - > { - create( - element: SimpleElement, - definition: CustomModifierDefinitionState, - vmArgs: VMArguments - ) { - let { delegate, ModifierClass } = definition; - let capturedArgs = vmArgs.capture(); - - let { useArgsProxy, passFactoryToCreate } = delegate.capabilities; - - let args = useArgsProxy ? argsProxyFor(capturedArgs, 'modifier') : reifyArgs(capturedArgs); - - let instance: ModifierInstance; - - if (DEBUG && deprecateMutationsInTrackingTransaction !== undefined) { - deprecateMutationsInTrackingTransaction(() => { - instance = delegate.createModifier( - passFactoryToCreate ? ModifierClass : ModifierClass.class, - args - ); - }); - } else { - instance = delegate.createModifier( - passFactoryToCreate ? ModifierClass : ModifierClass.class, - args - ); - } - - let tag = createUpdatableTag(); - let state: CustomModifierState; - if (useArgsProxy) { - state = { - tag, - element, - delegate, - args, - modifier: instance!, - }; - } else { - state = { - tag, - element, - delegate, - modifier: instance!, - get args() { - return reifyArgs(capturedArgs); - }, - }; - } - - if (DEBUG) { - state.debugName = definition.name; - } - - registerDestructor(state, () => delegate.destroyModifier(instance, state.args)); - - return state; - } - - getDebugName({ debugName }: CustomModifierState) { - return debugName!; - } - - getTag({ tag }: CustomModifierState) { - return tag; - } - - install(state: CustomModifierState) { - let { element, args, delegate, modifier } = state; - - let { capabilities } = delegate; - - if (capabilities.disableAutoTracking === true) { - untrack(() => delegate.installModifier(modifier, element, args)); - } else { - delegate.installModifier(modifier, element, args); - } - } - - update(state: CustomModifierState) { - let { args, delegate, modifier } = state; - let { capabilities } = delegate; - - if (capabilities.disableAutoTracking === true) { - untrack(() => delegate.updateModifier(modifier, args)); - } else { - delegate.updateModifier(modifier, args); - } - } - - getDestroyable(state: CustomModifierState) { - return state; - } -} - -class NonInteractiveCustomModifierManager - implements InternalModifierManager> { - create() { - return null; - } - - getDebugName() { - return ''; - } - - getTag() { - return null; - } - - install() {} - - update() {} - - getDestroyable() { - return null; - } -} - -const CUSTOM_INTERACTIVE_MODIFIER_MANAGER = new InteractiveCustomModifierManager(); -const CUSTOM_NON_INTERACTIVE_MODIFIER_MANAGER = new NonInteractiveCustomModifierManager(); diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/internal.ts b/packages/@ember/-internals/glimmer/lib/modifiers/internal.ts index 7c8e7928583..0fcdbcd83b6 100644 --- a/packages/@ember/-internals/glimmer/lib/modifiers/internal.ts +++ b/packages/@ember/-internals/glimmer/lib/modifiers/internal.ts @@ -1,14 +1,15 @@ import { Owner, setOwner } from '@ember/-internals/owner'; import { guidFor } from '@ember/-internals/utils'; import { assert } from '@ember/debug'; +import { registerDestructor } from '@glimmer/destroyable'; import { CapturedArguments, Destroyable, InternalModifierManager as ModifierManager, VMArguments, } from '@glimmer/interfaces'; +import { setInternalModifierManager } from '@glimmer/manager'; import { valueForRef } from '@glimmer/reference'; -import { registerDestructor, setModifierManager } from '@glimmer/runtime'; import { SimpleElement } from '@simple-dom/interface'; export default class InternalModifier { @@ -86,7 +87,7 @@ class InternalModifierManager return null; } - getDebugName({ name }: InternalModifierState): string { + getDebugName({ name }: typeof InternalModifier): string { return name; } @@ -104,4 +105,4 @@ class InternalModifierManager } } -setModifierManager((owner: Owner) => new InternalModifierManager(owner), InternalModifier); +setInternalModifierManager((owner: Owner) => new InternalModifierManager(owner), InternalModifier); diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/on.ts b/packages/@ember/-internals/glimmer/lib/modifiers/on.ts index 596d01be855..aaee250600d 100644 --- a/packages/@ember/-internals/glimmer/lib/modifiers/on.ts +++ b/packages/@ember/-internals/glimmer/lib/modifiers/on.ts @@ -1,9 +1,10 @@ -import { Owner } from '@ember/-internals/owner'; import { assert } from '@ember/debug'; +import { registerDestructor } from '@glimmer/destroyable'; import { DEBUG } from '@glimmer/env'; import { CapturedArguments, InternalModifierManager, VMArguments } from '@glimmer/interfaces'; +import { setInternalModifierManager } from '@glimmer/manager'; import { valueForRef } from '@glimmer/reference'; -import { registerDestructor, reifyNamed } from '@glimmer/runtime'; +import { reifyNamed } from '@glimmer/runtime'; import { createUpdatableTag, UpdatableTag } from '@glimmer/validator'; import { SimpleElement } from '@simple-dom/interface'; import buildUntouchableThis from '../utils/untouchable-this'; @@ -51,7 +52,6 @@ const SUPPORTS_EVENT_OPTIONS = (() => { export class OnModifierState { public tag = createUpdatableTag(); - public owner: Owner; public element: Element; public args: CapturedArguments; public eventName!: string; @@ -63,8 +63,7 @@ export class OnModifierState { public options?: AddEventListenerOptions; public shouldUpdate = true; - constructor(owner: Owner, element: Element, args: CapturedArguments) { - this.owner = owner; + constructor(element: Element, args: CapturedArguments) { this.element = element; this.args = args; } @@ -311,16 +310,8 @@ function addEventListener( @public @since 3.11.0 */ -export default class OnModifierManager - implements InternalModifierManager { +class OnModifierManager implements InternalModifierManager { public SUPPORTS_EVENT_OPTIONS: boolean = SUPPORTS_EVENT_OPTIONS; - public isInteractive: boolean; - private owner: Owner; - - constructor(owner: Owner, isInteractive: boolean) { - this.isInteractive = isInteractive; - this.owner = owner; - } getDebugName(): string { return 'on'; @@ -332,16 +323,12 @@ export default class OnModifierManager create( element: SimpleElement | Element, - _state: unknown, + _state: object, args: VMArguments ): OnModifierState | null { - if (!this.isInteractive) { - return null; - } - const capturedArgs = args.capture(); - return new OnModifierState(this.owner, element, capturedArgs); + return new OnModifierState(element, capturedArgs); } getTag(state: OnModifierState | null): UpdatableTag | null { @@ -395,3 +382,11 @@ export default class OnModifierManager return state; } } + +const ON_MODIFIER_MANAGER = new OnModifierManager(); + +const on = {}; + +setInternalModifierManager(() => ON_MODIFIER_MANAGER, on); + +export default on; diff --git a/packages/@ember/-internals/glimmer/lib/renderer.ts b/packages/@ember/-internals/glimmer/lib/renderer.ts index 3d59fcafc18..672876cae14 100644 --- a/packages/@ember/-internals/glimmer/lib/renderer.ts +++ b/packages/@ember/-internals/glimmer/lib/renderer.ts @@ -3,6 +3,7 @@ import { getOwner, Owner } from '@ember/-internals/owner'; import { getViewElement, getViewId } from '@ember/-internals/views'; import { assert } from '@ember/debug'; import { backburner, getCurrentRunLoop } from '@ember/runloop'; +import { destroy } from '@glimmer/destroyable'; import { DEBUG } from '@glimmer/env'; import { Bounds, @@ -25,7 +26,6 @@ import { clientBuilder, CurriedComponentDefinition, curry, - destroy, DOMChanges, DOMTreeConstruction, inTransaction, @@ -36,13 +36,12 @@ import { unwrapTemplate } from '@glimmer/util'; import { CURRENT_TAG, validateTag, valueForTag } from '@glimmer/validator'; import { SimpleDocument, SimpleElement, SimpleNode } from '@simple-dom/interface'; import RSVP from 'rsvp'; -import CompileTimeResolverImpl from './compile-time-lookup'; -import { BOUNDS } from './component'; +import { BOUNDS } from './component-managers/curly'; import { createRootOutlet } from './component-managers/outlet'; import { RootComponentDefinition } from './component-managers/root'; import { NodeDOMTreeConstruction } from './dom'; import { EmberEnvironmentDelegate } from './environment'; -import RuntimeResolver from './resolver'; +import ResolverImpl from './resolver'; import { Component } from './utils/curly-component-state-bucket'; import { OutletState } from './utils/outlet'; import OutletView from './views/outlet'; @@ -285,7 +284,7 @@ export abstract class Renderer { private _lastRevision = -1; private _destroyed = false; - readonly _runtimeResolver: RuntimeResolver; + readonly _runtimeResolver: ResolverImpl; constructor( owner: Owner, @@ -304,12 +303,11 @@ export abstract class Renderer { this._builder = builder; // resolver is exposed for tests - let runtimeResolver = (this._runtimeResolver = new RuntimeResolver(owner, env.isInteractive)); - let compileTimeResolver = new CompileTimeResolverImpl(runtimeResolver); + let resolver = (this._runtimeResolver = new ResolverImpl()); let sharedArtifacts = artifacts(); - this._context = programCompilationContext(sharedArtifacts, compileTimeResolver); + this._context = programCompilationContext(sharedArtifacts, resolver); let runtimeEnvironmentDelegate = new EmberEnvironmentDelegate(owner, env.isInteractive); this._runtime = runtimeContext( @@ -321,7 +319,7 @@ export abstract class Renderer { }, runtimeEnvironmentDelegate, sharedArtifacts, - runtimeResolver + resolver ); } @@ -333,19 +331,19 @@ export abstract class Renderer { debugRenderTree ); - return debugRenderTree!; + return debugRenderTree; } // renderer HOOKS - appendOutletView(view: OutletView, target: SimpleElement) { + appendOutletView(view: OutletView, target: SimpleElement): void { let definition = createRootOutlet(view); - this._appendDefinition(view, curry(definition), target); + this._appendDefinition(view, curry(definition, null), target); } - appendTo(view: Component, target: SimpleElement) { + appendTo(view: Component, target: SimpleElement): void { let definition = new RootComponentDefinition(view); - this._appendDefinition(view, curry(definition), target); + this._appendDefinition(view, curry(definition, null), target); } _appendDefinition( diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index 4ca1d316245..a5a54a9663f 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -1,43 +1,40 @@ import { privatize as P } from '@ember/-internals/container'; import { ENV } from '@ember/-internals/environment'; import { Factory, FactoryClass, LookupOptions, Owner } from '@ember/-internals/owner'; -import { EMBER_GLIMMER_HELPER_MANAGER } from '@ember/canary-features'; -import { isTemplateOnlyComponent } from '@ember/component/template-only'; import { assert, deprecate } from '@ember/debug'; import { PARTIALS } from '@ember/deprecated-features'; import EmberError from '@ember/error'; import { _instrumentStart } from '@ember/instrumentation'; +import { DEBUG } from '@glimmer/env'; import { - ComponentDefinition, - Helper, + CompileTimeResolver, + HelperDefinitionState, + ModifierDefinitionState, Option, PartialDefinition, + ResolvedComponentDefinition, RuntimeResolver, Template, TemplateFactory, } from '@glimmer/interfaces'; -import { PartialDefinitionImpl } from '@glimmer/opcode-compiler'; import { - getComponentManager, getComponentTemplate, + getInternalComponentManager, + setInternalHelperManager, +} from '@glimmer/manager'; +import { PartialDefinitionImpl } from '@glimmer/opcode-compiler'; +import { getDynamicVar, - getHelperManager, - getModifierManager, - isInternalComponentManager, - isInternalHelper, - isInternalModifierManager, - ModifierDefinition, + TEMPLATE_ONLY_COMPONENT_MANAGER, + templateOnlyComponent, } from '@glimmer/runtime'; -import { CurlyComponentDefinition } from './component-managers/curly'; -import { CustomManagerDefinition } from './component-managers/custom'; -import { InternalComponentDefinition } from './component-managers/internal'; -import { TemplateOnlyComponentDefinition } from './component-managers/template-only'; -import InternalComponent from './components/internal'; +import { _WeakSet } from '@glimmer/util'; +import { CURLY_COMPONENT_MANAGER } from './component-managers/curly'; import { + CLASSIC_HELPER_MANAGER_FACTORY, HelperFactory, HelperInstance, - isClassicHelperManager, - SIMPLE_CLASSIC_HELPER_MANAGER, + isClassicHelper, SimpleHelper, } from './helper'; import { default as componentAssertionHelper } from './helpers/-assert-implicit-component-helper-argument'; @@ -47,20 +44,19 @@ import { default as trackArray } from './helpers/-track-array'; import { default as action } from './helpers/action'; import { default as array } from './helpers/array'; import { default as concat } from './helpers/concat'; -import customHelper from './helpers/custom'; import { default as eachIn } from './helpers/each-in'; import { default as fn } from './helpers/fn'; import { default as get } from './helpers/get'; import { default as hash } from './helpers/hash'; import { inlineIf, inlineUnless } from './helpers/if-unless'; +import { internalHelper } from './helpers/internal-helper'; import { default as log } from './helpers/log'; import { default as mut } from './helpers/mut'; 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 OnModifierManager from './modifiers/on'; +import actionModifier from './modifiers/action'; +import onModifier from './modifiers/on'; import { mountHelper } from './syntax/mount'; import { outletHelper } from './syntax/outlet'; @@ -181,11 +177,7 @@ if (PARTIALS) { }; } -interface IBuiltInHelpers { - [name: string]: Helper | undefined; -} - -const BUILTINS_HELPERS: IBuiltInHelpers = { +const BUILTINS_HELPERS = { if: inlineIf, action, array, @@ -203,218 +195,99 @@ const BUILTINS_HELPERS: IBuiltInHelpers = { '-each-in': eachIn, '-normalize-class': normalizeClassHelper, '-track-array': trackArray, - '-get-dynamic-var': getDynamicVar, + '-get-dynamic-var': internalHelper(getDynamicVar), '-mount': mountHelper, '-outlet': outletHelper, '-assert-implicit-component-helper-argument': componentAssertionHelper, '-in-el-null': inElementNullCheckHelper, }; -interface IBuiltInModifiers { - [name: string]: ModifierDefinition | undefined; -} - -export default class RuntimeResolverImpl implements RuntimeResolver { - public isInteractive: boolean; - - private handles: any[] = [ - undefined, // ensure no falsy handle - ]; - private objToHandle = new WeakMap(); - - private builtInHelpers: IBuiltInHelpers = BUILTINS_HELPERS; - - private builtInModifiers: IBuiltInModifiers; - - private componentDefinitionCache: Map = new Map(); - - public componentDefinitionCount = 0; - public helperDefinitionCount = 0; - - constructor(owner: Owner, isInteractive: boolean) { - this.isInteractive = isInteractive; - - this.builtInModifiers = { - action: { manager: new ActionModifierManager(), state: null }, - on: { manager: new OnModifierManager(owner, isInteractive), state: null }, - }; - } - - /*** IRuntimeResolver ***/ - - /** - * public componentDefHandleCount = 0; - * Called while executing Append Op.PushDynamicComponentManager if string - */ - lookupComponent(name: string, owner: Owner): Option { - let handle = this.lookupComponentHandle(name, owner); - if (handle === null) { - assert( - `Could not find component named "${name}" (no component or template with that name was found)` - ); - return null; - } - return this.resolve(handle); - } - - lookupComponentHandle(name: string, owner: Owner) { - let nextHandle = this.handles.length; - let handle = this.handle(this._lookupComponentDefinition(name, owner)); - - assert( - 'Could not find component `