From 32b79662675b2a1ba0db836f72fd8fb5f433be85 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Mon, 6 Nov 2017 15:16:34 -0700 Subject: [PATCH 001/135] WIP: Upgrade glimmer-vm to 0.29.10 There is much left to do here. This is just the first pass, where I have done nothing but try to clear out the errors caused by the upgrade. Not all of the errors are cleared yet, largely because several exports from glimmer-vm have been removed and I don't know how to replace them (help wanted). Below is a list of the needed changes and problems I have encountered in the upgrade process. UPGRADE NOTES (starting at glimmer-vm 0.25.6) * Simple is now in @glimmer/interfaces * ComponentManager.getSelf cannot return null (returns RootReference?) * ComponentManager.getTag returns ComponentStateBucket.tag (: Tag) * Some code moved from ComponentManager.update to * ComponentManager.didUpdate * ComponentManager --> * ComponentManager * ComponentManager.create signature changed * ComponentStateBucket's defintion is now DefinitionState instead of * ComponentDefinition * ComponentManager.prepareArgs signature changed * ComponentManager.getCapabilities is new * CompiledDynamicTemplate is gone (no longer in runtime, anyway) see * https://github.com/glimmerjs/glimmer-vm/commit/79f2b4521f5a7d48d04e3fd34e224ddf5bc4c241#diff-d561208b0ad153d9273c2188e16c7442 * Must implicitly include @glimmer/vm and @glimmer/opcode-compiler and * @glimmer/encoder in ember-cli-build.js * compileLayout -> scanLayout -> prepareLayout -> new WrappedBuilder * isSafeString is no longer exported publicly. Is that intentional? * normalizeTextValue is no longer exported publicly. Is that * intentional? * isComponentDefinition is gone, kind of replaced by * `isCurriedComponentDefinition`. Neither is exported. * getComponentDefintion is no longer part of Environment. * referenceFromParts has been removed. * f3444e9ae0c7751047bdcd856e61344bfb548e12 * readDOMAttr has been removed. 316805b9175e01698120b9566ec51c88d075026a --- ember-cli-build.js | 18 +- package.json | 14 +- .../lib/component-managers/abstract.ts | 20 +- .../lib/component-managers/curly.ts | 68 ++++--- .../component-managers/definition-state.ts | 28 +++ .../lib/component-managers/mount.ts | 35 +++- .../lib/component-managers/outlet.ts | 44 +++-- .../lib/component-managers/render.ts | 53 ++++-- .../lib/component-managers/root.ts | 36 ++-- packages/ember-glimmer/lib/environment.ts | 54 +++--- .../ember-glimmer/lib/helpers/component.ts | 3 +- packages/ember-glimmer/lib/helpers/concat.ts | 1 - .../ember-glimmer/lib/modifiers/action.ts | 19 +- packages/ember-glimmer/lib/syntax/mount.ts | 1 + packages/ember-glimmer/lib/template.ts | 2 - packages/ember-glimmer/lib/utils/bindings.ts | 36 ++-- yarn.lock | 173 +++++++++++------- 17 files changed, 402 insertions(+), 203 deletions(-) create mode 100644 packages/ember-glimmer/lib/component-managers/definition-state.ts diff --git a/ember-cli-build.js b/ember-cli-build.js index d51fa4a89b2..b4dfcea47cb 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -65,8 +65,11 @@ module.exports = function(options) { glimmerPkgES('@glimmer/compiler', ['@glimmer/util', '@glimmer/wire-format', '@glimmer/syntax']), { annotation: '@glimmer/compiler' } ); + let glimmerEncoder = toES5(glimmerPkgES('@glimmer/encoder')); + let glimmerOpcodeComiler = toES5(glimmerPkgES('@glimmer/opcode-compiler', ['@glimmer/encoder'])); let glimmerReference = toES5(glimmerPkgES('@glimmer/reference', ['@glimmer/util'])); let glimmerUtil = toES5(glimmerPkgES('@glimmer/util')); + let glimmerVM = toES5(glimmerPkgES('@glimmer/vm')); let glimmerWireFormat = toES5(glimmerPkgES('@glimmer/wire-format', ['@glimmer/util'])); let babelDebugHelpersES5 = toES5(babelHelpers('debug'), { annotation: 'babel helpers debug' }); let inlineParser = toES5(handlebarsES(), { annotation: 'handlebars' }); @@ -136,8 +139,11 @@ module.exports = function(options) { emberMetalES5, emberConsoleES5, emberDebugES5, + glimmerEncoder, + glimmerOpcodeComiler, glimmerReference, glimmerUtil, + glimmerVM, glimmerWireFormat, backburner, version, @@ -197,8 +203,11 @@ module.exports = function(options) { emberDebugES5, glimmerSyntax, glimmerCompiler, + glimmerEncoder, + glimmerOpcodeComiler, glimmerReference, glimmerUtil, + glimmerVM, glimmerWireFormat, backburner, debugFeatures, @@ -229,8 +238,11 @@ module.exports = function(options) { }); let depsProd = [ + glimmerEncoder, + glimmerOpcodeComiler, glimmerReference, glimmerUtil, + glimmerVM, glimmerWireFormat, backburner, rsvp @@ -344,9 +356,11 @@ function dependenciesES6() { routeRecognizerES(), glimmerPkgES('@glimmer/node', ['@glimmer/runtime']), glimmerPkgES('@glimmer/runtime', [ - '@glimmer/util', + '@glimmer/opcode-compiler', '@glimmer/reference', - '@glimmer/wire-format' + '@glimmer/wire-format', + '@glimmer/util', + '@glimmer/vm' ]) ]; } diff --git a/package.json b/package.json index f6c82063310..1d0bb5df2f5 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,11 @@ "test:testem": "testem -f testem.dist.json" }, "dependencies": { + "@glimmer/compiler": "^0.29.10", + "@glimmer/node": "^0.29.10", + "@glimmer/reference": "^0.29.10", + "@glimmer/runtime": "^0.29.10", + "@glimmer/vm": "^0.29.10", "broccoli-funnel": "^2.0.1", "broccoli-merge-trees": "^2.0.0", "ember-cli-get-component-path-option": "^1.0.0", @@ -58,10 +63,11 @@ "resolve": "^1.3.3" }, "devDependencies": { - "@glimmer/compiler": "^0.25.6", - "@glimmer/node": "^0.25.6", - "@glimmer/reference": "^0.25.6", - "@glimmer/runtime": "^0.25.6", + "@glimmer/compiler": "^0.29.10", + "@glimmer/node": "^0.29.10", + "@glimmer/reference": "^0.29.10", + "@glimmer/runtime": "^0.29.10", + "@glimmer/vm": "^0.29.10", "aws-sdk": "^2.46.0", "babel-plugin-check-es2015-constants": "^6.22.0", "babel-plugin-debug-macros": "^0.1.10", diff --git a/packages/ember-glimmer/lib/component-managers/abstract.ts b/packages/ember-glimmer/lib/component-managers/abstract.ts index 3dd6ac47fb6..fa07aabafe9 100644 --- a/packages/ember-glimmer/lib/component-managers/abstract.ts +++ b/packages/ember-glimmer/lib/component-managers/abstract.ts @@ -1,13 +1,14 @@ -import { ProgramSymbolTable } from '@glimmer/interfaces'; +import { + ComponentCapabilities, +} from '@glimmer/interfaces'; import { Tag, VersionedPathReference } from '@glimmer/reference'; import { Bounds, - CompiledDynamicTemplate, - ComponentDefinition, ComponentManager, DynamicScope, ElementOperations, Environment, + Invocation, PreparedArguments, } from '@glimmer/runtime'; import { IArguments } from '@glimmer/runtime/dist/types/lib/vm/arguments'; @@ -23,7 +24,7 @@ import DebugStack from '../utils/debug-stack'; // tslint:disable-next-line:max-line-length // https://github.com/glimmerjs/glimmer-vm/blob/v0.24.0-beta.4/packages/%40glimmer/runtime/lib/component/interfaces.ts#L21 -export default abstract class AbstractManager implements ComponentManager { +export default abstract class AbstractManager implements ComponentManager { public debugStack: typeof DebugStack; public _pushToDebugStack: (name: string, environment: any) => void; public _pushEngineToDebugStack: (name: string, environment: any) => void; @@ -32,7 +33,7 @@ export default abstract class AbstractManager implements ComponentManager this.debugStack = undefined; } - prepareArgs(_definition: ComponentDefinition, _args: IArguments): Option { + prepareArgs(_state: U, _args: IArguments): Option { return null; } @@ -42,16 +43,17 @@ export default abstract class AbstractManager implements ComponentManager abstract create( env: Environment, - definition: ComponentDefinition, + definition: U, args: IArguments, dynamicScope: DynamicScope, caller: VersionedPathReference, hasDefaultBlock: boolean): T; abstract layoutFor( - definition: ComponentDefinition, + definition: any, component: T, - env: Environment): CompiledDynamicTemplate; + env: Environment): Invocation; abstract getSelf(component: T): VersionedPathReference; + abstract getCapabilities(state: U): ComponentCapabilities; didCreateElement(_component: T, _element: Element, _operations: ElementOperations): void { // noop @@ -68,7 +70,7 @@ export default abstract class AbstractManager implements ComponentManager // noop } - getTag(_bucket: T): Option { return null; } + abstract getTag(_bucket: T): Tag; // inheritors should also call `this._pushToDebugStack` // to ensure the rerendering assertion messages are diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 33161af7cda..76525127821 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -1,4 +1,3 @@ -import { Option } from '@glimmer/interfaces'; import { combineTagged, Tag, @@ -7,19 +6,22 @@ import { import { Arguments, Bounds, - CompiledDynamicProgram, - ComponentClass, ComponentDefinition, - ComponentManager, ElementOperations, + Invocation, NamedArguments, PositionalArguments, PreparedArguments, PrimitiveReference, - Simple, VM, } from '@glimmer/runtime'; import { Destroyable, Opaque } from '@glimmer/util'; +import { + ComponentCapabilities, + Option, + Simple, + VMHandle +} from '@glimmer/interfaces'; import { privatize as P } from 'container'; import { assert, @@ -53,6 +55,7 @@ import ComponentStateBucket, { Component } from '../utils/curly-component-state- import { processComponentArgs } from '../utils/process-args'; import { PropertyReference } from '../utils/references'; import AbstractManager from './abstract'; +import DefinitionState, { CAPABILITIES } from './definition-state'; const DEFAULT_LAYOUT = P`template:components/-default`; @@ -85,7 +88,7 @@ function applyAttributeBindings(element: Simple.Element, attributeBindings: any, } if (seen.indexOf('id') === -1) { - operations.addStaticAttribute(element, 'id', component.elementId); + operations.setAttribute('id', PrimitiveReference.create(component.elementId), true, null); } if (seen.indexOf('style') === -1) { @@ -140,9 +143,14 @@ export class PositionalArgumentReference { } } -export default class CurlyComponentManager extends AbstractManager { - prepareArgs(definition: CurlyComponentDefinition, args: Arguments): Option { - let componentPositionalParamsDefinition = definition.ComponentClass.class.positionalParams; +export default class CurlyComponentManager extends AbstractManager { + + getCapabilities(state: DefinitionState): ComponentCapabilities { + return state.capabilities; + } + + prepareArgs(state: DefinitionState, args: Arguments): Option { + let componentPositionalParamsDefinition = state.ComponentClass.class.positionalParams; if (DEBUG && componentPositionalParamsDefinition) { validatePositionalParameters(args.named, args.positional, componentPositionalParamsDefinition); @@ -152,7 +160,7 @@ export default class CurlyComponentManager extends AbstractManager 0; let needsPositionalParamMunging = componentHasPositionalParams && args.positional.length !== 0; - let isClosureComponent = definition.args; + let isClosureComponent = args; if (!needsPositionalParamMunging && !isClosureComponent) { return null; @@ -164,10 +172,10 @@ export default class CurlyComponentManager extends AbstractManager, hasBlock: boolean): ComponentStateBucket { + create(environment: Environment, state: DefinitionState, args: Arguments, dynamicScope: DynamicScope, callerSelfRef: VersionedPathReference, hasBlock: boolean): ComponentStateBucket { if (DEBUG) { - this._pushToDebugStack(`component:${definition.name}`, environment); + this._pushToDebugStack(`component:${state.name}`, environment); } let parentView = dynamicScope.view; - let factory = definition.ComponentClass; + let factory = state.ComponentClass; let capturedArgs = args.named.capture(); let props = processComponentArgs(capturedArgs); @@ -250,7 +258,7 @@ export default class CurlyComponentManager extends AbstractManager { - operations.addStaticAttribute(element, 'class', name); + operations.setAttribute('class', PrimitiveReference.create(name), false, null); }); } @@ -323,7 +330,7 @@ export default class CurlyComponentManager extends AbstractManager { + getTag({ component }: ComponentStateBucket): Tag { return component[DIRTY_TAG]; } @@ -442,16 +449,21 @@ export function rerenderInstrumentDetails(component: any): any { return component.instrumentDetails({ initialRender: false }); } -const MANAGER = new CurlyComponentManager(); - -export class CurlyComponentDefinition extends ComponentDefinition { +export class CurlyComponentDefinition implements ComponentDefinition { public template: OwnedTemplate; public args: Arguments | undefined; + public state: DefinitionState; // tslint:disable-next-line:no-shadowed-variable - constructor(name: string, ComponentClass: ComponentClass, template: OwnedTemplate, args: Arguments | undefined, customManager?: ComponentManager) { - super(name, customManager || MANAGER, ComponentClass); + constructor(public name: string, public manager: CurlyComponentManager, public ComponentClass: any, public handle: Option, template: OwnedTemplate, args?: Arguments) { this.template = template; this.args = args; + this.manager = manager; + this.state = { + name, + ComponentClass, + handle, + capabilities: CAPABILITIES + }; } } diff --git a/packages/ember-glimmer/lib/component-managers/definition-state.ts b/packages/ember-glimmer/lib/component-managers/definition-state.ts new file mode 100644 index 00000000000..55f1841657d --- /dev/null +++ b/packages/ember-glimmer/lib/component-managers/definition-state.ts @@ -0,0 +1,28 @@ +import { + ComponentCapabilities, + ProgramSymbolTable, + VMHandle +} from '@glimmer/interfaces'; +import { + Option +} from '@glimmer/util'; + +export const CAPABILITIES: ComponentCapabilities = { + dynamicLayout: true, + dynamicTag: true, + prepareArgs: false, + createArgs: true, + attributeHook: true, + elementHook: true +}; + +export default interface DefinitionState { + capabilities: ComponentCapabilities; + + name: string; + ComponentClass: any; + handle: Option; + symbolTable?: ProgramSymbolTable; + template?: any; + outletName?: string; +} diff --git a/packages/ember-glimmer/lib/component-managers/mount.ts b/packages/ember-glimmer/lib/component-managers/mount.ts index 32d74fbc2d2..37ed1401b69 100644 --- a/packages/ember-glimmer/lib/component-managers/mount.ts +++ b/packages/ember-glimmer/lib/component-managers/mount.ts @@ -2,21 +2,29 @@ import { Arguments, ComponentDefinition, } from '@glimmer/runtime'; +import { + ComponentCapabilities, + VMHandle +} from '@glimmer/interfaces'; import { Destroyable, Opaque, Option } from '@glimmer/util'; import { + Tag, VersionedPathReference } from '@glimmer/reference'; import { DEBUG } from 'ember-env-flags'; import { generateControllerFactory } from 'ember-routing'; import { EMBER_ENGINES_MOUNT_PARAMS } from 'ember/features'; +import { Component } from '../utils/curly-component-state-bucket'; +import { DIRTY_TAG } from '../component'; import { RootReference } from '../utils/references'; import Environment from '../environment'; import AbstractManager from './abstract'; +import DefinitionState, { CAPABILITIES } from './definition-state'; import { OutletLayoutCompiler } from './outlet'; // TODO: remove these stubbed interfaces when better typing is in place @@ -29,13 +37,18 @@ interface EngineType { interface EngineBucket { engine: EngineType; + component?: Component; controller?: any; modelReference?: any; modelRevision?: any; } -class MountManager extends AbstractManager { - create(environment: Environment, { name }: ComponentDefinition, args: Arguments) { +class MountManager extends AbstractManager { + getCapabilities(state: DefinitionState): ComponentCapabilities { + return state.capabilities; + } + + create(environment: Environment, { name }: DefinitionState, args: Arguments) { if (DEBUG) { this._pushEngineToDebugStack(`engine:${name}`, environment); } @@ -74,6 +87,11 @@ class MountManager extends AbstractManager { return new RootReference(controller); } + getTag({ component }: EngineBucket): Tag { + // TODO: is this the right tag? + return component[DIRTY_TAG]; + } + getDestructor({ engine }: EngineBucket): Option { return engine; } @@ -97,10 +115,15 @@ class MountManager extends AbstractManager { } } -const MOUNT_MANAGER = new MountManager(); +export class MountDefinition implements ComponentDefinition { + public state: DefinitionState; -export class MountDefinition extends ComponentDefinition { - constructor(name: string) { - super(name, MOUNT_MANAGER, null); + constructor(public name: string, public manager: MountManager, public ComponentClass: any, public handle: Option) { + this.state = { + name, + ComponentClass, + handle, + capabilities: CAPABILITIES + }; } } diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index c194d936430..36b3d90c533 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -1,10 +1,16 @@ -import { Option } from '@glimmer/interfaces'; +import { + ComponentCapabilities, + Option +} from '@glimmer/interfaces'; import { Arguments, ComponentDefinition, DynamicScope, - Environment, + Environment } from '@glimmer/runtime'; +import { + Tag +} from '@glimmer/reference'; import { Destroyable } from '@glimmer/util/dist/types'; import { DEBUG } from 'ember-env-flags'; import { _instrumentStart } from 'ember-metal'; @@ -16,6 +22,9 @@ import { } from '../template'; import { RootReference } from '../utils/references'; import AbstractManager from './abstract'; +import { Component } from '../utils/curly-component-state-bucket'; +import DefinitionState from './definition-state'; +import { DIRTY_TAG } from '../component'; function instrumentationPayload({ render: { name, outlet } }: {render: {name: string, outlet: string}}) { return { object: `${name}:${outlet}` }; @@ -30,6 +39,7 @@ interface OutletDynamicScope extends DynamicScope { class StateBucket { public outletState: any; public finalizer: any; + public component: Component; constructor(outletState: any) { this.outletState = outletState; @@ -47,9 +57,9 @@ class StateBucket { } } -class OutletComponentManager extends AbstractManager { +class OutletComponentManager extends AbstractManager { create(environment: Environment, - definition: OutletComponentDefinition, + definition: DefinitionState, _args: Arguments, dynamicScope: OutletDynamicScope) { if (DEBUG) { @@ -62,6 +72,10 @@ class OutletComponentManager extends AbstractManager { return new StateBucket(outletState); } + getCapabilities(state: DefinitionState): ComponentCapabilities { + return state.capabilities; + } + layoutFor(definition: OutletComponentDefinition, _bucket: StateBucket, env: Environment) { return (env as EmberEnvironment).getCompiledBlock(OutletLayoutCompiler, definition.template); } @@ -70,6 +84,11 @@ class OutletComponentManager extends AbstractManager { return new RootReference(outletState.render.controller); } + getTag({ component }: StateBucket): Tag { + // TODO: is this the right tag? + return component[DIRTY_TAG]; + } + didRenderLayout(bucket: StateBucket) { bucket.finalize(); @@ -83,10 +102,8 @@ class OutletComponentManager extends AbstractManager { } } -const MANAGER = new OutletComponentManager(); - class TopLevelOutletComponentManager extends OutletComponentManager { - create(environment: Environment, definition: OutletComponentDefinition, _args: Arguments, dynamicScope: OutletDynamicScope) { + create(environment: Environment, definition: DefinitionState, _args: Arguments, dynamicScope: OutletDynamicScope) { if (DEBUG) { this._pushToDebugStack(`template:${definition.template.meta.moduleName}`, environment); } @@ -98,12 +115,12 @@ class TopLevelOutletComponentManager extends OutletComponentManager { } } -const TOP_LEVEL_MANAGER = new TopLevelOutletComponentManager(); - -export class TopLevelOutletComponentDefinition extends ComponentDefinition { +export class TopLevelOutletComponentDefinition implements ComponentDefinition { public template: WrappedTemplateFactory; + public state: DefinitionState; + public manager: TopLevelOutletComponentManager; + constructor(instance: any) { - super('outlet', TOP_LEVEL_MANAGER, instance); this.template = instance.template; generateGuid(this); } @@ -126,12 +143,13 @@ class TopLevelOutletLayoutCompiler { TopLevelOutletLayoutCompiler.id = 'top-level-outlet'; -export class OutletComponentDefinition extends ComponentDefinition { +export class OutletComponentDefinition implements ComponentDefinition { public outletName: string; public template: OwnedTemplate; + public state: DefinitionState; + public manager: OutletComponentManager; constructor(outletName: string, template: OwnedTemplate) { - super('outlet', MANAGER, null); this.outletName = outletName; this.template = template; generateGuid(this); diff --git a/packages/ember-glimmer/lib/component-managers/render.ts b/packages/ember-glimmer/lib/component-managers/render.ts index 352dde6b538..933a4fd4198 100644 --- a/packages/ember-glimmer/lib/component-managers/render.ts +++ b/packages/ember-glimmer/lib/component-managers/render.ts @@ -1,20 +1,27 @@ import { - ComponentDefinition, - ComponentManager, + ComponentCapabilities, +} from '@glimmer/interfaces'; +import { + Tag +} from '@glimmer/reference'; +import { + Arguments, + ComponentDefinition } from '@glimmer/runtime'; -import { IArguments } from '@glimmer/runtime/dist/types/lib/vm/arguments'; import { assert } from 'ember-debug'; import { DEBUG } from 'ember-env-flags'; import { generateController, generateControllerFactory } from 'ember-routing'; +import { DIRTY_TAG } from '../component'; import Environment from '../environment'; import { DynamicScope } from '../renderer'; import { OwnedTemplate } from '../template'; import { RootReference } from '../utils/references'; import AbstractManager from './abstract'; +import DefinitionState from './definition-state'; import { OutletLayoutCompiler } from './outlet'; -export abstract class AbstractRenderManager extends AbstractManager { +export abstract class AbstractRenderManager extends AbstractManager { layoutFor(definition: RenderDefinition, _bucket: RenderState, env: Environment) { // only curly components can have lazy layout assert('definition is missing a template', !!definition.template); @@ -35,12 +42,13 @@ if (DEBUG) { export interface RenderState { controller: any; model: any; + component: any; } class SingletonRenderManager extends AbstractRenderManager { create(env: Environment, - definition: ComponentDefinition, - _args: IArguments, + definition: DefinitionState, + _args: Arguments, dynamicScope: DynamicScope) { let { name } = definition; let controller = env.owner.lookup(`controller:${name}`) || generateController(env.owner, name); @@ -56,6 +64,15 @@ class SingletonRenderManager extends AbstractRenderManager { return { controller } as RenderState; } + getCapabilities(state: DefinitionState): ComponentCapabilities { + return state.capabilities; + } + + getTag({ component }: RenderState): Tag { + // TODO: is this the right tag? + return component[DIRTY_TAG]; + } + getDestructor() { return null; } @@ -64,7 +81,10 @@ class SingletonRenderManager extends AbstractRenderManager { export const SINGLETON_RENDER_MANAGER = new SingletonRenderManager(); class NonSingletonRenderManager extends AbstractRenderManager { - create(environment: Environment, definition: RenderDefinition, args: IArguments, dynamicScope: DynamicScope) { + create(environment: Environment, + definition: DefinitionState, + args: Arguments, + dynamicScope: DynamicScope) { let { name, env } = definition; let modelRef = args.positional.at(0); let controllerFactory = env.owner.factoryFor(`controller:${name}`); @@ -80,13 +100,22 @@ class NonSingletonRenderManager extends AbstractRenderManager { dynamicScope.outletState = dynamicScope.rootOutletState.getOrphan(name); } - return { controller, model: modelRef }; + return { controller, model: modelRef }; } update({ controller, model }: RenderState) { controller.set('model', model.value()); } + getCapabilities(state: DefinitionState): ComponentCapabilities { + return state.capabilities; + } + + getTag({ component }: RenderState): Tag { + // TODO: is this the right tag? + return component[DIRTY_TAG]; + } + getDestructor({ controller }: RenderState) { return controller; } @@ -94,16 +123,18 @@ class NonSingletonRenderManager extends AbstractRenderManager { export const NON_SINGLETON_RENDER_MANAGER = new NonSingletonRenderManager(); -export class RenderDefinition extends ComponentDefinition { +export class RenderDefinition implements ComponentDefinition { public name: string; public template: OwnedTemplate | undefined; public env: Environment; + public state: DefinitionState; + public manager: SingletonRenderManager | NonSingletonRenderManager; - constructor(name: string, template: OwnedTemplate | undefined, env: Environment, manager: ComponentManager) { - super('render', manager, null); + constructor(name: string, template: OwnedTemplate, env: Environment, manager: SingletonRenderManager | NonSingletonRenderManager) { this.name = name; this.template = template; this.env = env; + this.manager = manager; } } diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index ef1b6167b14..1ebfb054a66 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -1,7 +1,13 @@ +import { + VMHandle +} from '@glimmer/interfaces'; import { Arguments, ComponentDefinition } from '@glimmer/runtime'; +import { + Option +} from '@glimmer/util'; import { DEBUG } from 'ember-env-flags'; import { _instrumentStart, @@ -10,13 +16,16 @@ import ComponentStateBucket from '../utils/curly-component-state-bucket'; import CurlyComponentManager, { initialRenderInstrumentDetails, processComponentInitializationAssertions, - CurlyComponentDefinition } from './curly'; import { DynamicScope } from '../renderer'; import Environment from '../environment'; +import DefintionState, { CAPABILITIES } from './definition-state'; class RootComponentManager extends CurlyComponentManager { - create(environment: Environment, definition: CurlyComponentDefinition, args: Arguments, dynamicScope: DynamicScope) { + create(environment: Environment, + definition: DefintionState, + args: Arguments, + dynamicScope: DynamicScope) { let component = definition.ComponentClass.create(); if (DEBUG) { @@ -48,19 +57,16 @@ class RootComponentManager extends CurlyComponentManager { } } -const ROOT_MANAGER = new RootComponentManager(); +export class RootComponentDefinition implements ComponentDefinition { + public state: DefintionState; + public manager: RootComponentManager; -export class RootComponentDefinition extends ComponentDefinition { - public template: any; - public args: any; - constructor(instance: ComponentStateBucket) { - super('-root', ROOT_MANAGER, { - class: instance.constructor, - create() { - return instance; - }, - }); - this.template = undefined; - this.args = undefined; + constructor(name: string, _manager: RootComponentManager, ComponentClass: any, handle: Option) { + this.state = { + name, + ComponentClass, + handle, + capabilities: CAPABILITIES + } } } diff --git a/packages/ember-glimmer/lib/environment.ts b/packages/ember-glimmer/lib/environment.ts index 4ca35ffd61c..86b04d730e9 100644 --- a/packages/ember-glimmer/lib/environment.ts +++ b/packages/ember-glimmer/lib/environment.ts @@ -1,20 +1,22 @@ +import { + Simple, + VMHandle +} from '@glimmer/interfaces'; +import { + WrappedBuilder +} from '@glimmer/opcode-compiler'; import { Reference, } from '@glimmer/reference'; import { - AttributeManager, - CompilableLayout, - CompiledDynamicProgram, - compileLayout, ComponentDefinition, + DynamicAttributeFactory, Environment as GlimmerEnvironment, getDynamicVar, Helper, - isSafeString, ModifierManager, PrimitiveReference, PartialDefinition, - Simple, } from '@glimmer/runtime'; import { Destroyable, Opaque, @@ -33,8 +35,8 @@ import { CurlyComponentDefinition, } from './component-managers/curly'; import { - populateMacros, -} from './syntax'; + CAPABILITIES +} from './component-managers/definition-state'; import DebugStack from './utils/debug-stack'; import createIterable from './utils/iterable'; import { @@ -85,7 +87,7 @@ function isTemplateFactory(template: OwnedTemplate | WrappedTemplateFactory): te export interface CompilerFactory { id: string; - new (template: OwnedTemplate | undefined): CompilableLayout; + new (template: OwnedTemplate): any; } export default class Environment extends GlimmerEnvironment { @@ -113,7 +115,7 @@ export default class Environment extends GlimmerEnvironment { Template: WrappedTemplateFactory | OwnedTemplate; owner: Container; }, OwnedTemplate>; - private _compilerCache: Cache>; + private _compilerCache: Cache>; constructor(injections: any) { super(injections); @@ -136,7 +138,7 @@ export default class Environment extends GlimmerEnvironment { customManager = owner.factoryFor(`component-manager:${managerId}`).class; } } - return new CurlyComponentDefinition(name, componentFactory, layout, undefined, customManager); + return new CurlyComponentDefinition(name, customManager, undefined, layout, customManager); } return undefined; }, ({ name, source, owner }) => { @@ -144,7 +146,7 @@ export default class Environment extends GlimmerEnvironment { let ownerGuid = guidFor(owner); - return ownerGuid + '|' + expandedName; + return `${ownerGuid}|${expandedName}`; }); this._templateCache = new Cache(1000, ({ Template, owner }) => { @@ -155,14 +157,14 @@ export default class Environment extends GlimmerEnvironment { // we were provided an instance already return Template; } - }, ({ Template, owner }) => guidFor(owner) + '|' + Template.id); + }, ({ Template, owner }) => `${guidFor(owner)}|${Template.id}`); this._compilerCache = new Cache(10, (Compiler) => { return new Cache(2000, (template) => { let compilable = new Compiler(template); - return compileLayout(compilable, this); + return new WrappedBuilder({asPartial: false, referrer: null}, compilable, CAPABILITIES); }, (template) => { - let owner = template.meta.owner; + let owner = template.owner; return guidFor(owner) + '|' + template.id; }); }, (Compiler) => Compiler.id); @@ -208,11 +210,13 @@ export default class Environment extends GlimmerEnvironment { : owner._resolveLocalLookupName(name, source); } + /* macros() { let macros = super.macros(); populateMacros(macros.blocks, macros.inlines); return macros; } + */ hasComponentDefinition() { return false; @@ -245,13 +249,11 @@ export default class Environment extends GlimmerEnvironment { return hasPartial(name, meta.owner); } - lookupPartial(name: string, meta: any): PartialDefinition { - let partial = { - name, - template: lookupPartial(name, meta.owner), - }; + lookupPartial(name: string, meta: any): PartialDefinition { + const template = lookupPartial(name, meta.owner); + const partial = new PartialDefinition( name, lookupPartial(name, meta.owner)); - if (partial.template) { + if (template) { return partial; } else { throw new Error(`${name} is not a partial`); @@ -355,29 +357,27 @@ export default class Environment extends GlimmerEnvironment { } if (DEBUG) { - class StyleAttributeManager extends AttributeManager { - setAttribute(dom: Environment, element: Simple.Element, value: Opaque) { + class StyleAttributeManager implements DynamicAttributeFactory { + setAttribute(_dom: Environment, _element: Simple.Element, value: Opaque) { warn(constructStyleDeprecationMessage(value), (() => { if (value === null || value === undefined || isSafeString(value)) { return true; } return false; })(), { id: 'ember-htmlbars.style-xss-warning' }); - super.setAttribute(dom, element, value); } - updateAttribute(dom: Environment, element: Element, value: Opaque) { + updateAttribute(_dom: Environment, _element: Element, value: Opaque) { warn(constructStyleDeprecationMessage(value), (() => { if (value === null || value === undefined || isSafeString(value)) { return true; } return false; })(), { id: 'ember-htmlbars.style-xss-warning' }); - super.updateAttribute(dom, element, value); } } - let STYLE_ATTRIBUTE_MANANGER = new StyleAttributeManager('style'); + let STYLE_ATTRIBUTE_MANANGER = new StyleAttributeManager(); Environment.prototype.attributeFor = function(element, attribute, isTrusting) { if (attribute === 'style' && !isTrusting) { diff --git a/packages/ember-glimmer/lib/helpers/component.ts b/packages/ember-glimmer/lib/helpers/component.ts index d6a78ce368d..454f9a97632 100644 --- a/packages/ember-glimmer/lib/helpers/component.ts +++ b/packages/ember-glimmer/lib/helpers/component.ts @@ -4,7 +4,6 @@ import { Arguments, Environment, - isComponentDefinition, VM } from '@glimmer/runtime'; import { assert } from 'ember-debug'; @@ -217,7 +216,9 @@ function createCurriedDefinition(definition: CurlyComponentDefinition, args: Arg return new CurlyComponentDefinition( definition.name, + definition.manager, definition.ComponentClass, + definition.state.handle, definition.template, curriedArgs, ); diff --git a/packages/ember-glimmer/lib/helpers/concat.ts b/packages/ember-glimmer/lib/helpers/concat.ts index 52ae7760ece..69d5d82fdc5 100644 --- a/packages/ember-glimmer/lib/helpers/concat.ts +++ b/packages/ember-glimmer/lib/helpers/concat.ts @@ -1,7 +1,6 @@ import { Arguments, CapturedArguments, - normalizeTextValue, VM } from '@glimmer/runtime'; import { InternalHelperReference } from '../utils/references'; diff --git a/packages/ember-glimmer/lib/modifiers/action.ts b/packages/ember-glimmer/lib/modifiers/action.ts index 47e2b430ec9..490e98e8ef2 100644 --- a/packages/ember-glimmer/lib/modifiers/action.ts +++ b/packages/ember-glimmer/lib/modifiers/action.ts @@ -1,11 +1,19 @@ +import { + Simple +} from '@glimmer/interfaces'; +import { + TagWrapper +} from '@glimmer/reference'; import { Arguments, CapturedNamedArguments, CapturedPositionalArguments, DynamicScope, - Simple + ModifierManager, } from '@glimmer/runtime'; -import { Destroyable } from '@glimmer/util'; +import { + Destroyable +} from '@glimmer/util'; import { assert } from 'ember-debug'; import { flaggedInstrument, run } from 'ember-metal'; import { uuid } from 'ember-utils'; @@ -172,7 +180,7 @@ export class ActionState { } // implements ModifierManager -export default class ActionModifierManager { +export default class ActionModifierManager implements ModifierManager { create(element: Simple.Element, args: Arguments, _dynamicScope: DynamicScope, dom: any) { let { named, positional } = args.capture(); let implicitTarget; @@ -238,6 +246,11 @@ export default class ActionModifierManager { actionState.eventName = actionState.getEventName(); } + getTag() { + // TODO: ModifierManager needs a getTag method. Where does this tag come from? + return new TagWrapper(); + } + getDestructor(modifier: Destroyable) { return modifier; } diff --git a/packages/ember-glimmer/lib/syntax/mount.ts b/packages/ember-glimmer/lib/syntax/mount.ts index bc636b0c5bb..a93b9fcd07b 100644 --- a/packages/ember-glimmer/lib/syntax/mount.ts +++ b/packages/ember-glimmer/lib/syntax/mount.ts @@ -113,6 +113,7 @@ class DynamicEngineReference { } this._lastName = nameOrDef; + // TODO: maybe I've got the MountDefinition constructor wrong... this._lastDef = new MountDefinition(nameOrDef); return this._lastDef; diff --git a/packages/ember-glimmer/lib/template.ts b/packages/ember-glimmer/lib/template.ts index 8131b7af028..83962ae9dec 100644 --- a/packages/ember-glimmer/lib/template.ts +++ b/packages/ember-glimmer/lib/template.ts @@ -25,8 +25,6 @@ export class WrappedTemplateFactory { constructor(public factory: TemplateFactory<{ moduleName: string; - }, { - owner: Container; }>) { this.id = factory.id; this.meta = factory.meta; diff --git a/packages/ember-glimmer/lib/utils/bindings.ts b/packages/ember-glimmer/lib/utils/bindings.ts index 67c9ec0b3a2..846920cf57c 100644 --- a/packages/ember-glimmer/lib/utils/bindings.ts +++ b/packages/ember-glimmer/lib/utils/bindings.ts @@ -1,15 +1,17 @@ -import { Opaque, Option } from '@glimmer/interfaces'; +import { + Opaque, + Option, + Simple +} from '@glimmer/interfaces'; import { CachedReference, combine, map, Reference, - referenceFromParts, Tag, } from '@glimmer/reference'; import { - ElementOperations, - Simple + ElementOperations } from '@glimmer/runtime'; import { Ops, @@ -80,7 +82,7 @@ export const AttributeBinding = { } }, - install(element: Simple.Element, component: Component, parsed: [string, string, boolean], operations: ElementOperations) { + install(_element: Simple.Element, component: Component, parsed: [string, string, boolean], operations: ElementOperations) { let [prop, attribute, isSimple] = parsed; if (attribute === 'id') { @@ -88,7 +90,8 @@ export const AttributeBinding = { if (elementId === undefined || elementId === null) { elementId = component.elementId; } - operations.addStaticAttribute(element, 'id', elementId); + operations.setAttribute('id', elementId, true, null); + // operations.addStaticAttribute(element, 'id', elementId); return; } @@ -101,7 +104,8 @@ export const AttributeBinding = { reference = new StyleBindingReference(reference, referenceForKey(component, 'isVisible')); } - operations.addDynamicAttribute(element, attribute, reference, false); + operations.setAttribute(attribute, reference, false, null); + // operations.addDynamicAttribute(element, attribute, reference, false); }, }; @@ -132,8 +136,14 @@ class StyleBindingReference extends CachedReference { } export const IsVisibleBinding = { - install(element: Simple.Element, component: Component, operations: ElementOperations) { - operations.addDynamicAttribute(element, 'style', map(referenceForKey(component, 'isVisible'), this.mapStyleValue), false); + install(_element: Simple.Element, component: Component, operations: ElementOperations) { + operations.setAttribute( + 'style', + map(referenceForKey(component, 'isVisible'), this.mapStyleValue), + false, + null + ); + // operations.addDynamicAttribute(element, 'style', map(referenceForKey(component, 'isVisible'), this.mapStyleValue), false); }, mapStyleValue(isVisible: boolean) { @@ -142,12 +152,13 @@ export const IsVisibleBinding = { }; export const ClassNameBinding = { - install(element: Simple.Element, component: Component, microsyntax: string, operations: ElementOperations) { + install(_element: Simple.Element, component: Component, microsyntax: string, operations: ElementOperations) { let [ prop, truthy, falsy ] = microsyntax.split(':'); let isStatic = prop === ''; if (isStatic) { - operations.addStaticAttribute(element, 'class', truthy); + operations.setAttribute('class', truthy, true, null); + // operations.addStaticAttribute(element, 'class', truthy); } else { let isPath = prop.indexOf('.') > -1; let parts = isPath ? prop.split('.') : []; @@ -160,7 +171,8 @@ export const ClassNameBinding = { ref = new ColonClassNameBindingReference(value, truthy, falsy); } - operations.addDynamicAttribute(element, 'class', ref, false); + operations.setAttribute('class', ref, false, null); + // operations.addDynamicAttribute(element, 'class', ref, false); } }, }; diff --git a/yarn.lock b/yarn.lock index 52e7bb63b19..9507c05780e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,78 +2,117 @@ # yarn lockfile v1 -"@glimmer/compiler@^0.25.6": - version "0.25.6" - resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.25.6.tgz#dcc2b8bfa6f36b70c34e41e85626f888315d3ad7" - dependencies: - "@glimmer/interfaces" "^0.25.6" - "@glimmer/syntax" "^0.25.6" - "@glimmer/util" "^0.25.6" - "@glimmer/wire-format" "^0.25.6" - simple-html-tokenizer "^0.3.0" - -"@glimmer/interfaces@^0.25.6": - version "0.25.6" - resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.25.6.tgz#88a6cdb4f414c3a82662cc5fc5cb5bfd91d4ef10" - dependencies: - "@glimmer/wire-format" "^0.25.6" - -"@glimmer/node@^0.25.6": - version "0.25.6" - resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.25.6.tgz#3887a79d8fd2cf9376511245babe87647e4349df" - dependencies: - "@glimmer/runtime" "^0.25.6" +"@glimmer/compiler@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.29.10.tgz#b0a3d53069605d78fdf1bf1bc3be28ae81402342" + dependencies: + "@glimmer/interfaces" "^0.29.10" + "@glimmer/syntax" "^0.29.10" + "@glimmer/util" "^0.29.10" + "@glimmer/wire-format" "^0.29.10" + simple-html-tokenizer "^0.4.1" + +"@glimmer/encoder@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.29.10.tgz#a49c61a0794d2e1b218ec0a563d0f84dca08334c" + +"@glimmer/interfaces@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.29.10.tgz#7744451ca329a42c62b08fa460808bccbddeb2ab" + dependencies: + "@glimmer/wire-format" "^0.29.10" + +"@glimmer/node@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.29.10.tgz#ba8a5cb45784a46bbb50c454c56d2188b82d97ab" + dependencies: + "@glimmer/compiler" "^0.29.10" + "@glimmer/interfaces" "^0.29.10" + "@glimmer/object-reference" "^0.29.10" + "@glimmer/runtime" "^0.29.10" simple-dom "^0.3.0" -"@glimmer/object-reference@^0.25.6": - version "0.25.6" - resolved "https://registry.yarnpkg.com/@glimmer/object-reference/-/object-reference-0.25.6.tgz#ab45f51c9416bdaff402a0ea3cedd3b1807b1158" - dependencies: - "@glimmer/reference" "^0.25.6" - "@glimmer/util" "^0.25.6" - -"@glimmer/object@^0.25.6": - version "0.25.6" - resolved "https://registry.yarnpkg.com/@glimmer/object/-/object-0.25.6.tgz#a07860e551980488c2839c6393f7a2c071d68a6e" - dependencies: - "@glimmer/object-reference" "^0.25.6" - "@glimmer/util" "^0.25.6" - -"@glimmer/reference@^0.25.6": - version "0.25.6" - resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.25.6.tgz#bc57ccc351fc4bcc5750bdb7760cec4b9ef628f4" - dependencies: - "@glimmer/util" "^0.25.6" +"@glimmer/object-reference@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/object-reference/-/object-reference-0.29.10.tgz#9e0acc15779611d306b66819088b0aee2cf06a48" + dependencies: + "@glimmer/reference" "^0.29.10" + "@glimmer/util" "^0.29.10" + +"@glimmer/object@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/object/-/object-0.29.10.tgz#ce450757598274e476f73f61a3a36a26f81642e5" + dependencies: + "@glimmer/object-reference" "^0.29.10" + "@glimmer/util" "^0.29.10" + +"@glimmer/opcode-compiler@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/opcode-compiler/-/opcode-compiler-0.29.10.tgz#37bb4413e614e442c908d2a38725c9358e4c7e45" + dependencies: + "@glimmer/encoder" "^0.29.10" + "@glimmer/interfaces" "^0.29.10" + "@glimmer/program" "^0.29.10" + "@glimmer/syntax" "^0.29.10" + "@glimmer/util" "^0.29.10" + "@glimmer/vm" "^0.29.10" + "@glimmer/wire-format" "^0.29.10" + simple-html-tokenizer "^0.4.1" + +"@glimmer/program@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.29.10.tgz#c9a2facda2812b6314f3f7f2153cd51f5e51bfba" + dependencies: + "@glimmer/encoder" "^0.29.10" + "@glimmer/interfaces" "^0.29.10" + "@glimmer/util" "^0.29.10" + +"@glimmer/reference@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.29.10.tgz#fc5db84f5b2a9aeef28e1407a54679cf5817acab" + dependencies: + "@glimmer/util" "^0.29.10" + +"@glimmer/runtime@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.29.10.tgz#90dce95aa6b596ff1134a11de1c77f50110c38b9" + dependencies: + "@glimmer/interfaces" "^0.29.10" + "@glimmer/object" "^0.29.10" + "@glimmer/object-reference" "^0.29.10" + "@glimmer/opcode-compiler" "^0.29.10" + "@glimmer/program" "^0.29.10" + "@glimmer/reference" "^0.29.10" + "@glimmer/util" "^0.29.10" + "@glimmer/vm" "^0.29.10" + "@glimmer/wire-format" "^0.29.10" + +"@glimmer/syntax@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.29.10.tgz#2a074223fc3b42d49c8b9345684a80b5133dc030" + dependencies: + "@glimmer/interfaces" "^0.29.10" + "@glimmer/util" "^0.29.10" + handlebars "^4.0.6" + simple-html-tokenizer "^0.4.1" -"@glimmer/runtime@^0.25.6": - version "0.25.6" - resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.25.6.tgz#2a776dcdd3b8f844e1f6b4e7ca4478b6dc560133" - dependencies: - "@glimmer/interfaces" "^0.25.6" - "@glimmer/object" "^0.25.6" - "@glimmer/object-reference" "^0.25.6" - "@glimmer/reference" "^0.25.6" - "@glimmer/util" "^0.25.6" - "@glimmer/wire-format" "^0.25.6" +"@glimmer/util@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.29.10.tgz#8662daf273ffef9254b8d943d39aa396ed7225a5" -"@glimmer/syntax@^0.25.6": - version "0.25.6" - resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.25.6.tgz#aeed43004ece8715d09189b61037c793225b4e88" +"@glimmer/vm@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.29.10.tgz#e723ea7d23960dd470cc73ec31e02fd74cab2cd8" dependencies: - "@glimmer/interfaces" "^0.25.6" - "@glimmer/util" "^0.25.6" - handlebars "^4.0.6" - simple-html-tokenizer "^0.3.0" - -"@glimmer/util@^0.25.6": - version "0.25.6" - resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.25.6.tgz#de8dde7f5d30f9c0e3e2f083e3f6d3426a92b302" + "@glimmer/interfaces" "^0.29.10" + "@glimmer/program" "^0.29.10" + "@glimmer/util" "^0.29.10" -"@glimmer/wire-format@^0.25.6": - version "0.25.6" - resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.25.6.tgz#f0543801d234e133bf72d2bdec68dd2c36c06eca" +"@glimmer/wire-format@^0.29.10": + version "0.29.10" + resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.29.10.tgz#90e82f67a6325468d6fee4f8dd7affc1070a9557" dependencies: - "@glimmer/util" "^0.25.6" + "@glimmer/util" "^0.29.10" abbrev@1: version "1.1.0" @@ -5580,10 +5619,6 @@ simple-fmt@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/simple-fmt/-/simple-fmt-0.1.0.tgz#191bf566a59e6530482cb25ab53b4a8dc85c3a6b" -simple-html-tokenizer@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/simple-html-tokenizer/-/simple-html-tokenizer-0.3.0.tgz#9b8b5559d80e331a544dd13dd59382e5d0d94411" - simple-html-tokenizer@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/simple-html-tokenizer/-/simple-html-tokenizer-0.4.1.tgz#028988bb7fe8b2e6645676d82052587d440b02d3" From 9155a4ea35e2186f8cdeb8e7af89ea3875303b14 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Fri, 17 Nov 2017 16:35:42 -0700 Subject: [PATCH 002/135] WIP Add skeleton resolvers, more upgrade work --- ember-cli-build.js | 4 ++ package.json | 1 + .../ember-glimmer/lib/compile-time-lookup.ts | 41 +++++++++++++++++++ .../lib/component-managers/abstract.ts | 8 ++-- .../lib/component-managers/curly.ts | 7 ++-- .../lib/component-managers/root.ts | 17 +++++--- packages/ember-glimmer/lib/component.ts | 1 - packages/ember-glimmer/lib/environment.ts | 4 ++ packages/ember-glimmer/lib/index.ts | 2 +- packages/ember-glimmer/lib/renderer.ts | 10 +++-- packages/ember-glimmer/lib/resolver.ts | 39 ++++++++++++++++++ packages/ember-glimmer/lib/template.ts | 22 +++++++++- .../ember-glimmer/lib/template_registry.ts | 2 +- 13 files changed, 137 insertions(+), 21 deletions(-) create mode 100644 packages/ember-glimmer/lib/compile-time-lookup.ts create mode 100644 packages/ember-glimmer/lib/resolver.ts diff --git a/ember-cli-build.js b/ember-cli-build.js index b4dfcea47cb..a0ca7cb7026 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -67,6 +67,7 @@ module.exports = function(options) { ); let glimmerEncoder = toES5(glimmerPkgES('@glimmer/encoder')); let glimmerOpcodeComiler = toES5(glimmerPkgES('@glimmer/opcode-compiler', ['@glimmer/encoder'])); + let glimmerProgram = toES5(glimmerPkgES('@glimmer/program')); let glimmerReference = toES5(glimmerPkgES('@glimmer/reference', ['@glimmer/util'])); let glimmerUtil = toES5(glimmerPkgES('@glimmer/util')); let glimmerVM = toES5(glimmerPkgES('@glimmer/vm')); @@ -141,6 +142,7 @@ module.exports = function(options) { emberDebugES5, glimmerEncoder, glimmerOpcodeComiler, + glimmerProgram, glimmerReference, glimmerUtil, glimmerVM, @@ -205,6 +207,7 @@ module.exports = function(options) { glimmerCompiler, glimmerEncoder, glimmerOpcodeComiler, + glimmerProgram, glimmerReference, glimmerUtil, glimmerVM, @@ -240,6 +243,7 @@ module.exports = function(options) { let depsProd = [ glimmerEncoder, glimmerOpcodeComiler, + glimmerProgram, glimmerReference, glimmerUtil, glimmerVM, diff --git a/package.json b/package.json index 1d0bb5df2f5..16433db381d 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "dependencies": { "@glimmer/compiler": "^0.29.10", "@glimmer/node": "^0.29.10", + "@glimmer/program": "^0.29.10", "@glimmer/reference": "^0.29.10", "@glimmer/runtime": "^0.29.10", "@glimmer/vm": "^0.29.10", diff --git a/packages/ember-glimmer/lib/compile-time-lookup.ts b/packages/ember-glimmer/lib/compile-time-lookup.ts new file mode 100644 index 00000000000..6e98c0aa95e --- /dev/null +++ b/packages/ember-glimmer/lib/compile-time-lookup.ts @@ -0,0 +1,41 @@ +import { CompileTimeLookup as ICompileTimeLookup, Specifier } from '@glimmer/opcode-compiler'; +import { + CAPABILITIES +} from './component-managers/definition-state'; +import RuntimeResolver from './resolver'; +import { CurlyComponentDefinition } from 'ember-glimmer/lib/component-managers/curly'; + +export default class CompileTimeLookup implements ICompileTimeLookup { + constructor(private resolver: RuntimeResolver) {} + private getComponentDefinition(handle: number) { + return this.resolver.resolve>(handle); + } + getCapabilities(handle: number) { + return this.getComponentDefinition(handle).getCapabilities(); + } + + getLayout(handle: number) { + const componentDefintion = this.resolver.resolve(handle); + const { manager } = componentDefintion; + return { + compile() { return handle; }, + symbolTable: null + }; + } + + lookupHelper(handle: number) { + + } + + lookupModifier(handle: number) { + + } + + lookupComponentSpec(handle: number) { + + } + + lookupPartial(handle: number) { + + } +} \ No newline at end of file diff --git a/packages/ember-glimmer/lib/component-managers/abstract.ts b/packages/ember-glimmer/lib/component-managers/abstract.ts index fa07aabafe9..94aa1875b9a 100644 --- a/packages/ember-glimmer/lib/component-managers/abstract.ts +++ b/packages/ember-glimmer/lib/component-managers/abstract.ts @@ -1,5 +1,6 @@ import { ComponentCapabilities, + VMHandle } from '@glimmer/interfaces'; import { Tag, VersionedPathReference } from '@glimmer/reference'; import { @@ -8,14 +9,13 @@ import { DynamicScope, ElementOperations, Environment, - Invocation, PreparedArguments, } from '@glimmer/runtime'; import { IArguments } from '@glimmer/runtime/dist/types/lib/vm/arguments'; import { Destroyable, Opaque, - Option + Option } from '@glimmer/util'; import { DEBUG } from 'ember-env-flags'; import DebugStack from '../utils/debug-stack'; @@ -51,9 +51,9 @@ export default abstract class AbstractManager implements ComponentManager< abstract layoutFor( definition: any, component: T, - env: Environment): Invocation; + env: Environment): VMHandle; abstract getSelf(component: T): VersionedPathReference; - abstract getCapabilities(state: U): ComponentCapabilities; + abstract getCapabilities(state: U): ComponentCapabilities; didCreateElement(_component: T, _element: Element, _operations: ElementOperations): void { // noop diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 76525127821..ddbe64a6add 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -8,7 +8,6 @@ import { Bounds, ComponentDefinition, ElementOperations, - Invocation, NamedArguments, PositionalArguments, PreparedArguments, @@ -117,8 +116,8 @@ class CurlyComponentLayoutCompiler { compile(builder: any) { builder.wrapLayout(this.template); - builder.tag.dynamic(tagName); - builder.attrs.dynamic('role', ariaRole); + // builder.tag.dynamic(tagName); + // builder.attrs.dynamic('role', ariaRole); builder.attrs.static('class', 'ember-view'); } } @@ -258,7 +257,7 @@ export default class CurlyComponentManager extends AbstractManager{{ValidationError}}

+

{{validationError}}

{{/if}} First name: {{/labeled-textfield}} diff --git a/packages/ember-glimmer/lib/renderer.ts b/packages/ember-glimmer/lib/renderer.ts index c69136593cb..04596d3316d 100644 --- a/packages/ember-glimmer/lib/renderer.ts +++ b/packages/ember-glimmer/lib/renderer.ts @@ -1,6 +1,7 @@ import { Option, Simple } from '@glimmer/interfaces'; import { CURRENT_TAG, VersionedPathReference } from '@glimmer/reference'; import { + clientBuilder, DynamicScope as GlimmerDynamicScope, IteratorResult, } from '@glimmer/runtime'; @@ -78,7 +79,6 @@ class RootState { alwaysRevalidate: boolean; }; public render: () => void; - private _removing: boolean; constructor( root: Opaque, @@ -95,14 +95,18 @@ class RootState { this.result = undefined; this.shouldReflush = false; this.destroyed = false; - this._removing = false; let options = this.options = { alwaysRevalidate: false, }; this.render = () => { - let iterator = template.render(self, parentElement, dynamicScope); + let iterator = template.renderLayout({ + self, + env, + builder: clientBuilder(env, { element: parentElement, nextSibling: null}), + dynamicScope + }); let iteratorResult: IteratorResult; do { diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts new file mode 100644 index 00000000000..4eeaea545ff --- /dev/null +++ b/packages/ember-glimmer/lib/resolver.ts @@ -0,0 +1,39 @@ +import { + RuntimeResolver as IRuntimeResolver +} from '@glimmer/interfaces'; +import { Specifier } from '@glimmer/opcode-compiler'; +import { PartialDefinition } from '@glimmer/runtime/dist/types/lib/partial'; + +import { + lookupComponent, + lookupPartial, +} from 'ember-views'; + +export default class RuntimeResolver implements IRuntimeResolver { + private partialsCache: PartialDefinition[]; + + constructor(public owner: any) { + this.partialsCache = []; + } + + lookupComponent(name: string, meta: Specifier) { + return lookupComponent(name, this.owner, meta); + } + + lookupPartial(name: string, _meta: Specifier) { + const partial = this.partialsCache.find(partial => partial.name === name); + let idx; + if (partial) { + idx = this.partialsCache.indexOf(partial); + } else { + this.partialsCache.push(lookupPartial(name, this.owner)); + idx = this.partialsCache.length - 1; + } + return idx; + } + + resolve(specifier: number) { + const cache = this.cacheFor[specifier]; + return cache[specifier] as T; + } +} \ No newline at end of file diff --git a/packages/ember-glimmer/lib/template.ts b/packages/ember-glimmer/lib/template.ts index 83962ae9dec..0dedce1a81f 100644 --- a/packages/ember-glimmer/lib/template.ts +++ b/packages/ember-glimmer/lib/template.ts @@ -1,10 +1,22 @@ +import { + LazyConstants, + Program +} from '@glimmer/program'; import { Template, templateFactory, TemplateFactory, } from '@glimmer/runtime'; +import { + EagerOpcodeBuilder, + OpcodeBuilderConstructor, + Macros +} from '@glimmer/opcode-compiler'; import { OWNER } from 'ember-utils'; +import RuntimeResolver from './resolver'; +import CompileTimeLookup from './compile-time-lookup'; + export interface Container { lookup(name: string): T; factoryFor(name: string): T; @@ -31,8 +43,14 @@ export class WrappedTemplateFactory { } create(props: any): OwnedTemplate { - let owner = props[OWNER]; - return this.factory.create(props.env, { owner }); + const owner = props[OWNER]; + const resolver = new RuntimeResolver(owner); + return this.factory.create({ + program: new Program(new LazyConstants(resolver)), + macros: new Macros(), + lookup: new CompileTimeLookup(resolver), + Builder: EagerOpcodeBuilder as OpcodeBuilderConstructor + }, { owner }); } } diff --git a/packages/ember-glimmer/lib/template_registry.ts b/packages/ember-glimmer/lib/template_registry.ts index cdc842de852..2a8896dc3fd 100644 --- a/packages/ember-glimmer/lib/template_registry.ts +++ b/packages/ember-glimmer/lib/template_registry.ts @@ -3,7 +3,7 @@ import { WrappedTemplateFactory } from './template'; // to support Ember.TEMPLATES but shield ember internals from this legacy // global API. interface TemplatesRegistry { - [name: string]: WrappedTemplateFactory + [name: string]: WrappedTemplateFactory; } let TEMPLATES: TemplatesRegistry = {}; From a09f6bb781ef415de58b529affcf1205e71fb369 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Fri, 17 Nov 2017 15:43:29 -0800 Subject: [PATCH 003/135] simple type fixes --- packages/ember-glimmer/lib/helpers/get.ts | 6 +++--- packages/ember-views/lib/index.d.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ember-glimmer/lib/helpers/get.ts b/packages/ember-glimmer/lib/helpers/get.ts index 5398f1c3042..f67f53999df 100644 --- a/packages/ember-glimmer/lib/helpers/get.ts +++ b/packages/ember-glimmer/lib/helpers/get.ts @@ -3,7 +3,7 @@ import { CONSTANT_TAG, isConst, PathReference, - referenceFromParts, + referenceForParts, TagWrapper, UpdatableTag, } from '@glimmer/reference'; @@ -78,7 +78,7 @@ class GetHelperReference extends CachedReference { static create(sourceReference: any, pathReference: PathReference) { if (isConst(pathReference)) { let parts = pathReference.value().split('.'); - return referenceFromParts(sourceReference, parts); + return referenceForParts(sourceReference, parts); } else { return new GetHelperReference(sourceReference, pathReference); } @@ -107,7 +107,7 @@ class GetHelperReference extends CachedReference { let pathType = typeof path; if (pathType === 'string') { - innerReference = referenceFromParts(this.sourceReference, path.split('.')); + innerReference = referenceForParts(this.sourceReference, path.split('.')); } else if (pathType === 'number') { innerReference = this.sourceReference.get('' + path); } diff --git a/packages/ember-views/lib/index.d.ts b/packages/ember-views/lib/index.d.ts index 179f14209b3..eae29b2cd8d 100644 --- a/packages/ember-views/lib/index.d.ts +++ b/packages/ember-views/lib/index.d.ts @@ -1,5 +1,5 @@ import { Opaque } from '@glimmer/util'; -import { Simple } from '@glimmer/runtime'; +import { Simple } from '@glimmer/interfaces'; export const ActionSupport: any; export const ChildViewsSupport: any; From 9f61acdde04719b84b9bbe654fc43418055ee3ad Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Fri, 17 Nov 2017 17:54:21 -0800 Subject: [PATCH 004/135] bump glimmer-vm because Tom's done cleanup in the resolver area. --- package.json | 22 ++-- packages/ember-utils/lib/index.d.ts | 13 ++- packages/ember-views/lib/index.d.ts | 3 +- yarn.lock | 164 ++++++++++++++-------------- 4 files changed, 107 insertions(+), 95 deletions(-) diff --git a/package.json b/package.json index 16433db381d..0bdff53550c 100644 --- a/package.json +++ b/package.json @@ -42,12 +42,12 @@ "test:testem": "testem -f testem.dist.json" }, "dependencies": { - "@glimmer/compiler": "^0.29.10", - "@glimmer/node": "^0.29.10", - "@glimmer/program": "^0.29.10", - "@glimmer/reference": "^0.29.10", - "@glimmer/runtime": "^0.29.10", - "@glimmer/vm": "^0.29.10", + "@glimmer/compiler": "^0.30.2", + "@glimmer/node": "^0.30.2", + "@glimmer/program": "^0.30.2", + "@glimmer/reference": "^0.30.2", + "@glimmer/runtime": "^0.30.2", + "@glimmer/vm": "^0.30.2", "broccoli-funnel": "^2.0.1", "broccoli-merge-trees": "^2.0.0", "ember-cli-get-component-path-option": "^1.0.0", @@ -64,11 +64,11 @@ "resolve": "^1.3.3" }, "devDependencies": { - "@glimmer/compiler": "^0.29.10", - "@glimmer/node": "^0.29.10", - "@glimmer/reference": "^0.29.10", - "@glimmer/runtime": "^0.29.10", - "@glimmer/vm": "^0.29.10", + "@glimmer/compiler": "^0.30.2", + "@glimmer/node": "^0.30.2", + "@glimmer/reference": "^0.30.2", + "@glimmer/runtime": "^0.30.2", + "@glimmer/vm": "^0.30.2", "aws-sdk": "^2.46.0", "babel-plugin-check-es2015-constants": "^6.22.0", "babel-plugin-debug-macros": "^0.1.10", diff --git a/packages/ember-utils/lib/index.d.ts b/packages/ember-utils/lib/index.d.ts index 04694a4db12..b6e4c921ed2 100644 --- a/packages/ember-utils/lib/index.d.ts +++ b/packages/ember-utils/lib/index.d.ts @@ -1,7 +1,18 @@ import { Opaque } from '@glimmer/interfaces'; +export interface Factory { + create(options: any): T; +} + +export interface Owner { + lookup(fullName: string, options?: { source: string }): T; + lookup(fullName: string, options?: { source: string }): any; + factoryFor(fullName: string, options?: { source: string }): Factory; + factoryFor(fullName: string, options?: { source: string }): Factory; +} + export const NAME_KEY: string; -export function getOwner(obj: any): any; +export function getOwner(obj: {}): Owner; export function symbol(debugName: string): string; export function assign(original: any, ...args: any[]): any; export const OWNER: string; diff --git a/packages/ember-views/lib/index.d.ts b/packages/ember-views/lib/index.d.ts index eae29b2cd8d..f5af9fb9bdc 100644 --- a/packages/ember-views/lib/index.d.ts +++ b/packages/ember-views/lib/index.d.ts @@ -1,5 +1,6 @@ import { Opaque } from '@glimmer/util'; import { Simple } from '@glimmer/interfaces'; +import { Owner } from 'ember-utils'; export const ActionSupport: any; export const ChildViewsSupport: any; @@ -18,7 +19,7 @@ export function constructStyleDeprecationMessage(affectedStyle: any): string; export function hasPartial(name: string, owner: any): boolean; -export function lookupComponent(owner: any, name: string, options: any): any; +export function lookupComponent(owner: Owner, name: string, options?: { source?: string }): any; export function lookupPartial(templateName: string, owner: any): any; diff --git a/yarn.lock b/yarn.lock index 9507c05780e..14fa4fb1a9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,117 +2,117 @@ # yarn lockfile v1 -"@glimmer/compiler@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.29.10.tgz#b0a3d53069605d78fdf1bf1bc3be28ae81402342" - dependencies: - "@glimmer/interfaces" "^0.29.10" - "@glimmer/syntax" "^0.29.10" - "@glimmer/util" "^0.29.10" - "@glimmer/wire-format" "^0.29.10" +"@glimmer/compiler@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.30.2.tgz#30dd08ca2473ca3b258f9b236e06a1cb7947288f" + dependencies: + "@glimmer/interfaces" "^0.30.2" + "@glimmer/syntax" "^0.30.2" + "@glimmer/util" "^0.30.2" + "@glimmer/wire-format" "^0.30.2" simple-html-tokenizer "^0.4.1" -"@glimmer/encoder@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.29.10.tgz#a49c61a0794d2e1b218ec0a563d0f84dca08334c" +"@glimmer/encoder@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.30.2.tgz#a9ae83636caa4890fd26fd9c34410cab54e15391" -"@glimmer/interfaces@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.29.10.tgz#7744451ca329a42c62b08fa460808bccbddeb2ab" +"@glimmer/interfaces@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.30.2.tgz#5b34ec121e23ee73e518902f09b6d4f60d3bf507" dependencies: - "@glimmer/wire-format" "^0.29.10" + "@glimmer/wire-format" "^0.30.2" -"@glimmer/node@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.29.10.tgz#ba8a5cb45784a46bbb50c454c56d2188b82d97ab" +"@glimmer/node@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.30.2.tgz#de2548558164a03dea2dcc901e6fc6c2c33c83c5" dependencies: - "@glimmer/compiler" "^0.29.10" - "@glimmer/interfaces" "^0.29.10" - "@glimmer/object-reference" "^0.29.10" - "@glimmer/runtime" "^0.29.10" + "@glimmer/compiler" "^0.30.2" + "@glimmer/interfaces" "^0.30.2" + "@glimmer/object-reference" "^0.30.2" + "@glimmer/runtime" "^0.30.2" simple-dom "^0.3.0" -"@glimmer/object-reference@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/object-reference/-/object-reference-0.29.10.tgz#9e0acc15779611d306b66819088b0aee2cf06a48" +"@glimmer/object-reference@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/object-reference/-/object-reference-0.30.2.tgz#6b08dfd3aabc5279dc137dd8224d145cf1511a01" dependencies: - "@glimmer/reference" "^0.29.10" - "@glimmer/util" "^0.29.10" + "@glimmer/reference" "^0.30.2" + "@glimmer/util" "^0.30.2" -"@glimmer/object@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/object/-/object-0.29.10.tgz#ce450757598274e476f73f61a3a36a26f81642e5" +"@glimmer/object@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/object/-/object-0.30.2.tgz#b66a2beaa1de28987ff0d4155d8d658527756b82" dependencies: - "@glimmer/object-reference" "^0.29.10" - "@glimmer/util" "^0.29.10" + "@glimmer/object-reference" "^0.30.2" + "@glimmer/util" "^0.30.2" -"@glimmer/opcode-compiler@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/opcode-compiler/-/opcode-compiler-0.29.10.tgz#37bb4413e614e442c908d2a38725c9358e4c7e45" +"@glimmer/opcode-compiler@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/opcode-compiler/-/opcode-compiler-0.30.2.tgz#4fe6f06302af2381e6cfb315c306092c0ea3a34e" dependencies: - "@glimmer/encoder" "^0.29.10" - "@glimmer/interfaces" "^0.29.10" - "@glimmer/program" "^0.29.10" - "@glimmer/syntax" "^0.29.10" - "@glimmer/util" "^0.29.10" - "@glimmer/vm" "^0.29.10" - "@glimmer/wire-format" "^0.29.10" + "@glimmer/encoder" "^0.30.2" + "@glimmer/interfaces" "^0.30.2" + "@glimmer/program" "^0.30.2" + "@glimmer/syntax" "^0.30.2" + "@glimmer/util" "^0.30.2" + "@glimmer/vm" "^0.30.2" + "@glimmer/wire-format" "^0.30.2" simple-html-tokenizer "^0.4.1" -"@glimmer/program@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.29.10.tgz#c9a2facda2812b6314f3f7f2153cd51f5e51bfba" +"@glimmer/program@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.30.2.tgz#189ff3fe126a4104d2495b8b35bffda4ef835d04" dependencies: - "@glimmer/encoder" "^0.29.10" - "@glimmer/interfaces" "^0.29.10" - "@glimmer/util" "^0.29.10" + "@glimmer/encoder" "^0.30.2" + "@glimmer/interfaces" "^0.30.2" + "@glimmer/util" "^0.30.2" -"@glimmer/reference@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.29.10.tgz#fc5db84f5b2a9aeef28e1407a54679cf5817acab" +"@glimmer/reference@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.30.2.tgz#4a06d3c03b4f490cec38451342fdce8aa7af4d30" dependencies: - "@glimmer/util" "^0.29.10" + "@glimmer/util" "^0.30.2" -"@glimmer/runtime@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.29.10.tgz#90dce95aa6b596ff1134a11de1c77f50110c38b9" +"@glimmer/runtime@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.30.2.tgz#ef876cec85049c8cef0c4a0a6cee1a93e5be9bb6" dependencies: - "@glimmer/interfaces" "^0.29.10" - "@glimmer/object" "^0.29.10" - "@glimmer/object-reference" "^0.29.10" - "@glimmer/opcode-compiler" "^0.29.10" - "@glimmer/program" "^0.29.10" - "@glimmer/reference" "^0.29.10" - "@glimmer/util" "^0.29.10" - "@glimmer/vm" "^0.29.10" - "@glimmer/wire-format" "^0.29.10" + "@glimmer/interfaces" "^0.30.2" + "@glimmer/object" "^0.30.2" + "@glimmer/object-reference" "^0.30.2" + "@glimmer/opcode-compiler" "^0.30.2" + "@glimmer/program" "^0.30.2" + "@glimmer/reference" "^0.30.2" + "@glimmer/util" "^0.30.2" + "@glimmer/vm" "^0.30.2" + "@glimmer/wire-format" "^0.30.2" -"@glimmer/syntax@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.29.10.tgz#2a074223fc3b42d49c8b9345684a80b5133dc030" +"@glimmer/syntax@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.30.2.tgz#c1acbf44d4c73e7b112192c398e71476cd24e825" dependencies: - "@glimmer/interfaces" "^0.29.10" - "@glimmer/util" "^0.29.10" + "@glimmer/interfaces" "^0.30.2" + "@glimmer/util" "^0.30.2" handlebars "^4.0.6" simple-html-tokenizer "^0.4.1" -"@glimmer/util@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.29.10.tgz#8662daf273ffef9254b8d943d39aa396ed7225a5" +"@glimmer/util@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.30.2.tgz#dd3ed4293b97ce7d89f3b8682381e666c43ba6d7" -"@glimmer/vm@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.29.10.tgz#e723ea7d23960dd470cc73ec31e02fd74cab2cd8" +"@glimmer/vm@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.30.2.tgz#cb2bc6f29ebcfceb6506ecd6d97c832a22aa8106" dependencies: - "@glimmer/interfaces" "^0.29.10" - "@glimmer/program" "^0.29.10" - "@glimmer/util" "^0.29.10" + "@glimmer/interfaces" "^0.30.2" + "@glimmer/program" "^0.30.2" + "@glimmer/util" "^0.30.2" -"@glimmer/wire-format@^0.29.10": - version "0.29.10" - resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.29.10.tgz#90e82f67a6325468d6fee4f8dd7affc1070a9557" +"@glimmer/wire-format@^0.30.2": + version "0.30.2" + resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.30.2.tgz#ce4a4c903ada28ee2c62b857b69dfdc06512f53a" dependencies: - "@glimmer/util" "^0.29.10" + "@glimmer/util" "^0.30.2" abbrev@1: version "1.1.0" From c3a8ba3a209b25f6a64dfba1aeec82ae0fbc3d3f Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Sat, 18 Nov 2017 02:33:06 -0800 Subject: [PATCH 005/135] improve types --- packages/container/lib/index.d.ts | 3 +- packages/ember-glimmer/lib/template.ts | 48 +++++++++++++------------- packages/ember-utils/lib/index.d.ts | 22 +++++++++--- packages/ember-views/lib/index.d.ts | 20 ++++++++--- 4 files changed, 58 insertions(+), 35 deletions(-) diff --git a/packages/container/lib/index.d.ts b/packages/container/lib/index.d.ts index fe97d1abc0f..8dbde3f5450 100644 --- a/packages/container/lib/index.d.ts +++ b/packages/container/lib/index.d.ts @@ -1,6 +1,7 @@ +import { Owner } from 'ember-utils'; interface Container { registry: any; - owner: any | null; + owner: Owner | null; cache: any | null; factoryManagerCache: any | null; isDestroyed: boolean; diff --git a/packages/ember-glimmer/lib/template.ts b/packages/ember-glimmer/lib/template.ts index 0dedce1a81f..ffe6ae7db5a 100644 --- a/packages/ember-glimmer/lib/template.ts +++ b/packages/ember-glimmer/lib/template.ts @@ -1,3 +1,9 @@ +import { + EagerOpcodeBuilder, + Macros, + OpcodeBuilderConstructor, + TemplateOptions +} from '@glimmer/opcode-compiler'; import { LazyConstants, Program @@ -7,58 +13,52 @@ import { templateFactory, TemplateFactory, } from '@glimmer/runtime'; -import { - EagerOpcodeBuilder, - OpcodeBuilderConstructor, - Macros -} from '@glimmer/opcode-compiler'; -import { OWNER } from 'ember-utils'; - -import RuntimeResolver from './resolver'; +import { OWNER, Owner } from 'ember-utils'; +import { TemplateMeta } from 'ember-views'; import CompileTimeLookup from './compile-time-lookup'; +import RuntimeResolver from './resolver'; -export interface Container { - lookup(name: string): T; - factoryFor(name: string): T; - buildChildEngineInstance(name: string): T; - hasRegistration(name: string, options?: any): boolean; -} - -export type OwnedTemplate = Template<{ - moduleName: string; - owner: Container; -}>; +export type OwnedTemplate = Template; export class WrappedTemplateFactory { id: string; meta: { moduleName: string; + managerId?: string; }; constructor(public factory: TemplateFactory<{ moduleName: string; + managerId?: string; }>) { this.id = factory.id; this.meta = factory.meta; } create(props: any): OwnedTemplate { - const owner = props[OWNER]; + const owner: Owner = props[OWNER]; const resolver = new RuntimeResolver(owner); - return this.factory.create({ + // I'm pretty sure there is only supposed to be one of these + // injected into all templates. + const options: TemplateOptions<{ + moduleName: string; + managerId?: string; + }> = { program: new Program(new LazyConstants(resolver)), macros: new Macros(), - lookup: new CompileTimeLookup(resolver), + resolver: new CompileTimeLookup(resolver), Builder: EagerOpcodeBuilder as OpcodeBuilderConstructor - }, { owner }); + }; + return this.factory.create(options, { owner }); } } export default function template(json: any) { const factory = templateFactory<{ moduleName: string; + managerId?: string; }, { - owner: Container; + owner: Owner; }>(json); return new WrappedTemplateFactory(factory); } diff --git a/packages/ember-utils/lib/index.d.ts b/packages/ember-utils/lib/index.d.ts index b6e4c921ed2..234f5648c9b 100644 --- a/packages/ember-utils/lib/index.d.ts +++ b/packages/ember-utils/lib/index.d.ts @@ -1,14 +1,26 @@ import { Opaque } from '@glimmer/interfaces'; export interface Factory { - create(options: any): T; + class: any; + fullName: string; + normalizedName: string; + create(props?: { [prop: string]: any; }): T; +} + +export interface LookupOptions { + source: string; } export interface Owner { - lookup(fullName: string, options?: { source: string }): T; - lookup(fullName: string, options?: { source: string }): any; - factoryFor(fullName: string, options?: { source: string }): Factory; - factoryFor(fullName: string, options?: { source: string }): Factory; + lookup(fullName: string, options?: LookupOptions): T; + lookup(fullName: string, options?: LookupOptions): any; + factoryFor(fullName: string, options?: LookupOptions): Factory; + factoryFor(fullName: string, options?: LookupOptions): Factory; + buildChildEngineInstance(name: string): T; + hasRegistration(name: string, options?: LookupOptions): boolean; + + // maybe not needed, we were only using for cache key + _resolveLocalLookupName(name: string, source: string): any; } export const NAME_KEY: string; diff --git a/packages/ember-views/lib/index.d.ts b/packages/ember-views/lib/index.d.ts index f5af9fb9bdc..210c5f17d12 100644 --- a/packages/ember-views/lib/index.d.ts +++ b/packages/ember-views/lib/index.d.ts @@ -1,6 +1,13 @@ import { Opaque } from '@glimmer/util'; import { Simple } from '@glimmer/interfaces'; -import { Owner } from 'ember-utils'; +import { Template } from '@glimmer/runtime'; +import { Owner, Factory } from 'ember-utils'; + +export interface TemplateMeta { + owner: Owner; + moduleName: string; + managerId?: string; +} export const ActionSupport: any; export const ChildViewsSupport: any; @@ -10,8 +17,8 @@ export const ViewMixin: any; export const ViewStateSupport: any; export const TextSupport: any; -export function getViewElement(view: Opaque): Element; -export function setViewElement(view: Opaque, element: Element | null): void; +export function getViewElement(view: Opaque): Simple.Element; +export function setViewElement(view: Opaque, element: Simple.Element | null): void; export function isSimpleClick(event: Event): boolean; @@ -19,9 +26,12 @@ export function constructStyleDeprecationMessage(affectedStyle: any): string; export function hasPartial(name: string, owner: any): boolean; -export function lookupComponent(owner: Owner, name: string, options?: { source?: string }): any; +export function lookupComponent(owner: Owner, name: string, options?: { source?: string }): { + layout: Template; + component: Factory; +}; -export function lookupPartial(templateName: string, owner: any): any; +export function lookupPartial(templateName: string, owner: Owner): any; export function getViewId(view: any): string; From 636f95bfe835c12d20df2de7f7484665c4dd627d Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Sat, 18 Nov 2017 02:39:40 -0800 Subject: [PATCH 006/135] more resolver stuff --- .../ember-glimmer/lib/compile-time-lookup.ts | 49 ++-- .../lib/component-managers/curly.ts | 50 ++-- .../lib/component-managers/root.ts | 17 +- packages/ember-glimmer/lib/environment.ts | 233 +----------------- packages/ember-glimmer/lib/renderer.ts | 12 +- packages/ember-glimmer/lib/resolver.ts | 212 ++++++++++++++-- .../lib/utils/curly-component-state-bucket.ts | 1 + tslint.json | 7 +- 8 files changed, 267 insertions(+), 314 deletions(-) diff --git a/packages/ember-glimmer/lib/compile-time-lookup.ts b/packages/ember-glimmer/lib/compile-time-lookup.ts index 6e98c0aa95e..a8ed20a3510 100644 --- a/packages/ember-glimmer/lib/compile-time-lookup.ts +++ b/packages/ember-glimmer/lib/compile-time-lookup.ts @@ -1,41 +1,36 @@ -import { CompileTimeLookup as ICompileTimeLookup, Specifier } from '@glimmer/opcode-compiler'; -import { - CAPABILITIES -} from './component-managers/definition-state'; +import { ComponentCapabilities, Option, ProgramSymbolTable } from '@glimmer/interfaces'; +import { CompileTimeLookup as ICompileTimeLookup } from '@glimmer/opcode-compiler'; +import { CompilableTemplate, ComponentDefinition } from '@glimmer/runtime'; +import { TemplateMeta } from 'ember-views'; import RuntimeResolver from './resolver'; -import { CurlyComponentDefinition } from 'ember-glimmer/lib/component-managers/curly'; -export default class CompileTimeLookup implements ICompileTimeLookup { +export default class CompileTimeLookup implements ICompileTimeLookup { constructor(private resolver: RuntimeResolver) {} - private getComponentDefinition(handle: number) { - return this.resolver.resolve>(handle); - } - getCapabilities(handle: number) { - return this.getComponentDefinition(handle).getCapabilities(); - } - getLayout(handle: number) { - const componentDefintion = this.resolver.resolve(handle); - const { manager } = componentDefintion; - return { - compile() { return handle; }, - symbolTable: null - }; + getCapabilities(handle: number): ComponentCapabilities { + let definition = this.resolver.resolve>(handle); + let { manager, state } = definition!; + return manager.getCapabilities(state); } - lookupHelper(handle: number) { - + getLayout(_handle: number): Option> { + // const componentDefintion: CurlyComponentDefinition = this.resolver.resolve(handle); + return null; } - lookupModifier(handle: number) { - + lookupHelper(name: string, referrer: TemplateMeta): Option { + return this.resolver.lookupHelper(name, referrer); } - lookupComponentSpec(handle: number) { - + lookupModifier(name: string, referrer: TemplateMeta): Option { + return this.resolver.lookupModifier(name, referrer); } - lookupPartial(handle: number) { + lookupComponentDefinition(name: string, referrer: TemplateMeta): Option { + return this.resolver.lookupComponentDefinition(name, referrer); + } + lookupPartial(name: string, referrer: TemplateMeta): Option { + return this.resolver.lookupPartial(name, referrer); } -} \ No newline at end of file +} diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index ddbe64a6add..6017c740c0b 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -1,3 +1,9 @@ +import { + ComponentCapabilities, + Option, + Simple, + VMHandle +} from '@glimmer/interfaces'; import { combineTagged, Tag, @@ -8,19 +14,15 @@ import { Bounds, ComponentDefinition, ElementOperations, + Invocation, NamedArguments, PositionalArguments, PreparedArguments, PrimitiveReference, - VM, + WithDynamicLayout, + WithDynamicTagName, } from '@glimmer/runtime'; import { Destroyable, Opaque } from '@glimmer/util'; -import { - ComponentCapabilities, - Option, - Simple, - VMHandle -} from '@glimmer/interfaces'; import { privatize as P } from 'container'; import { assert, @@ -34,7 +36,7 @@ import { assign, OWNER, } from 'ember-utils'; -import { setViewElement } from 'ember-views'; +import { setViewElement, TemplateMeta } from 'ember-views'; import { BOUNDS, DIRTY_TAG, @@ -44,6 +46,7 @@ import { } from '../component'; import Environment from '../environment'; import { DynamicScope } from '../renderer'; +import RuntimeResolver from '../resolver'; import { OwnedTemplate, WrappedTemplateFactory } from '../template'; import { AttributeBinding, @@ -95,16 +98,17 @@ function applyAttributeBindings(element: Simple.Element, attributeBindings: any, } } -function tagName(vm: VM) { - let dynamicScope: DynamicScope = vm.dynamicScope() as DynamicScope; - // tslint:disable-next-line:no-shadowed-variable - let { tagName } = dynamicScope.view!; - return PrimitiveReference.create(tagName === '' ? null : tagName || 'div'); -} +// TODO there is a hook for dynamic attributes +// function tagName(vm: VM) { +// let dynamicScope: DynamicScope = vm.dynamicScope() as DynamicScope; +// // tslint:disable-next-line:no-shadowed-variable +// let { tagName } = dynamicScope.view!; +// return PrimitiveReference.create(tagName === '' ? null : tagName || 'div'); +// } -function ariaRole(vm: VM) { - return vm.getSelf().get('ariaRole'); -} +// function ariaRole(vm: VM) { +// return vm.getSelf().get('ariaRole'); +// } class CurlyComponentLayoutCompiler { static id: string; @@ -142,7 +146,17 @@ export class PositionalArgumentReference { } } -export default class CurlyComponentManager extends AbstractManager { +export default class CurlyComponentManager extends AbstractManager + implements WithDynamicTagName, + WithDynamicLayout { + + getDynamicLayout(_component: Opaque, _resolver: RuntimeResolver): Invocation { + throw new Error('Method not implemented.'); + } + + getTagName(_component: Opaque): Option { + throw new Error('Method not implemented.'); + } getCapabilities(state: DefinitionState): ComponentCapabilities { return state.capabilities; diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index abb274c5f65..d8b7806b3f4 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -6,25 +6,25 @@ import { ComponentDefinition } from '@glimmer/runtime'; import { - Option, Opaque + Option } from '@glimmer/util'; import { DEBUG } from 'ember-env-flags'; import { _instrumentStart, } from 'ember-metal'; -import ComponentStateBucket from '../utils/curly-component-state-bucket'; +import Environment from '../environment'; +import { DynamicScope } from '../renderer'; +import ComponentStateBucket, { Component } from '../utils/curly-component-state-bucket'; import CurlyComponentManager, { initialRenderInstrumentDetails, processComponentInitializationAssertions, } from './curly'; -import { DynamicScope, View } from '../renderer'; -import Environment from '../environment'; import DefintionState, { CAPABILITIES } from './definition-state'; class RootComponentManager extends CurlyComponentManager { - component: View; + component: Component; - constructor(component: View) { + constructor(component: Component) { super(); this.component = component; } @@ -66,14 +66,13 @@ class RootComponentManager extends CurlyComponentManager { export class RootComponentDefinition implements ComponentDefinition { public state: DefintionState; - public manager: RootComponentManager; - constructor(name: string, _manager: RootComponentManager, ComponentClass: any, handle: Option) { + constructor(name: string, public manager: RootComponentManager, ComponentClass: any, handle: Option) { this.state = { name, ComponentClass, handle, capabilities: CAPABILITIES - } + }; } } diff --git a/packages/ember-glimmer/lib/environment.ts b/packages/ember-glimmer/lib/environment.ts index 51ce47606eb..3607a3144b4 100644 --- a/packages/ember-glimmer/lib/environment.ts +++ b/packages/ember-glimmer/lib/environment.ts @@ -1,89 +1,38 @@ import { Simple, - VMHandle } from '@glimmer/interfaces'; -import { - WrappedBuilder -} from '@glimmer/opcode-compiler'; import { Reference, } from '@glimmer/reference'; import { - ComponentDefinition, DynamicAttributeFactory, Environment as GlimmerEnvironment, - getDynamicVar, - Helper, - ModifierManager, PrimitiveReference, - PartialDefinition, } from '@glimmer/runtime'; import { Destroyable, Opaque, } from '@glimmer/util'; import { warn } from 'ember-debug'; import { DEBUG } from 'ember-env-flags'; -import { _instrumentStart, Cache } from 'ember-metal'; -import { guidFor, OWNER } from 'ember-utils'; +import { OWNER, Owner } from 'ember-utils'; import { constructStyleDeprecationMessage, - hasPartial, lookupComponent, - lookupPartial, } from 'ember-views'; -import { - CurlyComponentDefinition, -} from './component-managers/curly'; -import { - CAPABILITIES -} from './component-managers/definition-state'; import DebugStack from './utils/debug-stack'; import createIterable from './utils/iterable'; import { - ClassBasedHelperReference, ConditionalReference, RootPropertyReference, - SimpleHelperReference, UpdatableReference, } from './utils/references'; -import { default as classHelper } from './helpers/-class'; -import { default as htmlSafeHelper } from './helpers/-html-safe'; -import { default as inputTypeHelper } from './helpers/-input-type'; -import { default as normalizeClassHelper } from './helpers/-normalize-class'; -import { default as action } from './helpers/action'; -import { default as componentHelper } from './helpers/component'; -import { default as concat } from './helpers/concat'; -import { default as eachIn } from './helpers/each-in'; -import { default as get } from './helpers/get'; -import { default as hash } from './helpers/hash'; -import { - inlineIf, - inlineUnless, -} from './helpers/if-unless'; -import { default as loc } from './helpers/loc'; -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 { default as ActionModifierManager } from './modifiers/action'; import installPlatformSpecificProtocolForURL from './protocol-for-url'; import { EMBER_MODULE_UNIFICATION, - GLIMMER_CUSTOM_COMPONENT_MANAGER, } from 'ember/features'; -import { Container, OwnedTemplate, WrappedTemplateFactory } from './template'; - -function instrumentationPayload(name: string) { - return { object: `component:${name}` }; -} - -function isTemplateFactory(template: OwnedTemplate | WrappedTemplateFactory): template is WrappedTemplateFactory { - return typeof (template as WrappedTemplateFactory).create === 'function'; -} +import { OwnedTemplate } from './template'; export interface CompilerFactory { id: string; @@ -95,27 +44,12 @@ export default class Environment extends GlimmerEnvironment { return new this(options); } - public owner: Container; + public owner: Owner; public isInteractive: boolean; public destroyedComponents: Destroyable[]; - public builtInModifiers: { - [name: string]: ModifierManager; - }; - public builtInHelpers: { - [name: string]: Helper; - }; + public debugStack: typeof DebugStack; public inTransaction: boolean; - private _definitionCache: Cache<{ - name: string; - source: string; - owner: Container; - }, CurlyComponentDefinition | undefined>; - private _templateCache: Cache<{ - Template: WrappedTemplateFactory | OwnedTemplate; - owner: Container; - }, OwnedTemplate>; - private _compilerCache: Cache>; constructor(injections: any) { super(injections); @@ -127,73 +61,6 @@ export default class Environment extends GlimmerEnvironment { installPlatformSpecificProtocolForURL(this); - this._definitionCache = new Cache(2000, ({ name, source, owner }) => { - let { component: componentFactory, layout } = lookupComponent(owner, name, { source }); - let customManager: any; - if (componentFactory || layout) { - if (GLIMMER_CUSTOM_COMPONENT_MANAGER) { - let managerId = layout && layout.meta.managerId; - - if (managerId) { - customManager = owner.factoryFor(`component-manager:${managerId}`).class; - } - } - return new CurlyComponentDefinition(name, customManager, undefined, layout, customManager); - } - return undefined; - }, ({ name, source, owner }) => { - let expandedName = source && this._resolveLocalLookupName(name, source, owner) || name; - - let ownerGuid = guidFor(owner); - - return `${ownerGuid}|${expandedName}`; - }); - - this._templateCache = new Cache(1000, ({ Template, owner }) => { - if (isTemplateFactory(Template)) { - // we received a factory - return Template.create({ env: this, [OWNER]: owner }); - } else { - // we were provided an instance already - return Template; - } - }, ({ Template, owner }) => `${guidFor(owner)}|${Template.id}`); - - this._compilerCache = new Cache(10, (Compiler) => { - return new Cache(2000, (template) => { - let compilable = new Compiler(template); - return new WrappedBuilder({asPartial: false, referrer: null}, compilable, CAPABILITIES); - }, (template) => { - let owner = template.owner; - return guidFor(owner) + '|' + template.id; - }); - }, (Compiler) => Compiler.id); - - this.builtInModifiers = { - action: new ActionModifierManager(), - }; - - this.builtInHelpers = { - 'if': inlineIf, - action, - concat, - get, - hash, - loc, - log, - mut, - 'query-params': queryParams, - readonly, - unbound, - 'unless': inlineUnless, - '-class': classHelper, - '-each-in': eachIn, - '-input-type': inputTypeHelper, - '-normalize-class': normalizeClassHelper, - '-html-safe': htmlSafeHelper, - '-get-dynamic-var': getDynamicVar, - }; - if (DEBUG) { this.debugStack = new DebugStack(); } @@ -218,102 +85,10 @@ export default class Environment extends GlimmerEnvironment { } */ - hasComponentDefinition() { - return false; - } - - getComponentDefinition(name: string, { owner, moduleName }: any): ComponentDefinition { - let finalizer = _instrumentStart('render.getComponentDefinition', instrumentationPayload, name); - let source = moduleName && `template:${moduleName}`; - let definition = this._definitionCache.get({ name, source, owner }); - finalizer(); - // TODO the glimmer-vm wants this to always have a def - // but internally we need it to sometimes be undefined - return definition!; - } - - // normally templates should be exported at the proper module name - // and cached in the container, but this cache supports templates - // that have been set directly on the component's layout property - getTemplate(Template: WrappedTemplateFactory, owner: Container): OwnedTemplate { - return this._templateCache.get({ Template, owner }); - } - - // a Compiler can wrap the template so it needs its own cache - getCompiledBlock(Compiler: any, template: OwnedTemplate) { - let compilerCache = this._compilerCache.get(Compiler); - return compilerCache.get(template); - } - - hasPartial(name: string, meta: any): boolean { - return hasPartial(name, meta.owner); - } - - lookupPartial(name: string, meta: any): PartialDefinition { - const template = lookupPartial(name, meta.owner); - const partial = new PartialDefinition( name, lookupPartial(name, meta.owner)); - - if (template) { - return partial; - } else { - throw new Error(`${name} is not a partial`); - } - } - lookupComponent(name: string, meta: any) { return lookupComponent(meta.owner, name, meta); } - hasHelper(name: string, { owner, moduleName }: {owner: Container, moduleName: string}): boolean { - if (name === 'component' || this.builtInHelpers[name]) { - return true; - } - - let options = { source: `template:${moduleName}` }; - - return owner.hasRegistration(`helper:${name}`, options) || - owner.hasRegistration(`helper:${name}`); - } - - lookupHelper(name: string, meta: any): Helper { - if (name === 'component') { - return (vm, args) => componentHelper(vm, args, meta); - } - - let { owner, moduleName } = meta; - let helper = this.builtInHelpers[name]; - - if (helper) { - return helper; - } - - let options = moduleName && { source: `template:${moduleName}` } || {}; - let helperFactory = owner.factoryFor(`helper:${name}`, options) || owner.factoryFor(`helper:${name}`); - - // TODO: try to unify this into a consistent protocol to avoid wasteful closure allocations - if (helperFactory.class.isHelperInstance) { - return (_vm, args) => SimpleHelperReference.create(helperFactory.class.compute, args.capture()); - } else if (helperFactory.class.isHelperFactory) { - return (vm, args) => ClassBasedHelperReference.create(helperFactory, vm, args.capture()); - } else { - throw new Error(`${name} is not a helper`); - } - } - - hasModifier(name: string) { - return !!this.builtInModifiers[name]; - } - - lookupModifier(name: string) { - let modifier = this.builtInModifiers[name]; - - if (modifier) { - return modifier; - } else { - throw new Error(`${name} is not a modifier`); - } - } - toConditionalReference(reference: UpdatableReference): ConditionalReference | RootPropertyReference | PrimitiveReference { return ConditionalReference.create(reference); } diff --git a/packages/ember-glimmer/lib/renderer.ts b/packages/ember-glimmer/lib/renderer.ts index 04596d3316d..871e3ac30fe 100644 --- a/packages/ember-glimmer/lib/renderer.ts +++ b/packages/ember-glimmer/lib/renderer.ts @@ -2,8 +2,11 @@ import { Option, Simple } from '@glimmer/interfaces'; import { CURRENT_TAG, VersionedPathReference } from '@glimmer/reference'; import { clientBuilder, + ComponentDefinition, DynamicScope as GlimmerDynamicScope, IteratorResult, + NULL_REFERENCE, + RenderResult, } from '@glimmer/runtime'; import { Opaque } from '@glimmer/util'; import { assert } from 'ember-debug'; @@ -27,21 +30,14 @@ import ComponentStateBucket, { Component } from './utils/curly-component-state-b import { RootReference } from './utils/references'; import OutletView, { OutletState, RootOutletStateReference } from './views/outlet'; -import { ComponentDefinition, NULL_REFERENCE, RenderResult } from '@glimmer/runtime'; - const { backburner } = run; -export interface View { - tagName: string | null; - appendChild(child: View): void; -} - export class DynamicScope implements GlimmerDynamicScope { outletState: VersionedPathReference>; rootOutletState: RootOutletStateReference | undefined; constructor( - public view: View | null, + public view: Component | null, outletState: VersionedPathReference>, rootOutletState?: RootOutletStateReference) { this.outletState = outletState; diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 4eeaea545ff..f8470c05f87 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -1,39 +1,207 @@ import { - RuntimeResolver as IRuntimeResolver + ComponentDefinition, + Opaque, + Option, + RuntimeResolver as IRuntimeResolver, + VMHandle } from '@glimmer/interfaces'; -import { Specifier } from '@glimmer/opcode-compiler'; -import { PartialDefinition } from '@glimmer/runtime/dist/types/lib/partial'; - +import { getDynamicVar, Helper, ModifierManager, PartialDefinition } from '@glimmer/runtime'; +import { LookupOptions, Owner } from 'ember-utils'; import { lookupComponent, lookupPartial, + TemplateMeta, } from 'ember-views'; +import { GLIMMER_CUSTOM_COMPONENT_MANAGER } from 'ember/features'; +import { CurlyComponentDefinition } from './component-managers/curly'; +import { default as classHelper } from './helpers/-class'; +import { default as htmlSafeHelper } from './helpers/-html-safe'; +import { default as inputTypeHelper } from './helpers/-input-type'; +import { default as normalizeClassHelper } from './helpers/-normalize-class'; +import { default as action } from './helpers/action'; +import { default as componentHelper } from './helpers/component'; +import { default as concat } from './helpers/concat'; +import { default as eachIn } from './helpers/each-in'; +import { default as get } from './helpers/get'; +import { default as hash } from './helpers/hash'; +import { + inlineIf, + inlineUnless, +} from './helpers/if-unless'; +import { default as loc } from './helpers/loc'; +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 { ClassBasedHelperReference, SimpleHelperReference } from './utils/references'; + +function makeOptions(moduleName: string) { + return moduleName !== undefined ? { source: `template:${moduleName}`} : undefined; +} + +export default class RuntimeResolver implements IRuntimeResolver { + public builtInHelpers: { + [name: string]: Helper | undefined; + }; + + public builtInModifiers: { + [name: string]: ModifierManager; + }; + + private handles: any[] = []; + + constructor(public owner: Owner) { + this.builtInHelpers = { + 'if': inlineIf, + action, + concat, + get, + hash, + loc, + log, + mut, + 'query-params': queryParams, + readonly, + unbound, + 'unless': inlineUnless, + '-class': classHelper, + '-each-in': eachIn, + '-input-type': inputTypeHelper, + '-normalize-class': normalizeClassHelper, + '-html-safe': htmlSafeHelper, + '-get-dynamic-var': getDynamicVar, + }; + + this.builtInModifiers = { + action: new ActionModifierManager(), + }; + } + + /*** IRuntimeResolver ***/ + + /** + * Called while executing Append Op.PushDynamicComponentManager if string + */ + lookupComponent(name: string, meta: TemplateMeta): Option { + let handle = this.lookupComponentDefinition(name, meta); + if (handle === null) return null; + return this.resolve(handle); + } + + lookupPartial(name: string, meta: TemplateMeta): Option { + let partial = this._lookupPartial(name, meta); + return this.getHandle(partial); + } -export default class RuntimeResolver implements IRuntimeResolver { - private partialsCache: PartialDefinition[]; + /** + * Called by RuntimeConstants to lookup unresolved handles. + */ + resolve(handle: number): U { + return this.handles[handle]; + } + // End IRuntimeResolver + + /** + * Called by CompileTimeLookup compiling Unknown or Helper OpCode + */ + lookupHelper(name: string, meta: TemplateMeta): Option { + return this.getHandle( + this._lookupHelper(name, meta)); + } - constructor(public owner: any) { - this.partialsCache = []; + /** + * Called by CompileTimeLookup compiling the Component OpCode + */ + lookupComponentDefinition(name: string, meta: TemplateMeta): Option { + return this.getHandle( + this._lookupComponentDefinition(name, meta)); } - lookupComponent(name: string, meta: Specifier) { - return lookupComponent(name, this.owner, meta); + /** + * Called by CompileTimeLookup compiling the + */ + lookupModifier(name: string, _meta: TemplateMeta): Option { + return this.getHandle( + this._lookupModifier(name)); } + // end CompileTimeLookup + + private _lookupHelper(name: string, meta: TemplateMeta): Helper { + if (name === 'component') { + return (vm, args) => componentHelper(vm, args, meta); + } + + let helper = this.builtInHelpers[name]; + if (helper !== undefined) { + return helper; + } + + let { owner, moduleName } = meta; - lookupPartial(name: string, _meta: Specifier) { - const partial = this.partialsCache.find(partial => partial.name === name); - let idx; - if (partial) { - idx = this.partialsCache.indexOf(partial); + let options: LookupOptions | undefined; + if (moduleName !== undefined) { + options = { source: `template:${moduleName}` }; + } + + let helperFactory = owner.factoryFor(`helper:${name}`, options) || owner.factoryFor(`helper:${name}`); + + // TODO: try to unify this into a consistent protocol to avoid wasteful closure allocations + if (helperFactory.class.isHelperInstance) { + return (_vm, args) => SimpleHelperReference.create(helperFactory.class.compute, args.capture()); + } else if (helperFactory.class.isHelperFactory) { + return (vm, args) => ClassBasedHelperReference.create(helperFactory, vm, args.capture()); } else { - this.partialsCache.push(lookupPartial(name, this.owner)); - idx = this.partialsCache.length - 1; + throw new Error(`${name} is not a helper`); } - return idx; } - resolve(specifier: number) { - const cache = this.cacheFor[specifier]; - return cache[specifier] as T; + private _lookupPartial(name: string, meta: TemplateMeta): PartialDefinition { + const template = lookupPartial(name, meta.owner); + const partial = new PartialDefinition( name, lookupPartial(name, meta.owner)); + + if (template) { + return partial; + } else { + throw new Error(`${name} is not a partial`); + } + } + + private _lookupModifier(name: string) { + let modifier = this.builtInModifiers[name]; + if (modifier !== undefined) { + return modifier; + } else { + throw new Error(`${name} is not a modifier`); + } + } + + private _lookupComponentDefinition(name: string, meta: TemplateMeta): Option { + let { layout } = lookupComponent(meta.owner, name, makeOptions(meta.moduleName)); + + let customManager; + if (GLIMMER_CUSTOM_COMPONENT_MANAGER) { + let managerId = layout && layout.referrer.managerId; + + if (managerId) { + customManager = meta.owner.factoryFor(`component-manager:${managerId}`).class; + } + } + + let layoutHandle = this.getHandle(layout) as Option; + + return new CurlyComponentDefinition(name, customManager, undefined, layoutHandle, customManager); + } + + private getHandle(obj: any | null | undefined) { + if (obj === undefined || obj === null) { + return null; + } + let handle: number | undefined = obj.__handle; + if (handle === undefined) { + handle = obj.__handle = this.handles.push(obj) - 1; + } + return handle; } -} \ No newline at end of file +} diff --git a/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts b/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts index d0681ce61b0..ce9863adac4 100644 --- a/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts +++ b/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts @@ -12,6 +12,7 @@ export interface Component { elementId: string; tagName: string; isDestroying: boolean; + appendChild(view: Component): void; trigger(event: string): void; destroy(): void; setProperties(props: { diff --git a/tslint.json b/tslint.json index 0943a1d2394..d1eb7fac9be 100644 --- a/tslint.json +++ b/tslint.json @@ -16,6 +16,11 @@ "semicolon": [true, "always"], "triple-equals": true, "class-name": true, - "no-require-imports": true + "no-require-imports": true, + "no-duplicate-imports": true, + "ordered-imports": true, + "quotemark": { + "options": ["single", "avoid-escape"] + } } } From 32116addd881bab595d467233675717f55bec81e Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Sat, 18 Nov 2017 03:07:10 -0800 Subject: [PATCH 007/135] more fixes and todos --- .../lib/component-managers/curly.ts | 11 ++++++-- .../lib/component-managers/mount.ts | 8 ++++-- .../lib/component-managers/outlet.ts | 28 +++++++++++-------- .../lib/component-managers/render.ts | 9 +++--- .../lib/component-managers/root.ts | 20 ++++--------- .../ember-glimmer/lib/protocol-for-url.ts | 2 +- packages/ember-glimmer/lib/utils/bindings.ts | 6 ++-- packages/ember-glimmer/lib/views/outlet.ts | 10 +++---- 8 files changed, 49 insertions(+), 45 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 6017c740c0b..e8651bd8cd7 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -274,16 +274,21 @@ export default class CurlyComponentManager extends AbstractManager { return bucket; } - layoutFor(_definition: ComponentDefinition, { engine }: EngineBucket, env: Environment) { - let template = engine.lookup(`template:application`); - return env.getCompiledBlock(OutletLayoutCompiler, template); + layoutFor(_definition: ComponentDefinition, _bucket: EngineBucket, _env: Environment) { + // let template = engine.lookup(`template:application`); + throw Error('use resolver.lookupTemplate resolver.compileTemplate'); + // needs to use resolver + // return env.getCompiledBlock(CurlyComponentLayoutCompiler, template); } getSelf(bucket: EngineBucket): VersionedPathReference { diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index 36b3d90c533..e3168605871 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -1,30 +1,30 @@ import { ComponentCapabilities, - Option + Option, + VMHandle } from '@glimmer/interfaces'; +import { + Tag +} from '@glimmer/reference'; import { Arguments, ComponentDefinition, DynamicScope, Environment } from '@glimmer/runtime'; -import { - Tag -} from '@glimmer/reference'; import { Destroyable } from '@glimmer/util/dist/types'; import { DEBUG } from 'ember-env-flags'; import { _instrumentStart } from 'ember-metal'; import { generateGuid, guidFor } from 'ember-utils'; -import EmberEnvironment from '../environment'; +import { DIRTY_TAG } from '../component'; import { OwnedTemplate, WrappedTemplateFactory, } from '../template'; +import { Component } from '../utils/curly-component-state-bucket'; import { RootReference } from '../utils/references'; import AbstractManager from './abstract'; -import { Component } from '../utils/curly-component-state-bucket'; import DefinitionState from './definition-state'; -import { DIRTY_TAG } from '../component'; function instrumentationPayload({ render: { name, outlet } }: {render: {name: string, outlet: string}}) { return { object: `${name}:${outlet}` }; @@ -76,8 +76,13 @@ class OutletComponentManager extends AbstractManager { - layoutFor(definition: RenderDefinition, _bucket: RenderState, env: Environment) { + layoutFor(definition: RenderDefinition, _bucket: RenderState, _env: Environment): VMHandle { // only curly components can have lazy layout assert('definition is missing a template', !!definition.template); - return env.getCompiledBlock(OutletLayoutCompiler, definition.template!); + + throw Error('use resolver.lookupTemplate resolver.compileTemplate'); + // return env.getCompiledBlock(OutletLayoutCompiler, definition.template!); } getSelf({ controller }: RenderState) { diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index d8b7806b3f4..50c8d48935e 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -1,13 +1,7 @@ -import { - VMHandle -} from '@glimmer/interfaces'; import { Arguments, ComponentDefinition } from '@glimmer/runtime'; -import { - Option -} from '@glimmer/util'; import { DEBUG } from 'ember-env-flags'; import { _instrumentStart, @@ -19,7 +13,7 @@ import CurlyComponentManager, { initialRenderInstrumentDetails, processComponentInitializationAssertions, } from './curly'; -import DefintionState, { CAPABILITIES } from './definition-state'; +import DefintionState from './definition-state'; class RootComponentManager extends CurlyComponentManager { component: Component; @@ -65,14 +59,10 @@ class RootComponentManager extends CurlyComponentManager { } export class RootComponentDefinition implements ComponentDefinition { - public state: DefintionState; + state: DefintionState; + manager: RootComponentManager; - constructor(name: string, public manager: RootComponentManager, ComponentClass: any, handle: Option) { - this.state = { - name, - ComponentClass, - handle, - capabilities: CAPABILITIES - }; + constructor(public component: ComponentStateBucket) { + // TODO initialize } } diff --git a/packages/ember-glimmer/lib/protocol-for-url.ts b/packages/ember-glimmer/lib/protocol-for-url.ts index 98cd8582d1a..16f2458e9b2 100644 --- a/packages/ember-glimmer/lib/protocol-for-url.ts +++ b/packages/ember-glimmer/lib/protocol-for-url.ts @@ -1,8 +1,8 @@ /* globals module, URL */ import { environment as emberEnvironment } from 'ember-environment'; -import Environment from './environment'; import { IS_NODE, require } from 'node-module'; +import Environment from './environment'; let nodeURL: any; let parsingNode: HTMLAnchorElement; diff --git a/packages/ember-glimmer/lib/utils/bindings.ts b/packages/ember-glimmer/lib/utils/bindings.ts index 846920cf57c..1ad7524942c 100644 --- a/packages/ember-glimmer/lib/utils/bindings.ts +++ b/packages/ember-glimmer/lib/utils/bindings.ts @@ -19,15 +19,15 @@ import { import { assert } from 'ember-debug'; import { get } from 'ember-metal'; import { String as StringUtils } from 'ember-runtime'; -import { Component } from './curly-component-state-bucket'; import { ROOT_REF } from '../component'; +import { Component } from './curly-component-state-bucket'; import { htmlSafe, isHTMLSafe, SafeString } from './string'; function referenceForKey(component: Component, key: string) { return component[ROOT_REF].get(key); } -function referenceForParts(component: Component, parts: string[]) { +function referenceForParts(component: Component, parts: string[]): Reference { let isAttrs = parts[0] === 'attrs'; // TODO deprecate this @@ -39,7 +39,7 @@ function referenceForParts(component: Component, parts: string[]) { } } - return referenceFromParts(component[ROOT_REF], parts); + return referenceForParts(component[ROOT_REF], parts); } // TODO we should probably do this transform at build time diff --git a/packages/ember-glimmer/lib/views/outlet.ts b/packages/ember-glimmer/lib/views/outlet.ts index 238579daaa5..a4480558c1a 100644 --- a/packages/ember-glimmer/lib/views/outlet.ts +++ b/packages/ember-glimmer/lib/views/outlet.ts @@ -3,9 +3,9 @@ import { DirtyableTag, Tag, TagWrapper, VersionedPathReference } from '@glimmer/ import { Opaque, Option } from '@glimmer/util'; import { environment } from 'ember-environment'; import { run } from 'ember-metal'; -import { assign, OWNER } from 'ember-utils'; +import { assign, OWNER, Owner } from 'ember-utils'; import { Renderer } from '../renderer'; -import { Container, OwnedTemplate } from '../template'; +import { OwnedTemplate } from '../template'; export class RootOutletStateReference implements VersionedPathReference> { tag: Tag; @@ -88,7 +88,7 @@ class ChildOutletStateReference implements VersionedPathReference { } export interface RenderState { - owner: Container | undefined; + owner: Owner | undefined; into: string | undefined; outlet: string; name: string; @@ -112,7 +112,7 @@ export interface BootEnvironment { export default class OutletView { private _environment: BootEnvironment; public renderer: Renderer; - public owner: Container; + public owner: Owner; public template: OwnedTemplate; public outletState: Option; public _tag: TagWrapper; @@ -139,7 +139,7 @@ export default class OutletView { return new OutletView(_environment, renderer, owner, template); } - constructor(_environment: BootEnvironment, renderer: Renderer, owner: Container, template: OwnedTemplate) { + constructor(_environment: BootEnvironment, renderer: Renderer, owner: Owner, template: OwnedTemplate) { this._environment = _environment; this.renderer = renderer; this.owner = owner; From c825a4c8324f4e2609db565ef083f85cc0ad8d80 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Sat, 18 Nov 2017 03:58:39 -0800 Subject: [PATCH 008/135] more WIP --- .../lib/component-managers/mount.ts | 21 ++++++------- .../lib/component-managers/root.ts | 23 ++++++++++++-- packages/ember-glimmer/lib/renderer.ts | 31 +++++++++++++++---- packages/ember-metal/lib/index.d.ts | 2 ++ 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/mount.ts b/packages/ember-glimmer/lib/component-managers/mount.ts index 58d91db9fb7..c5956faa287 100644 --- a/packages/ember-glimmer/lib/component-managers/mount.ts +++ b/packages/ember-glimmer/lib/component-managers/mount.ts @@ -1,31 +1,30 @@ -import { - Arguments, - ComponentDefinition, -} from '@glimmer/runtime'; import { ComponentCapabilities, VMHandle } from '@glimmer/interfaces'; +import { + Tag, + VersionedPathReference +} from '@glimmer/reference'; +import { + Arguments, + ComponentDefinition, +} from '@glimmer/runtime'; import { Destroyable, Opaque, Option } from '@glimmer/util'; -import { - Tag, - VersionedPathReference -} from '@glimmer/reference'; import { DEBUG } from 'ember-env-flags'; import { generateControllerFactory } from 'ember-routing'; import { EMBER_ENGINES_MOUNT_PARAMS } from 'ember/features'; -import { Component } from '../utils/curly-component-state-bucket'; import { DIRTY_TAG } from '../component'; -import { RootReference } from '../utils/references'; import Environment from '../environment'; +import { Component } from '../utils/curly-component-state-bucket'; +import { RootReference } from '../utils/references'; import AbstractManager from './abstract'; import DefinitionState, { CAPABILITIES } from './definition-state'; -import { OutletLayoutCompiler } from './outlet'; // TODO: remove these stubbed interfaces when better typing is in place interface EngineType { diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index 50c8d48935e..2223cc64f46 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -1,3 +1,4 @@ +import { ComponentCapabilities } from '@glimmer/interfaces'; import { Arguments, ComponentDefinition @@ -14,6 +15,7 @@ import CurlyComponentManager, { processComponentInitializationAssertions, } from './curly'; import DefintionState from './definition-state'; +import { peekMeta } from 'ember-metal'; class RootComponentManager extends CurlyComponentManager { component: Component; @@ -58,11 +60,28 @@ class RootComponentManager extends CurlyComponentManager { } } +export const CURLY_CAPABILITIES: ComponentCapabilities = { + dynamicLayout: true, + dynamicTag: true, + prepareArgs: true, + createArgs: true, + attributeHook: true, + elementHook: true +}; + export class RootComponentDefinition implements ComponentDefinition { state: DefintionState; manager: RootComponentManager; - constructor(public component: ComponentStateBucket) { - // TODO initialize + constructor(public component: Component) { + let manager = new RootComponentManager(component); + this.manager = manager; + let factory = peekMeta(component)._factory; + this.state = { + name: factory.fullName, + capabilities: CURLY_CAPABILITIES, + ComponentClass: factory, + handle: null + }; } } diff --git a/packages/ember-glimmer/lib/renderer.ts b/packages/ember-glimmer/lib/renderer.ts index 871e3ac30fe..33c4f251edd 100644 --- a/packages/ember-glimmer/lib/renderer.ts +++ b/packages/ember-glimmer/lib/renderer.ts @@ -1,8 +1,10 @@ import { Option, Simple } from '@glimmer/interfaces'; -import { CURRENT_TAG, VersionedPathReference } from '@glimmer/reference'; +import { CONSTANT_TAG, CURRENT_TAG, VersionedPathReference } from '@glimmer/reference'; import { + CapturedArguments, clientBuilder, ComponentDefinition, + CurriedComponentDefinition, DynamicScope as GlimmerDynamicScope, IteratorResult, NULL_REFERENCE, @@ -26,7 +28,7 @@ import { TopLevelOutletComponentDefinition } from './component-managers/outlet'; import { RootComponentDefinition } from './component-managers/root'; import Environment from './environment'; import { OwnedTemplate } from './template'; -import ComponentStateBucket, { Component } from './utils/curly-component-state-bucket'; +import { Component } from './utils/curly-component-state-bucket'; import { RootReference } from './utils/references'; import OutletView, { OutletState, RootOutletStateReference } from './views/outlet'; @@ -203,6 +205,23 @@ function loopEnd() { backburner.on('begin', loopBegin); backburner.on('end', loopEnd); +// const EMPTY_NAMED = new CapturedNamedArguments(CONSTANT_TAG, [], []); +// const EMPTY_POSITIONAL = new CapturedPositionalArguments(CONSTANT_TAG, []); +export const EMPTY_ARGS: CapturedArguments = { + tag: CONSTANT_TAG, + length: 0, + positional: { + tag: CONSTANT_TAG, + length: 0, + references: [] as VersionedPathReference[], + }, + named: { + tag: CONSTANT_TAG, + length: 0, + names: [] as string[], + references: [] as VersionedPathReference[] + }} as any; + export abstract class Renderer { private _env: Environment; private _rootTemplate: any; @@ -237,15 +256,15 @@ export abstract class Renderer { this._appendDefinition(view, definition, target, outletStateReference); } - appendTo(view: ComponentStateBucket, target: Simple.Element) { + appendTo(view: Component, target: Simple.Element) { let rootDef = new RootComponentDefinition(view); - - this._appendDefinition(view, rootDef, target); + let def = new CurriedComponentDefinition(rootDef as any, EMPTY_ARGS); + this._appendDefinition(view, def, target); } _appendDefinition( root: Opaque, - definition: ComponentDefinition, + definition: ComponentDefinition | CurriedComponentDefinition, target: Simple.Element, outletStateReference?: RootOutletStateReference) { let self = new RootReference(definition); diff --git a/packages/ember-metal/lib/index.d.ts b/packages/ember-metal/lib/index.d.ts index 7f814ab3df7..bdf32c30ddc 100644 --- a/packages/ember-metal/lib/index.d.ts +++ b/packages/ember-metal/lib/index.d.ts @@ -11,6 +11,8 @@ interface IRun { backburner: IBackburner } +export function peekMeta(obj: any): any; + export const run: IRun; export const PROPERTY_DID_CHANGE: symbol; From 2765f31d0573c53b150867b75f13fa24a5ca47b2 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Sat, 18 Nov 2017 04:30:55 -0800 Subject: [PATCH 009/135] now to compiling root layout --- .../lib/component-managers/root.ts | 28 +++++++++++-------- .../lib/utils/curly-component-state-bucket.ts | 4 +-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index 2223cc64f46..e282d9619e6 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -6,6 +6,7 @@ import { import { DEBUG } from 'ember-env-flags'; import { _instrumentStart, + peekMeta, } from 'ember-metal'; import Environment from '../environment'; import { DynamicScope } from '../renderer'; @@ -15,7 +16,6 @@ import CurlyComponentManager, { processComponentInitializationAssertions, } from './curly'; import DefintionState from './definition-state'; -import { peekMeta } from 'ember-metal'; class RootComponentManager extends CurlyComponentManager { component: Component; @@ -25,9 +25,13 @@ class RootComponentManager extends CurlyComponentManager { this.component = component; } + getLayout(...args: any[]) { + console.log(...args); + } + create(environment: Environment, - _: DefintionState, - args: Arguments, + _state: DefintionState, + _args: Arguments | null, dynamicScope: DynamicScope) { let component = this.component; @@ -56,15 +60,17 @@ class RootComponentManager extends CurlyComponentManager { processComponentInitializationAssertions(component, {}); } - return new ComponentStateBucket(environment, component, args.named.capture(), finalizer); + return new ComponentStateBucket(environment, component, null, finalizer); } } -export const CURLY_CAPABILITIES: ComponentCapabilities = { - dynamicLayout: true, - dynamicTag: true, - prepareArgs: true, - createArgs: true, +// ROOT is the top-level template it has nothing but one yield. +// it is supposed to have a dummy element +export const ROOT_CAPABILITIES: ComponentCapabilities = { + dynamicLayout: false, + dynamicTag: false, + prepareArgs: false, + createArgs: false, attributeHook: true, elementHook: true }; @@ -79,9 +85,9 @@ export class RootComponentDefinition implements ComponentDefinition { let factory = peekMeta(component)._factory; this.state = { name: factory.fullName, - capabilities: CURLY_CAPABILITIES, + capabilities: ROOT_CAPABILITIES, ComponentClass: factory, - handle: null + handle: null, }; } } diff --git a/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts b/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts index ce9863adac4..63c914f4301 100644 --- a/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts +++ b/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts @@ -38,9 +38,9 @@ export default class ComponentStateBucket { public classRef: VersionedReference | null = null; public argsRevision: Revision; - constructor(public environment: Environment, public component: Component, public args: CapturedNamedArguments, public finalizer: Finalizer) { + constructor(public environment: Environment, public component: Component, public args: CapturedNamedArguments | null, public finalizer: Finalizer) { this.classRef = null; - this.argsRevision = args.tag.value(); + this.argsRevision = args === null ? 0 : args.tag.value(); } destroy() { From aaada07db8c4f2d6242c4954c732da59ceadf80e Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Tue, 21 Nov 2017 13:13:58 -0800 Subject: [PATCH 010/135] WIP: Start getDynamicLayout and compileTemplate --- .../lib/component-managers/curly.ts | 26 +++++++++++++++---- .../lib/component-managers/root.ts | 16 ++++++++---- packages/ember-glimmer/lib/resolver.ts | 11 +++----- .../lib/test-cases/abstract-rendering.js | 2 +- 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index e8651bd8cd7..7ce340af01b 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -4,6 +4,7 @@ import { Simple, VMHandle } from '@glimmer/interfaces'; +import { WrappedBuilder } from '@glimmer/opcode-compiler'; import { combineTagged, Tag, @@ -150,8 +151,23 @@ export default class CurlyComponentManager extends AbstractManager, WithDynamicLayout { - getDynamicLayout(_component: Opaque, _resolver: RuntimeResolver): Invocation { - throw new Error('Method not implemented.'); + getDynamicLayout(component: Opaque, resolver: RuntimeResolver): Invocation { + const handle = resolver.lookupComponent(component.name, component.ComponentClass); + if (!handle) { + throw new Error('Missing dynamic layout'); + } + + return resolver.compileTemplate(handle, component.layout.name, (template, options) => { + const builder = new WrappedBuilder( + assign({}, options, { asPartial: false, referrer: null }), + template, + CAPABILITIES + ); + return { + handle: builder.compile(), + symbolTable: builder.symbolTable + }; + }); } getTagName(_component: Opaque): Option { @@ -369,10 +385,10 @@ export default class CurlyComponentManager extends AbstractManager { return (vm, args) => componentHelper(vm, args, meta); } - let helper = this.builtInHelpers[name]; + const helper = this.builtInHelpers[name]; if (helper !== undefined) { return helper; } - let { owner, moduleName } = meta; + const { owner, moduleName } = meta; - let options: LookupOptions | undefined; - if (moduleName !== undefined) { - options = { source: `template:${moduleName}` }; - } + const options: LookupOptions | undefined = makeOptions(moduleName); - let helperFactory = owner.factoryFor(`helper:${name}`, options) || owner.factoryFor(`helper:${name}`); + const helperFactory = owner.factoryFor(`helper:${name}`, options) || owner.factoryFor(`helper:${name}`); // TODO: try to unify this into a consistent protocol to avoid wasteful closure allocations if (helperFactory.class.isHelperInstance) { diff --git a/packages/internal-test-helpers/lib/test-cases/abstract-rendering.js b/packages/internal-test-helpers/lib/test-cases/abstract-rendering.js index 56833587425..b1c16c9fd11 100644 --- a/packages/internal-test-helpers/lib/test-cases/abstract-rendering.js +++ b/packages/internal-test-helpers/lib/test-cases/abstract-rendering.js @@ -72,7 +72,7 @@ export default class AbstractRenderingTestCase extends AbstractTestCase { layoutName: '-top-level' }); - owner.register('component:-top-level', Component.extend(attrs)); + owner.register('-top-level', Component.extend(attrs)); this.component = owner.lookup('component:-top-level'); From c85c9822660807124599766f6889484a7d53e454 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 21 Nov 2017 14:12:16 -0800 Subject: [PATCH 011/135] hacks to get a little further --- .../ember-glimmer/lib/component-managers/curly.ts | 12 +++++++++--- .../ember-glimmer/lib/component-managers/root.ts | 4 ++-- .../lib/utils/curly-component-state-bucket.ts | 1 + .../lib/test-cases/abstract-rendering.js | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 7ce340af01b..4bd861ea2e3 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -35,6 +35,7 @@ import { } from 'ember-metal'; import { assign, + getOwner, OWNER, } from 'ember-utils'; import { setViewElement, TemplateMeta } from 'ember-views'; @@ -151,13 +152,18 @@ export default class CurlyComponentManager extends AbstractManager, WithDynamicLayout { - getDynamicLayout(component: Opaque, resolver: RuntimeResolver): Invocation { - const handle = resolver.lookupComponent(component.name, component.ComponentClass); + getDynamicLayout(component: ComponentStateBucket, resolver: RuntimeResolver): Invocation { + const owner = getOwner(component.component); + const layoutName = component.component.layoutName!; + const handle = resolver.lookupComponent(layoutName, { + owner, + moduleName: '', + }); if (!handle) { throw new Error('Missing dynamic layout'); } - return resolver.compileTemplate(handle, component.layout.name, (template, options) => { + return resolver.compileTemplate(handle, layoutName, (template, options) => { const builder = new WrappedBuilder( assign({}, options, { asPartial: false, referrer: null }), template, diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index e0f7b20a38b..b1fdb49d602 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -72,7 +72,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: ComponentCapabilities = { - dynamicLayout: false, + dynamicLayout: true, dynamicTag: false, prepareArgs: false, createArgs: false, @@ -90,7 +90,7 @@ export class RootComponentDefinition implements ComponentDefinition { let factory = peekMeta(component)._factory; console.log(factory); this.state = { - name: factory.fullName, + name: factory.fullName.slice(10), capabilities: ROOT_CAPABILITIES, ComponentClass: factory, handle: null, diff --git a/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts b/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts index 63c914f4301..9bbc2980436 100644 --- a/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts +++ b/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts @@ -6,6 +6,7 @@ import Environment from '../environment'; export interface Component { _debugContainerKey: string; _transitionTo(name: string): void; + layoutName?: string; attributeBindings: any; classNames: any; classNameBindings: any; diff --git a/packages/internal-test-helpers/lib/test-cases/abstract-rendering.js b/packages/internal-test-helpers/lib/test-cases/abstract-rendering.js index b1c16c9fd11..56833587425 100644 --- a/packages/internal-test-helpers/lib/test-cases/abstract-rendering.js +++ b/packages/internal-test-helpers/lib/test-cases/abstract-rendering.js @@ -72,7 +72,7 @@ export default class AbstractRenderingTestCase extends AbstractTestCase { layoutName: '-top-level' }); - owner.register('-top-level', Component.extend(attrs)); + owner.register('component:-top-level', Component.extend(attrs)); this.component = owner.lookup('component:-top-level'); From cd0a5e7da05de375ac0337bce0bddc7912325fad Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 22 Nov 2017 06:26:40 -0700 Subject: [PATCH 012/135] WIP Add getLayout to outlet manager --- .../lib/component-managers/curly.ts | 2 +- .../lib/component-managers/outlet.ts | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 4bd861ea2e3..2bef879b7f2 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -155,7 +155,7 @@ export default class CurlyComponentManager extends AbstractManager { +class OutletComponentManager extends AbstractManager + implements WithStaticLayout { create(environment: Environment, definition: DefinitionState, _args: Arguments, @@ -72,6 +77,14 @@ class OutletComponentManager extends AbstractManager Date: Mon, 27 Nov 2017 16:13:53 -0800 Subject: [PATCH 013/135] Cleanup curried stuff. --- packages/ember-glimmer/lib/renderer.ts | 28 +++++--------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/packages/ember-glimmer/lib/renderer.ts b/packages/ember-glimmer/lib/renderer.ts index 33c4f251edd..784b1fcb491 100644 --- a/packages/ember-glimmer/lib/renderer.ts +++ b/packages/ember-glimmer/lib/renderer.ts @@ -1,10 +1,10 @@ import { Option, Simple } from '@glimmer/interfaces'; -import { CONSTANT_TAG, CURRENT_TAG, VersionedPathReference } from '@glimmer/reference'; +import { CURRENT_TAG, VersionedPathReference } from '@glimmer/reference'; import { - CapturedArguments, clientBuilder, ComponentDefinition, CurriedComponentDefinition, + curry, DynamicScope as GlimmerDynamicScope, IteratorResult, NULL_REFERENCE, @@ -205,23 +205,6 @@ function loopEnd() { backburner.on('begin', loopBegin); backburner.on('end', loopEnd); -// const EMPTY_NAMED = new CapturedNamedArguments(CONSTANT_TAG, [], []); -// const EMPTY_POSITIONAL = new CapturedPositionalArguments(CONSTANT_TAG, []); -export const EMPTY_ARGS: CapturedArguments = { - tag: CONSTANT_TAG, - length: 0, - positional: { - tag: CONSTANT_TAG, - length: 0, - references: [] as VersionedPathReference[], - }, - named: { - tag: CONSTANT_TAG, - length: 0, - names: [] as string[], - references: [] as VersionedPathReference[] - }} as any; - export abstract class Renderer { private _env: Environment; private _rootTemplate: any; @@ -253,13 +236,12 @@ export abstract class Renderer { let definition = new TopLevelOutletComponentDefinition(view); let outletStateReference = view.toReference(); - this._appendDefinition(view, definition, target, outletStateReference); + this._appendDefinition(view, curry(definition), target, outletStateReference); } appendTo(view: Component, target: Simple.Element) { - let rootDef = new RootComponentDefinition(view); - let def = new CurriedComponentDefinition(rootDef as any, EMPTY_ARGS); - this._appendDefinition(view, def, target); + let def = new RootComponentDefinition(view); + this._appendDefinition(view, curry(def), target); } _appendDefinition( From 5d1c1ab58058952d77812167575c05361d8da6ba Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Mon, 27 Nov 2017 17:27:38 -0800 Subject: [PATCH 014/135] more cleanup of Outlet manager --- .../lib/component-managers/abstract.ts | 3 +- .../lib/component-managers/outlet.ts | 189 +++++++++--------- 2 files changed, 92 insertions(+), 100 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/abstract.ts b/packages/ember-glimmer/lib/component-managers/abstract.ts index 94aa1875b9a..2b67b86ba58 100644 --- a/packages/ember-glimmer/lib/component-managers/abstract.ts +++ b/packages/ember-glimmer/lib/component-managers/abstract.ts @@ -1,5 +1,6 @@ import { ComponentCapabilities, + Simple, VMHandle } from '@glimmer/interfaces'; import { Tag, VersionedPathReference } from '@glimmer/reference'; @@ -55,7 +56,7 @@ export default abstract class AbstractManager implements ComponentManager< abstract getSelf(component: T): VersionedPathReference; abstract getCapabilities(state: U): ComponentCapabilities; - didCreateElement(_component: T, _element: Element, _operations: ElementOperations): void { + didCreateElement(_component: T, _element: Simple.Element, _operations: ElementOperations): void { // noop } diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index ae166abb4a6..18514ea05df 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -1,34 +1,32 @@ import { ComponentCapabilities, Option, - VMHandle + Unique } from '@glimmer/interfaces'; import { - Tag + Tag, VersionedPathReference } from '@glimmer/reference'; import { Arguments, ComponentDefinition, - DynamicScope, + ElementOperations, Environment, Invocation, + WithDynamicTagName, WithStaticLayout } from '@glimmer/runtime'; -import { Destroyable, Opaque } from '@glimmer/util/dist/types'; +import { Destroyable } from '@glimmer/util/dist/types'; import { DEBUG } from 'ember-env-flags'; import { _instrumentStart } from 'ember-metal'; -import { generateGuid, guidFor } from 'ember-utils'; -import { TemplateMeta } from 'ember-views'; -import { DIRTY_TAG } from '../component'; +import { guidFor } from 'ember-utils'; +import { TemplateMeta } from 'ember-views'; +import { DynamicScope } from '../renderer'; import RuntimeResolver from '../resolver'; import { OwnedTemplate, - WrappedTemplateFactory, } from '../template'; -import { Component } from '../utils/curly-component-state-bucket'; -import { RootReference } from '../utils/references'; +import { default as OutletView, OutletState } from '../views/outlet'; import AbstractManager from './abstract'; -import DefinitionState from './definition-state'; function instrumentationPayload({ render: { name, outlet } }: {render: {name: string, outlet: string}}) { return { object: `${name}:${outlet}` }; @@ -36,22 +34,15 @@ function instrumentationPayload({ render: { name, outlet } }: {render: {name: st function NOOP() {/**/} -interface OutletDynamicScope extends DynamicScope { - outletState: any; -} - -class StateBucket { - public outletState: any; - public finalizer: any; - public component: Component; +class OutletInstanceState { + public finalizer: () => void; - constructor(outletState: any) { - this.outletState = outletState; + constructor(public outletState: VersionedPathReference) { this.instrument(); } instrument() { - this.finalizer = _instrumentStart('render.outlet', instrumentationPayload, this.outletState); + this.finalizer = _instrumentStart('render.outlet', instrumentationPayload, this.outletState.value()); } finalize() { @@ -61,53 +52,58 @@ class StateBucket { } } -class OutletComponentManager extends AbstractManager - implements WithStaticLayout { +export const CAPABILITIES: ComponentCapabilities = { + dynamicLayout: false, + dynamicTag: false, + prepareArgs: false, + createArgs: false, + attributeHook: false, + elementHook: false +}; + +class OutletComponentManager extends AbstractManager + implements WithStaticLayout { + create(environment: Environment, - definition: DefinitionState, + definition: OutletComponentDefinitionState, _args: Arguments, - dynamicScope: OutletDynamicScope) { + dynamicScope: DynamicScope) { if (DEBUG) { - this._pushToDebugStack(`template:${definition.template.meta.moduleName}`, environment); + this._pushToDebugStack(`template:${definition.template.referrer.moduleName}`, environment); } - + // TODO revisit missing outletName let outletStateReference = dynamicScope.outletState = - dynamicScope.outletState.get('outlets').get(definition.outletName); - let outletState = outletStateReference.value(); - return new StateBucket(outletState); + dynamicScope.outletState.get('outlets').get(definition.outletName!) as VersionedPathReference; + return new OutletInstanceState(outletStateReference); } - getLayout(state: DefinitionState, resolver: RuntimeResolver): Invocation { - const handle = resolver.lookupComponentDefinition(state.name, state.ComponentClass); - return { - handle, - symbolTable: state.symbolTable - }; + layoutFor(_state: OutletComponentDefinitionState, _component: OutletInstanceState, _env: Environment): Unique<'Handle'> { + throw new Error('Method not implemented.'); } - getCapabilities(state: DefinitionState): ComponentCapabilities { - return state.capabilities; + getLayout(state: OutletComponentDefinitionState, _resolver: RuntimeResolver): Invocation { + // The router has already resolved the template + const layout = state.template.asLayout(); + return { + handle: layout.compile(), + symbolTable: layout.symbolTable + }; } - layoutFor( - _definition: OutletComponentDefinition, - _component: StateBucket, - _env: Environment): VMHandle { - throw new Error('TODO'); - // TODO resolver.compileTemplate - // return (env as EmberEnvironment).getCompiledBlock(OutletLayoutCompiler, definition.template); + getCapabilities(): ComponentCapabilities { + return CAPABILITIES; } - getSelf({ outletState }: StateBucket) { - return new RootReference(outletState.render.controller); + getSelf({ outletState }: OutletInstanceState) { + return outletState; } - getTag({ component }: StateBucket): Tag { + getTag({ outletState }: OutletInstanceState): Tag { // TODO: is this the right tag? - return component[DIRTY_TAG]; + return outletState.tag; } - didRenderLayout(bucket: StateBucket) { + didRenderLayout(bucket: OutletInstanceState) { bucket.finalize(); if (DEBUG) { @@ -120,71 +116,66 @@ class OutletComponentManager extends AbstractManager { + + getTagName(_component: OutletInstanceState) { + return 'div'; + } + + create(environment: Environment, definition: TopOutletComponentDefinitionState, _args: Arguments, dynamicScope: DynamicScope) { if (DEBUG) { - this._pushToDebugStack(`template:${definition.template.meta.moduleName}`, environment); + this._pushToDebugStack(`template:${definition.template.referrer.moduleName}`, environment); } - return new StateBucket(dynamicScope.outletState.value()); + // TODO: top level outlet should always have outletState, assert + return new OutletInstanceState(dynamicScope.outletState as VersionedPathReference); + } + + getCapabilities(): ComponentCapabilities { + return TOP_CAPABILITIES; } - layoutFor(_definition: OutletComponentDefinition, _bucket: StateBucket, _env: Environment): VMHandle { - throw new Error('TODO resolver.compileTemplate and get invocation handle'); - // eturn (env as EmberEnvironment).getCompiledBlock(TopLevelOutletLayoutCompiler, definition.template); + didCreateElement(_component: OutletInstanceState, _element: Element, _operations: ElementOperations): void { + // to add GUID id and class + _element.setAttribute('class', 'ember-view'); + _element.setAttribute('id', guidFor(_component)); } } -export class TopLevelOutletComponentDefinition implements ComponentDefinition { - public template: WrappedTemplateFactory; - public state: DefinitionState; - public manager: TopLevelOutletComponentManager; +const TOP_MANAGER = new TopLevelOutletComponentManager(); - constructor(instance: any) { - this.template = instance.template; - generateGuid(this); - } +export interface TopOutletComponentDefinitionState { + template: OwnedTemplate; } -class TopLevelOutletLayoutCompiler { - static id: string; - public template: WrappedTemplateFactory; - constructor(template: WrappedTemplateFactory) { - this.template = template; - } +export class TopLevelOutletComponentDefinition implements ComponentDefinition { + public state: TopOutletComponentDefinitionState; + public manager: TopLevelOutletComponentManager = TOP_MANAGER; - compile(builder: any) { - builder.wrapLayout(this.template); - builder.tag.static('div'); - builder.attrs.static('id', guidFor(this)); - builder.attrs.static('class', 'ember-view'); + constructor(instance: OutletView) { + this.state = { + template: instance.template as OwnedTemplate, + }; } } -TopLevelOutletLayoutCompiler.id = 'top-level-outlet'; +const OUTLET_MANAGER = new OutletComponentManager(); -export class OutletComponentDefinition implements ComponentDefinition { - public outletName: string; - public template: OwnedTemplate; - public state: DefinitionState; - public manager: OutletComponentManager; - - constructor(outletName: string, template: OwnedTemplate) { - this.outletName = outletName; - this.template = template; - generateGuid(this); - } +export interface OutletComponentDefinitionState { + outletName: string; + template: OwnedTemplate; } -export class OutletLayoutCompiler { - static id: string; - public template: WrappedTemplateFactory; - constructor(template: WrappedTemplateFactory) { - this.template = template; - } +export class OutletComponentDefinition implements ComponentDefinition { + public state: OutletComponentDefinitionState; + public manager: OutletComponentManager = OUTLET_MANAGER; - compile(builder: any) { - builder.wrapLayout(this.template); + constructor(outletName: string, template: OwnedTemplate) { + this.state = { outletName, template }; } } - -OutletLayoutCompiler.id = 'outlet'; From 56cafa32ca073fbc5dc2646d070b5bd60e986063 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Mon, 27 Nov 2017 18:50:23 -0800 Subject: [PATCH 015/135] make compileOptions injected and populate macros --- packages/ember-glimmer/lib/compile-options.ts | 35 +++++++++++++++++++ packages/ember-glimmer/lib/setup-registry.ts | 5 +++ packages/ember-glimmer/lib/syntax.ts | 8 ++--- packages/ember-glimmer/lib/template.ts | 24 +------------ 4 files changed, 43 insertions(+), 29 deletions(-) create mode 100644 packages/ember-glimmer/lib/compile-options.ts diff --git a/packages/ember-glimmer/lib/compile-options.ts b/packages/ember-glimmer/lib/compile-options.ts new file mode 100644 index 00000000000..83c678f0e6d --- /dev/null +++ b/packages/ember-glimmer/lib/compile-options.ts @@ -0,0 +1,35 @@ +import { CompileTimeProgram } from '@glimmer/interfaces'; +import { + LazyOpcodeBuilder, + Macros, + OpcodeBuilderConstructor, + TemplateOptions +} from '@glimmer/opcode-compiler'; +import { LazyConstants, Program } from '@glimmer/program'; +import { getOwner } from 'ember-utils'; +import { TemplateMeta } from 'ember-views'; +import CompileTimeLookup from './compile-time-lookup'; +import RuntimeResolver from './resolver'; +import { populateMacros } from './syntax'; + +export default class CompileOptions implements TemplateOptions { + program: CompileTimeProgram; + macros: Macros; + Builder: OpcodeBuilderConstructor; + resolver: CompileTimeLookup; + + constructor(resolver: RuntimeResolver) { + const program = new Program(new LazyConstants(resolver)); + const macros = new Macros(); + populateMacros(macros.blocks, macros.inlines); + this.program = program; + this.macros = macros; + this.resolver = new CompileTimeLookup(resolver); + this.Builder = LazyOpcodeBuilder as OpcodeBuilderConstructor; + } + + static create(injections: any) { + const resolver = new RuntimeResolver(getOwner(injections)); + return new this(resolver); + } +} diff --git a/packages/ember-glimmer/lib/setup-registry.ts b/packages/ember-glimmer/lib/setup-registry.ts index 1ef6be22ba2..8cb556accca 100644 --- a/packages/ember-glimmer/lib/setup-registry.ts +++ b/packages/ember-glimmer/lib/setup-registry.ts @@ -1,5 +1,6 @@ import { privatize as P } from 'container'; import { environment } from 'ember-environment'; +import CompileOptions from './compile-options'; import Component from './component'; import Checkbox from './components/checkbox'; import LinkToComponent from './components/link-to'; @@ -62,7 +63,11 @@ export function setupEngineRegistry(registry: Registry) { registry.register(P`template:components/-default`, ComponentTemplate); registry.register('service:-glimmer-environment', Environment); + + registry.register('service:-compile-options', CompileOptions); + registry.injection('template', 'env', 'service:-glimmer-environment'); + registry.injection('template', 'compileOptions', 'service:-compile-options'); registry.optionsForType('helper', { instantiate: false }); diff --git a/packages/ember-glimmer/lib/syntax.ts b/packages/ember-glimmer/lib/syntax.ts index 1675048a9a9..1f06665ba9d 100644 --- a/packages/ember-glimmer/lib/syntax.ts +++ b/packages/ember-glimmer/lib/syntax.ts @@ -1,9 +1,5 @@ import { assert } from 'ember-debug'; import { textAreaMacro } from './syntax/-text-area'; -import { - blockComponentMacro, - inlineComponentMacro, -} from './syntax/dynamic-component'; import { inputMacro } from './syntax/input'; import { mountMacro } from './syntax/mount'; import { outletMacro } from './syntax/outlet'; @@ -64,13 +60,13 @@ export function registerMacros(macro: any) { export function populateMacros(blocks: any, inlines: any) { inlines.add('outlet', outletMacro); - inlines.add('component', inlineComponentMacro); + // inlines.add('component', inlineComponentMacro); inlines.add('render', renderMacro); inlines.add('mount', mountMacro); inlines.add('input', inputMacro); inlines.add('textarea', textAreaMacro); inlines.addMissing(refineInlineSyntax); - blocks.add('component', blockComponentMacro); + // blocks.add('component', blockComponentMacro); blocks.addMissing(refineBlockSyntax); for (let i = 0; i < experimentalMacros.length; i++) { diff --git a/packages/ember-glimmer/lib/template.ts b/packages/ember-glimmer/lib/template.ts index ffe6ae7db5a..18e8f9fac73 100644 --- a/packages/ember-glimmer/lib/template.ts +++ b/packages/ember-glimmer/lib/template.ts @@ -1,13 +1,3 @@ -import { - EagerOpcodeBuilder, - Macros, - OpcodeBuilderConstructor, - TemplateOptions -} from '@glimmer/opcode-compiler'; -import { - LazyConstants, - Program -} from '@glimmer/program'; import { Template, templateFactory, @@ -15,8 +5,6 @@ import { } from '@glimmer/runtime'; import { OWNER, Owner } from 'ember-utils'; import { TemplateMeta } from 'ember-views'; -import CompileTimeLookup from './compile-time-lookup'; -import RuntimeResolver from './resolver'; export type OwnedTemplate = Template; @@ -37,19 +25,9 @@ export class WrappedTemplateFactory { create(props: any): OwnedTemplate { const owner: Owner = props[OWNER]; - const resolver = new RuntimeResolver(owner); // I'm pretty sure there is only supposed to be one of these // injected into all templates. - const options: TemplateOptions<{ - moduleName: string; - managerId?: string; - }> = { - program: new Program(new LazyConstants(resolver)), - macros: new Macros(), - resolver: new CompileTimeLookup(resolver), - Builder: EagerOpcodeBuilder as OpcodeBuilderConstructor - }; - return this.factory.create(options, { owner }); + return this.factory.create(props.compileOptions, { owner }); } } From 9226d7225542f602e7619233c4b88e2a5ccd2099 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Mon, 27 Nov 2017 20:18:09 -0800 Subject: [PATCH 016/135] update get more typing --- packages/ember-glimmer/lib/compile-options.ts | 2 +- packages/ember-glimmer/lib/syntax.ts | 4 +++- packages/ember-glimmer/lib/syntax/outlet.ts | 21 ++++++++++++------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/ember-glimmer/lib/compile-options.ts b/packages/ember-glimmer/lib/compile-options.ts index 83c678f0e6d..6f619846e36 100644 --- a/packages/ember-glimmer/lib/compile-options.ts +++ b/packages/ember-glimmer/lib/compile-options.ts @@ -21,7 +21,7 @@ export default class CompileOptions implements TemplateOptions { constructor(resolver: RuntimeResolver) { const program = new Program(new LazyConstants(resolver)); const macros = new Macros(); - populateMacros(macros.blocks, macros.inlines); + populateMacros(macros); this.program = program; this.macros = macros; this.resolver = new CompileTimeLookup(resolver); diff --git a/packages/ember-glimmer/lib/syntax.ts b/packages/ember-glimmer/lib/syntax.ts index 1f06665ba9d..fbbe8f0e78f 100644 --- a/packages/ember-glimmer/lib/syntax.ts +++ b/packages/ember-glimmer/lib/syntax.ts @@ -1,3 +1,4 @@ +import { Macros } from '@glimmer/opcode-compiler'; import { assert } from 'ember-debug'; import { textAreaMacro } from './syntax/-text-area'; import { inputMacro } from './syntax/input'; @@ -58,7 +59,8 @@ export function registerMacros(macro: any) { experimentalMacros.push(macro); } -export function populateMacros(blocks: any, inlines: any) { +export function populateMacros(macros: Macros) { + let { inlines, blocks } = macros; inlines.add('outlet', outletMacro); // inlines.add('component', inlineComponentMacro); inlines.add('render', renderMacro); diff --git a/packages/ember-glimmer/lib/syntax/outlet.ts b/packages/ember-glimmer/lib/syntax/outlet.ts index 1a4e190b024..5f1dc63f6a9 100644 --- a/packages/ember-glimmer/lib/syntax/outlet.ts +++ b/packages/ember-glimmer/lib/syntax/outlet.ts @@ -1,3 +1,5 @@ +import { Option } from '@glimmer/interfaces'; +import { OpcodeBuilder } from '@glimmer/opcode-compiler'; import { combine, ConstReference, @@ -8,6 +10,8 @@ import { Arguments, VM, } from '@glimmer/runtime'; +import * as WireFormat from '@glimmer/wire-format'; +import { TemplateMeta } from 'ember-views'; import { OutletComponentDefinition } from '../component-managers/outlet'; import { DynamicScope } from '../renderer'; @@ -133,12 +137,13 @@ function outletComponentFor(vm: VM, args: Arguments) { @for Ember.Templates.helpers @public */ -export function outletMacro(_name: string, params: any[], _hash: any[], builder: any) { - if (!params) { - params = []; - } - let definitionArgs = [params.slice(0, 1), null, null, null]; - let emptyArgs = [[], null, null, null]; // FIXME - builder.component.dynamic(definitionArgs, outletComponentFor, emptyArgs); +export const outletMacro = (_name: string, _params: Option, _hash: Option, _builder: OpcodeBuilder) => { + // if (!params) { + // params = []; + // } + // let definitionArgs = [params.slice(0, 1), null, null, null]; + // let emptyArgs = [[], null, null, null]; // FIXME + // builder.component.dynamic(definitionArgs, outletComponentFor, emptyArgs); + return true; -} +}; From 4c2a910eefe765a0349e850fcbf86c698825a4cd Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 28 Nov 2017 00:09:33 -0800 Subject: [PATCH 017/135] Hello World outlet test passes. --- packages/ember-glimmer/lib/helpers/outlet.ts | 51 +++++++++++ packages/ember-glimmer/lib/resolver.ts | 2 + packages/ember-glimmer/lib/syntax.ts | 2 +- packages/ember-glimmer/lib/syntax/outlet.ts | 95 +------------------- 4 files changed, 57 insertions(+), 93 deletions(-) create mode 100644 packages/ember-glimmer/lib/helpers/outlet.ts diff --git a/packages/ember-glimmer/lib/helpers/outlet.ts b/packages/ember-glimmer/lib/helpers/outlet.ts new file mode 100644 index 00000000000..b8836e04d46 --- /dev/null +++ b/packages/ember-glimmer/lib/helpers/outlet.ts @@ -0,0 +1,51 @@ +import { combine, ConstReference, Reference, RevisionTag, TagWrapper, UpdatableTag, VersionedPathReference } from '@glimmer/reference'; +import { + Arguments, + CurriedComponentDefinition, + curry, + VM, +} from '@glimmer/runtime'; +import { OutletComponentDefinition } from '../component-managers/outlet'; +import { DynamicScope } from '../renderer'; +import { OutletState } from '../views/outlet'; + +export default function outlet(vm: VM, args: Arguments) { + let scope = vm.dynamicScope() as DynamicScope; + let outletNameRef: Reference; + if (args.positional.length === 0) { + outletNameRef = new ConstReference('main'); + } else { + outletNameRef = args.positional.at>(0); + } + return new OutletComponentReference(outletNameRef, scope.outletState); +} + +class OutletComponentReference implements Reference { + public tag: TagWrapper; + private outletStateTag: TagWrapper; + private definition: any | null; + private lastState: any | null; + + constructor(private outletNameRef: Reference, + private parentOutletStateRef: VersionedPathReference) { + this.outletNameRef = outletNameRef; + this.parentOutletStateRef = parentOutletStateRef; + this.definition = null; + this.lastState = null; + let outletStateTag = this.outletStateTag = UpdatableTag.create(parentOutletStateRef.tag); + this.tag = combine([outletStateTag, outletNameRef.tag]); + } + + value(): CurriedComponentDefinition | null { + let outletName = this.outletNameRef.value(); + let parentState = this.parentOutletStateRef.value(); + if (!parentState) return null; + let outletState = parentState.outlets[outletName]; + if (!outletState) return null; + let renderState = outletState.render; + if (!renderState) return null; + let template = renderState.template; + if (!template) return null; + return curry(new OutletComponentDefinition(outletName, template)); + } +} \ No newline at end of file diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 79569a1388c..289ff0aab7c 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -31,6 +31,7 @@ import { import { default as loc } from './helpers/loc'; import { default as log } from './helpers/log'; import { default as mut } from './helpers/mut'; +import { default as outlet } from './helpers/outlet'; import { default as queryParams } from './helpers/query-param'; import { default as readonly } from './helpers/readonly'; import { default as unbound } from './helpers/unbound'; @@ -72,6 +73,7 @@ export default class RuntimeResolver implements IRuntimeResolver { '-normalize-class': normalizeClassHelper, '-html-safe': htmlSafeHelper, '-get-dynamic-var': getDynamicVar, + '-outlet': outlet, }; this.builtInModifiers = { diff --git a/packages/ember-glimmer/lib/syntax.ts b/packages/ember-glimmer/lib/syntax.ts index fbbe8f0e78f..4c43a160f1f 100644 --- a/packages/ember-glimmer/lib/syntax.ts +++ b/packages/ember-glimmer/lib/syntax.ts @@ -67,7 +67,7 @@ export function populateMacros(macros: Macros) { inlines.add('mount', mountMacro); inlines.add('input', inputMacro); inlines.add('textarea', textAreaMacro); - inlines.addMissing(refineInlineSyntax); + // inlines.addMissing(refineInlineSyntax); // blocks.add('component', blockComponentMacro); blocks.addMissing(refineBlockSyntax); diff --git a/packages/ember-glimmer/lib/syntax/outlet.ts b/packages/ember-glimmer/lib/syntax/outlet.ts index 5f1dc63f6a9..070fd832024 100644 --- a/packages/ember-glimmer/lib/syntax/outlet.ts +++ b/packages/ember-glimmer/lib/syntax/outlet.ts @@ -1,91 +1,7 @@ import { Option } from '@glimmer/interfaces'; import { OpcodeBuilder } from '@glimmer/opcode-compiler'; -import { - combine, - ConstReference, - TagWrapper, - UpdatableTag, -} from '@glimmer/reference'; -import { - Arguments, - VM, -} from '@glimmer/runtime'; import * as WireFormat from '@glimmer/wire-format'; import { TemplateMeta } from 'ember-views'; -import { OutletComponentDefinition } from '../component-managers/outlet'; -import { DynamicScope } from '../renderer'; - -class OutletComponentReference { - public outletNameRef: any; - public parentOutletStateRef: any; - public definition: any; - public lastState: any; - public outletStateTag: TagWrapper; - public tag: any; - - constructor(outletNameRef: any, parentOutletStateRef: any) { - this.outletNameRef = outletNameRef; - this.parentOutletStateRef = parentOutletStateRef; - this.definition = null; - this.lastState = null; - let outletStateTag = this.outletStateTag = UpdatableTag.create(parentOutletStateRef.tag); - this.tag = combine([outletStateTag.inner, outletNameRef.tag]); - } - - value() { - let { outletNameRef, parentOutletStateRef, definition, lastState } = this; - - let outletName = outletNameRef.value(); - let outletStateRef = parentOutletStateRef.get('outlets').get(outletName); - let newState = this.lastState = outletStateRef.value(); - - this.outletStateTag.inner.update(outletStateRef.tag); - - definition = revalidate(definition, lastState, newState); - - let hasTemplate = newState && newState.render.template; - - if (definition) { - return definition; - } else if (hasTemplate) { - return this.definition = new OutletComponentDefinition(outletName, newState.render.template); - } else { - return this.definition = null; - } - } -} - -function revalidate(definition: any, lastState: any, newState: any) { - if (!lastState && !newState) { - return definition; - } - - if (!lastState && newState || lastState && !newState) { - return null; - } - - if ( - newState.render.template === lastState.render.template && - newState.render.controller === lastState.render.controller - ) { - return definition; - } - - return null; -} - -function outletComponentFor(vm: VM, args: Arguments) { - let { outletState } = vm.dynamicScope() as DynamicScope; - - let outletNameRef; - if (args.positional.length === 0) { - outletNameRef = new ConstReference('main'); - } else { - outletNameRef = args.positional.at(0); - } - - return new OutletComponentReference(outletNameRef, outletState); -} /** The `{{outlet}}` helper lets you specify where a child route will render in @@ -137,13 +53,8 @@ function outletComponentFor(vm: VM, args: Arguments) { @for Ember.Templates.helpers @public */ -export const outletMacro = (_name: string, _params: Option, _hash: Option, _builder: OpcodeBuilder) => { - // if (!params) { - // params = []; - // } - // let definitionArgs = [params.slice(0, 1), null, null, null]; - // let emptyArgs = [[], null, null, null]; // FIXME - // builder.component.dynamic(definitionArgs, outletComponentFor, emptyArgs); - +export const outletMacro = (_name: string, params: Option, hash: Option, builder: OpcodeBuilder) => { + let expr: WireFormat.Expressions.Helper = [WireFormat.Ops.Helper, '-outlet', params || [], hash]; + builder.guardedAppend(expr, false); return true; }; From fadb79af811ec454ca7f5200cd8141ddb1b3c857 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Tue, 28 Nov 2017 15:06:45 -0700 Subject: [PATCH 018/135] WIP: Get curly components to render with class and id The contents are not rendering at all, and a lot of the code is not handling error cases. This is just to get the component to render at all. --- .../lib/component-managers/curly.ts | 34 ++++++++++++++----- .../lib/component-managers/root.ts | 1 - packages/ember-glimmer/lib/environment.ts | 6 ++-- packages/ember-glimmer/lib/resolver.ts | 28 +++++++++++---- .../lib/utils/curly-component-state-bucket.ts | 6 ++-- 5 files changed, 52 insertions(+), 23 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 2bef879b7f2..08df1cdfb14 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -4,7 +4,10 @@ import { Simple, VMHandle } from '@glimmer/interfaces'; -import { WrappedBuilder } from '@glimmer/opcode-compiler'; +import { + CompileOptions, + WrappedBuilder +} from '@glimmer/opcode-compiler'; import { combineTagged, Tag, @@ -24,6 +27,9 @@ import { WithDynamicTagName, } from '@glimmer/runtime'; import { Destroyable, Opaque } from '@glimmer/util'; +import { + SerializedTemplate +} from '@glimmer/wire-format'; import { privatize as P } from 'container'; import { assert, @@ -36,6 +42,7 @@ import { import { assign, getOwner, + guidFor, OWNER, } from 'ember-utils'; import { setViewElement, TemplateMeta } from 'ember-views'; @@ -74,7 +81,7 @@ function aliasIdToElementId(args: Arguments, props: any) { // We must traverse the attributeBindings in reverse keeping track of // what has already been applied. This is essentially refining the concatenated // properties applying right to left. -function applyAttributeBindings(element: Simple.Element, attributeBindings: any, component: Component, operations: ElementOperations) { +function applyAttributeBindings(element: Simple.Element, attributeBindings: Array, component: Component, operations: ElementOperations) { let seen: string[] = []; let i = attributeBindings.length - 1; @@ -159,11 +166,12 @@ export default class CurlyComponentManager extends AbstractManager { + return resolver.compileTemplate(handle, layoutName, (template: SerializedTemplate, options: CompileOptions) => { const builder = new WrappedBuilder( assign({}, options, { asPartial: false, referrer: null }), template, @@ -176,8 +184,11 @@ export default class CurlyComponentManager extends AbstractManager { - throw new Error('Method not implemented.'); + getTagName(state: ComponentStateBucket): Option { + let { component } = state; + + return (component && component.tagName) || 'div'; + // throw new Error('Method not implemented.'); } getCapabilities(state: DefinitionState): ComponentCapabilities { @@ -331,10 +342,15 @@ export default class CurlyComponentManager extends AbstractManager { + classNameBindings.forEach((binding: string) => { ClassNameBinding.install(element, component, binding, operations); }); } @@ -391,7 +407,7 @@ export default class CurlyComponentManager extends AbstractManager { } // End IRuntimeResolver + compileTemplate(_handle: number, layoutName: string, create: (block: SerializedTemplate, options: CompileOptions) => Invocation) { + let template = this.owner.lookup(`template:${layoutName}`); + + // TODO: handle template not found + let { parsedLayout, options } = template as any; + return create(parsedLayout, options); + } + /** * Called by CompileTimeLookup compiling Unknown or Helper OpCode */ lookupHelper(name: string, meta: TemplateMeta): Option { - return this.getHandle( - this._lookupHelper(name, meta)); + let handle = this._lookupHelper(name, meta); + if (handle !== null) { + return this.getHandle(handle); + } + return null; } /** @@ -130,7 +143,7 @@ export default class RuntimeResolver implements IRuntimeResolver { } // end CompileTimeLookup - private _lookupHelper(name: string, meta: TemplateMeta): Helper { + private _lookupHelper(name: string, meta: TemplateMeta): Option { if (name === 'component') { return (vm, args) => componentHelper(vm, args, meta); } @@ -147,12 +160,13 @@ export default class RuntimeResolver implements IRuntimeResolver { const helperFactory = owner.factoryFor(`helper:${name}`, options) || owner.factoryFor(`helper:${name}`); // TODO: try to unify this into a consistent protocol to avoid wasteful closure allocations - if (helperFactory.class.isHelperInstance) { + if (helperFactory && helperFactory.class.isHelperInstance) { return (_vm, args) => SimpleHelperReference.create(helperFactory.class.compute, args.capture()); - } else if (helperFactory.class.isHelperFactory) { + } else if (helperFactory && helperFactory.class.isHelperFactory) { return (vm, args) => ClassBasedHelperReference.create(helperFactory, vm, args.capture()); } else { - throw new Error(`${name} is not a helper`); + return null; + // throw new Error(`${name} is not a helper`); } } diff --git a/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts b/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts index 9bbc2980436..8adfe81d399 100644 --- a/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts +++ b/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts @@ -7,9 +7,9 @@ export interface Component { _debugContainerKey: string; _transitionTo(name: string): void; layoutName?: string; - attributeBindings: any; - classNames: any; - classNameBindings: any; + attributeBindings: Array; + classNames: Array; + classNameBindings: Array; elementId: string; tagName: string; isDestroying: boolean; From 29880cff9e475d475339d30142dbc2e6740b1723 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 28 Nov 2017 15:01:55 -0800 Subject: [PATCH 019/135] Workaround for qunit-fixture not having class=ember-application removed --- tests/index.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/index.html b/tests/index.html index a42092358ad..5346fe5d3ec 100644 --- a/tests/index.html +++ b/tests/index.html @@ -177,6 +177,14 @@ $('#qunit-tests').addClass('hideskipped'); } }); + + QUnit.testDone(function() { + var oldFixture = document.getElementById('qunit-fixture'); + var parent = oldFixture.parentElement; + var newFixture = document.createElement('div'); + newFixture.id = 'qunit-fixture'; + parent.replaceChild(newFixture, oldFixture); + }); })(); From a4d9579bc5a21e936a5262e3e3eb3339fe585bcb Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 28 Nov 2017 15:14:53 -0800 Subject: [PATCH 020/135] compile-options should be a singleton across app and engines --- packages/ember-application/lib/system/engine-instance.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/ember-application/lib/system/engine-instance.js b/packages/ember-application/lib/system/engine-instance.js index cb93574602d..f1f0e67a4c7 100644 --- a/packages/ember-application/lib/system/engine-instance.js +++ b/packages/ember-application/lib/system/engine-instance.js @@ -180,6 +180,7 @@ const EngineInstance = EmberObject.extend(RegistryProxyMixin, ContainerProxyMixi '-view-registry:main', `renderer:-${env.isInteractive ? 'dom' : 'inert'}`, 'service:-document', + 'service:-compile-options', ]; if (env.isInteractive) { From 5b159dc05d1961a1c6f5ca514e0a0f64fcfb4152 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 28 Nov 2017 15:58:26 -0800 Subject: [PATCH 021/135] don't leak handles across resolver instances --- packages/ember-glimmer/lib/resolver.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 494b784e362..213c0d74bc1 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -54,6 +54,7 @@ export default class RuntimeResolver implements IRuntimeResolver { }; private handles: any[] = []; + private objToHandle = new WeakMap(); constructor(public owner: Owner) { this.builtInHelpers = { @@ -211,9 +212,10 @@ export default class RuntimeResolver implements IRuntimeResolver { if (obj === undefined || obj === null) { return null; } - let handle: number | undefined = obj.__handle; + let handle: number | undefined = this.objToHandle.get(obj); if (handle === undefined) { - handle = obj.__handle = this.handles.push(obj) - 1; + handle = this.handles.push(obj) - 1; + this.objToHandle.set(obj, handle); } return handle; } From baa243bd43ab756550243821a95e0730b87acb3b Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 28 Nov 2017 16:13:12 -0800 Subject: [PATCH 022/135] fix issue that was from a merge with master --- packages/ember-glimmer/lib/resolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 213c0d74bc1..359fe9c7a5c 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -162,7 +162,7 @@ export default class RuntimeResolver implements IRuntimeResolver { // TODO: try to unify this into a consistent protocol to avoid wasteful closure allocations if (helperFactory && helperFactory.class.isHelperInstance) { - return (_vm, args) => SimpleHelperReference.create(helperFactory.class.compute, args.capture()); + return (vm, args) => SimpleHelperReference.create(helperFactory, vm, args.capture()); } else if (helperFactory && helperFactory.class.isHelperFactory) { return (vm, args) => ClassBasedHelperReference.create(helperFactory, vm, args.capture()); } else { From 1d554114a323064be740a27a28a598bbac6f4a9b Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 28 Nov 2017 17:49:53 -0800 Subject: [PATCH 023/135] fix AST plugins --- .../lib/plugins/assert-input-helper-without-block.js | 2 +- .../lib/plugins/assert-reserved-named-arguments.js | 2 +- .../lib/plugins/deprecate-render-model.js | 2 +- .../ember-template-compiler/lib/plugins/deprecate-render.js | 2 +- .../ember-template-compiler/lib/plugins/extract-pragma-tag.js | 2 +- .../lib/plugins/transform-action-syntax.js | 2 +- .../lib/plugins/transform-angle-bracket-components.js | 2 +- .../lib/plugins/transform-attrs-into-args.js | 2 +- .../lib/plugins/transform-dot-component-invocation.js | 2 +- .../lib/plugins/transform-each-in-into-each.js | 2 +- .../lib/plugins/transform-has-block-syntax.js | 2 +- .../lib/plugins/transform-inline-link-to.js | 2 +- .../lib/plugins/transform-input-on-to-onEvent.js | 2 +- .../lib/plugins/transform-input-type-syntax.js | 2 +- .../lib/plugins/transform-old-binding-syntax.js | 2 +- .../lib/plugins/transform-old-class-binding-syntax.js | 2 +- .../lib/plugins/transform-quoted-bindings-into-just-bindings.js | 2 +- .../lib/plugins/transform-top-level-components.js | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/ember-template-compiler/lib/plugins/assert-input-helper-without-block.js b/packages/ember-template-compiler/lib/plugins/assert-input-helper-without-block.js index e607f6cae62..7cdd29987e3 100644 --- a/packages/ember-template-compiler/lib/plugins/assert-input-helper-without-block.js +++ b/packages/ember-template-compiler/lib/plugins/assert-input-helper-without-block.js @@ -7,7 +7,7 @@ export default function errorOnInputWithContent(env) { return { name: 'assert-input-helper-without-block', - visitors: { + visitor: { BlockStatement(node) { if (node.path.original !== 'input') { return; } diff --git a/packages/ember-template-compiler/lib/plugins/assert-reserved-named-arguments.js b/packages/ember-template-compiler/lib/plugins/assert-reserved-named-arguments.js index 09ae0ebcbde..6d4aa5e51a7 100644 --- a/packages/ember-template-compiler/lib/plugins/assert-reserved-named-arguments.js +++ b/packages/ember-template-compiler/lib/plugins/assert-reserved-named-arguments.js @@ -7,7 +7,7 @@ export default function assertReservedNamedArguments(env) { return { name: 'assert-reserved-named-arguments', - visitors: { + visitor: { PathExpression(node) { if (node.original[0] === '@') { assert(assertMessage(moduleName, node)); diff --git a/packages/ember-template-compiler/lib/plugins/deprecate-render-model.js b/packages/ember-template-compiler/lib/plugins/deprecate-render-model.js index 0e84f3651ad..0c8d435fb7b 100644 --- a/packages/ember-template-compiler/lib/plugins/deprecate-render-model.js +++ b/packages/ember-template-compiler/lib/plugins/deprecate-render-model.js @@ -8,7 +8,7 @@ export default function deprecateRenderModel(env) { return { name: 'deprecate-render-model', - visitors: { + visitor: { MustacheStatement(node) { if (node.path.original === 'render' && node.params.length > 1) { node.params.forEach(param => { diff --git a/packages/ember-template-compiler/lib/plugins/deprecate-render.js b/packages/ember-template-compiler/lib/plugins/deprecate-render.js index 69cc74e0a24..0178b7a87d9 100644 --- a/packages/ember-template-compiler/lib/plugins/deprecate-render.js +++ b/packages/ember-template-compiler/lib/plugins/deprecate-render.js @@ -7,7 +7,7 @@ export default function deprecateRender(env) { return { name: 'deprecate-render', - visitors: { + visitor: { MustacheStatement(node) { if (node.path.original !== 'render') { return; } if (node.params.length !== 1) { return; } diff --git a/packages/ember-template-compiler/lib/plugins/extract-pragma-tag.js b/packages/ember-template-compiler/lib/plugins/extract-pragma-tag.js index f0cd7183712..3c40a434869 100644 --- a/packages/ember-template-compiler/lib/plugins/extract-pragma-tag.js +++ b/packages/ember-template-compiler/lib/plugins/extract-pragma-tag.js @@ -6,7 +6,7 @@ export default function extractPragmaTag(env) { return { name: 'exract-pragma-tag', - visitors: { + visitor: { MustacheStatement: { enter(node) { if (node.path.type === 'PathExpression' && node.path.original === PRAGMA_TAG) { diff --git a/packages/ember-template-compiler/lib/plugins/transform-action-syntax.js b/packages/ember-template-compiler/lib/plugins/transform-action-syntax.js index 1bc0339ba9b..3b12392d087 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-action-syntax.js +++ b/packages/ember-template-compiler/lib/plugins/transform-action-syntax.js @@ -29,7 +29,7 @@ export default function transformActionSyntax({ syntax }) { return { name: 'transform-action-syntax', - visitors: { + visitor: { ElementModifierStatement(node) { if (isAction(node)) { insertThisAsFirstParam(node, b); diff --git a/packages/ember-template-compiler/lib/plugins/transform-angle-bracket-components.js b/packages/ember-template-compiler/lib/plugins/transform-angle-bracket-components.js index 46ea0d3662b..c778770906b 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-angle-bracket-components.js +++ b/packages/ember-template-compiler/lib/plugins/transform-angle-bracket-components.js @@ -2,7 +2,7 @@ export default function transformAngleBracketComponents(env) { return { name: 'transform-angle-bracket-components', - visitors: { + visitor: { ComponentNode(node) { node.tag = `<${node.tag}>`; } diff --git a/packages/ember-template-compiler/lib/plugins/transform-attrs-into-args.js b/packages/ember-template-compiler/lib/plugins/transform-attrs-into-args.js index 55dd0045277..dbb9e907d10 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-attrs-into-args.js +++ b/packages/ember-template-compiler/lib/plugins/transform-attrs-into-args.js @@ -30,7 +30,7 @@ export default function transformAttrsIntoArgs(env) { return { name: 'transform-attrs-into-args', - visitors: { + visitor: { Program: { enter(node) { let parent = stack[stack.length - 1]; diff --git a/packages/ember-template-compiler/lib/plugins/transform-dot-component-invocation.js b/packages/ember-template-compiler/lib/plugins/transform-dot-component-invocation.js index 4cb8693330d..7edd10d42dc 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-dot-component-invocation.js +++ b/packages/ember-template-compiler/lib/plugins/transform-dot-component-invocation.js @@ -58,7 +58,7 @@ export default function transformDotComponentInvocation(env) { return { name: 'transform-dot-component-invocation', - visitors: { + visitor: { MustacheStatement: (node) => { if (isInlineInvocation(node.path, node.params, node.hash)) { wrapInComponent(node, b); diff --git a/packages/ember-template-compiler/lib/plugins/transform-each-in-into-each.js b/packages/ember-template-compiler/lib/plugins/transform-each-in-into-each.js index 8805428b6e3..91426126921 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-each-in-into-each.js +++ b/packages/ember-template-compiler/lib/plugins/transform-each-in-into-each.js @@ -24,7 +24,7 @@ export default function transformEachInIntoEach(env) { return { name: 'transform-each-in-into-each', - visitors: { + visitor: { BlockStatement(node) { if (node.path.original === 'each-in') { node.params[0] = b.sexpr(b.path('-each-in'), [node.params[0]]); diff --git a/packages/ember-template-compiler/lib/plugins/transform-has-block-syntax.js b/packages/ember-template-compiler/lib/plugins/transform-has-block-syntax.js index 5e4058c61d6..6ecb24246d8 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-has-block-syntax.js +++ b/packages/ember-template-compiler/lib/plugins/transform-has-block-syntax.js @@ -30,7 +30,7 @@ export default function transformHasBlockSyntax(env) { return { name: 'transform-has-block-syntax', - visitors: { + visitor: { PathExpression(node) { if (TRANSFORMATIONS[node.original]) { return b.sexpr(b.path(TRANSFORMATIONS[node.original])); diff --git a/packages/ember-template-compiler/lib/plugins/transform-inline-link-to.js b/packages/ember-template-compiler/lib/plugins/transform-inline-link-to.js index 15c6829687a..58534adac51 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-inline-link-to.js +++ b/packages/ember-template-compiler/lib/plugins/transform-inline-link-to.js @@ -26,7 +26,7 @@ export default function transformInlineLinkTo(env) { return { name: 'transform-inline-link-to', - visitors: { + visitor: { MustacheStatement(node) { if (node.path.original === 'link-to') { let content = node.escaped ? node.params[0] : unsafeHtml(b, node.params[0]); diff --git a/packages/ember-template-compiler/lib/plugins/transform-input-on-to-onEvent.js b/packages/ember-template-compiler/lib/plugins/transform-input-on-to-onEvent.js index 23bb94cfaa4..137bf800632 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-input-on-to-onEvent.js +++ b/packages/ember-template-compiler/lib/plugins/transform-input-on-to-onEvent.js @@ -30,7 +30,7 @@ export default function transformInputOnToOnEvent(env) { return { name: 'transform-input-on-to-onEvent', - visitors: { + visitor: { MustacheStatement(node) { if (node.path.original !== 'input') { return; diff --git a/packages/ember-template-compiler/lib/plugins/transform-input-type-syntax.js b/packages/ember-template-compiler/lib/plugins/transform-input-type-syntax.js index 356120137f5..eb1458d5bbc 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-input-type-syntax.js +++ b/packages/ember-template-compiler/lib/plugins/transform-input-type-syntax.js @@ -29,7 +29,7 @@ export default function transformInputTypeSyntax(env) { return { name: 'transform-input-type-syntax', - visitors: { + visitor: { MustacheStatement(node) { if (isInput(node)) { insertTypeHelperParameter(node, b); diff --git a/packages/ember-template-compiler/lib/plugins/transform-old-binding-syntax.js b/packages/ember-template-compiler/lib/plugins/transform-old-binding-syntax.js index 72dc067b41f..176445d89bf 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-old-binding-syntax.js +++ b/packages/ember-template-compiler/lib/plugins/transform-old-binding-syntax.js @@ -8,7 +8,7 @@ export default function transformOldBindingSyntax(env) { return { name: 'transform-old-binding-syntax', - visitors: { + visitor: { BlockStatement(node) { processHash(b, node, moduleName); }, diff --git a/packages/ember-template-compiler/lib/plugins/transform-old-class-binding-syntax.js b/packages/ember-template-compiler/lib/plugins/transform-old-class-binding-syntax.js index a1bff353aee..4d3f333a058 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-old-class-binding-syntax.js +++ b/packages/ember-template-compiler/lib/plugins/transform-old-class-binding-syntax.js @@ -4,7 +4,7 @@ export default function transformOldClassBindingSyntax(env) { return { name: 'transform-old-class-binding-syntax', - visitors: { + visitor: { MustacheStatement(node) { process(b, node); }, diff --git a/packages/ember-template-compiler/lib/plugins/transform-quoted-bindings-into-just-bindings.js b/packages/ember-template-compiler/lib/plugins/transform-quoted-bindings-into-just-bindings.js index 58a7bb87feb..986d4d5fff7 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-quoted-bindings-into-just-bindings.js +++ b/packages/ember-template-compiler/lib/plugins/transform-quoted-bindings-into-just-bindings.js @@ -3,7 +3,7 @@ export default function transformQuotedBindingsIntoJustBindings(env) { return { name: 'transform-quoted-bindings-into-just-bindings', - visitors: { + visitor: { ElementNode(node) { let styleAttr = getStyleAttr(node); diff --git a/packages/ember-template-compiler/lib/plugins/transform-top-level-components.js b/packages/ember-template-compiler/lib/plugins/transform-top-level-components.js index fe906bfc6d2..0b185ef05d1 100644 --- a/packages/ember-template-compiler/lib/plugins/transform-top-level-components.js +++ b/packages/ember-template-compiler/lib/plugins/transform-top-level-components.js @@ -2,7 +2,7 @@ export default function transformTopLevelComponent(env) { return { name: 'transform-top-level-component', - visitors: { + visitor: { Program(node) { hasSingleComponentNode(node, component => { component.tag = `@${component.tag}`; From 9c3b095276d84607006baa5d5184428ca27fae2a Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 28 Nov 2017 18:10:27 -0800 Subject: [PATCH 024/135] Outlets should return render.controller as their self --- packages/ember-glimmer/lib/component-managers/outlet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index 18514ea05df..80ff294afb5 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -95,7 +95,7 @@ class OutletComponentManager extends AbstractManager Date: Wed, 29 Nov 2017 09:15:41 -0800 Subject: [PATCH 025/135] outlets should update --- packages/ember-glimmer/lib/syntax/outlet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/syntax/outlet.ts b/packages/ember-glimmer/lib/syntax/outlet.ts index 070fd832024..4f48ce6fd96 100644 --- a/packages/ember-glimmer/lib/syntax/outlet.ts +++ b/packages/ember-glimmer/lib/syntax/outlet.ts @@ -55,6 +55,6 @@ import { TemplateMeta } from 'ember-views'; */ export const outletMacro = (_name: string, params: Option, hash: Option, builder: OpcodeBuilder) => { let expr: WireFormat.Expressions.Helper = [WireFormat.Ops.Helper, '-outlet', params || [], hash]; - builder.guardedAppend(expr, false); + builder.dynamicComponent(expr, [], null, false, null, null); return true; }; From 14c7a9d8997b0f1981b2e5b7d08cde5114322320 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Thu, 30 Nov 2017 10:27:12 -0700 Subject: [PATCH 026/135] Fix missing results from merge --- tests/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/index.html b/tests/index.html index a5c8f0daa19..20561b03bcb 100644 --- a/tests/index.html +++ b/tests/index.html @@ -182,7 +182,7 @@ } }); - QUnit.testDone(function() { + QUnit.testDone(function(results) { var oldFixture = document.getElementById('qunit-fixture'); var parent = oldFixture.parentElement; var newFixture = document.createElement('div'); From 8d9041c39e95c342627920c6a5dfbc25fd1889c0 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Thu, 30 Nov 2017 15:24:00 -0700 Subject: [PATCH 027/135] WIP: Rendering the contents of components --- .../ember-glimmer/lib/component-managers/curly.ts | 7 +++---- packages/ember-glimmer/lib/environment.ts | 13 ++++--------- packages/ember-glimmer/lib/resolver.ts | 4 ++-- packages/ember-glimmer/lib/syntax.ts | 12 ++++++++---- packages/ember-glimmer/lib/utils/references.ts | 11 +++++++++-- 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 08df1cdfb14..81dd4a9df48 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -188,7 +188,6 @@ export default class CurlyComponentManager extends AbstractManager, template: OwnedTemplate, args?: Arguments) { + constructor(public name: string, public manager: CurlyComponentManager = CURLY_COMPONENT_MANAGER, public ComponentClass: any, public handle: Option, template: OwnedTemplate, args?: Arguments) { this.template = template; this.args = args; - this.manager = manager; this.state = { name, ComponentClass, diff --git a/packages/ember-glimmer/lib/environment.ts b/packages/ember-glimmer/lib/environment.ts index 9e20f7a3e6a..c6ded229a94 100644 --- a/packages/ember-glimmer/lib/environment.ts +++ b/packages/ember-glimmer/lib/environment.ts @@ -33,6 +33,8 @@ import { EMBER_MODULE_UNIFICATION, } from 'ember/features'; import { OwnedTemplate } from './template'; +import { Attribute } from '@glimmer/interfaces/dist/types/lib/dom/simple'; +import { DynamicAttribute } from '@glimmer/runtime/dist/types/lib/vm/attributes/dynamic'; export interface CompilerFactory { id: string; @@ -156,19 +158,12 @@ if (DEBUG) { } } - let STYLE_ATTRIBUTE_MANANGER = new StyleAttributeManager(); + // let STYLE_ATTRIBUTE_MANANGER = new StyleAttributeManager(); -<<<<<<< HEAD - Environment.prototype.attributeFor = function(element, attribute, isTrusting) { + Environment.prototype.attributeFor = function (element, attribute, isTrusting) { // if (attribute === 'style' && !isTrusting) { // return STYLE_ATTRIBUTE_MANANGER; // } -======= - Environment.prototype.attributeFor = function (element, attribute, isTrusting) { - if (attribute === 'style' && !isTrusting) { - return STYLE_ATTRIBUTE_MANANGER; - } ->>>>>>> origin/master return GlimmerEnvironment.prototype.attributeFor.call(this, element, attribute, isTrusting); }; diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 55a053aafd4..b261f7efb11 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -190,7 +190,7 @@ export default class RuntimeResolver implements IRuntimeResolver { } private _lookupComponentDefinition(name: string, meta: TemplateMeta): Option { - let { layout } = lookupComponent(meta.owner, name, makeOptions(meta.moduleName)); + let { layout, component } = lookupComponent(meta.owner, name, makeOptions(meta.moduleName)); let customManager; if (GLIMMER_CUSTOM_COMPONENT_MANAGER) { @@ -203,7 +203,7 @@ export default class RuntimeResolver implements IRuntimeResolver { let layoutHandle = this.getHandle(layout) as Option; - return new CurlyComponentDefinition(name, customManager, undefined, layoutHandle, customManager); + return new CurlyComponentDefinition(name, customManager, component, layoutHandle, customManager); } private getHandle(obj: any | null | undefined) { diff --git a/packages/ember-glimmer/lib/syntax.ts b/packages/ember-glimmer/lib/syntax.ts index 4c43a160f1f..ef76a6865a0 100644 --- a/packages/ember-glimmer/lib/syntax.ts +++ b/packages/ember-glimmer/lib/syntax.ts @@ -1,5 +1,6 @@ -import { Macros } from '@glimmer/opcode-compiler'; +import { Macros, WrappedBuilder } from '@glimmer/opcode-compiler'; import { assert } from 'ember-debug'; +import { TemplateMeta } from 'ember-views'; import { textAreaMacro } from './syntax/-text-area'; import { inputMacro } from './syntax/input'; import { mountMacro } from './syntax/mount'; @@ -9,11 +10,14 @@ import { hashToArgs } from './syntax/utils'; import { wrapComponentClassAttribute } from './utils/bindings'; function refineInlineSyntax(name: string, params: any[], hash: any, builder: any) { - assert(`You attempted to overwrite the built-in helper "${name}" which is not allowed. Please rename the helper.`, !(builder.env.builtInHelpers[name] && builder.env.owner.hasRegistration(`helper:${name}`))); + assert(`You attempted to overwrite the built-in helper "${name}" which is not allowed. Please rename the helper.`, !(builder.resolver.resolver.builtInHelpers[name] && builder.resolver.resolver.owner.hasRegistration(`helper:${name}`))); let definition; if (name.indexOf('-') > -1) { - definition = builder.env.getComponentDefinition(name, builder.meta.templateMeta); + definition = builder.resolver.lookupComponentDefinition(name, { + owner: builder.resolver.resolver.owner, + moduleName: '' + }); } if (definition) { @@ -67,7 +71,7 @@ export function populateMacros(macros: Macros) { inlines.add('mount', mountMacro); inlines.add('input', inputMacro); inlines.add('textarea', textAreaMacro); - // inlines.addMissing(refineInlineSyntax); + inlines.addMissing(refineInlineSyntax); // blocks.add('component', blockComponentMacro); blocks.addMissing(refineBlockSyntax); diff --git a/packages/ember-glimmer/lib/utils/references.ts b/packages/ember-glimmer/lib/utils/references.ts index 82e579eb17d..bd14eebf1a8 100644 --- a/packages/ember-glimmer/lib/utils/references.ts +++ b/packages/ember-glimmer/lib/utils/references.ts @@ -1,9 +1,12 @@ +import { Opaque } from '@glimmer/interfaces'; import { combine, CONSTANT_TAG, ConstReference, DirtyableTag, isConst, + PathReference, + Tag, TagWrapper, UpdatableTag, } from '@glimmer/reference'; @@ -24,6 +27,7 @@ import { watchKey, } from 'ember-metal'; import { + HAS_NATIVE_WEAKMAP, symbol, } from 'ember-utils'; import { @@ -49,7 +53,7 @@ if (DEBUG) { // performance penalty on Chrome (tested through 59). // // See: https://bugs.chromium.org/p/v8/issues/detail?id=6450 - if (!Object.isFrozen(obj)) { + if (!Object.isFrozen(obj) && HAS_NATIVE_WEAKMAP) { Object.freeze(obj); } }; @@ -57,13 +61,16 @@ if (DEBUG) { // @abstract // @implements PathReference -class EmberPathReference { +abstract class EmberPathReference implements PathReference { // @abstract get tag() // @abstract value() + public tag: Tag; get(key: string): any { return PropertyReference.create(this, key); } + + abstract value(): Opaque; } // @abstract From 37fefd1c730b00ad3576603cc97bf1eeb0d33be9 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Fri, 1 Dec 2017 21:58:06 -0700 Subject: [PATCH 028/135] Update refineBlockSyntax with new object shape --- packages/ember-glimmer/lib/syntax.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/ember-glimmer/lib/syntax.ts b/packages/ember-glimmer/lib/syntax.ts index ef76a6865a0..4936ed6eb28 100644 --- a/packages/ember-glimmer/lib/syntax.ts +++ b/packages/ember-glimmer/lib/syntax.ts @@ -1,6 +1,5 @@ -import { Macros, WrappedBuilder } from '@glimmer/opcode-compiler'; +import { Macros } from '@glimmer/opcode-compiler'; import { assert } from 'ember-debug'; -import { TemplateMeta } from 'ember-views'; import { textAreaMacro } from './syntax/-text-area'; import { inputMacro } from './syntax/input'; import { mountMacro } from './syntax/mount'; @@ -34,11 +33,14 @@ function refineBlockSyntax(name: string, params: any[], hash: any, _default: any return false; } - let meta = builder.meta.templateMeta; + let meta = { + owner: builder.resolver.resolver.owner, + moduleName: '' + }; let definition; if (name.indexOf('-') > -1) { - definition = builder.env.getComponentDefinition(name, meta); + definition = builder.resolver.lookupComponentDefinition(name, meta); } if (definition) { From 29f3f151c1fef6b95052e8fee0bdaf6596ed1a00 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 6 Dec 2017 10:44:27 -0700 Subject: [PATCH 029/135] WIP Add CURLY_CAPABILITIES and update prepareArgs The prepareArgs implementation is taken directly from glimmer-vm's Emberish Curly component. I left the original implemenation in there, commented out, because I feel like something from that original implementation is probably necessary for the update implementation, but I can't really say what. --- .../lib/component-managers/curly.ts | 121 +++++++++++------- packages/ember-glimmer/lib/resolver.ts | 8 +- 2 files changed, 82 insertions(+), 47 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 81dd4a9df48..7a95c5dbd73 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -26,7 +26,7 @@ import { WithDynamicLayout, WithDynamicTagName, } from '@glimmer/runtime'; -import { Destroyable, Opaque } from '@glimmer/util'; +import { Destroyable, EMPTY_ARRAY, Opaque } from '@glimmer/util'; import { SerializedTemplate } from '@glimmer/wire-format'; @@ -66,7 +66,7 @@ import ComponentStateBucket, { Component } from '../utils/curly-component-state- import { processComponentArgs } from '../utils/process-args'; import { PropertyReference } from '../utils/references'; import AbstractManager from './abstract'; -import DefinitionState, { CAPABILITIES } from './definition-state'; +import DefinitionState from './definition-state'; const DEFAULT_LAYOUT = P`template:components/-default`; @@ -175,7 +175,7 @@ export default class CurlyComponentManager extends AbstractManager { - let componentPositionalParamsDefinition = state.ComponentClass.class.positionalParams; - - if (DEBUG && componentPositionalParamsDefinition) { - validatePositionalParameters(args.named, args.positional, componentPositionalParamsDefinition); - } - - let componentHasRestStylePositionalParams = typeof componentPositionalParamsDefinition === 'string'; - let componentHasPositionalParams = componentHasRestStylePositionalParams || - componentPositionalParamsDefinition.length > 0; - let needsPositionalParamMunging = componentHasPositionalParams && args.positional.length !== 0; - let isClosureComponent = args; - - if (!needsPositionalParamMunging && !isClosureComponent) { - return null; - } - - let capturedArgs = args.capture(); - // grab raw positional references array - let positional = capturedArgs.positional.references; - - // handle prep for closure component with positional params - let curriedNamed; - if (args) { - let remainingDefinitionPositionals = args.positional.slice(positional.length); - positional = positional.concat(remainingDefinitionPositionals); - curriedNamed = args.named; - } + const { positionalParams } = state.ComponentClass.class; + + if (typeof positionalParams === 'string') { + if (args.named.has(positionalParams)) { + if (args.positional.length === 0) { + return null; + } else { + throw new Error('You cannot specify positional parameters and the has argument...'); + } + } - // handle positionalParams - let positionalParamsToNamed; - if (componentHasRestStylePositionalParams) { - positionalParamsToNamed = { - [componentPositionalParamsDefinition]: new PositionalArgumentReference(positional), + const named = { + ...args.named.capture().map + }; + named[positionalParams] = args.positional.capture(); + return { positional: EMPTY_ARRAY, named }; + } else if (Array.isArray(positionalParams)) { + const named = { + ...args.named.capture().map }; - positional = []; - } else if (componentHasPositionalParams) { - positionalParamsToNamed = {}; - let length = Math.min(positional.length, componentPositionalParamsDefinition.length); - for (let i = 0; i < length; i++) { - let name = componentPositionalParamsDefinition[i]; - positionalParamsToNamed[name] = positional[i]; + const count = Math.min(positionalParams.length, args.positional.length); + for (let i=0; i, hasBlock: boolean): ComponentStateBucket { @@ -504,6 +523,16 @@ export function initialRenderInstrumentDetails(component: any): any { export function rerenderInstrumentDetails(component: any): any { return component.instrumentDetails({ initialRender: false }); } + +export const CURLY_CAPABILITIES: ComponentCapabilities = { + dynamicLayout: true, + dynamicTag: true, + prepareArgs: true, + createArgs: true, + attributeHook: true, + elementHook: true +}; + const CURLY_COMPONENT_MANAGER = new CurlyComponentManager(); export class CurlyComponentDefinition implements ComponentDefinition { public template: OwnedTemplate; @@ -518,7 +547,7 @@ export class CurlyComponentDefinition implements ComponentDefinition { name, ComponentClass, handle, - capabilities: CAPABILITIES + capabilities: CURLY_CAPABILITIES }; } } diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index b261f7efb11..1e68751f796 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -6,6 +6,7 @@ import { VMHandle } from '@glimmer/interfaces'; import { getDynamicVar, Helper, ModifierManager, PartialDefinition, ScannableTemplate, Invocation } from '@glimmer/runtime'; +import { privatize as P } from 'container'; import { LookupOptions, Owner } from 'ember-utils'; import { lookupComponent, @@ -39,6 +40,8 @@ import { ClassBasedHelperReference, SimpleHelperReference } from './utils/refere import { CompileOptions } from '@glimmer/opcode-compiler'; import { SerializedTemplateBlock, SerializedTemplate } from '@glimmer/wire-format'; +const DEFAULT_LAYOUT = P`template:components/-default`; + function makeOptions(moduleName: string) { return moduleName !== undefined ? { source: `template:${moduleName}`} : undefined; } @@ -109,7 +112,10 @@ export default class RuntimeResolver implements IRuntimeResolver { compileTemplate(_handle: number, layoutName: string, create: (block: SerializedTemplate, options: CompileOptions) => Invocation) { let template = this.owner.lookup(`template:${layoutName}`); - // TODO: handle template not found + if (!template) { + template = this.owner.lookup(DEFAULT_LAYOUT); + } + let { parsedLayout, options } = template as any; return create(parsedLayout, options); } From 8a8bbcea01ef24419483f13fcdc19d5ab967ecce Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Thu, 7 Dec 2017 10:53:55 -0700 Subject: [PATCH 030/135] A tagName of empty string means no tag --- packages/ember-glimmer/lib/component-managers/curly.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 7a95c5dbd73..12a171eeb00 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -187,6 +187,9 @@ export default class CurlyComponentManager extends AbstractManager { let { component } = state; + if (component.tagName === '') { + return null; + } return (component && component.tagName) || 'div'; } From ab2db9db18f5cb2867a1c39ca6b94c5ca2773b13 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Tue, 12 Dec 2017 14:56:45 -0700 Subject: [PATCH 031/135] WIP ONly use dynamicLayout when the state has no layout --- .../ember-glimmer/lib/compile-time-lookup.ts | 15 ++- .../lib/component-managers/curly.ts | 94 ++++++++++++------- packages/ember-glimmer/lib/resolver.ts | 16 +++- 3 files changed, 83 insertions(+), 42 deletions(-) diff --git a/packages/ember-glimmer/lib/compile-time-lookup.ts b/packages/ember-glimmer/lib/compile-time-lookup.ts index a8ed20a3510..6b339b719ca 100644 --- a/packages/ember-glimmer/lib/compile-time-lookup.ts +++ b/packages/ember-glimmer/lib/compile-time-lookup.ts @@ -13,9 +13,18 @@ export default class CompileTimeLookup implements ICompileTimeLookup> { - // const componentDefintion: CurlyComponentDefinition = this.resolver.resolve(handle); - return null; + getLayout(handle: number): Option> { + const { manager, state } = this.resolver.resolve(handle); + const capabilities = manager.getCapabilities(state); + if (capabilities.dynamicLayout === true) { + return null; + } + + const invocation = manager.getLayout(state, this.resolver); + return { + compile() { return invocation.handle; }, + symbolTable: invocation.symbolTable + }; } lookupHelper(name: string, referrer: TemplateMeta): Option { diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 12a171eeb00..87594a0b792 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -1,6 +1,7 @@ import { ComponentCapabilities, Option, + ProgramSymbolTable, Simple, VMHandle } from '@glimmer/interfaces'; @@ -30,7 +31,6 @@ import { Destroyable, EMPTY_ARRAY, Opaque } from '@glimmer/util'; import { SerializedTemplate } from '@glimmer/wire-format'; -import { privatize as P } from 'container'; import { assert, } from 'ember-debug'; @@ -43,7 +43,6 @@ import { assign, getOwner, guidFor, - OWNER, } from 'ember-utils'; import { setViewElement, TemplateMeta } from 'ember-views'; import { @@ -68,8 +67,6 @@ import { PropertyReference } from '../utils/references'; import AbstractManager from './abstract'; import DefinitionState from './definition-state'; -const DEFAULT_LAYOUT = P`template:components/-default`; - function aliasIdToElementId(args: Arguments, props: any) { if (args.named.has('id')) { // tslint:disable-next-line:max-line-length @@ -159,8 +156,25 @@ export default class CurlyComponentManager extends AbstractManager, WithDynamicLayout { + getLayout(state: DefinitionState, resolver: RuntimeResolver) { + const handle = resolver.lookupComponentDefinition(state.name, { + // TODO: How do I find an owner here? + owner: getOwner(/* ??? */), + moduleName: '' + }); + return { + handle, + symbolTable: state.symbolTable + }; + } + getDynamicLayout(component: ComponentStateBucket, resolver: RuntimeResolver): Invocation { + console.log('dynamic'); + const Template = get(component.component, 'layout'); const owner = getOwner(component.component); + if (Template) { + return Template; + } const layoutName = component.component.layoutName!; const handle = resolver.lookupComponentDefinition(layoutName, { owner, @@ -194,7 +208,11 @@ export default class CurlyComponentManager extends AbstractManager { @@ -282,11 +300,11 @@ export default class CurlyComponentManager extends AbstractManager { return component[ROOT_REF]; @@ -541,16 +559,22 @@ export class CurlyComponentDefinition implements ComponentDefinition { public template: OwnedTemplate; public args: Arguments | undefined; public state: DefinitionState; + public symbolTable: ProgramSymbolTable | undefined; // tslint:disable-next-line:no-shadowed-variable constructor(public name: string, public manager: CurlyComponentManager = CURLY_COMPONENT_MANAGER, public ComponentClass: any, public handle: Option, template: OwnedTemplate, args?: Arguments) { + const layout = template && template.asLayout(); + const symbolTable = layout ? layout.symbolTable : undefined; + this.symbolTable = symbolTable; this.template = template; this.args = args; this.state = { name, ComponentClass, handle, - capabilities: CURLY_CAPABILITIES + template, + capabilities: CURLY_CAPABILITIES, + symbolTable }; } } diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 1e68751f796..f79671acea5 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -5,7 +5,16 @@ import { RuntimeResolver as IRuntimeResolver, VMHandle } from '@glimmer/interfaces'; -import { getDynamicVar, Helper, ModifierManager, PartialDefinition, ScannableTemplate, Invocation } from '@glimmer/runtime'; +import { CompileOptions } from '@glimmer/opcode-compiler'; +import { + getDynamicVar, + Helper, + Invocation, + ModifierManager, + PartialDefinition, + ScannableTemplate +} from '@glimmer/runtime'; +import { SerializedTemplate } from '@glimmer/wire-format'; import { privatize as P } from 'container'; import { LookupOptions, Owner } from 'ember-utils'; import { @@ -37,8 +46,6 @@ import { default as readonly } from './helpers/readonly'; import { default as unbound } from './helpers/unbound'; import ActionModifierManager from './modifiers/action'; import { ClassBasedHelperReference, SimpleHelperReference } from './utils/references'; -import { CompileOptions } from '@glimmer/opcode-compiler'; -import { SerializedTemplateBlock, SerializedTemplate } from '@glimmer/wire-format'; const DEFAULT_LAYOUT = P`template:components/-default`; @@ -136,7 +143,8 @@ export default class RuntimeResolver implements IRuntimeResolver { */ lookupComponentDefinition(name: string, meta: TemplateMeta): Option { return this.getHandle( - this._lookupComponentDefinition(name, meta)); + this._lookupComponentDefinition(name, meta) + ); } /** From b738a10a1aa81e522ba511e8739b5c10a3fba0bc Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 13 Dec 2017 11:37:14 -0700 Subject: [PATCH 032/135] WIP more work on non dynamicLayouts It's still broken - infinite loop this time --- .../ember-glimmer/lib/component-managers/curly.ts | 11 ++++------- packages/ember-glimmer/lib/resolver.ts | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 87594a0b792..61ab504715a 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -156,14 +156,10 @@ export default class CurlyComponentManager extends AbstractManager, WithDynamicLayout { - getLayout(state: DefinitionState, resolver: RuntimeResolver) { - const handle = resolver.lookupComponentDefinition(state.name, { - // TODO: How do I find an owner here? - owner: getOwner(/* ??? */), - moduleName: '' - }); + getLayout(state: DefinitionState) { + console.log('static'); return { - handle, + handle: state.handle, symbolTable: state.symbolTable }; } @@ -186,6 +182,7 @@ export default class CurlyComponentManager extends AbstractManager, options: CompileOptions) => { + console.log('recompiling'); const builder = new WrappedBuilder( assign({}, options, { asPartial: false, referrer: null }), template, diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index f79671acea5..83f0f88fcc4 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -217,7 +217,7 @@ export default class RuntimeResolver implements IRuntimeResolver { let layoutHandle = this.getHandle(layout) as Option; - return new CurlyComponentDefinition(name, customManager, component, layoutHandle, customManager); + return new CurlyComponentDefinition(name, customManager, component, layoutHandle, layout); } private getHandle(obj: any | null | undefined) { From d99305912a967251ab813880554a2a2453c778ca Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Wed, 13 Dec 2017 18:43:07 -0800 Subject: [PATCH 033/135] Fix compiling layouts --- .../lib/system/engine-instance.js | 2 +- packages/ember-glimmer/lib/compile-options.ts | 35 ---- .../ember-glimmer/lib/compile-time-lookup.ts | 26 +-- .../lib/component-managers/curly.ts | 103 +++++++----- .../lib/component-managers/outlet.ts | 4 +- .../lib/component-managers/root.ts | 8 +- packages/ember-glimmer/lib/helpers/outlet.ts | 7 +- packages/ember-glimmer/lib/resolver.ts | 158 +++++++++--------- packages/ember-glimmer/lib/setup-registry.ts | 9 +- packages/ember-glimmer/lib/syntax.ts | 46 ++--- packages/ember-glimmer/lib/syntax/outlet.ts | 4 +- packages/ember-glimmer/lib/syntax/utils.ts | 9 +- .../ember-glimmer/lib/template-options.ts | 10 ++ packages/ember-glimmer/lib/template.ts | 55 +++--- .../ember-glimmer/lib/template_registry.ts | 8 +- .../lib/templates/component.d.ts | 4 +- .../ember-glimmer/lib/templates/empty.d.ts | 4 +- .../ember-glimmer/lib/templates/link-to.d.ts | 4 +- .../ember-glimmer/lib/templates/outlet.d.ts | 4 +- .../ember-glimmer/lib/templates/root.d.ts | 4 +- packages/ember-glimmer/lib/utils/bindings.ts | 26 +-- .../ember-glimmer/lib/utils/references.ts | 3 +- packages/ember-views/lib/index.d.ts | 11 +- 23 files changed, 269 insertions(+), 275 deletions(-) delete mode 100644 packages/ember-glimmer/lib/compile-options.ts create mode 100644 packages/ember-glimmer/lib/template-options.ts diff --git a/packages/ember-application/lib/system/engine-instance.js b/packages/ember-application/lib/system/engine-instance.js index f1f0e67a4c7..11a47369643 100644 --- a/packages/ember-application/lib/system/engine-instance.js +++ b/packages/ember-application/lib/system/engine-instance.js @@ -180,7 +180,7 @@ const EngineInstance = EmberObject.extend(RegistryProxyMixin, ContainerProxyMixi '-view-registry:main', `renderer:-${env.isInteractive ? 'dom' : 'inert'}`, 'service:-document', - 'service:-compile-options', + P`template-options:main`, ]; if (env.isInteractive) { diff --git a/packages/ember-glimmer/lib/compile-options.ts b/packages/ember-glimmer/lib/compile-options.ts deleted file mode 100644 index 6f619846e36..00000000000 --- a/packages/ember-glimmer/lib/compile-options.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { CompileTimeProgram } from '@glimmer/interfaces'; -import { - LazyOpcodeBuilder, - Macros, - OpcodeBuilderConstructor, - TemplateOptions -} from '@glimmer/opcode-compiler'; -import { LazyConstants, Program } from '@glimmer/program'; -import { getOwner } from 'ember-utils'; -import { TemplateMeta } from 'ember-views'; -import CompileTimeLookup from './compile-time-lookup'; -import RuntimeResolver from './resolver'; -import { populateMacros } from './syntax'; - -export default class CompileOptions implements TemplateOptions { - program: CompileTimeProgram; - macros: Macros; - Builder: OpcodeBuilderConstructor; - resolver: CompileTimeLookup; - - constructor(resolver: RuntimeResolver) { - const program = new Program(new LazyConstants(resolver)); - const macros = new Macros(); - populateMacros(macros); - this.program = program; - this.macros = macros; - this.resolver = new CompileTimeLookup(resolver); - this.Builder = LazyOpcodeBuilder as OpcodeBuilderConstructor; - } - - static create(injections: any) { - const resolver = new RuntimeResolver(getOwner(injections)); - return new this(resolver); - } -} diff --git a/packages/ember-glimmer/lib/compile-time-lookup.ts b/packages/ember-glimmer/lib/compile-time-lookup.ts index 6b339b719ca..dbf759c670f 100644 --- a/packages/ember-glimmer/lib/compile-time-lookup.ts +++ b/packages/ember-glimmer/lib/compile-time-lookup.ts @@ -1,10 +1,14 @@ import { ComponentCapabilities, Option, ProgramSymbolTable } from '@glimmer/interfaces'; import { CompileTimeLookup as ICompileTimeLookup } from '@glimmer/opcode-compiler'; -import { CompilableTemplate, ComponentDefinition } from '@glimmer/runtime'; -import { TemplateMeta } from 'ember-views'; +import { CompilableTemplate, ComponentDefinition, ComponentManager, WithStaticLayout } from '@glimmer/runtime'; +import { OwnedTemplateMeta } from 'ember-views'; import RuntimeResolver from './resolver'; -export default class CompileTimeLookup implements ICompileTimeLookup { +interface StaticComponentManager extends WithStaticLayout, + ComponentManager { +} + +export default class CompileTimeLookup implements ICompileTimeLookup { constructor(private resolver: RuntimeResolver) {} getCapabilities(handle: number): ComponentCapabilities { @@ -13,33 +17,35 @@ export default class CompileTimeLookup implements ICompileTimeLookup> { - const { manager, state } = this.resolver.resolve(handle); + getLayout(handle: number): Option> { + const { manager, state } = this.resolver.resolve>>(handle); const capabilities = manager.getCapabilities(state); - if (capabilities.dynamicLayout === true) { + + if (capabilities.dynamicLayout) { return null; } const invocation = manager.getLayout(state, this.resolver); return { + // TODO: this seems weird, it already is compiled compile() { return invocation.handle; }, symbolTable: invocation.symbolTable }; } - lookupHelper(name: string, referrer: TemplateMeta): Option { + lookupHelper(name: string, referrer: OwnedTemplateMeta): Option { return this.resolver.lookupHelper(name, referrer); } - lookupModifier(name: string, referrer: TemplateMeta): Option { + lookupModifier(name: string, referrer: OwnedTemplateMeta): Option { return this.resolver.lookupModifier(name, referrer); } - lookupComponentDefinition(name: string, referrer: TemplateMeta): Option { + lookupComponentDefinition(name: string, referrer: OwnedTemplateMeta): Option { return this.resolver.lookupComponentDefinition(name, referrer); } - lookupPartial(name: string, referrer: TemplateMeta): Option { + lookupPartial(name: string, referrer: OwnedTemplateMeta): Option { return this.resolver.lookupPartial(name, referrer); } } diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 61ab504715a..3cf08438c4f 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -3,12 +3,10 @@ import { Option, ProgramSymbolTable, Simple, + Unique, VMHandle } from '@glimmer/interfaces'; -import { - CompileOptions, - WrappedBuilder -} from '@glimmer/opcode-compiler'; +import { ParsedLayout, WrappedBuilder } from '@glimmer/opcode-compiler'; import { combineTagged, Tag, @@ -26,25 +24,22 @@ import { PrimitiveReference, WithDynamicLayout, WithDynamicTagName, + WithStaticLayout, } from '@glimmer/runtime'; import { Destroyable, EMPTY_ARRAY, Opaque } from '@glimmer/util'; -import { - SerializedTemplate -} from '@glimmer/wire-format'; +import { privatize as P } from 'container'; import { assert, } from 'ember-debug'; import { DEBUG } from 'ember-env-flags'; import { - _instrumentStart, - get, + _instrumentStart, get, } from 'ember-metal'; import { - assign, getOwner, guidFor, } from 'ember-utils'; -import { setViewElement, TemplateMeta } from 'ember-views'; +import { OwnedTemplateMeta, setViewElement } from 'ember-views'; import { BOUNDS, DIRTY_TAG, @@ -55,7 +50,7 @@ import { import Environment from '../environment'; import { DynamicScope } from '../renderer'; import RuntimeResolver from '../resolver'; -import { OwnedTemplate, WrappedTemplateFactory } from '../template'; +import { Factory as TemplateFactory, OwnedTemplate } from '../template'; import { AttributeBinding, ClassNameBinding, @@ -118,9 +113,9 @@ function applyAttributeBindings(element: Simple.Element, attributeBindings: Arra class CurlyComponentLayoutCompiler { static id: string; - public template: WrappedTemplateFactory; + public template: TemplateFactory; - constructor(template: WrappedTemplateFactory) { + constructor(template: TemplateFactory) { this.template = template; } @@ -152,52 +147,68 @@ export class PositionalArgumentReference { } } +const DEFAULT_LAYOUT = P`template:components/-default`; + export default class CurlyComponentManager extends AbstractManager - implements WithDynamicTagName, - WithDynamicLayout { + implements WithStaticLayout, + WithDynamicTagName, + WithDynamicLayout { + + layoutFor(_state: DefinitionState, _component: ComponentStateBucket, _env: Environment): Unique<'Handle'> { + throw new Error('Method not implemented.'); + } - getLayout(state: DefinitionState) { + getLayout(state: DefinitionState, _resolver: RuntimeResolver): Invocation { console.log('static'); return { - handle: state.handle, - symbolTable: state.symbolTable + handle: state.handle!, + symbolTable: state.symbolTable! }; } - getDynamicLayout(component: ComponentStateBucket, resolver: RuntimeResolver): Invocation { - console.log('dynamic'); - const Template = get(component.component, 'layout'); - const owner = getOwner(component.component); + templateFor(component: Component): OwnedTemplate { + let Template = get(component, 'layout'); + let owner = getOwner(component); if (Template) { - return Template; + throw new Error('need to add injections to directly imported factory'); + // return env.getTemplate(Template, owner); } - const layoutName = component.component.layoutName!; - const handle = resolver.lookupComponentDefinition(layoutName, { - owner, - moduleName: '', - }); - - if (handle === null) { - throw new Error('Missing dynamic layout'); + let layoutName = get(component, 'layoutName'); + if (layoutName) { + let template = owner.lookup('template:' + layoutName); + if (template) { + return template; + } } + return owner.lookup(DEFAULT_LAYOUT); + } - return resolver.compileTemplate(handle, layoutName, (template: SerializedTemplate, options: CompileOptions) => { - console.log('recompiling'); - const builder = new WrappedBuilder( - assign({}, options, { asPartial: false, referrer: null }), - template, - CURLY_CAPABILITIES - ); - return { - handle: builder.compile(), - symbolTable: builder.symbolTable - }; - }); + compileDynamicLayout(component: Component, resolver: RuntimeResolver): Invocation { + const template = this.templateFor(component); + const compileOptions = Object.assign({}, + resolver.templateOptions, + { asPartial: false, referrer: template.referrer}); + // TODO fix this getting private + const parsed: ParsedLayout = (template as any).parsedLayout; + const layout = new WrappedBuilder( + compileOptions, + parsed, + CURLY_CAPABILITIES, + ); + // NEEDS TO BE CACHED + return { + handle: layout.compile(), + symbolTable: layout.symbolTable, + }; } - getTagName(state: ComponentStateBucket): Option { - let { component } = state; + getDynamicLayout(state: ComponentStateBucket, resolver: RuntimeResolver): Invocation { + console.log('dynamic'); + return this.compileDynamicLayout(state.component, resolver); + } + getTagName(state: ComponentStateBucket): Option { + const { component } = state; if (component.tagName === '') { return null; } diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index 80ff294afb5..0251949ed28 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -19,7 +19,7 @@ import { Destroyable } from '@glimmer/util/dist/types'; import { DEBUG } from 'ember-env-flags'; import { _instrumentStart } from 'ember-metal'; import { guidFor } from 'ember-utils'; -import { TemplateMeta } from 'ember-views'; +import { OwnedTemplateMeta } from 'ember-views'; import { DynamicScope } from '../renderer'; import RuntimeResolver from '../resolver'; import { @@ -62,7 +62,7 @@ export const CAPABILITIES: ComponentCapabilities = { }; class OutletComponentManager extends AbstractManager - implements WithStaticLayout { + implements WithStaticLayout { create(environment: Environment, definition: OutletComponentDefinitionState, diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index 3a356f0bd91..2e6013ebb9e 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -26,12 +26,8 @@ class RootComponentManager extends CurlyComponentManager { this.component = component; } - getLayout(state: DefinitionState, resolver: RuntimeResolver) { - const handle = resolver.lookupComponent(state.name, state.ComponentClass); - return { - handle, - symbolTable: state.symbolTable - }; + getLayout(_state: DefinitionState, resolver: RuntimeResolver) { + return this.compileDynamicLayout(this.component, resolver); } create(environment: Environment, diff --git a/packages/ember-glimmer/lib/helpers/outlet.ts b/packages/ember-glimmer/lib/helpers/outlet.ts index b8836e04d46..d865cc4cae6 100644 --- a/packages/ember-glimmer/lib/helpers/outlet.ts +++ b/packages/ember-glimmer/lib/helpers/outlet.ts @@ -3,6 +3,7 @@ import { Arguments, CurriedComponentDefinition, curry, + UNDEFINED_REFERENCE, VM, } from '@glimmer/runtime'; import { OutletComponentDefinition } from '../component-managers/outlet'; @@ -20,7 +21,7 @@ export default function outlet(vm: VM, args: Arguments) { return new OutletComponentReference(outletNameRef, scope.outletState); } -class OutletComponentReference implements Reference { +class OutletComponentReference implements VersionedPathReference { public tag: TagWrapper; private outletStateTag: TagWrapper; private definition: any | null; @@ -48,4 +49,8 @@ class OutletComponentReference implements Reference { - public builtInHelpers: { - [name: string]: Helper | undefined; +const BUILTINS_HELPERS = { + 'if': inlineIf, + action, + concat, + get, + hash, + log, + mut, + 'query-params': queryParams, + readonly, + unbound, + 'unless': inlineUnless, + '-class': classHelper, + '-each-in': eachIn, + '-input-type': inputTypeHelper, + '-normalize-class': normalizeClassHelper, + '-html-safe': htmlSafeHelper, + '-get-dynamic-var': getDynamicVar, + '-outlet': outlet, +}; + +const BUILTIN_MODIFIERS = { + action: new ActionModifierManager(), +}; + +export default class RuntimeResolver implements IRuntimeResolver { + public templateOptions = { + program: new Program(new LazyConstants(this)), + macros: new Macros(), + resolver: new CompileTimeLookup(this), + Builder: LazyOpcodeBuilder as OpcodeBuilderConstructor, }; - public builtInModifiers: { - [name: string]: ModifierManager; - }; + // creates compileOptions for DI + public static create() { + return new this().templateOptions; + } private handles: any[] = []; private objToHandle = new WeakMap(); - constructor(public owner: Owner) { - this.builtInHelpers = { - 'if': inlineIf, - action, - concat, - get, - hash, - log, - mut, - 'query-params': queryParams, - readonly, - unbound, - 'unless': inlineUnless, - '-class': classHelper, - '-each-in': eachIn, - '-input-type': inputTypeHelper, - '-normalize-class': normalizeClassHelper, - '-html-safe': htmlSafeHelper, - '-get-dynamic-var': getDynamicVar, - '-outlet': outlet, - }; - - this.builtInModifiers = { - action: new ActionModifierManager(), - }; + private builtInHelpers: { + [name: string]: Helper | undefined; + } = BUILTINS_HELPERS; + + private builtInModifiers: { + [name: string]: ModifierManager; + } = BUILTIN_MODIFIERS; + + constructor() { + populateMacros(this.templateOptions.macros); } /*** IRuntimeResolver ***/ @@ -97,15 +110,15 @@ export default class RuntimeResolver implements IRuntimeResolver { /** * Called while executing Append Op.PushDynamicComponentManager if string */ - lookupComponent(name: string, meta: TemplateMeta): Option { + lookupComponent(name: string, meta: OwnedTemplateMeta): Option { let handle = this.lookupComponentDefinition(name, meta); if (handle === null) return null; return this.resolve(handle); } - lookupPartial(name: string, meta: TemplateMeta): Option { + lookupPartial(name: string, meta: OwnedTemplateMeta): Option { let partial = this._lookupPartial(name, meta); - return this.getHandle(partial); + return this.handle(partial); } /** @@ -116,24 +129,17 @@ export default class RuntimeResolver implements IRuntimeResolver { } // End IRuntimeResolver - compileTemplate(_handle: number, layoutName: string, create: (block: SerializedTemplate, options: CompileOptions) => Invocation) { - let template = this.owner.lookup(`template:${layoutName}`); - - if (!template) { - template = this.owner.lookup(DEFAULT_LAYOUT); - } - - let { parsedLayout, options } = template as any; - return create(parsedLayout, options); + compileTemplate(template: OwnedTemplate, create: (template: OwnedTemplate, templateOptions: TemplateOptions) => Invocation): Invocation { + return create(template, this.templateOptions); } /** * Called by CompileTimeLookup compiling Unknown or Helper OpCode */ - lookupHelper(name: string, meta: TemplateMeta): Option { + lookupHelper(name: string, meta: OwnedTemplateMeta): Option { let handle = this._lookupHelper(name, meta); if (handle !== null) { - return this.getHandle(handle); + return this.handle(handle); } return null; } @@ -141,22 +147,32 @@ export default class RuntimeResolver implements IRuntimeResolver { /** * Called by CompileTimeLookup compiling the Component OpCode */ - lookupComponentDefinition(name: string, meta: TemplateMeta): Option { - return this.getHandle( - this._lookupComponentDefinition(name, meta) - ); + lookupComponentDefinition(name: string, meta: OwnedTemplateMeta): Option { + return this.handle(this._lookupComponentDefinition(name, meta)); } /** * Called by CompileTimeLookup compiling the */ - lookupModifier(name: string, _meta: TemplateMeta): Option { - return this.getHandle( - this._lookupModifier(name)); + lookupModifier(name: string, _meta: OwnedTemplateMeta): Option { + return this.handle(this._lookupModifier(name)); } // end CompileTimeLookup - private _lookupHelper(name: string, meta: TemplateMeta): Option { + // needed for latebound + private handle(obj: any | null | undefined) { + if (obj === undefined || obj === null) { + return null; + } + let handle: number | undefined = this.objToHandle.get(obj); + if (handle === undefined) { + handle = this.handles.push(obj) - 1; + this.objToHandle.set(obj, handle); + } + return handle; + } + + private _lookupHelper(name: string, meta: OwnedTemplateMeta): Option { if (name === 'component') { return (vm, args) => componentHelper(vm, args, meta); } @@ -183,7 +199,7 @@ export default class RuntimeResolver implements IRuntimeResolver { } } - private _lookupPartial(name: string, meta: TemplateMeta): PartialDefinition { + private _lookupPartial(name: string, meta: OwnedTemplateMeta): PartialDefinition { const template = lookupPartial(name, meta.owner); const partial = new PartialDefinition( name, lookupPartial(name, meta.owner)); @@ -203,7 +219,7 @@ export default class RuntimeResolver implements IRuntimeResolver { } } - private _lookupComponentDefinition(name: string, meta: TemplateMeta): Option { + private _lookupComponentDefinition(name: string, meta: OwnedTemplateMeta): Option { let { layout, component } = lookupComponent(meta.owner, name, makeOptions(meta.moduleName)); let customManager; @@ -215,20 +231,8 @@ export default class RuntimeResolver implements IRuntimeResolver { } } - let layoutHandle = this.getHandle(layout) as Option; + let layoutHandle = this.handle(layout) as Option; return new CurlyComponentDefinition(name, customManager, component, layoutHandle, layout); } - - private getHandle(obj: any | null | undefined) { - if (obj === undefined || obj === null) { - return null; - } - let handle: number | undefined = this.objToHandle.get(obj); - if (handle === undefined) { - handle = this.handles.push(obj) - 1; - this.objToHandle.set(obj, handle); - } - return handle; - } } diff --git a/packages/ember-glimmer/lib/setup-registry.ts b/packages/ember-glimmer/lib/setup-registry.ts index 664747764b3..69b98efc16f 100644 --- a/packages/ember-glimmer/lib/setup-registry.ts +++ b/packages/ember-glimmer/lib/setup-registry.ts @@ -1,6 +1,5 @@ import { privatize as P } from 'container'; import { environment } from 'ember-environment'; -import CompileOptions from './compile-options'; import Component from './component'; import Checkbox from './components/checkbox'; import LinkToComponent from './components/link-to'; @@ -12,12 +11,13 @@ import { NodeDOMTreeConstruction, } from './dom'; import Environment from './environment'; +import loc from './helpers/loc'; import { InertRenderer, InteractiveRenderer } from './renderer'; +import TemplateOptions from './template-options'; import ComponentTemplate from './templates/component'; import OutletTemplate from './templates/outlet'; import RootTemplate from './templates/root'; import OutletView from './views/outlet'; -import loc from './helpers/loc'; interface Registry { injection(name: string, name2: string, name3: string): void; @@ -65,10 +65,9 @@ export function setupEngineRegistry(registry: Registry) { registry.register('service:-glimmer-environment', Environment); - registry.register('service:-compile-options', CompileOptions); + registry.register(P`template-options:main`, TemplateOptions); - registry.injection('template', 'env', 'service:-glimmer-environment'); - registry.injection('template', 'compileOptions', 'service:-compile-options'); + registry.injection('template', 'options', P`template-options:main`); registry.optionsForType('helper', { instantiate: false }); diff --git a/packages/ember-glimmer/lib/syntax.ts b/packages/ember-glimmer/lib/syntax.ts index 4936ed6eb28..50fe1bbb023 100644 --- a/packages/ember-glimmer/lib/syntax.ts +++ b/packages/ember-glimmer/lib/syntax.ts @@ -1,5 +1,7 @@ -import { Macros } from '@glimmer/opcode-compiler'; -import { assert } from 'ember-debug'; +import { CompilableBlock, Macros, OpcodeBuilder } from '@glimmer/opcode-compiler'; +import { Option } from '@glimmer/util'; +import { Core } from '@glimmer/wire-format'; +import { OwnedTemplateMeta } from 'ember-views'; import { textAreaMacro } from './syntax/-text-area'; import { inputMacro } from './syntax/input'; import { mountMacro } from './syntax/mount'; @@ -8,50 +10,38 @@ import { renderMacro } from './syntax/render'; import { hashToArgs } from './syntax/utils'; import { wrapComponentClassAttribute } from './utils/bindings'; -function refineInlineSyntax(name: string, params: any[], hash: any, builder: any) { - assert(`You attempted to overwrite the built-in helper "${name}" which is not allowed. Please rename the helper.`, !(builder.resolver.resolver.builtInHelpers[name] && builder.resolver.resolver.owner.hasRegistration(`helper:${name}`))); - - let definition; - if (name.indexOf('-') > -1) { - definition = builder.resolver.lookupComponentDefinition(name, { - owner: builder.resolver.resolver.owner, - moduleName: '' - }); +function refineInlineSyntax(name: string, params: Option, hash: Option, builder: OpcodeBuilder): boolean { + // assert(`You attempted to overwrite the built-in helper "${name}" which is not allowed. Please rename the helper.`, !(builder.resolver.resolver.builtInHelpers[name] && builder.resolver.resolver.owner.hasRegistration(`helper:${name}`))); + if (name.indexOf('-') === -1) { + return false; } - if (definition) { - wrapComponentClassAttribute(hash); - builder.component.static(definition, [params, hashToArgs(hash), null, null]); + let handle = builder.resolver.lookupComponentDefinition(name, builder.referrer); + + if (handle !== null) { + builder.component.static(handle, [params === null ? [] : params, hashToArgs(hash), null, null]); return true; } return false; } -function refineBlockSyntax(name: string, params: any[], hash: any, _default: any, inverse: any, builder: any) { +function refineBlockSyntax(name: string, params: Core.Params, hash: Core.Hash, template: Option, inverse: Option, builder: OpcodeBuilder) { if (name.indexOf('-') === -1) { return false; } - let meta = { - owner: builder.resolver.resolver.owner, - moduleName: '' - }; - - let definition; - if (name.indexOf('-') > -1) { - definition = builder.resolver.lookupComponentDefinition(name, meta); - } + let handle = builder.resolver.lookupComponentDefinition(name, builder.referrer); - if (definition) { + if (handle !== null) { wrapComponentClassAttribute(hash); - builder.component.static(definition, [params, hashToArgs(hash), _default, inverse]); + builder.component.static(handle, [params, hashToArgs(hash), template, inverse]); return true; } - assert(`A component or helper named "${name}" could not be found`, builder.env.hasHelper(name, meta)); + // assert(`A component or helper named "${name}" could not be found`, builder.resolver.hasHelper(name, builder.referrer)); - assert(`Helpers may not be used in the block form, for example {{#${name}}}{{/${name}}}. Please use a component, or alternatively use the helper in combination with a built-in Ember helper, for example {{#if (${name})}}{{/if}}.`, !builder.env.hasHelper(name, meta)); + // assert(`Helpers may not be used in the block form, for example {{#${name}}}{{/${name}}}. Please use a component, or alternatively use the helper in combination with a built-in Ember helper, for example {{#if (${name})}}{{/if}}.`, !builder.env.hasHelper(name, meta)); return false; } diff --git a/packages/ember-glimmer/lib/syntax/outlet.ts b/packages/ember-glimmer/lib/syntax/outlet.ts index 4f48ce6fd96..2b546ac6f26 100644 --- a/packages/ember-glimmer/lib/syntax/outlet.ts +++ b/packages/ember-glimmer/lib/syntax/outlet.ts @@ -1,7 +1,7 @@ import { Option } from '@glimmer/interfaces'; import { OpcodeBuilder } from '@glimmer/opcode-compiler'; import * as WireFormat from '@glimmer/wire-format'; -import { TemplateMeta } from 'ember-views'; +import { OwnedTemplateMeta } from 'ember-views'; /** The `{{outlet}}` helper lets you specify where a child route will render in @@ -53,7 +53,7 @@ import { TemplateMeta } from 'ember-views'; @for Ember.Templates.helpers @public */ -export const outletMacro = (_name: string, params: Option, hash: Option, builder: OpcodeBuilder) => { +export const outletMacro = (_name: string, params: Option, hash: Option, builder: OpcodeBuilder) => { let expr: WireFormat.Expressions.Helper = [WireFormat.Ops.Helper, '-outlet', params || [], hash]; builder.dynamicComponent(expr, [], null, false, null, null); return true; diff --git a/packages/ember-glimmer/lib/syntax/utils.ts b/packages/ember-glimmer/lib/syntax/utils.ts index 69d357a106e..4cdf934920d 100644 --- a/packages/ember-glimmer/lib/syntax/utils.ts +++ b/packages/ember-glimmer/lib/syntax/utils.ts @@ -1,5 +1,8 @@ -export function hashToArgs(hash: any[]) { - if (hash === null) { return null; } - let names = hash[0].map((key: string) => `@${key}`); +import { Option } from '@glimmer/util'; +import { Core } from '@glimmer/wire-format'; + +export function hashToArgs(hash: Option): Option { + if (hash === null) return null; + let names = hash[0].map(key => `@${key}`); return [names, hash[1]]; } diff --git a/packages/ember-glimmer/lib/template-options.ts b/packages/ember-glimmer/lib/template-options.ts new file mode 100644 index 00000000000..15535f1c4d3 --- /dev/null +++ b/packages/ember-glimmer/lib/template-options.ts @@ -0,0 +1,10 @@ +import { TemplateOptions } from '@glimmer/opcode-compiler'; +import { OwnedTemplateMeta } from 'ember-views'; +import RuntimeResolver from './resolver'; + +// factory for DI +export default { + create(): TemplateOptions { + return new RuntimeResolver().templateOptions; + } +}; diff --git a/packages/ember-glimmer/lib/template.ts b/packages/ember-glimmer/lib/template.ts index 18e8f9fac73..de2d85c6b06 100644 --- a/packages/ember-glimmer/lib/template.ts +++ b/packages/ember-glimmer/lib/template.ts @@ -1,42 +1,43 @@ +import { TemplateOptions } from '@glimmer/opcode-compiler'; import { Template, templateFactory, TemplateFactory, } from '@glimmer/runtime'; -import { OWNER, Owner } from 'ember-utils'; -import { TemplateMeta } from 'ember-views'; +import { SerializedTemplateWithLazyBlock } from '@glimmer/wire-format/dist/types'; +import { getOwner } from 'ember-utils'; +import { OwnedTemplateMeta, StaticTemplateMeta } from 'ember-views'; -export type OwnedTemplate = Template; +export type StaticTemplate = SerializedTemplateWithLazyBlock; +export type OwnedTemplate = Template; -export class WrappedTemplateFactory { +export default function template(json: StaticTemplate): Factory { + return new FactoryWrapper(templateFactory(json)); +} + +export interface Injections { + options: TemplateOptions; +} + +export interface Factory { id: string; - meta: { - moduleName: string; - managerId?: string; - }; + meta: StaticTemplateMeta; + create(injections: Injections): OwnedTemplate; +} + +class FactoryWrapper implements Factory { + public id: string; + public meta: StaticTemplateMeta; - constructor(public factory: TemplateFactory<{ - moduleName: string; - managerId?: string; - }>) { + constructor(public factory: TemplateFactory) { this.id = factory.id; this.meta = factory.meta; } - create(props: any): OwnedTemplate { - const owner: Owner = props[OWNER]; - // I'm pretty sure there is only supposed to be one of these - // injected into all templates. - return this.factory.create(props.compileOptions, { owner }); + create(injections: { + options: TemplateOptions; + }): OwnedTemplate { + const owner = getOwner(injections); + return this.factory.create(injections.options, { owner }); } } - -export default function template(json: any) { - const factory = templateFactory<{ - moduleName: string; - managerId?: string; - }, { - owner: Owner; - }>(json); - return new WrappedTemplateFactory(factory); -} diff --git a/packages/ember-glimmer/lib/template_registry.ts b/packages/ember-glimmer/lib/template_registry.ts index 2a8896dc3fd..68901bc9787 100644 --- a/packages/ember-glimmer/lib/template_registry.ts +++ b/packages/ember-glimmer/lib/template_registry.ts @@ -1,9 +1,9 @@ -import { WrappedTemplateFactory } from './template'; +import { Factory } from './template'; // STATE within a module is frowned upon, this exists // to support Ember.TEMPLATES but shield ember internals from this legacy // global API. interface TemplatesRegistry { - [name: string]: WrappedTemplateFactory; + [name: string]: Factory; } let TEMPLATES: TemplatesRegistry = {}; @@ -15,7 +15,7 @@ export function getTemplates() { return TEMPLATES; } -export function getTemplate(name: string): WrappedTemplateFactory | void { +export function getTemplate(name: string): Factory | void { if (TEMPLATES.hasOwnProperty(name)) { return TEMPLATES[name]; } @@ -25,6 +25,6 @@ export function hasTemplate(name: string): boolean { return TEMPLATES.hasOwnProperty(name); } -export function setTemplate(name: string, template: WrappedTemplateFactory): WrappedTemplateFactory { +export function setTemplate(name: string, template: Factory): Factory { return TEMPLATES[name] = template; } diff --git a/packages/ember-glimmer/lib/templates/component.d.ts b/packages/ember-glimmer/lib/templates/component.d.ts index 01e88b1186d..786bb5e91a8 100644 --- a/packages/ember-glimmer/lib/templates/component.d.ts +++ b/packages/ember-glimmer/lib/templates/component.d.ts @@ -1,3 +1,3 @@ -import { WrappedTemplateFactory } from '../template'; -declare const TEMPLATE: WrappedTemplateFactory; +import { Factory } from '../template'; +declare const TEMPLATE: Factory; export default TEMPLATE; diff --git a/packages/ember-glimmer/lib/templates/empty.d.ts b/packages/ember-glimmer/lib/templates/empty.d.ts index 01e88b1186d..786bb5e91a8 100644 --- a/packages/ember-glimmer/lib/templates/empty.d.ts +++ b/packages/ember-glimmer/lib/templates/empty.d.ts @@ -1,3 +1,3 @@ -import { WrappedTemplateFactory } from '../template'; -declare const TEMPLATE: WrappedTemplateFactory; +import { Factory } from '../template'; +declare const TEMPLATE: Factory; export default TEMPLATE; diff --git a/packages/ember-glimmer/lib/templates/link-to.d.ts b/packages/ember-glimmer/lib/templates/link-to.d.ts index 01e88b1186d..786bb5e91a8 100644 --- a/packages/ember-glimmer/lib/templates/link-to.d.ts +++ b/packages/ember-glimmer/lib/templates/link-to.d.ts @@ -1,3 +1,3 @@ -import { WrappedTemplateFactory } from '../template'; -declare const TEMPLATE: WrappedTemplateFactory; +import { Factory } from '../template'; +declare const TEMPLATE: Factory; export default TEMPLATE; diff --git a/packages/ember-glimmer/lib/templates/outlet.d.ts b/packages/ember-glimmer/lib/templates/outlet.d.ts index 01e88b1186d..786bb5e91a8 100644 --- a/packages/ember-glimmer/lib/templates/outlet.d.ts +++ b/packages/ember-glimmer/lib/templates/outlet.d.ts @@ -1,3 +1,3 @@ -import { WrappedTemplateFactory } from '../template'; -declare const TEMPLATE: WrappedTemplateFactory; +import { Factory } from '../template'; +declare const TEMPLATE: Factory; export default TEMPLATE; diff --git a/packages/ember-glimmer/lib/templates/root.d.ts b/packages/ember-glimmer/lib/templates/root.d.ts index 01e88b1186d..786bb5e91a8 100644 --- a/packages/ember-glimmer/lib/templates/root.d.ts +++ b/packages/ember-glimmer/lib/templates/root.d.ts @@ -1,3 +1,3 @@ -import { WrappedTemplateFactory } from '../template'; -declare const TEMPLATE: WrappedTemplateFactory; +import { Factory } from '../template'; +declare const TEMPLATE: Factory; export default TEMPLATE; diff --git a/packages/ember-glimmer/lib/utils/bindings.ts b/packages/ember-glimmer/lib/utils/bindings.ts index 1ad7524942c..473f4df1e69 100644 --- a/packages/ember-glimmer/lib/utils/bindings.ts +++ b/packages/ember-glimmer/lib/utils/bindings.ts @@ -13,9 +13,7 @@ import { import { ElementOperations } from '@glimmer/runtime'; -import { - Ops, -} from '@glimmer/wire-format'; +import { Core, Ops } from '@glimmer/wire-format'; import { assert } from 'ember-debug'; import { get } from 'ember-metal'; import { String as StringUtils } from 'ember-runtime'; @@ -43,26 +41,28 @@ function referenceForParts(component: Component, parts: string[]): Reference { } // TODO we should probably do this transform at build time -export function wrapComponentClassAttribute(hash: any[]) { - if (!hash) { - return hash; +export function wrapComponentClassAttribute(hash: Core.Hash) { + if (hash === null) { + return; } let [ keys, values ] = hash; - let index = keys.indexOf('class'); + let index = keys === null ? -1 : keys.indexOf('class'); if (index !== -1) { - let [ type ] = values[index]; + let value = values[index]; + if (!Array.isArray(value)) { + return; + } + + let [ type ] = value; if (type === Ops.Get || type === Ops.MaybeLocal) { - let getExp = values[index]; - let path = getExp[getExp.length - 1]; + let path = value[value.length - 1]; let propName = path[path.length - 1]; - hash[1][index] = [Ops.Helper, ['-class'], [getExp, propName]]; + values[index] = [Ops.Helper, '-class', [value, propName], null]; } } - - return hash; } export const AttributeBinding = { diff --git a/packages/ember-glimmer/lib/utils/references.ts b/packages/ember-glimmer/lib/utils/references.ts index bd14eebf1a8..562ecbda052 100644 --- a/packages/ember-glimmer/lib/utils/references.ts +++ b/packages/ember-glimmer/lib/utils/references.ts @@ -27,7 +27,6 @@ import { watchKey, } from 'ember-metal'; import { - HAS_NATIVE_WEAKMAP, symbol, } from 'ember-utils'; import { @@ -53,7 +52,7 @@ if (DEBUG) { // performance penalty on Chrome (tested through 59). // // See: https://bugs.chromium.org/p/v8/issues/detail?id=6450 - if (!Object.isFrozen(obj) && HAS_NATIVE_WEAKMAP) { + if (!Object.isFrozen(obj)) { Object.freeze(obj); } }; diff --git a/packages/ember-views/lib/index.d.ts b/packages/ember-views/lib/index.d.ts index 210c5f17d12..6cf1f307d41 100644 --- a/packages/ember-views/lib/index.d.ts +++ b/packages/ember-views/lib/index.d.ts @@ -1,9 +1,14 @@ -import { Opaque } from '@glimmer/util'; import { Simple } from '@glimmer/interfaces'; +import { Opaque } from '@glimmer/util'; import { Template } from '@glimmer/runtime'; import { Owner, Factory } from 'ember-utils'; -export interface TemplateMeta { +export interface StaticTemplateMeta { + moduleName: string; + managerId?: string; +} + +export interface OwnedTemplateMeta extends StaticTemplateMeta { owner: Owner; moduleName: string; managerId?: string; @@ -27,7 +32,7 @@ export function constructStyleDeprecationMessage(affectedStyle: any): string; export function hasPartial(name: string, owner: any): boolean; export function lookupComponent(owner: Owner, name: string, options?: { source?: string }): { - layout: Template; + layout: Template; component: Factory; }; From cd19c1420c91a8c5090805fa6ae87fe350f7f65c Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Wed, 13 Dec 2017 22:20:44 -0800 Subject: [PATCH 034/135] fix wrapper in top level outlet --- .../lib/component-managers/outlet.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index 0251949ed28..0c9f3f1906e 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -3,6 +3,7 @@ import { Option, Unique } from '@glimmer/interfaces'; +import { WrappedBuilder, ParsedLayout } from '@glimmer/opcode-compiler'; import { Tag, VersionedPathReference } from '@glimmer/reference'; @@ -128,6 +129,25 @@ class TopLevelOutletComponentManager extends OutletComponentManager return 'div'; } + getLayout(state: OutletComponentDefinitionState, resolver: RuntimeResolver): Invocation { + // The router has already resolved the template + const template = state.template; + const compileOptions = Object.assign({}, + resolver.templateOptions, + { asPartial: false, referrer: template.referrer}); + // TODO fix this getting private + const parsed: ParsedLayout = (template as any).parsedLayout; + const layout = new WrappedBuilder( + compileOptions, + parsed, + TOP_CAPABILITIES, + ); + return { + handle: layout.compile(), + symbolTable: layout.symbolTable + }; + } + create(environment: Environment, definition: TopOutletComponentDefinitionState, _args: Arguments, dynamicScope: DynamicScope) { if (DEBUG) { this._pushToDebugStack(`template:${definition.template.referrer.moduleName}`, environment); From bb6f51230628321fe25f1c713aae58aad65b210d Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 14 Dec 2017 00:00:14 -0800 Subject: [PATCH 035/135] drop hack --- packages/ember-glimmer/lib/component-managers/curly.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 3cf08438c4f..8418d91c922 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -312,7 +312,6 @@ export default class CurlyComponentManager extends AbstractManager Date: Thu, 14 Dec 2017 00:17:27 -0800 Subject: [PATCH 036/135] fix tag in action modifier --- packages/ember-glimmer/lib/modifiers/action.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/ember-glimmer/lib/modifiers/action.ts b/packages/ember-glimmer/lib/modifiers/action.ts index 490e98e8ef2..f68e9a98d5d 100644 --- a/packages/ember-glimmer/lib/modifiers/action.ts +++ b/packages/ember-glimmer/lib/modifiers/action.ts @@ -2,7 +2,7 @@ import { Simple } from '@glimmer/interfaces'; import { - TagWrapper + TagWrapper, RevisionTag } from '@glimmer/reference'; import { Arguments, @@ -11,7 +11,7 @@ import { DynamicScope, ModifierManager, } from '@glimmer/runtime'; -import { +import { Destroyable } from '@glimmer/util'; import { assert } from 'ember-debug'; @@ -78,8 +78,9 @@ export class ActionState { public implicitTarget: any; public dom: any; public eventName: any; + public tag: TagWrapper; - constructor(element: Simple.Element, actionId: number, actionName: any, actionArgs: any[], namedArgs: CapturedNamedArguments, positionalArgs: CapturedPositionalArguments, implicitTarget: any, dom: any) { + constructor(element: Simple.Element, actionId: number, actionName: any, actionArgs: any[], namedArgs: CapturedNamedArguments, positionalArgs: CapturedPositionalArguments, implicitTarget: any, dom: any, tag: TagWrapper) { this.element = element; this.actionId = actionId; this.actionName = actionName; @@ -89,6 +90,7 @@ export class ActionState { this.implicitTarget = implicitTarget; this.dom = dom; this.eventName = this.getEventName(); + this.tag = tag; } getEventName() { @@ -182,7 +184,7 @@ export class ActionState { // implements ModifierManager export default class ActionModifierManager implements ModifierManager { create(element: Simple.Element, args: Arguments, _dynamicScope: DynamicScope, dom: any) { - let { named, positional } = args.capture(); + let { named, positional, tag } = args.capture(); let implicitTarget; let actionName; let actionNameRef: any; @@ -223,6 +225,7 @@ export default class ActionModifierManager implements ModifierManager Date: Thu, 14 Dec 2017 12:26:44 -0800 Subject: [PATCH 037/135] curly components always have a view --- packages/ember-glimmer/lib/resolver.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 5fa50b8703b..be192640819 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -14,6 +14,7 @@ import { ModifierManager, PartialDefinition } from '@glimmer/runtime'; +import { privatize as P } from 'container'; import { LookupOptions } from 'ember-utils'; import { lookupComponent, @@ -233,6 +234,6 @@ export default class RuntimeResolver implements IRuntimeResolver; - return new CurlyComponentDefinition(name, customManager, component, layoutHandle, layout); + return new CurlyComponentDefinition(name, customManager, component || meta.owner.factoryFor(P`component:-default`), layoutHandle, layout); } } From 47d7be520c6a90ab804f26a37425df518e0a2a57 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Fri, 15 Dec 2017 21:16:37 -0800 Subject: [PATCH 038/135] static layout only seems to be able to be curried make dynamic even when we know the layout statically --- .../lib/component-managers/curly.ts | 61 ++++++-------- .../component-managers/definition-state.ts | 9 -- .../lib/component-managers/mount.ts | 13 ++- .../lib/component-managers/root.ts | 6 +- packages/ember-glimmer/lib/renderer.ts | 82 ++++++++++--------- packages/ember-glimmer/lib/resolver.ts | 2 +- packages/ember-glimmer/lib/template.ts | 4 +- 7 files changed, 84 insertions(+), 93 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 579e0e0f885..b54a5a49afe 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -6,7 +6,7 @@ import { Unique, VMHandle } from '@glimmer/interfaces'; -import { ParsedLayout, WrappedBuilder } from '@glimmer/opcode-compiler'; +import { ParsedLayout, TemplateOptions, WrappedBuilder } from '@glimmer/opcode-compiler'; import { combineTagged, Tag, @@ -70,6 +70,10 @@ function aliasIdToElementId(args: Arguments, props: any) { } } +function isTemplateFactory(template: OwnedTemplate | TemplateFactory): template is TemplateFactory { + return typeof (template as TemplateFactory).create === 'function'; +} + // We must traverse the attributeBindings in reverse keeping track of // what has already been applied. This is essentially refining the concatenated // properties applying right to left. @@ -111,24 +115,6 @@ function applyAttributeBindings(element: Simple.Element, attributeBindings: Arra // return vm.getSelf().get('ariaRole'); // } -class CurlyComponentLayoutCompiler { - static id: string; - public template: TemplateFactory; - - constructor(template: TemplateFactory) { - this.template = template; - } - - compile(builder: any) { - builder.wrapLayout(this.template); - // builder.tag.dynamic(tagName); - // builder.attrs.dynamic('role', ariaRole); - builder.attrs.static('class', 'ember-view'); - } -} - -CurlyComponentLayoutCompiler.id = 'curly'; - export class PositionalArgumentReference { public tag: any; private _references: any; @@ -161,18 +147,24 @@ export default class CurlyComponentManager extends AbstractManager): OwnedTemplate { + let Template = get(component, 'layout') as TemplateFactory | OwnedTemplate | undefined; + if (Template !== undefined) { + // This needs to be cached by template.id + if (isTemplateFactory(Template)) { + return Template.create({ options }); + } else { + // we were provided an instance already + return Template; + } } + let owner = getOwner(component); let layoutName = get(component, 'layoutName'); if (layoutName) { let template = owner.lookup('template:' + layoutName); @@ -184,7 +176,7 @@ export default class CurlyComponentManager extends AbstractManager { @@ -311,6 +299,11 @@ export default class CurlyComponentManager extends AbstractManager { getTag({ component }: EngineBucket): Tag { // TODO: is this the right tag? - return component[DIRTY_TAG]; + return component![DIRTY_TAG]; } getDestructor({ engine }: EngineBucket): Option { @@ -124,7 +124,14 @@ export class MountDefinition implements ComponentDefinition { name, ComponentClass, handle, - capabilities: CAPABILITIES + capabilities: { + dynamicLayout: true, + dynamicTag: true, + prepareArgs: true, + createArgs: true, + attributeHook: true, + elementHook: true + } }; } } diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index 2e6013ebb9e..ea756543e36 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -69,9 +69,9 @@ class RootComponentManager extends CurlyComponentManager { // it is supposed to have a dummy element export const ROOT_CAPABILITIES: ComponentCapabilities = { dynamicLayout: true, - dynamicTag: false, - prepareArgs: false, - createArgs: false, + dynamicTag: true, + prepareArgs: true, + createArgs: true, attributeHook: true, elementHook: true }; diff --git a/packages/ember-glimmer/lib/renderer.ts b/packages/ember-glimmer/lib/renderer.ts index 784b1fcb491..462f15b96d9 100644 --- a/packages/ember-glimmer/lib/renderer.ts +++ b/packages/ember-glimmer/lib/renderer.ts @@ -148,11 +148,12 @@ class RootState { if (needsTransaction) { env.begin(); } - - result.destroy(); - - if (needsTransaction) { - env.commit(); + try { + result.destroy(); + } finally { + if (needsTransaction) { + env.commit(); + } } } } @@ -347,44 +348,45 @@ export abstract class Renderer { do { env.begin(); - - // ensure that for the first iteration of the loop - // each root is processed - initialRootsLength = roots.length; - globalShouldReflush = false; - - for (let i = 0; i < roots.length; i++) { - let root = roots[i]; - - if (root.destroyed) { - // add to the list of roots to be removed - // they will be removed from `this._roots` later - removedRoots.push(root); - - // skip over roots that have been marked as destroyed - continue; + try { + // ensure that for the first iteration of the loop + // each root is processed + initialRootsLength = roots.length; + globalShouldReflush = false; + + for (let i = 0; i < roots.length; i++) { + let root = roots[i]; + + if (root.destroyed) { + // add to the list of roots to be removed + // they will be removed from `this._roots` later + removedRoots.push(root); + + // skip over roots that have been marked as destroyed + continue; + } + + let { shouldReflush } = root; + + // when processing non-initial reflush loops, + // do not process more roots than needed + if (i >= initialRootsLength && !shouldReflush) { + continue; + } + + root.options.alwaysRevalidate = shouldReflush; + // track shouldReflush based on this roots render result + shouldReflush = root.shouldReflush = runInTransaction(root, 'render'); + + // globalShouldReflush should be `true` if *any* of + // the roots need to reflush + globalShouldReflush = globalShouldReflush || shouldReflush; } - let { shouldReflush } = root; - - // when processing non-initial reflush loops, - // do not process more roots than needed - if (i >= initialRootsLength && !shouldReflush) { - continue; - } - - root.options.alwaysRevalidate = shouldReflush; - // track shouldReflush based on this roots render result - shouldReflush = root.shouldReflush = runInTransaction(root, 'render'); - - // globalShouldReflush should be `true` if *any* of - // the roots need to reflush - globalShouldReflush = globalShouldReflush || shouldReflush; + this._lastRevision = CURRENT_TAG.value(); + } finally { + env.commit(); } - - this._lastRevision = CURRENT_TAG.value(); - - env.commit(); } while (globalShouldReflush || roots.length > initialRootsLength); // remove any roots that were destroyed during this transaction diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index be192640819..8038154bda7 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -79,7 +79,7 @@ const BUILTIN_MODIFIERS = { }; export default class RuntimeResolver implements IRuntimeResolver { - public templateOptions = { + public templateOptions: TemplateOptions = { program: new Program(new LazyConstants(this)), macros: new Macros(), resolver: new CompileTimeLookup(this), diff --git a/packages/ember-glimmer/lib/template.ts b/packages/ember-glimmer/lib/template.ts index de2d85c6b06..c255a8b624a 100644 --- a/packages/ember-glimmer/lib/template.ts +++ b/packages/ember-glimmer/lib/template.ts @@ -34,9 +34,7 @@ class FactoryWrapper implements Factory { this.meta = factory.meta; } - create(injections: { - options: TemplateOptions; - }): OwnedTemplate { + create(injections: Injections): OwnedTemplate { const owner = getOwner(injections); return this.factory.create(injections.options, { owner }); } From d6dc6aa1428d68f68a996d116cf9cca700c09672 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Mon, 18 Dec 2017 16:39:46 -0700 Subject: [PATCH 039/135] Fix computed layout test and falsy class test --- .../ember-glimmer/lib/component-managers/curly.ts | 15 ++++++++++----- packages/ember-glimmer/lib/template.ts | 1 + packages/ember-utils/lib/index.d.ts | 1 + 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 3613d93fc90..3e94fda3435 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -38,6 +38,7 @@ import { import { getOwner, guidFor, + setOwner } from 'ember-utils'; import { OwnedTemplateMeta, setViewElement } from 'ember-views'; import { @@ -50,7 +51,11 @@ import { import Environment from '../environment'; import { DynamicScope } from '../renderer'; import RuntimeResolver from '../resolver'; -import { Factory as TemplateFactory, OwnedTemplate } from '../template'; +import { + Factory as TemplateFactory, + Injections, + OwnedTemplate +} from '../template'; import { AttributeBinding, ClassNameBinding, @@ -145,7 +150,6 @@ export default class CurlyComponentManager extends AbstractManager; + [key: string]: any; } export interface Factory { diff --git a/packages/ember-utils/lib/index.d.ts b/packages/ember-utils/lib/index.d.ts index 4e39c4f23ff..a07781dc2a9 100644 --- a/packages/ember-utils/lib/index.d.ts +++ b/packages/ember-utils/lib/index.d.ts @@ -25,6 +25,7 @@ export interface Owner { export const NAME_KEY: string; export function getOwner(obj: {}): Owner; +export function setOwner(obj: {}, owner: Owner): void; export function symbol(debugName: string): string; export function assign(original: any, ...args: any[]): any; export const OWNER: string; From bedbc2132010cab64f7063c3d1692f5e1a950044 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Mon, 18 Dec 2017 21:10:12 -0700 Subject: [PATCH 040/135] A few more curly tests passing --- .../ember-glimmer/lib/component-managers/curly.ts | 11 ++++++++--- packages/ember-glimmer/lib/resolver.ts | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 3e94fda3435..0e911c86f8a 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -224,7 +224,7 @@ export default class CurlyComponentManager extends AbstractManager; - return new CurlyComponentDefinition(name, customManager, component || meta.owner.factoryFor(P`component:-default`), layoutHandle, layout); + return (layout || component) ? new CurlyComponentDefinition(name, customManager, component || meta.owner.factoryFor(P`component:-default`), layoutHandle, layout) : null; } } From 0703c15ff167bf494aa76130926d09e3c0d71d55 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 19 Dec 2017 16:07:44 -0800 Subject: [PATCH 041/135] Fixes to tags --- packages/ember-glimmer/lib/component.ts | 2 +- packages/ember-glimmer/lib/helper.ts | 2 +- packages/ember-metal/lib/index.d.ts | 6 ++++-- packages/ember-metal/lib/tags.js | 2 +- packages/ember-runtime/lib/mixins/-proxy.js | 4 ++-- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/ember-glimmer/lib/component.ts b/packages/ember-glimmer/lib/component.ts index 2c85d459375..ea8abbd267d 100644 --- a/packages/ember-glimmer/lib/component.ts +++ b/packages/ember-glimmer/lib/component.ts @@ -565,7 +565,7 @@ const Component = CoreView.extend( init() { this._super(...arguments); this[IS_DISPATCHING_ATTRS] = false; - this[DIRTY_TAG] = new DirtyableTag(); + this[DIRTY_TAG] = DirtyableTag.create(); this[ROOT_REF] = new RootReference(this); this[BOUNDS] = null; diff --git a/packages/ember-glimmer/lib/helper.ts b/packages/ember-glimmer/lib/helper.ts index 731ec973adc..c7aff8bfd78 100644 --- a/packages/ember-glimmer/lib/helper.ts +++ b/packages/ember-glimmer/lib/helper.ts @@ -56,7 +56,7 @@ let Helper = FrameworkObject.extend({ init() { this._super(...arguments); - this[RECOMPUTE_TAG] = new DirtyableTag(); + this[RECOMPUTE_TAG] = DirtyableTag.create(); }, /** diff --git a/packages/ember-metal/lib/index.d.ts b/packages/ember-metal/lib/index.d.ts index bdf32c30ddc..0e9950027fb 100644 --- a/packages/ember-metal/lib/index.d.ts +++ b/packages/ember-metal/lib/index.d.ts @@ -1,3 +1,5 @@ +import { Tag } from '@glimmer/reference'; + interface IBackburner { join(...args: any[]): void; on(...args: any[]): void; @@ -35,9 +37,9 @@ export function didRender(object: any, key: string, reference: any): boolean; export function isNone(obj: any): boolean; -export function tagForProperty(object: any, propertyKey: string, _meta?: any): any; +export function tagForProperty(object: any, propertyKey: string, _meta?: any): Tag; -export function tagFor(object: any, _meta?: any): any; +export function tagFor(object: any, _meta?: any): Tag; export function watchKey(obj: any, keyName: string, meta?: any): void; diff --git a/packages/ember-metal/lib/tags.js b/packages/ember-metal/lib/tags.js index 83f49aedb4b..387200cbf5e 100644 --- a/packages/ember-metal/lib/tags.js +++ b/packages/ember-metal/lib/tags.js @@ -9,7 +9,7 @@ export function setHasViews(fn) { } function makeTag() { - return new DirtyableTag(); + return DirtyableTag.create(); } export function tagForProperty(object, propertyKey, _meta) { diff --git a/packages/ember-runtime/lib/mixins/-proxy.js b/packages/ember-runtime/lib/mixins/-proxy.js index ecd45100fbc..fcfbeecadaf 100644 --- a/packages/ember-runtime/lib/mixins/-proxy.js +++ b/packages/ember-runtime/lib/mixins/-proxy.js @@ -41,8 +41,8 @@ class ProxyTag extends CachedTag { let content = get(proxy, 'content'); this.proxy = proxy; - this.proxyWrapperTag = new DirtyableTag(); - this.proxyContentTag = new UpdatableTag(tagFor(content)); + this.proxyWrapperTag = DirtyableTag.create(); + this.proxyContentTag = UpdatableTag.create(tagFor(content)); } compute() { From 3aace9b6fee8da49c1e7672647fd42ef0309c0e8 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 20 Dec 2017 05:37:36 -0700 Subject: [PATCH 042/135] Use inner tag for dirtying --- packages/ember-glimmer/lib/component.ts | 2 +- packages/ember-glimmer/lib/helper.ts | 4 ++-- packages/ember-metal/lib/tags.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ember-glimmer/lib/component.ts b/packages/ember-glimmer/lib/component.ts index ea8abbd267d..a3b27d2a7d7 100644 --- a/packages/ember-glimmer/lib/component.ts +++ b/packages/ember-glimmer/lib/component.ts @@ -594,7 +594,7 @@ const Component = CoreView.extend( }, rerender() { - this[DIRTY_TAG].dirty(); + this[DIRTY_TAG].inner.dirty(); this._super(); }, diff --git a/packages/ember-glimmer/lib/helper.ts b/packages/ember-glimmer/lib/helper.ts index c7aff8bfd78..037c56e95f0 100644 --- a/packages/ember-glimmer/lib/helper.ts +++ b/packages/ember-glimmer/lib/helper.ts @@ -2,8 +2,8 @@ @module @ember/component */ -import { Dict, Opaque } from '@glimmer/util'; import { DirtyableTag } from '@glimmer/reference'; +import { Dict, Opaque } from '@glimmer/util'; import { FrameworkObject } from 'ember-runtime'; import { symbol } from 'ember-utils'; @@ -87,7 +87,7 @@ let Helper = FrameworkObject.extend({ @since 1.13.0 */ recompute() { - this[RECOMPUTE_TAG].dirty(); + this[RECOMPUTE_TAG].inner.dirty(); }, /** diff --git a/packages/ember-metal/lib/tags.js b/packages/ember-metal/lib/tags.js index 387200cbf5e..cb6c5e5e844 100644 --- a/packages/ember-metal/lib/tags.js +++ b/packages/ember-metal/lib/tags.js @@ -47,7 +47,7 @@ export function markObjectAsDirty(meta, propertyKey) { let propertyTag = tags !== undefined ? tags[propertyKey] : undefined; if (propertyTag !== undefined) { - propertyTag.dirty(); + propertyTag.inner.dirty(); } if (propertyKey === 'content' && meta.isProxy()) { From 621eecaec3ed7e3e6470ef9ed596cf801238e0db Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 20 Dec 2017 13:36:31 -0700 Subject: [PATCH 043/135] Use resolver for input component lookup --- packages/ember-glimmer/lib/syntax/input.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/ember-glimmer/lib/syntax/input.ts b/packages/ember-glimmer/lib/syntax/input.ts index d1b7e519301..3f85f6b5e5c 100644 --- a/packages/ember-glimmer/lib/syntax/input.ts +++ b/packages/ember-glimmer/lib/syntax/input.ts @@ -1,13 +1,17 @@ /** @module ember */ +import { + LazyOpcodeBuilder, + TemplateMeta +} from '@glimmer/opcode-compiler'; import { assert } from 'ember-debug'; import { wrapComponentClassAttribute } from '../utils/bindings'; import { dynamicComponentMacro } from './dynamic-component'; import { hashToArgs } from './utils'; -function buildSyntax(type: string, params: any[], hash: any, builder: any) { - let definition = builder.env.getComponentDefinition(type, builder.meta.templateMeta); +function buildSyntax(type: string, params: any[], hash: any, builder: LazyOpcodeBuilder) { + let definition = builder.resolver.lookupComponentDefinition(type, builder.referrer); builder.component.static(definition, [params, hashToArgs(hash), null, null]); return true; } From 41ac2a64c47352668827095fdf22dc939e51e39c Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Thu, 21 Dec 2017 06:32:28 -0700 Subject: [PATCH 044/135] Update mountMacro, in-element, and a tag --- packages/ember-glimmer/lib/syntax/mount.ts | 17 ++++++++++------- .../tests/integration/syntax/in-element-test.js | 10 +++++----- packages/ember-runtime/lib/mixins/-proxy.js | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/ember-glimmer/lib/syntax/mount.ts b/packages/ember-glimmer/lib/syntax/mount.ts index a93b9fcd07b..b061f45f99e 100644 --- a/packages/ember-glimmer/lib/syntax/mount.ts +++ b/packages/ember-glimmer/lib/syntax/mount.ts @@ -1,14 +1,18 @@ /** @module ember */ +import { Option } from '@glimmer/interfaces'; +import { OpcodeBuilder } from '@glimmer/opcode-compiler'; import { Arguments, VM } from '@glimmer/runtime'; +import * as WireFormat from '@glimmer/wire-format'; import { assert } from 'ember-debug'; +import { OwnedTemplateMeta } from 'ember-views'; import { EMBER_ENGINES_MOUNT_PARAMS } from 'ember/features'; -import Environment from '../environment'; import { MountDefinition } from '../component-managers/mount'; +import Environment from '../environment'; import { hashToArgs } from './utils'; function dynamicEngineFor(vm: VM, args: Arguments, meta: any) { @@ -59,22 +63,21 @@ function dynamicEngineFor(vm: VM, args: Arguments, meta: any) { @category ember-application-engines @public */ -export function mountMacro(_name: string, params: any[], hash: any, builder: any) { +export function mountMacro(_name: string, params: Option, hash: Option, builder: OpcodeBuilder) { if (EMBER_ENGINES_MOUNT_PARAMS) { assert( 'You can only pass a single positional argument to the {{mount}} helper, e.g. {{mount "chat-engine"}}.', - params.length === 1, + params!.length === 1, ); } else { assert( 'You can only pass a single argument to the {{mount}} helper, e.g. {{mount "chat-engine"}}.', - params.length === 1 && hash === null, + params!.length === 1 && hash === null, ); } - let definitionArgs = [params.slice(0, 1), null, null, null]; - let args = [null, hashToArgs(hash), null, null]; - builder.component.dynamic(definitionArgs, dynamicEngineFor, args); + let expr: WireFormat.Expressions.Helper = [WireFormat.Ops.Helper, 'mount', params || [], hash]; + builder.dynamicComponent(expr, [], null, false, null, null); return true; } diff --git a/packages/ember-glimmer/tests/integration/syntax/in-element-test.js b/packages/ember-glimmer/tests/integration/syntax/in-element-test.js index 31e6235ac03..d5743860595 100644 --- a/packages/ember-glimmer/tests/integration/syntax/in-element-test.js +++ b/packages/ember-glimmer/tests/integration/syntax/in-element-test.js @@ -4,14 +4,14 @@ import { strip } from '../../utils/abstract-test-case'; import Component from '../../../component'; import { set } from 'ember-metal'; -moduleFor('{{-in-element}}', class extends RenderingTest { +moduleFor('{{in-element}}', class extends RenderingTest { ['@test allows rendering into an external element']() { let someElement = document.createElement('div'); this.render(strip` - {{#-in-element someElement}} + {{#in-element someElement}} {{text}} - {{/-in-element}} + {{/in-element}} `, { someElement, text: 'Whoop!' @@ -54,9 +54,9 @@ moduleFor('{{-in-element}}', class extends RenderingTest { this.render(strip` {{#if showModal}} - {{#-in-element someElement}} + {{#in-element someElement}} {{modal-display text=text}} - {{/-in-element}} + {{/in-element}} {{/if}} `, { someElement, diff --git a/packages/ember-runtime/lib/mixins/-proxy.js b/packages/ember-runtime/lib/mixins/-proxy.js index fcfbeecadaf..8f39a4a33bc 100644 --- a/packages/ember-runtime/lib/mixins/-proxy.js +++ b/packages/ember-runtime/lib/mixins/-proxy.js @@ -50,7 +50,7 @@ class ProxyTag extends CachedTag { } dirty() { - this.proxyWrapperTag.dirty(); + this.proxyWrapperTag.inner.dirty(); } contentDidChange() { From db6ad51832d0991b3ba71e468ea5b892df22f2d0 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Thu, 21 Dec 2017 13:37:49 -0700 Subject: [PATCH 045/135] attrs no longer has a `value` --- packages/ember/tests/component_context_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember/tests/component_context_test.js b/packages/ember/tests/component_context_test.js index f7dd1f53d7f..a8d63bebcaf 100644 --- a/packages/ember/tests/component_context_test.js +++ b/packages/ember/tests/component_context_test.js @@ -126,7 +126,7 @@ moduleFor('Application Lifecycle - Component Context', class extends Application ComponentClass: Component.extend({ didInsertElement() { // FIXME: I'm unsure if this is even the right way to access attrs - this.$().html(this.get('attrs.attrs.value')); + this.$().html(this.get('attrs.attrs')); } }) }); From 07b933153a6caa2d0b9e17fda85d849732f8d13c Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Fri, 22 Dec 2017 15:10:28 -0700 Subject: [PATCH 046/135] normalizeTextValue no longer seems to be necessary --- packages/ember-glimmer/lib/helpers/concat.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/helpers/concat.ts b/packages/ember-glimmer/lib/helpers/concat.ts index 69d5d82fdc5..49af7a5f4cf 100644 --- a/packages/ember-glimmer/lib/helpers/concat.ts +++ b/packages/ember-glimmer/lib/helpers/concat.ts @@ -26,7 +26,7 @@ import { InternalHelperReference } from '../utils/references'; @since 1.13.0 */ function concat({ positional }: CapturedArguments) { - return positional.value().map(normalizeTextValue).join(''); + return positional.value().join(''); } export default function(_vm: VM, args: Arguments) { From 2cbd6beb8fb4bfc81c07c1d7c4fdbb2170aac6dd Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 2 Jan 2018 15:21:51 -0800 Subject: [PATCH 047/135] Fix WRAPPER check, I got it backward after the merge. --- packages/ember-glimmer/lib/component-managers/outlet.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index 41184657f1f..85065ddbcdf 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -134,6 +134,8 @@ class TopLevelOutletComponentManager extends OutletComponentManager const template = state.template; let layout: TopLevelSyntax; if (EMBER_GLIMMER_REMOVE_APPLICATION_TEMPLATE_WRAPPER) { + layout = template.asLayout(); + } else { const compileOptions = Object.assign({}, resolver.templateOptions, { asPartial: false, referrer: template.referrer}); @@ -144,8 +146,6 @@ class TopLevelOutletComponentManager extends OutletComponentManager parsed, TOP_CAPABILITIES, ); - } else { - layout = template.asLayout(); } return { handle: layout.compile(), From 560a3044b794625480b18be11b0bb73480c2b1d5 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 2 Jan 2018 16:11:13 -0800 Subject: [PATCH 048/135] hack two way flushing tag stuff --- .../ember-glimmer/lib/utils/references.ts | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/packages/ember-glimmer/lib/utils/references.ts b/packages/ember-glimmer/lib/utils/references.ts index 144437d272f..3211adb65a3 100644 --- a/packages/ember-glimmer/lib/utils/references.ts +++ b/packages/ember-glimmer/lib/utils/references.ts @@ -5,10 +5,11 @@ import { ConstReference, DirtyableTag, isConst, - PathReference, + RevisionTag, Tag, TagWrapper, UpdatableTag, + VersionedPathReference, } from '@glimmer/reference'; import { CapturedArguments, @@ -59,7 +60,7 @@ if (DEBUG) { // @abstract // @implements PathReference -abstract class EmberPathReference implements PathReference { +abstract class EmberPathReference implements VersionedPathReference { // @abstract get tag() // @abstract value() public tag: Tag; @@ -75,7 +76,7 @@ abstract class EmberPathReference implements PathReference { export class CachedReference extends EmberPathReference { private _lastRevision: any; private _lastValue: any; - public tag: any; + public tag: Tag; constructor() { super(); @@ -119,16 +120,27 @@ export class RootReference extends ConstReference { } } -let TwoWayFlushDetectionTag: any; +interface TwoWayFlushDetectionTag extends RevisionTag { + didCompute(parent: Opaque): void; +} + +let TwoWayFlushDetectionTag: { + new (tag: Tag, key: string, ref: VersionedPathReference): TwoWayFlushDetectionTag; + create(tag: Tag, key: string, ref: VersionedPathReference): TagWrapper; +}; if (EMBER_GLIMMER_DETECT_BACKTRACKING_RERENDER) { TwoWayFlushDetectionTag = class { - public tag: any; - public parent: any; + public tag: Tag; + public parent: Opaque; public key: string; public ref: any; - constructor(tag: TagWrapper, key: string, ref: any) { + static create(tag: Tag, key: string, ref: VersionedPathReference): TagWrapper { + return new TagWrapper((tag as any).type, new TwoWayFlushDetectionTag(tag, key, ref)); + } + + constructor(tag: Tag, key: string, ref: any) { this.tag = tag; this.parent = null; this.key = key; @@ -159,7 +171,7 @@ if (EMBER_GLIMMER_DETECT_BACKTRACKING_RERENDER) { } export class PropertyReference extends CachedReference { - static create(parentReference: any, propertyKey: string) { + static create(parentReference: VersionedPathReference, propertyKey: string) { if (isConst(parentReference)) { return new RootPropertyReference(parentReference.value(), propertyKey); } else { @@ -167,12 +179,12 @@ export class PropertyReference extends CachedReference { } } - get(key: string) { + get(key: string): VersionedPathReference { return new NestedPropertyReference(this, key); } } -export class RootPropertyReference extends PropertyReference { +export class RootPropertyReference extends PropertyReference implements VersionedPathReference { private _parentValue: any; private _propertyKey: string; @@ -183,7 +195,7 @@ export class RootPropertyReference extends PropertyReference { this._propertyKey = propertyKey; if (EMBER_GLIMMER_DETECT_BACKTRACKING_RERENDER) { - this.tag = new TwoWayFlushDetectionTag(tagForProperty(parentValue, propertyKey), propertyKey, this); + this.tag = TwoWayFlushDetectionTag.create(tagForProperty(parentValue, propertyKey), propertyKey, this); } else { this.tag = tagForProperty(parentValue, propertyKey); } @@ -197,7 +209,7 @@ export class RootPropertyReference extends PropertyReference { let { _parentValue, _propertyKey } = this; if (EMBER_GLIMMER_DETECT_BACKTRACKING_RERENDER) { - this.tag.didCompute(_parentValue); + (this.tag.inner as TwoWayFlushDetectionTag).didCompute(_parentValue); } return get(_parentValue, _propertyKey); @@ -213,7 +225,7 @@ export class NestedPropertyReference extends PropertyReference { private _parentObjectTag: TagWrapper; private _propertyKey: string; - constructor(parentReference: any, propertyKey: string) { + constructor(parentReference: VersionedPathReference, propertyKey: string) { super(); let parentReferenceTag = parentReference.tag; @@ -225,7 +237,7 @@ export class NestedPropertyReference extends PropertyReference { if (EMBER_GLIMMER_DETECT_BACKTRACKING_RERENDER) { let tag = combine([parentReferenceTag, parentObjectTag]); - this.tag = new TwoWayFlushDetectionTag(tag, propertyKey, this); + this.tag = TwoWayFlushDetectionTag.create(tag, propertyKey, this); } else { this.tag = combine([parentReferenceTag, parentObjectTag]); } @@ -250,7 +262,7 @@ export class NestedPropertyReference extends PropertyReference { } if (EMBER_GLIMMER_DETECT_BACKTRACKING_RERENDER) { - this.tag.didCompute(parentValue); + (this.tag.inner as TwoWayFlushDetectionTag).didCompute(parentValue); } return get(parentValue, _propertyKey); From 63e19eb79ddb6c6fe9df9c1c7e43caf1629c32d8 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Thu, 4 Jan 2018 10:54:20 -0700 Subject: [PATCH 049/135] Update getTag to actually get a useful tag --- packages/ember-glimmer/lib/component-managers/curly.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 0e911c86f8a..7101a85f97f 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -8,6 +8,7 @@ import { } from '@glimmer/interfaces'; import { ParsedLayout, TemplateOptions, WrappedBuilder } from '@glimmer/opcode-compiler'; import { + combine, combineTagged, Tag, VersionedPathReference, @@ -436,8 +437,9 @@ export default class CurlyComponentManager extends AbstractManager Date: Thu, 4 Jan 2018 11:34:35 -0700 Subject: [PATCH 050/135] Bring over referenceFromParts --- packages/ember-glimmer/lib/utils/bindings.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/utils/bindings.ts b/packages/ember-glimmer/lib/utils/bindings.ts index ac03821d00a..ea68746a3ea 100644 --- a/packages/ember-glimmer/lib/utils/bindings.ts +++ b/packages/ember-glimmer/lib/utils/bindings.ts @@ -9,6 +9,7 @@ import { map, Reference, Tag, + VersionedPathReference } from '@glimmer/reference'; import { ElementOperations @@ -25,6 +26,16 @@ function referenceForKey(component: Component, key: string) { return component[ROOT_REF].get(key); } +function referenceFromParts(root: VersionedPathReference, parts: string[]): VersionedPathReference { + let reference = root; + + for (let i=0; i Date: Thu, 4 Jan 2018 13:27:31 -0700 Subject: [PATCH 051/135] Fix attribute bindings integration tests --- packages/ember-glimmer/lib/utils/bindings.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/ember-glimmer/lib/utils/bindings.ts b/packages/ember-glimmer/lib/utils/bindings.ts index ea68746a3ea..d00693231fe 100644 --- a/packages/ember-glimmer/lib/utils/bindings.ts +++ b/packages/ember-glimmer/lib/utils/bindings.ts @@ -12,7 +12,8 @@ import { VersionedPathReference } from '@glimmer/reference'; import { - ElementOperations + ElementOperations, + PrimitiveReference } from '@glimmer/runtime'; import { Core, Ops } from '@glimmer/wire-format'; import { assert } from 'ember-debug'; @@ -82,7 +83,7 @@ export const AttributeBinding = { if (colonIndex === -1) { assert('You cannot use class as an attributeBinding, use classNameBindings instead.', microsyntax !== 'class'); - return [microsyntax, microsyntax, true]; + return [microsyntax, microsyntax.toLowerCase(), true]; } else { let prop = microsyntax.substring(0, colonIndex); let attribute = microsyntax.substring(colonIndex + 1); @@ -101,6 +102,7 @@ export const AttributeBinding = { if (elementId === undefined || elementId === null) { elementId = component.elementId; } + elementId = PrimitiveReference.create(elementId); operations.setAttribute('id', elementId, true, null); // operations.addStaticAttribute(element, 'id', elementId); return; From 69b95f515642b10110076ebdd37ab6a04a69d32c Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Fri, 5 Jan 2018 11:50:27 -0700 Subject: [PATCH 052/135] Use primitive reference for static class names Using just a string is not enough because operations.setAttribute expects a reference, not a primitive --- packages/ember-glimmer/lib/utils/bindings.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ember-glimmer/lib/utils/bindings.ts b/packages/ember-glimmer/lib/utils/bindings.ts index d00693231fe..8e4c62ce1bb 100644 --- a/packages/ember-glimmer/lib/utils/bindings.ts +++ b/packages/ember-glimmer/lib/utils/bindings.ts @@ -173,8 +173,7 @@ export const ClassNameBinding = { let isStatic = prop === ''; if (isStatic) { - operations.setAttribute('class', truthy, true, null); - // operations.addStaticAttribute(element, 'class', truthy); + operations.setAttribute('class', PrimitiveReference.create(truthy), true, null); } else { let isPath = prop.indexOf('.') > -1; let parts = isPath ? prop.split('.') : []; From 21c4c133daca61ebf8b5b42433e50b189d2d4ece Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Fri, 5 Jan 2018 14:03:51 -0800 Subject: [PATCH 053/135] fix some more tests --- packages/ember-metal/lib/tags.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ember-metal/lib/tags.js b/packages/ember-metal/lib/tags.js index cb6c5e5e844..d8f5700a13d 100644 --- a/packages/ember-metal/lib/tags.js +++ b/packages/ember-metal/lib/tags.js @@ -40,7 +40,7 @@ export function markObjectAsDirty(meta, propertyKey) { let objectTag = meta.readableTag(); if (objectTag !== undefined) { - objectTag.dirty(); + objectTag.inner.dirty(); } let tags = meta.readableTags(); @@ -51,7 +51,7 @@ export function markObjectAsDirty(meta, propertyKey) { } if (propertyKey === 'content' && meta.isProxy()) { - objectTag.contentDidChange(); + objectTag.inner.contentDidChange(); } if (objectTag !== undefined || propertyTag !== undefined) { From 142b176d10fa07c158d5ebde77b788fd5a6db387 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Fri, 5 Jan 2018 14:12:53 -0800 Subject: [PATCH 054/135] Fix get helper --- packages/ember-glimmer/lib/helpers/get.ts | 24 ++++++++++--------- packages/ember-glimmer/lib/utils/bindings.ts | 11 +-------- .../ember-glimmer/lib/utils/references.ts | 10 ++++++++ 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/packages/ember-glimmer/lib/helpers/get.ts b/packages/ember-glimmer/lib/helpers/get.ts index f67f53999df..ee24ef97cf1 100644 --- a/packages/ember-glimmer/lib/helpers/get.ts +++ b/packages/ember-glimmer/lib/helpers/get.ts @@ -1,11 +1,13 @@ +import { Opaque } from '@glimmer/interfaces'; import { combine, CONSTANT_TAG, isConst, PathReference, - referenceForParts, + Tag, TagWrapper, UpdatableTag, + VersionedPathReference, } from '@glimmer/reference'; import { Arguments, @@ -13,7 +15,7 @@ import { VM } from '@glimmer/runtime'; import { set } from 'ember-metal'; -import { CachedReference, UPDATE } from '../utils/references'; +import { CachedReference, referenceFromParts, UPDATE } from '../utils/references'; /** @module ember @@ -68,23 +70,23 @@ export default function(_vm: VM, args: Arguments) { } class GetHelperReference extends CachedReference { - public sourceReference: any; - public pathReference: PathReference; - public lastPath: any; - public innerReference: any; + public sourceReference: VersionedPathReference; + public pathReference: PathReference; + public lastPath: string | null; + public innerReference: VersionedPathReference; public innerTag: TagWrapper; - public tag: any; + public tag: Tag; - static create(sourceReference: any, pathReference: PathReference) { + static create(sourceReference: VersionedPathReference, pathReference: PathReference) { if (isConst(pathReference)) { let parts = pathReference.value().split('.'); - return referenceForParts(sourceReference, parts); + return referenceFromParts(sourceReference, parts); } else { return new GetHelperReference(sourceReference, pathReference); } } - constructor(sourceReference: any, pathReference: PathReference) { + constructor(sourceReference: VersionedPathReference, pathReference: PathReference) { super(); this.sourceReference = sourceReference; this.pathReference = pathReference; @@ -107,7 +109,7 @@ class GetHelperReference extends CachedReference { let pathType = typeof path; if (pathType === 'string') { - innerReference = referenceForParts(this.sourceReference, path.split('.')); + innerReference = referenceFromParts(this.sourceReference, path.split('.')); } else if (pathType === 'number') { innerReference = this.sourceReference.get('' + path); } diff --git a/packages/ember-glimmer/lib/utils/bindings.ts b/packages/ember-glimmer/lib/utils/bindings.ts index 8e4c62ce1bb..b6a919d7efc 100644 --- a/packages/ember-glimmer/lib/utils/bindings.ts +++ b/packages/ember-glimmer/lib/utils/bindings.ts @@ -21,22 +21,13 @@ import { get } from 'ember-metal'; import { String as StringUtils } from 'ember-runtime'; import { ROOT_REF } from '../component'; import { Component } from './curly-component-state-bucket'; +import { referenceFromParts } from './references'; import { htmlSafe, isHTMLSafe, SafeString } from './string'; function referenceForKey(component: Component, key: string) { return component[ROOT_REF].get(key); } -function referenceFromParts(root: VersionedPathReference, parts: string[]): VersionedPathReference { - let reference = root; - - for (let i=0; i { return new UnboundReference(get(this.inner, key)); } } + +export function referenceFromParts(root: VersionedPathReference, parts: string[]): VersionedPathReference { + let reference = root; + + for (let i=0; i Date: Fri, 5 Jan 2018 18:55:43 -0800 Subject: [PATCH 055/135] Fix rendering of array and object proxies. --- packages/ember-glimmer/lib/utils/iterable.ts | 10 +++-- packages/ember-metal/lib/tags.js | 11 +++--- packages/ember-runtime/lib/index.d.ts | 2 + packages/ember-runtime/lib/index.js | 2 +- packages/ember-runtime/lib/mixins/-proxy.js | 39 ++++++-------------- 5 files changed, 27 insertions(+), 37 deletions(-) diff --git a/packages/ember-glimmer/lib/utils/iterable.ts b/packages/ember-glimmer/lib/utils/iterable.ts index 090113c8ca3..a0a60928179 100644 --- a/packages/ember-glimmer/lib/utils/iterable.ts +++ b/packages/ember-glimmer/lib/utils/iterable.ts @@ -8,6 +8,7 @@ import { import { Opaque } from '@glimmer/util'; import { get, isProxy, tagFor, tagForProperty } from 'ember-metal'; import { + _contentFor, isEmberArray, objectAt, } from 'ember-runtime'; @@ -204,13 +205,16 @@ class EachInIterable { let { ref, keyFor, valueTag } = this; let iterable = ref.value(); - - valueTag.inner.update(tagFor(iterable)); + let tag = tagFor(iterable); if (isProxy(iterable)) { - iterable = get(iterable, 'content'); + // this is because the each-in doesn't actually get(proxy, 'key') but bypasses it + // and the proxy's tag is lazy updated on access + iterable = _contentFor(iterable); } + valueTag.inner.update(tag); + let typeofIterable = typeof iterable; if (iterable !== null && (typeofIterable === 'object' || typeofIterable === 'function')) { diff --git a/packages/ember-metal/lib/tags.js b/packages/ember-metal/lib/tags.js index d8f5700a13d..a1591c2f177 100644 --- a/packages/ember-metal/lib/tags.js +++ b/packages/ember-metal/lib/tags.js @@ -40,7 +40,11 @@ export function markObjectAsDirty(meta, propertyKey) { let objectTag = meta.readableTag(); if (objectTag !== undefined) { - objectTag.inner.dirty(); + if (meta.isProxy()) { + objectTag.inner.first.inner.dirty(); + } else { + objectTag.inner.dirty(); + } } let tags = meta.readableTags(); @@ -50,10 +54,6 @@ export function markObjectAsDirty(meta, propertyKey) { propertyTag.inner.dirty(); } - if (propertyKey === 'content' && meta.isProxy()) { - objectTag.inner.contentDidChange(); - } - if (objectTag !== undefined || propertyTag !== undefined) { ensureRunloop(); } @@ -62,6 +62,7 @@ export function markObjectAsDirty(meta, propertyKey) { let backburner; function ensureRunloop() { if (backburner === undefined) { + // TODO why does this need to be lazy backburner = require('ember-metal').run.backburner; } diff --git a/packages/ember-runtime/lib/index.d.ts b/packages/ember-runtime/lib/index.d.ts index 2edc0f9536e..cc7401443d0 100644 --- a/packages/ember-runtime/lib/index.d.ts +++ b/packages/ember-runtime/lib/index.d.ts @@ -21,3 +21,5 @@ export const String: { export function objectAt(arr: any, i: number): any; export function isEmberArray(arr: any): boolean; + +export function _contentFor(proxy: any): any; diff --git a/packages/ember-runtime/lib/index.js b/packages/ember-runtime/lib/index.js index 225d414171f..59437b33b2e 100644 --- a/packages/ember-runtime/lib/index.js +++ b/packages/ember-runtime/lib/index.js @@ -33,7 +33,7 @@ export { export { default as Copyable } from './mixins/copyable'; export { default as Enumerable } from './mixins/enumerable'; export { - default as _ProxyMixin + default as _ProxyMixin, contentFor as _contentFor } from './mixins/-proxy'; export { onLoad, diff --git a/packages/ember-runtime/lib/mixins/-proxy.js b/packages/ember-runtime/lib/mixins/-proxy.js index 8f39a4a33bc..2cacb870685 100644 --- a/packages/ember-runtime/lib/mixins/-proxy.js +++ b/packages/ember-runtime/lib/mixins/-proxy.js @@ -2,7 +2,7 @@ @module ember */ -import { CachedTag, DirtyableTag, UpdatableTag } from '@glimmer/reference'; +import { combine, CONSTANT_TAG, DirtyableTag, UpdatableTag } from '@glimmer/reference'; import { get, set, @@ -15,7 +15,7 @@ import { propertyDidChange, defineProperty, Mixin, - tagFor, + tagFor } from 'ember-metal'; import { assert, @@ -34,29 +34,11 @@ function contentPropertyDidChange(content, contentKey) { propertyDidChange(this, key); } -class ProxyTag extends CachedTag { - constructor(proxy) { - super(); - - let content = get(proxy, 'content'); - - this.proxy = proxy; - this.proxyWrapperTag = DirtyableTag.create(); - this.proxyContentTag = UpdatableTag.create(tagFor(content)); - } - - compute() { - return Math.max(this.proxyWrapperTag.value(), this.proxyContentTag.value()); - } - - dirty() { - this.proxyWrapperTag.inner.dirty(); - } - - contentDidChange() { - let content = get(this.proxy, 'content'); - this.proxyContentTag.update(tagFor(content)); - } +export function contentFor(proxy, m) { + let content = get(proxy, 'content'); + let tag = (m === undefined ? meta(proxy) : m).readableTag(); + tag.inner.second.inner.update(tagFor(content)); + return content; } /** @@ -82,7 +64,7 @@ export default Mixin.create({ this._super(...arguments); let m = meta(this); m.setProxy(); - m.writableTag((source)=> new ProxyTag(source)); + m.writableTag(() => combine([DirtyableTag.create(), UpdatableTag.create(CONSTANT_TAG)])); }, isTruthy: bool('content'), @@ -100,7 +82,7 @@ export default Mixin.create({ }, unknownProperty(key) { - let content = get(this, 'content'); + let content = contentFor(this); if (content) { return get(content, key); } @@ -116,7 +98,8 @@ export default Mixin.create({ return value; } - let content = get(this, 'content'); + let content = contentFor(this, m); + assert(`Cannot delegate set('${key}', ${value}) to the \'content\' property of object proxy ${this}: its 'content' is undefined.`, content); return set(content, key, value); From 13e950529d6837d70dfd3dc1125e53a32536e07a Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Fri, 5 Jan 2018 21:38:53 -0700 Subject: [PATCH 056/135] Fix a few contextual component tests --- .../lib/component-managers/curly.ts | 7 +- packages/ember-glimmer/lib/utils/bindings.ts | 5 +- .../components/contextual-components-test.js | 121 +++++++++++++++--- 3 files changed, 106 insertions(+), 27 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 7101a85f97f..d2c3d6ea14e 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -19,8 +19,6 @@ import { ComponentDefinition, ElementOperations, Invocation, - NamedArguments, - PositionalArguments, PreparedArguments, PrimitiveReference, WithDynamicLayout, @@ -61,6 +59,7 @@ import { AttributeBinding, ClassNameBinding, IsVisibleBinding, + referenceForKey } from '../utils/bindings'; import ComponentStateBucket, { Component } from '../utils/curly-component-state-bucket'; import { processComponentArgs } from '../utils/process-args'; @@ -242,7 +241,7 @@ export default class CurlyComponentManager extends AbstractManager this.rerender()); - this.assertText('ZackGabon '); + this.assertText('Gabon Zack Zack Gabon '); this.runTask(() => this.context.set('model.greeting', 'Good morning ')); - this.assertText('ZackGood morning '); + this.assertText('Good morning Zack Zack Good morning '); - this.runTask(() => this.context.set('model.name', 'Matthew')); + this.runTask(() => this.context.set('model.name', 'Matthew ')); - this.assertText('MatthewGood morning '); + this.assertText('Good morning Matthew Matthew Good morning '); - this.runTask(() => this.context.set('model', { greeting: 'Gabon ', name: 'Zack' })); + this.runTask(() => this.context.set('model', { greeting: 'Gabon ', name: 'Zack ' })); - this.assertText('ZackGabon '); + this.assertText('Gabon Zack Zack Gabon '); } ['@test GH#13742 keeps nested rest positional parameters if nested and rendered with no positional parameters']() { @@ -155,15 +155,15 @@ moduleFor('Components test: contextual components', class extends RenderingTest this.render('{{component (component (component "-looked-up" model.greeting model.name) model.name model.greeting)}}', { model: { greeting: 'Gabon ', - name: 'Zack' + name: 'Zack ' } }); - this.assertText('ZackGabon '); + this.assertText('Gabon Zack Zack Gabon '); this.runTask(() => this.rerender()); - this.assertText('ZackGabon '); + this.assertText('Gabon Zack Zack Gabon '); this.runTask(() => this.context.set('model.greeting', 'Good morning ')); @@ -284,7 +284,7 @@ moduleFor('Components test: contextual components', class extends RenderingTest this.assertText('Hodi'); } - ['@test nested components overwrite named positional parameters']() { + ['@test nested components do not overwrite positional parameters']() { this.registerComponent('-looked-up', { ComponentClass: Component.extend().reopenClass({ positionalParams: ['name', 'age'] @@ -294,11 +294,79 @@ moduleFor('Components test: contextual components', class extends RenderingTest this.render('{{component (component (component "-looked-up" "Sergio" 29) "Marvin" 21) "Hodari"}}'); - this.assertText('Hodari 21'); + this.assertText('Sergio 29'); + + this.runTask(() => this.rerender()); + + this.assertText('Sergio 29'); + } + + ['@test positional parameters are combined not clobbered']() { + this.registerComponent('-looked-up', { + ComponentClass: Component.extend().reopenClass({ + positionalParams: ['greeting', 'name', 'age'] + }), + template: '{{greeting}} {{name}} {{age}}' + }); + + this.render('{{component (component (component "-looked-up" "Hi") "Max") 9}}'); + + this.assertText('Hi Max 9'); + + this.runTask(() => this.rerender()); + + this.assertText('Hi Max 9'); + } + + ['@test nested components positional parameters are overridden by named parameters']() { + this.registerComponent('-looked-up', { + ComponentClass: Component.extend().reopenClass({ + positionalParams: ['name', 'age'] + }), + template: '{{name}} {{age}}' + }); + + this.render('{{component (component (component "-looked-up" "Sergio" 29) name="Marvin" age=21)}}'); + + this.assertText('Marvin 21'); this.runTask(() => this.rerender()); - this.assertText('Hodari 21'); + this.assertText('Marvin 21'); + } + + ['@test nested components with positional params at outer layer are overwriten by hash parameters']() { + this.registerComponent('-looked-up', { + ComponentClass: Component.extend().reopenClass({ + positionalParams: ['greeting', 'name', 'age'] + }), + template: '{{greeting}} {{name}} {{age}}' + }); + + this.render(strip` + {{#with (component "-looked-up" "Hola" "Dolores" 33) as |first|}} + {{#with (component first greeting="Hej" name="Sigmundur") as |second|}} + {{component second greeting=model.greeting}} + {{/with}} + {{/with}}`, { + model: { + greeting: 'Hodi' + } + }); + + this.assertText('Hodi Sigmundur 33'); + + this.runTask(() => this.rerender()); + + this.assertText('Hodi Sigmundur 33'); + + this.runTask(() => this.context.set('model.greeting', 'Kaixo')); + + this.assertText('Kaixo Sigmundur 33'); + + this.runTask(() => this.context.set('model', { greeting: 'Hodi' })); + + this.assertText('Hodi Sigmundur 33'); } ['@test nested components overwrite hash parameters']() { @@ -354,19 +422,19 @@ moduleFor('Components test: contextual components', class extends RenderingTest } }); - this.assertText('Inner 28'); + this.assertText('Outer 28'); this.runTask(() => this.rerender()); - this.assertText('Inner 28'); + this.assertText('Outer 28'); this.runTask(() => this.context.set('model.outerAge', 29)); - this.assertText('Inner 29'); + this.assertText('Outer 29'); this.runTask(() => this.context.set('model.outerName', 'Not outer')); - this.assertText('Inner 29'); + this.assertText('Not outer 29'); this.runTask(() => { this.context.set('model', { @@ -375,7 +443,7 @@ moduleFor('Components test: contextual components', class extends RenderingTest }); }); - this.assertText('Inner 28'); + this.assertText('Outer 28'); } ['@test bound outer hash parameters get updated in the right scope']() { @@ -421,7 +489,7 @@ moduleFor('Components test: contextual components', class extends RenderingTest this.assertText('Inner 28'); } - ['@test conflicting positional and hash parameters raise and assertion if in the same component context']() { + ['@test conflicting positional and hash parameters raise an assertion if in the same component context']() { this.registerComponent('-looked-up', { ComponentClass: Component.extend().reopenClass({ positionalParams: ['name'] @@ -434,6 +502,19 @@ moduleFor('Components test: contextual components', class extends RenderingTest }, 'You cannot specify both a positional param (at position 0) and the hash argument `name`.'); } + ['@test conflicting positional and hash parameters raise and assertion if in the same component context with prior curried positional params']() { + this.registerComponent('-looked-up', { + ComponentClass: Component.extend().reopenClass({ + positionalParams: ['name'] + }), + template: '{{greeting}} {{name}}' + }); + + expectAssertion(() => { + this.render('{{component (component "-looked-up" "Hodari") "Sergio" name="Hodi"}}'); + }, 'You cannot specify both a positional param (at position 0) and the hash argument `name`.'); + } + ['@test conflicting positional and hash parameters does not raise an assertion if rerendered']() { // In some cases, rerendering with a positional param used to cause an // assertion. This test checks it does not. From 44f52006414f11a49ff5efcc5f6088093f4e3ab0 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Mon, 8 Jan 2018 11:25:52 -0700 Subject: [PATCH 057/135] Fix textarea helper tests --- packages/ember-glimmer/lib/syntax/-text-area.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/ember-glimmer/lib/syntax/-text-area.ts b/packages/ember-glimmer/lib/syntax/-text-area.ts index d1139df630f..5f62f320ecd 100644 --- a/packages/ember-glimmer/lib/syntax/-text-area.ts +++ b/packages/ember-glimmer/lib/syntax/-text-area.ts @@ -1,8 +1,12 @@ +import { + LazyOpcodeBuilder, + TemplateMeta +} from '@glimmer/opcode-compiler'; import { wrapComponentClassAttribute } from '../utils/bindings'; import { hashToArgs } from './utils'; -export function textAreaMacro(_name: string, params: any[], hash: any, builder: any) { - let definition = builder.env.getComponentDefinition('-text-area', builder.meta.templateMeta); +export function textAreaMacro(_name: string, params: any[], hash: any, builder: LazyOpcodeBuilder) { + let definition = builder.resolver.lookupComponentDefinition('-text-area', builder.referrer); wrapComponentClassAttribute(hash); builder.component.static(definition, [params, hashToArgs(hash), null, null]); return true; From 4d9d2f6332c0d05a124f1e26080e1df7a0ffa5c5 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Mon, 8 Jan 2018 16:38:03 -0700 Subject: [PATCH 058/135] Dasherize classes, more thorough readDOMAttr --- .../lib/component-managers/curly.ts | 11 ++++++++--- packages/ember-glimmer/lib/component.ts | 16 +++++++++++++++- packages/ember-glimmer/lib/utils/bindings.ts | 2 +- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index d2c3d6ea14e..c5815fff295 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -34,6 +34,7 @@ import { DEBUG } from 'ember-env-flags'; import { _instrumentStart, get, } from 'ember-metal'; +import { String as StringUtils } from 'ember-runtime'; import { getOwner, guidFor, @@ -59,7 +60,8 @@ import { AttributeBinding, ClassNameBinding, IsVisibleBinding, - referenceForKey + referenceForKey, + ColonClassNameBindingReference } from '../utils/bindings'; import ComponentStateBucket, { Component } from '../utils/curly-component-state-bucket'; import { processComponentArgs } from '../utils/process-args'; @@ -382,7 +384,7 @@ export default class CurlyComponentManager extends AbstractManager> { } } -class ColonClassNameBindingReference extends CachedReference> { +export class ColonClassNameBindingReference extends CachedReference> { public tag: Tag; constructor(private inner: Reference, From f93ff4746f7da8d5373fddf7fc0cb95554e1421c Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Mon, 8 Jan 2018 18:05:58 -0800 Subject: [PATCH 059/135] Currently all outlets are rerendering and even though that is not correct, this test navigates away from the page if it causes a click on a detached anchor because there is no view to prevent default. So temporarily work around it. --- .../link_to_transitioning_classes_test.js | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/ember/tests/helpers/link_to_test/link_to_transitioning_classes_test.js b/packages/ember/tests/helpers/link_to_test/link_to_transitioning_classes_test.js index 7819e67eec7..c9a217bf412 100644 --- a/packages/ember/tests/helpers/link_to_test/link_to_transitioning_classes_test.js +++ b/packages/ember/tests/helpers/link_to_test/link_to_transitioning_classes_test.js @@ -201,12 +201,16 @@ moduleFor(`The {{link-to}} helper: .transitioning-in .transitioning-out CSS clas } [`@test while a transition is underway with nested link-to's`](assert) { - let $index = this.$('#index-link'); + // TODO undo changes to this test but currently this test navigates away if navigation + // outlet is not stable and the second $about.click() is triggered. let $about = this.$('#about-link'); - let $other = this.$('#other-link'); $about.click(); + let $index = this.$('#index-link'); + $about = this.$('#about-link'); + let $other = this.$('#other-link'); + assertHasClass(assert, $index, 'active'); assertHasNoClass(assert, $about, 'active'); assertHasNoClass(assert, $about, 'active'); @@ -221,6 +225,10 @@ moduleFor(`The {{link-to}} helper: .transitioning-in .transitioning-out CSS clas this.resolveAbout(); + $index = this.$('#index-link'); + $about = this.$('#about-link'); + $other = this.$('#other-link'); + assertHasNoClass(assert, $index, 'active'); assertHasClass(assert, $about, 'active'); assertHasNoClass(assert, $other, 'active'); @@ -235,6 +243,10 @@ moduleFor(`The {{link-to}} helper: .transitioning-in .transitioning-out CSS clas $other.click(); + $index = this.$('#index-link'); + $about = this.$('#about-link'); + $other = this.$('#other-link'); + assertHasNoClass(assert, $index, 'active'); assertHasClass(assert, $about, 'active'); assertHasNoClass(assert, $other, 'active'); @@ -249,6 +261,10 @@ moduleFor(`The {{link-to}} helper: .transitioning-in .transitioning-out CSS clas this.resolveOther(); + $index = this.$('#index-link'); + $about = this.$('#about-link'); + $other = this.$('#other-link'); + assertHasNoClass(assert, $index, 'active'); assertHasNoClass(assert, $about, 'active'); assertHasClass(assert, $other, 'active'); @@ -263,6 +279,9 @@ moduleFor(`The {{link-to}} helper: .transitioning-in .transitioning-out CSS clas $about.click(); + $index = this.$('#index-link'); + $about = this.$('#about-link'); + $other = this.$('#other-link'); assertHasNoClass(assert, $index, 'active'); assertHasNoClass(assert, $about, 'active'); @@ -278,6 +297,10 @@ moduleFor(`The {{link-to}} helper: .transitioning-in .transitioning-out CSS clas this.resolveAbout(); + $index = this.$('#index-link'); + $about = this.$('#about-link'); + $other = this.$('#other-link'); + assertHasNoClass(assert, $index, 'active'); assertHasClass(assert, $about, 'active'); assertHasNoClass(assert, $other, 'active'); From a8bb87b4a1606c83cf0b30783d2addcdf6f24955 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 8 Jan 2018 21:33:42 -0500 Subject: [PATCH 060/135] Fix template injection tests. --- packages/ember-application/tests/system/application_test.js | 2 +- packages/ember-application/tests/system/engine_test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ember-application/tests/system/application_test.js b/packages/ember-application/tests/system/application_test.js index a92e767454e..624b95619a5 100644 --- a/packages/ember-application/tests/system/application_test.js +++ b/packages/ember-application/tests/system/application_test.js @@ -164,7 +164,7 @@ moduleFor('Ember.Application', class extends ApplicationTestCase { verifyRegistration(assert, application, P`template:components/-default`); verifyRegistration(assert, application, 'template:-outlet'); verifyInjection(assert, application, 'view:-outlet', 'template', 'template:-outlet'); - verifyInjection(assert, application, 'template', 'env', 'service:-glimmer-environment'); + verifyInjection(assert, application, 'template', 'options', P`template-options:main`); assert.deepEqual(application.registeredOptionsForType('helper'), { instantiate: false }, `optionsForType 'helper'`); } diff --git a/packages/ember-application/tests/system/engine_test.js b/packages/ember-application/tests/system/engine_test.js index 41cf7a9c5c6..8b592037443 100644 --- a/packages/ember-application/tests/system/engine_test.js +++ b/packages/ember-application/tests/system/engine_test.js @@ -77,7 +77,7 @@ moduleFor('Ember.Engine', class extends TestCase { verifyRegistration(assert, engine, P`template:components/-default`); verifyRegistration(assert, engine, 'template:-outlet'); verifyInjection(assert, engine, 'view:-outlet', 'template', 'template:-outlet'); - verifyInjection(assert, engine, 'template', 'env', 'service:-glimmer-environment'); + verifyInjection(assert, engine, 'template', 'options', P`template-options:main`); assert.deepEqual(engine.registeredOptionsForType('helper'), { instantiate: false }, `optionsForType 'helper'`); } }); From bffc7e74e6461c2486df68d94724b0a5389205fc Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Mon, 8 Jan 2018 18:36:10 -0800 Subject: [PATCH 061/135] Fix bad merge --- packages/ember-glimmer/lib/syntax.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/ember-glimmer/lib/syntax.ts b/packages/ember-glimmer/lib/syntax.ts index 7012529fc87..dab8e5dc395 100644 --- a/packages/ember-glimmer/lib/syntax.ts +++ b/packages/ember-glimmer/lib/syntax.ts @@ -3,15 +3,15 @@ import { Option } from '@glimmer/util'; import { Core } from '@glimmer/wire-format'; import { ENV } from 'ember-environment'; import { OwnedTemplateMeta } from 'ember-views'; +import { EMBER_TEMPLATE_BLOCK_LET_HELPER } from 'ember/features'; import { textAreaMacro } from './syntax/-text-area'; import { inputMacro } from './syntax/input'; +import { blockLetMacro } from './syntax/let'; import { mountMacro } from './syntax/mount'; import { outletMacro } from './syntax/outlet'; import { renderMacro } from './syntax/render'; import { hashToArgs } from './syntax/utils'; -import { blockLetMacro } from './syntax/let'; import { wrapComponentClassAttribute } from './utils/bindings'; -import { EMBER_TEMPLATE_BLOCK_LET_HELPER } from 'ember/features'; function refineInlineSyntax(name: string, params: Option, hash: Option, builder: OpcodeBuilder): boolean { // assert(`You attempted to overwrite the built-in helper "${name}" which is not allowed. Please rename the helper.`, !(builder.resolver.resolver.builtInHelpers[name] && builder.resolver.resolver.owner.hasRegistration(`helper:${name}`))); @@ -70,14 +70,9 @@ export function populateMacros(macros: Macros) { inlines.add('input', inputMacro); inlines.add('textarea', textAreaMacro); inlines.addMissing(refineInlineSyntax); -<<<<<<< HEAD - // blocks.add('component', blockComponentMacro); -======= - blocks.add('component', blockComponentMacro); if (EMBER_TEMPLATE_BLOCK_LET_HELPER === true) { blocks.add('let', blockLetMacro); } ->>>>>>> origin/master blocks.addMissing(refineBlockSyntax); for (let i = 0; i < experimentalMacros.length; i++) { From cb47ca0651ca68e32f02b001905db313b67a9549 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Mon, 8 Jan 2018 19:06:01 -0800 Subject: [PATCH 062/135] Get some more input tests passing --- packages/ember-glimmer/lib/syntax/-text-area.ts | 2 +- packages/ember-glimmer/lib/syntax/input.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ember-glimmer/lib/syntax/-text-area.ts b/packages/ember-glimmer/lib/syntax/-text-area.ts index 5f62f320ecd..c7b8e4be6c7 100644 --- a/packages/ember-glimmer/lib/syntax/-text-area.ts +++ b/packages/ember-glimmer/lib/syntax/-text-area.ts @@ -8,6 +8,6 @@ import { hashToArgs } from './utils'; export function textAreaMacro(_name: string, params: any[], hash: any, builder: LazyOpcodeBuilder) { let definition = builder.resolver.lookupComponentDefinition('-text-area', builder.referrer); wrapComponentClassAttribute(hash); - builder.component.static(definition, [params, hashToArgs(hash), null, null]); + builder.component.static(definition!, [params, hashToArgs(hash), null, null]); return true; } diff --git a/packages/ember-glimmer/lib/syntax/input.ts b/packages/ember-glimmer/lib/syntax/input.ts index 3f85f6b5e5c..f1e23432cb2 100644 --- a/packages/ember-glimmer/lib/syntax/input.ts +++ b/packages/ember-glimmer/lib/syntax/input.ts @@ -7,12 +7,11 @@ import { } from '@glimmer/opcode-compiler'; import { assert } from 'ember-debug'; import { wrapComponentClassAttribute } from '../utils/bindings'; -import { dynamicComponentMacro } from './dynamic-component'; import { hashToArgs } from './utils'; function buildSyntax(type: string, params: any[], hash: any, builder: LazyOpcodeBuilder) { let definition = builder.resolver.lookupComponentDefinition(type, builder.referrer); - builder.component.static(definition, [params, hashToArgs(hash), null, null]); + builder.component.static(definition!, [params, hashToArgs(hash), null, null]); return true; } @@ -170,7 +169,8 @@ export function inputMacro(_name: string, params: any[], hash: any[], builder: a if (typeIndex > -1) { let typeArg = values[typeIndex]; if (Array.isArray(typeArg)) { - return dynamicComponentMacro(params, hash, null, null, builder); + throw new Error('TODO convert to component invoke'); + // return dynamicComponentMacro(params, hash, null, null, builder); } else if (typeArg === 'checkbox') { assert( '{{input type=\'checkbox\'}} does not support setting `value=someBooleanValue`; ' + From ae93c140533207e2043ec583cce9fb6d2260de30 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 9 Jan 2018 12:51:12 -0800 Subject: [PATCH 063/135] Add @glimmer/debug if present when building in development. --- ember-cli-build.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ember-cli-build.js b/ember-cli-build.js index bf3023deef2..dc183b604cc 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -36,12 +36,12 @@ const { rollupEmberMetal } = require('./broccoli/packages'); const SHOULD_ROLLUP = true; +const ENV = process.env.EMBER_ENV || 'development'; module.exports = function() { let loader = internalLoader(); let license = emberLicense(); let nodeModule = nodeModuleUtils(); - let ENV = process.env.EMBER_ENV || 'development'; let debugFeatures = toES5(emberFeaturesES()); let version = toES5(emberVersionES()); let emberTesting = emberPkgES('ember-testing'); @@ -310,11 +310,23 @@ module.exports = function() { }; function dependenciesES6() { + let glimmerEntries = ['@glimmer/node', '@glimmer/runtime']; + if (ENV === 'development') { + let hasGlimmerDebug = true; + try { + require('@glimmer/debug'); + } catch (e) { + hasGlimmerDebug = false; + } + if (hasGlimmerDebug) { + glimmerEntries.push('@glimmer/debug', '@glimmer/local-debug-flags'); + } + } return [ dagES(), routerES(), routeRecognizerES(), - ...glimmerTrees(['@glimmer/node', '@glimmer/runtime']), + ...glimmerTrees(glimmerEntries), ]; } From c5d0f9233b86ddd08394a1ddcd0f60f2b36f983c Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Tue, 9 Jan 2018 13:51:16 -0700 Subject: [PATCH 064/135] getComponentDefinition instrumentation --- .../lib/component-managers/curly.ts | 4 ++-- .../ember-glimmer/lib/components/link-to.ts | 2 +- packages/ember-glimmer/lib/resolver.ts | 19 +++++++++++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index c5815fff295..722290d0aeb 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -59,9 +59,9 @@ import { import { AttributeBinding, ClassNameBinding, + ColonClassNameBindingReference, IsVisibleBinding, - referenceForKey, - ColonClassNameBindingReference + referenceForKey } from '../utils/bindings'; import ComponentStateBucket, { Component } from '../utils/curly-component-state-bucket'; import { processComponentArgs } from '../utils/process-args'; diff --git a/packages/ember-glimmer/lib/components/link-to.ts b/packages/ember-glimmer/lib/components/link-to.ts index 7eb44740ad1..857b4b6b3bc 100644 --- a/packages/ember-glimmer/lib/components/link-to.ts +++ b/packages/ember-glimmer/lib/components/link-to.ts @@ -296,8 +296,8 @@ @public */ -import { DEBUG } from 'ember-env-flags'; import { assert, warn } from 'ember-debug'; +import { DEBUG } from 'ember-env-flags'; import { computed, flaggedInstrument, diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 3edb4ccb282..66220a05037 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -15,6 +15,7 @@ import { PartialDefinition } from '@glimmer/runtime'; import { privatize as P } from 'container'; +import { _instrumentStart } from 'ember-metal'; import { LookupOptions } from 'ember-utils'; import { lookupComponent, @@ -49,6 +50,10 @@ import { populateMacros } from './syntax'; import { OwnedTemplate } from './template'; import { ClassBasedHelperReference, SimpleHelperReference } from './utils/references'; +function instrumentationPayload(name: string) { + return { object: `component:${name}` }; +} + function makeOptions(moduleName: string) { return moduleName !== undefined ? { source: `template:${moduleName}`} : undefined; } @@ -232,8 +237,18 @@ export default class RuntimeResolver implements IRuntimeResolver; - - return (layout || component) ? new CurlyComponentDefinition(name, customManager, component || meta.owner.factoryFor(P`component:-default`), layoutHandle, layout) : null; + let definition = (layout || component) ? + new CurlyComponentDefinition( + name, + customManager, + component || meta.owner.factoryFor(P`component:-default`), + layoutHandle, + layout + ) : null; + + finalizer(); + return definition; } } From f69116d27e5bc5698c83e0d615ae8185ddd8b7c7 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 9 Jan 2018 13:29:31 -0800 Subject: [PATCH 065/135] Fix outlet manager getSelf() --- packages/ember-glimmer/lib/component-managers/outlet.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index 85065ddbcdf..2ee04c8b0d5 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -26,6 +26,7 @@ import RuntimeResolver from '../resolver'; import { OwnedTemplate, } from '../template'; +import { RootReference } from '../utils/references'; import { default as OutletView, OutletState } from '../views/outlet'; import AbstractManager from './abstract'; @@ -96,7 +97,12 @@ class OutletComponentManager extends AbstractManager Date: Tue, 9 Jan 2018 15:34:25 -0700 Subject: [PATCH 066/135] Fix style warning tests --- packages/ember-glimmer/lib/environment.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/ember-glimmer/lib/environment.ts b/packages/ember-glimmer/lib/environment.ts index 256825c2846..0a6f67ae14b 100644 --- a/packages/ember-glimmer/lib/environment.ts +++ b/packages/ember-glimmer/lib/environment.ts @@ -1,6 +1,3 @@ -import { - Simple, -} from '@glimmer/interfaces'; import { Reference, } from '@glimmer/reference'; @@ -8,6 +5,7 @@ import { DynamicAttributeFactory, Environment as GlimmerEnvironment, PrimitiveReference, + SafeString } from '@glimmer/runtime'; import { Destroyable, Opaque, @@ -36,6 +34,10 @@ import { } from 'ember/features'; import { OwnedTemplate } from './template'; +function isSafeString(value: Opaque): value is SafeString { + return typeof value === 'object' && value !== null && typeof (value as any).toHTML === 'function'; +} + export interface CompilerFactory { id: string; new (template: OwnedTemplate): any; @@ -217,7 +219,10 @@ export default class Environment extends GlimmerEnvironment { if (DEBUG) { class StyleAttributeManager implements DynamicAttributeFactory { - setAttribute(_dom: Environment, _element: Simple.Element, value: Opaque) { + + constructor() { } + + set(_dom: Environment, value: Opaque) { warn(constructStyleDeprecationMessage(value), (() => { if (value === null || value === undefined || isSafeString(value)) { return true; @@ -226,7 +231,7 @@ if (DEBUG) { })(), { id: 'ember-htmlbars.style-xss-warning' }); } - updateAttribute(_dom: Environment, _element: Element, value: Opaque) { + update(_dom: Environment, value: Opaque) { warn(constructStyleDeprecationMessage(value), (() => { if (value === null || value === undefined || isSafeString(value)) { return true; @@ -236,12 +241,11 @@ if (DEBUG) { } } - // let STYLE_ATTRIBUTE_MANANGER = new StyleAttributeManager(); Environment.prototype.attributeFor = function (element, attribute, isTrusting) { - // if (attribute === 'style' && !isTrusting) { - // return STYLE_ATTRIBUTE_MANANGER; - // } + if (attribute === 'style' && !isTrusting) { + return StyleAttributeManager; + } return GlimmerEnvironment.prototype.attributeFor.call(this, element, attribute, isTrusting); }; From 3a93fc84bfb586762cf8dc6db5666019aa465a20 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Tue, 9 Jan 2018 16:05:38 -0700 Subject: [PATCH 067/135] A better approach to the StyleAttributeManager --- packages/ember-glimmer/lib/environment.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/ember-glimmer/lib/environment.ts b/packages/ember-glimmer/lib/environment.ts index 0a6f67ae14b..216330e2578 100644 --- a/packages/ember-glimmer/lib/environment.ts +++ b/packages/ember-glimmer/lib/environment.ts @@ -2,10 +2,11 @@ import { Reference, } from '@glimmer/reference'; import { - DynamicAttributeFactory, + ElementBuilder, Environment as GlimmerEnvironment, PrimitiveReference, - SafeString + SafeString, + SimpleDynamicAttribute } from '@glimmer/runtime'; import { Destroyable, Opaque, @@ -218,30 +219,31 @@ export default class Environment extends GlimmerEnvironment { } if (DEBUG) { - class StyleAttributeManager implements DynamicAttributeFactory { + class StyleAttributeManager extends SimpleDynamicAttribute { - constructor() { } - - set(_dom: Environment, value: Opaque) { + set(dom: ElementBuilder, value: Opaque, _env: GlimmerEnvironment) { warn(constructStyleDeprecationMessage(value), (() => { if (value === null || value === undefined || isSafeString(value)) { return true; } return false; })(), { id: 'ember-htmlbars.style-xss-warning' }); + + super.set(dom, value, _env); } - update(_dom: Environment, value: Opaque) { + update(value: Opaque, _env: GlimmerEnvironment) { warn(constructStyleDeprecationMessage(value), (() => { if (value === null || value === undefined || isSafeString(value)) { return true; } return false; })(), { id: 'ember-htmlbars.style-xss-warning' }); + + super.update(value, _env); } } - Environment.prototype.attributeFor = function (element, attribute, isTrusting) { if (attribute === 'style' && !isTrusting) { return StyleAttributeManager; From 188631ab04d1f7a363c70bdf410068ff9bea3191 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 9 Jan 2018 15:04:13 -0800 Subject: [PATCH 068/135] Remove duplicate isHTMLSafe and pass all params in attributeFor --- packages/ember-glimmer/lib/environment.ts | 28 ++++++++-------------- packages/ember-glimmer/lib/utils/string.ts | 2 +- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/packages/ember-glimmer/lib/environment.ts b/packages/ember-glimmer/lib/environment.ts index 216330e2578..47a8fe4b641 100644 --- a/packages/ember-glimmer/lib/environment.ts +++ b/packages/ember-glimmer/lib/environment.ts @@ -5,8 +5,7 @@ import { ElementBuilder, Environment as GlimmerEnvironment, PrimitiveReference, - SafeString, - SimpleDynamicAttribute + SimpleDynamicAttribute, } from '@glimmer/runtime'; import { Destroyable, Opaque, @@ -25,6 +24,7 @@ import { RootPropertyReference, UpdatableReference, } from './utils/references'; +import { isHTMLSafe } from './utils/string'; import installPlatformSpecificProtocolForURL from './protocol-for-url'; @@ -35,10 +35,6 @@ import { } from 'ember/features'; import { OwnedTemplate } from './template'; -function isSafeString(value: Opaque): value is SafeString { - return typeof value === 'object' && value !== null && typeof (value as any).toHTML === 'function'; -} - export interface CompilerFactory { id: string; new (template: OwnedTemplate): any; @@ -220,35 +216,31 @@ export default class Environment extends GlimmerEnvironment { if (DEBUG) { class StyleAttributeManager extends SimpleDynamicAttribute { - - set(dom: ElementBuilder, value: Opaque, _env: GlimmerEnvironment) { + set(dom: ElementBuilder, value: Opaque, env: GlimmerEnvironment): void { warn(constructStyleDeprecationMessage(value), (() => { - if (value === null || value === undefined || isSafeString(value)) { + if (value === null || value === undefined || isHTMLSafe(value)) { return true; } return false; })(), { id: 'ember-htmlbars.style-xss-warning' }); - - super.set(dom, value, _env); + super.set(dom, value, env); } - - update(value: Opaque, _env: GlimmerEnvironment) { + update(value: Opaque, env: GlimmerEnvironment): void { warn(constructStyleDeprecationMessage(value), (() => { - if (value === null || value === undefined || isSafeString(value)) { + if (value === null || value === undefined || isHTMLSafe(value)) { return true; } return false; })(), { id: 'ember-htmlbars.style-xss-warning' }); - - super.update(value, _env); + super.update(value, env); } } - Environment.prototype.attributeFor = function (element, attribute, isTrusting) { + Environment.prototype.attributeFor = function (element, attribute: string, isTrusting: boolean, _namespace?) { if (attribute === 'style' && !isTrusting) { return StyleAttributeManager; } - return GlimmerEnvironment.prototype.attributeFor.call(this, element, attribute, isTrusting); + return GlimmerEnvironment.prototype.attributeFor.call(this, element, attribute, isTrusting, _namespace); }; } diff --git a/packages/ember-glimmer/lib/utils/string.ts b/packages/ember-glimmer/lib/utils/string.ts index 0f020ed778a..31e28cc0b4d 100644 --- a/packages/ember-glimmer/lib/utils/string.ts +++ b/packages/ember-glimmer/lib/utils/string.ts @@ -101,6 +101,6 @@ export function htmlSafe(str: string) { @return {Boolean} `true` if the string was decorated with `htmlSafe`, `false` otherwise. @public */ -export function isHTMLSafe(str: string | SafeString): str is SafeString { +export function isHTMLSafe(str: any | null | undefined): str is SafeString { return str !== null && typeof str === 'object' && typeof str.toHTML === 'function'; } From 38ae8fbe0b1c8b0fb26dab7e847744aeb3060928 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 9 Jan 2018 15:16:09 -0800 Subject: [PATCH 069/135] cleanup some type errors --- packages/ember-environment/lib/index.d.ts | 2 -- packages/ember-glimmer/lib/simple-dom.d.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/ember-environment/lib/index.d.ts b/packages/ember-environment/lib/index.d.ts index 49d3f1b5325..78b0d804287 100644 --- a/packages/ember-environment/lib/index.d.ts +++ b/packages/ember-environment/lib/index.d.ts @@ -11,5 +11,3 @@ export const environment: { export const ENV: { _ENABLE_RENDER_SUPPORT: boolean; }; - -export const ENV: any; \ No newline at end of file diff --git a/packages/ember-glimmer/lib/simple-dom.d.ts b/packages/ember-glimmer/lib/simple-dom.d.ts index b75dcd91bff..c608bc8f162 100644 --- a/packages/ember-glimmer/lib/simple-dom.d.ts +++ b/packages/ember-glimmer/lib/simple-dom.d.ts @@ -1,4 +1,4 @@ declare module "simple-dom" { - import { Simple } from "@glimmer/runtime"; + import { Simple } from "@glimmer/interfaces"; export interface Document extends Simple.Document {} } From d7d9540c137bb488ab0b08b3c1fe25192c6317b9 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 9 Jan 2018 15:37:15 -0800 Subject: [PATCH 070/135] Some small cleanup ahead of fixing outlet stability --- packages/ember-glimmer/lib/renderer.ts | 19 +++++++++---------- .../ember-glimmer/lib/utils/references.ts | 4 ++-- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/ember-glimmer/lib/renderer.ts b/packages/ember-glimmer/lib/renderer.ts index 34df0928f5e..06221aa7e6f 100644 --- a/packages/ember-glimmer/lib/renderer.ts +++ b/packages/ember-glimmer/lib/renderer.ts @@ -2,7 +2,6 @@ import { Option, Simple } from '@glimmer/interfaces'; import { CURRENT_TAG, VersionedPathReference } from '@glimmer/reference'; import { clientBuilder, - ComponentDefinition, CurriedComponentDefinition, curry, DynamicScope as GlimmerDynamicScope, @@ -30,7 +29,7 @@ import { RootComponentDefinition } from './component-managers/root'; import Environment from './environment'; import { OwnedTemplate } from './template'; import { Component } from './utils/curly-component-state-bucket'; -import { RootReference } from './utils/references'; +import { UnboundReference } from './utils/references'; import OutletView, { OutletState, RootOutletStateReference } from './views/outlet'; const { backburner } = run; @@ -70,7 +69,7 @@ export class DynamicScope implements GlimmerDynamicScope { class RootState { public id: string; public env: Environment; - public root: Opaque; + public root: Component | OutletView; public result: RenderResult | undefined; public shouldReflush: boolean; public destroyed: boolean; @@ -80,7 +79,7 @@ class RootState { public render: () => void; constructor( - root: Opaque, + root: Component | OutletView, env: Environment, template: OwnedTemplate, self: VersionedPathReference, @@ -129,7 +128,7 @@ class RootState { this.destroyed = true; this.env = undefined as any; - this.root = null; + this.root = null as any; this.result = undefined; this.render = undefined as any; @@ -281,11 +280,11 @@ export abstract class Renderer { } _appendDefinition( - root: Opaque, - definition: ComponentDefinition | CurriedComponentDefinition, + root: OutletView | Component, + definition: CurriedComponentDefinition, target: Simple.Element, outletStateReference?: RootOutletStateReference) { - let self = new RootReference(definition); + let self = new UnboundReference(definition); let dynamicScope = new DynamicScope(null, outletStateReference || NULL_REFERENCE, outletStateReference); let rootState = new RootState(root, this._env, this._rootTemplate, self, target, dynamicScope); @@ -296,13 +295,13 @@ export abstract class Renderer { this._scheduleRevalidate(); } - register(view: Opaque) { + register(view: any) { let id = getViewId(view); assert('Attempted to register a view with an id already in use: ' + id, !this._viewRegistry[id]); this._viewRegistry[id] = view; } - unregister(view: Opaque) { + unregister(view: any) { delete this._viewRegistry[getViewId(view)]; } diff --git a/packages/ember-glimmer/lib/utils/references.ts b/packages/ember-glimmer/lib/utils/references.ts index b8acdacabd7..52f73fbab92 100644 --- a/packages/ember-glimmer/lib/utils/references.ts +++ b/packages/ember-glimmer/lib/utils/references.ts @@ -444,8 +444,8 @@ export class InternalHelperReference extends CachedReference { } // @implements PathReference -export class UnboundReference extends ConstReference { - static create(value: any) { +export class UnboundReference extends ConstReference { + static create(value: T) { if (typeof value === 'object' && value !== null) { return new UnboundReference(value); } else { From 660198c3c55ddafde639ed310e1a6ca866031ecf Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 9 Jan 2018 16:29:54 -0800 Subject: [PATCH 071/135] Fix typing issues split old builder.dynamic.component into builder.dynamicComponent with a helper expression. --- packages/ember-glimmer/lib/helpers/action.ts | 2 +- .../ember-glimmer/lib/helpers/component.ts | 282 ------------------ packages/ember-glimmer/lib/resolver.ts | 4 - packages/ember-glimmer/lib/syntax/input.ts | 18 +- packages/ember-glimmer/lib/syntax/mount.ts | 5 +- packages/ember-glimmer/lib/syntax/render.ts | 24 +- 6 files changed, 25 insertions(+), 310 deletions(-) delete mode 100644 packages/ember-glimmer/lib/helpers/component.ts diff --git a/packages/ember-glimmer/lib/helpers/action.ts b/packages/ember-glimmer/lib/helpers/action.ts index 4b4e079418a..cc366f45572 100644 --- a/packages/ember-glimmer/lib/helpers/action.ts +++ b/packages/ember-glimmer/lib/helpers/action.ts @@ -272,7 +272,7 @@ export const ACTION = symbol('ACTION'); @for Ember.Templates.helpers @public */ -export default function(_vm: VM, args: Arguments): UnboundReference { +export default function(_vm: VM, args: Arguments): UnboundReference { let { named, positional } = args; let capturedArgs = positional.capture(); diff --git a/packages/ember-glimmer/lib/helpers/component.ts b/packages/ember-glimmer/lib/helpers/component.ts deleted file mode 100644 index c82de652f17..00000000000 --- a/packages/ember-glimmer/lib/helpers/component.ts +++ /dev/null @@ -1,282 +0,0 @@ -/** - @module ember -*/ -import { - Arguments, - CapturedArguments, - Environment, - VM -} from '@glimmer/runtime'; -import { assert } from 'ember-debug'; -import { assign } from 'ember-utils'; -import { - CurlyComponentDefinition, - validatePositionalParameters, -} from '../component-managers/curly'; -import { CachedReference } from '../utils/references'; - -/** - The `{{component}}` helper lets you add instances of `Component` to a - template. See [Component](/api/classes/Ember.Component.html) for - additional information on how a `Component` functions. - `{{component}}`'s primary use is for cases where you want to dynamically - change which type of component is rendered as the state of your application - changes. This helper has three modes: inline, block, and nested. - - ### Inline Form - - Given the following template: - - ```app/application.hbs - {{component infographicComponentName}} - ``` - - And the following application code: - - ```app/controllers/application.js - import Controller from '@ember/controller'; - import { computed } from '@ember/object'; - - export default Controller.extend({ - infographicComponentName: computed('isMarketOpen', { - get() { - if (this.get('isMarketOpen')) { - return 'live-updating-chart'; - } else { - return 'market-close-summary'; - } - } - }) - }); - ``` - - The `live-updating-chart` component will be appended when `isMarketOpen` is - `true`, and the `market-close-summary` component will be appended when - `isMarketOpen` is `false`. If the value changes while the app is running, - the component will be automatically swapped out accordingly. - Note: You should not use this helper when you are consistently rendering the same - component. In that case, use standard component syntax, for example: - - ```app/templates/application.hbs - {{live-updating-chart}} - ``` - - ### Block Form - - Using the block form of this helper is similar to using the block form - of a component. Given the following application template: - - ```app/templates/application.hbs - {{#component infographicComponentName}} - Last update: {{lastUpdateTimestamp}} - {{/component}} - ``` - - The following controller code: - - ```app/controllers/application.js - import Controller from '@ember/controller'; - import { computed } from '@ember/object'; - - export default Controller.extend({ - lastUpdateTimestamp: computed(function() { - return new Date(); - }), - - infographicComponentName: computed('isMarketOpen', { - get() { - if (this.get('isMarketOpen')) { - return 'live-updating-chart'; - } else { - return 'market-close-summary'; - } - } - }) - }); - ``` - - And the following component template: - - ```app/templates/components/live-updating-chart.hbs - {{! chart }} - {{yield}} - ``` - - The `Last Update: {{lastUpdateTimestamp}}` will be rendered in place of the `{{yield}}`. - - ### Nested Usage - - The `component` helper can be used to package a component path with initial attrs. - The included attrs can then be merged during the final invocation. - For example, given a `person-form` component with the following template: - - ```app/templates/components/person-form.hbs - {{yield (hash - nameInput=(component "my-input-component" value=model.name placeholder="First Name") - )}} - ``` - - When yielding the component via the `hash` helper, the component is invoked directly. - See the following snippet: - - ``` - {{#person-form as |form|}} - {{form.nameInput placeholder="Username"}} - {{/person-form}} - ``` - - Which outputs an input whose value is already bound to `model.name` and `placeholder` - is "Username". - - When yielding the component without the hash helper use the `component` helper. - For example, below is a `full-name` component template: - - ```handlebars - {{yield (component "my-input-component" value=model.name placeholder="Name")}} - ``` - - ``` - {{#full-name as |field|}} - {{component field placeholder="Full name"}} - {{/full-name}} - ``` - - @method component - @since 1.11.0 - @for Ember.Templates.helpers - @public -*/ -export class ClosureComponentReference extends CachedReference { - static create(args: CapturedArguments, meta: any, env: Environment) { - return new ClosureComponentReference(args, meta, env); - } - - public defRef: any; - public tag: any; - public args: CapturedArguments; - public meta: any; - public env: Environment; - public lastDefinition: any; - public lastName: string | undefined; - - constructor(args: CapturedArguments, meta: any, env: Environment) { - super(); - - let firstArg = args.positional.at(0); - this.defRef = firstArg; - this.tag = firstArg.tag; - this.args = args; - this.meta = meta; - this.env = env; - this.lastDefinition = undefined; - this.lastName = undefined; - } - - compute() { - // TODO: Figure out how to extract this because it's nearly identical to - // DynamicComponentReference::compute(). The only differences besides - // currying are in the assertion messages. - let { args, defRef, env, meta, lastDefinition, lastName } = this; - let nameOrDef = defRef.value(); - let definition: CurlyComponentDefinition; - - if (nameOrDef && nameOrDef === lastName) { - return lastDefinition; - } - - this.lastName = nameOrDef; - - if (typeof nameOrDef === 'string') { - // tslint:disable-next-line:max-line-length - assert('You cannot use the input helper as a contextual helper. Please extend TextField or Checkbox to use it as a contextual component.', nameOrDef !== 'input'); - // tslint:disable-next-line:max-line-length - assert('You cannot use the textarea helper as a contextual helper. Please extend TextArea to use it as a contextual component.', nameOrDef !== 'textarea'); - definition = env.getComponentDefinition(nameOrDef, meta); - // tslint:disable-next-line:max-line-length - assert(`The component helper cannot be used without a valid component name. You used "${nameOrDef}" via (component "${nameOrDef}")`, !!definition); - } else if (isComponentDefinition(nameOrDef)) { - definition = nameOrDef; - } else { - assert( - `You cannot create a component from ${nameOrDef} using the {{component}} helper`, - nameOrDef, - ); - return null; - } - - let newDef = createCurriedDefinition(definition, args); - - this.lastDefinition = newDef; - - return newDef; - } -} - -function createCurriedDefinition(definition: CurlyComponentDefinition, args: CapturedArguments) { - let curriedArgs = curryArgs(definition, args); - - return new CurlyComponentDefinition( - definition.name, - definition.manager, - definition.ComponentClass, - definition.state.handle, - definition.template, - curriedArgs, - ); -} - -function curryArgs(definition: CurlyComponentDefinition, newArgs: CapturedArguments): any { - let { args, ComponentClass } = definition; - let positionalParams = ComponentClass.class.positionalParams; - - // The args being passed in are from the (component ...) invocation, - // so the first positional argument is actually the name or component - // definition. It needs to be dropped in order for any actual positional - // args to coincide with the ComponentClass's positionParams. - - // For "normal" curly components this slicing is done at the syntax layer, - // but we don't have that luxury here. - - let [, ...slicedPositionalArgs] = newArgs.positional.references; - - if (positionalParams && slicedPositionalArgs.length) { - validatePositionalParameters(newArgs.named, slicedPositionalArgs, positionalParams); - } - - let isRest = typeof positionalParams === 'string'; - - // For non-rest position params, we need to perform the position -> name mapping - // at each layer to avoid a collision later when the args are used to construct - // the component instance (inside of processArgs(), inside of create()). - let positionalToNamedParams = {}; - - if (!isRest && positionalParams.length > 0) { - let limit = Math.min(positionalParams.length, slicedPositionalArgs.length); - - for (let i = 0; i < limit; i++) { - let name = positionalParams[i]; - positionalToNamedParams[name] = slicedPositionalArgs[i]; - } - - slicedPositionalArgs.length = 0; // Throw them away since you're merged in. - } - - // args (aka 'oldArgs') may be undefined or simply be empty args, so - // we need to fall back to an empty array or object. - let oldNamed = args && args.named || {}; - let oldPositional = args && args.positional || []; - - // Merge positional arrays - let positional = new Array(Math.max(oldPositional.length, slicedPositionalArgs.length)); - positional.splice(0, oldPositional.length, ...oldPositional); - positional.splice(0, slicedPositionalArgs.length, ...slicedPositionalArgs); - - // Merge named maps - let named = assign({}, oldNamed, positionalToNamedParams, newArgs.named.map); - - return { positional, named }; -} - -export default function(vm: VM, args: Arguments, meta: any) { - return ClosureComponentReference.create(args.capture(), meta, vm.env); -} diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 66220a05037..6b5f36126de 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -30,7 +30,6 @@ import { default as htmlSafeHelper } from './helpers/-html-safe'; import { default as inputTypeHelper } from './helpers/-input-type'; import { default as normalizeClassHelper } from './helpers/-normalize-class'; import { default as action } from './helpers/action'; -import { default as componentHelper } from './helpers/component'; import { default as concat } from './helpers/concat'; import { default as eachIn } from './helpers/each-in'; import { default as get } from './helpers/get'; @@ -179,9 +178,6 @@ export default class RuntimeResolver implements IRuntimeResolver { - if (name === 'component') { - return (vm, args) => componentHelper(vm, args, meta); - } const helper = this.builtInHelpers[name]; if (helper !== undefined) { diff --git a/packages/ember-glimmer/lib/syntax/input.ts b/packages/ember-glimmer/lib/syntax/input.ts index f1e23432cb2..d0dfc7b8741 100644 --- a/packages/ember-glimmer/lib/syntax/input.ts +++ b/packages/ember-glimmer/lib/syntax/input.ts @@ -1,15 +1,15 @@ /** @module ember */ -import { - LazyOpcodeBuilder, - TemplateMeta -} from '@glimmer/opcode-compiler'; +import { Option } from '@glimmer/interfaces'; +import { OpcodeBuilder } from '@glimmer/opcode-compiler'; +import * as WireFormat from '@glimmer/wire-format'; import { assert } from 'ember-debug'; +import { OwnedTemplateMeta } from 'ember-views'; import { wrapComponentClassAttribute } from '../utils/bindings'; import { hashToArgs } from './utils'; -function buildSyntax(type: string, params: any[], hash: any, builder: LazyOpcodeBuilder) { +function buildSyntax(type: string, params: any[], hash: any, builder: OpcodeBuilder) { let definition = builder.resolver.lookupComponentDefinition(type, builder.referrer); builder.component.static(definition!, [params, hashToArgs(hash), null, null]); return true; @@ -151,9 +151,9 @@ function buildSyntax(type: string, params: any[], hash: any, builder: LazyOpcode @public */ -export function inputMacro(_name: string, params: any[], hash: any[], builder: any) { - let keys; - let values; +export function inputMacro(_name: string, params: Option, hash: Option, builder: OpcodeBuilder) { + let keys: WireFormat.Core.Expression[] | undefined; + let values: WireFormat.Core.Expression[] | undefined; let typeIndex = -1; let valueIndex = -1; @@ -167,7 +167,7 @@ export function inputMacro(_name: string, params: any[], hash: any[], builder: a if (!params) { params = []; } if (typeIndex > -1) { - let typeArg = values[typeIndex]; + let typeArg = values![typeIndex]; if (Array.isArray(typeArg)) { throw new Error('TODO convert to component invoke'); // return dynamicComponentMacro(params, hash, null, null, builder); diff --git a/packages/ember-glimmer/lib/syntax/mount.ts b/packages/ember-glimmer/lib/syntax/mount.ts index b061f45f99e..102b886ce23 100644 --- a/packages/ember-glimmer/lib/syntax/mount.ts +++ b/packages/ember-glimmer/lib/syntax/mount.ts @@ -13,9 +13,8 @@ import { OwnedTemplateMeta } from 'ember-views'; import { EMBER_ENGINES_MOUNT_PARAMS } from 'ember/features'; import { MountDefinition } from '../component-managers/mount'; import Environment from '../environment'; -import { hashToArgs } from './utils'; -function dynamicEngineFor(vm: VM, args: Arguments, meta: any) { +export function mountHelper(vm: VM, args: Arguments, meta: any) { let env = vm.env; let nameRef = args.positional.at(0); @@ -76,7 +75,7 @@ export function mountMacro(_name: string, params: Option ); } - let expr: WireFormat.Expressions.Helper = [WireFormat.Ops.Helper, 'mount', params || [], hash]; + let expr: WireFormat.Expressions.Helper = [WireFormat.Ops.Helper, '-mount', params || [], hash]; builder.dynamicComponent(expr, [], null, false, null, null); return true; } diff --git a/packages/ember-glimmer/lib/syntax/render.ts b/packages/ember-glimmer/lib/syntax/render.ts index dec5022c922..c83b3c9bea5 100644 --- a/packages/ember-glimmer/lib/syntax/render.ts +++ b/packages/ember-glimmer/lib/syntax/render.ts @@ -4,12 +4,16 @@ Remove after 3.4 once _ENABLE_RENDER_SUPPORT flag is no longer needed. */ +import { Option } from '@glimmer/interfaces'; +import { OpcodeBuilder } from '@glimmer/opcode-compiler'; import { ConstReference, isConst } from '@glimmer/reference'; import { Arguments, VM, } from '@glimmer/runtime'; +import * as WireFormat from '@glimmer/wire-format'; import { assert } from 'ember-debug'; +import { OwnedTemplateMeta } from 'ember-views'; import { NON_SINGLETON_RENDER_MANAGER, RenderDefinition, @@ -17,9 +21,8 @@ import { } from '../component-managers/render'; import Environment from '../environment'; import { OwnedTemplate } from '../template'; -import { hashToArgs } from './utils'; -function makeComponentDefinition(vm: VM, args: Arguments) { +export function makeComponentDefinition(vm: VM, args: Arguments) { let env = vm.env as Environment; let nameRef = args.positional.at(0); @@ -52,9 +55,9 @@ function makeComponentDefinition(vm: VM, args: Arguments) { } if (args.positional.length === 1) { - return new ConstReference(new RenderDefinition(controllerName, template, env, SINGLETON_RENDER_MANAGER)); + return new ConstReference(new RenderDefinition(controllerName, template!, env, SINGLETON_RENDER_MANAGER)); } else { - return new ConstReference(new RenderDefinition(controllerName, template, env, NON_SINGLETON_RENDER_MANAGER)); + return new ConstReference(new RenderDefinition(controllerName, template!, env, NON_SINGLETON_RENDER_MANAGER)); } } @@ -130,12 +133,11 @@ function makeComponentDefinition(vm: VM, args: Arguments) { @public @deprecated Use a component instead */ -export function renderMacro(_name: string, params: any[], hash: any[], builder: any) { - if (!params) { - params = []; - } - let definitionArgs = [params.slice(0), hash, null, null]; - let args = [params.slice(1), hashToArgs(hash), null, null]; - builder.component.dynamic(definitionArgs, makeComponentDefinition, args); +export function renderMacro(_name: string, params: Option, hash: Option, builder: OpcodeBuilder) { + // TODO needs makeComponentDefinition a helper that returns a curried definition + // TODO not sure all args are for definition or component + // likely the controller name should be a arg to create? + let expr: WireFormat.Expressions.Helper = [WireFormat.Ops.Helper, '-render', params || [], hash]; + builder.dynamicComponent(expr, null, null, false, null, null); return true; } From d3c2b332e6efef9a18d4c69ef1282bf5a5815553 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 9 Jan 2018 17:07:10 -0800 Subject: [PATCH 072/135] Fix let syntax --- packages/ember-glimmer/lib/syntax/let.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/ember-glimmer/lib/syntax/let.ts b/packages/ember-glimmer/lib/syntax/let.ts index a03d6cab11c..feb98036918 100644 --- a/packages/ember-glimmer/lib/syntax/let.ts +++ b/packages/ember-glimmer/lib/syntax/let.ts @@ -1,4 +1,7 @@ -import { compileList } from "@glimmer/runtime"; +import { Option } from '@glimmer/interfaces'; +import { OpcodeBuilder, CompilableBlock } from '@glimmer/opcode-compiler'; +import * as WireFormat from '@glimmer/wire-format'; +import { OwnedTemplateMeta } from 'ember-views'; /** @module ember @@ -38,7 +41,14 @@ import { compileList } from "@glimmer/runtime"; @for Ember.Templates.helpers @public */ -export function blockLetMacro(params: any, _hash: any, _default: any, _inverse: any, builder: any) { - compileList(params, builder); - builder.invokeStatic(_default, params.length); +export function blockLetMacro(_name: string, params: WireFormat.Core.Params, _hash: WireFormat.Core.Hash, template: Option, _inverse: Option, builder: OpcodeBuilder) { + if (template !== null) { + if (params !== null) { + builder.compileParams(params); + builder.invokeStaticBlock(template, params.length); + } else { + builder.invokeStatic(template); + } + } + return true; } From ecf32d205f5fbee73f703a7a3aaadf30bb360092 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 9 Jan 2018 17:35:25 -0800 Subject: [PATCH 073/135] This isn't used and built in --- .../lib/syntax/dynamic-component.ts | 72 ------------------- 1 file changed, 72 deletions(-) delete mode 100644 packages/ember-glimmer/lib/syntax/dynamic-component.ts diff --git a/packages/ember-glimmer/lib/syntax/dynamic-component.ts b/packages/ember-glimmer/lib/syntax/dynamic-component.ts deleted file mode 100644 index ca5643759e3..00000000000 --- a/packages/ember-glimmer/lib/syntax/dynamic-component.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { - Arguments, - Environment, - isComponentDefinition, - VM -} from '@glimmer/runtime'; -import { assert } from 'ember-debug'; -import { hashToArgs } from './utils'; - -function dynamicComponentFor(vm: VM, args: Arguments, meta: any) { - let env = vm.env; - let nameRef = args.positional.at(0); - - return new DynamicComponentReference({ nameRef, env, meta, args: null }); -} - -export function dynamicComponentMacro(params: any[], hash: any, _default: any, _inverse: any, builder: any) { - let definitionArgs = [params.slice(0, 1), null, null, null]; - let args = [params.slice(1), hashToArgs(hash), null, null]; - builder.component.dynamic(definitionArgs, dynamicComponentFor, args); - return true; -} - -export function blockComponentMacro(params: any[], hash: any, _default: any, inverse: any, builder: any) { - let definitionArgs = [params.slice(0, 1), null, null, null]; - let args = [params.slice(1), hashToArgs(hash), _default, inverse]; - builder.component.dynamic(definitionArgs, dynamicComponentFor, args); - return true; -} - -export function inlineComponentMacro(_name: string, params: any[], hash: any, builder: any) { - let definitionArgs = [params.slice(0, 1), null, null, null]; - let args = [params.slice(1), hashToArgs(hash), null, null]; - builder.component.dynamic(definitionArgs, dynamicComponentFor, args); - return true; -} - -class DynamicComponentReference { - public tag: any; - public nameRef: any; - public env: Environment; - public meta: any; - public args: Arguments; - - constructor({ nameRef, env, meta, args }: any) { - this.tag = nameRef.tag; - this.nameRef = nameRef; - this.env = env; - this.meta = meta; - this.args = args; - } - - value() { - let { env, nameRef, meta } = this; - let nameOrDef = nameRef.value(); - - if (typeof nameOrDef === 'string') { - let definition = env.getComponentDefinition(nameOrDef, meta); - - // tslint:disable-next-line:max-line-length - assert(`Could not find component named "${nameOrDef}" (no component or template with that name was found)`, !!definition); - - return definition; - } else if (isComponentDefinition(nameOrDef)) { - return nameOrDef; - } else { - return null; - } - } - - get() { /* NOOP */ } -} From 22cd04fa7fa184ea0c1f680054174bbefa43d5c7 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Wed, 10 Jan 2018 10:09:25 -0800 Subject: [PATCH 074/135] fix let macro signature --- packages/ember-glimmer/lib/syntax/let.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ember-glimmer/lib/syntax/let.ts b/packages/ember-glimmer/lib/syntax/let.ts index feb98036918..bd02002cb5b 100644 --- a/packages/ember-glimmer/lib/syntax/let.ts +++ b/packages/ember-glimmer/lib/syntax/let.ts @@ -1,5 +1,5 @@ import { Option } from '@glimmer/interfaces'; -import { OpcodeBuilder, CompilableBlock } from '@glimmer/opcode-compiler'; +import { CompilableBlock, OpcodeBuilder } from '@glimmer/opcode-compiler'; import * as WireFormat from '@glimmer/wire-format'; import { OwnedTemplateMeta } from 'ember-views'; @@ -41,7 +41,7 @@ import { OwnedTemplateMeta } from 'ember-views'; @for Ember.Templates.helpers @public */ -export function blockLetMacro(_name: string, params: WireFormat.Core.Params, _hash: WireFormat.Core.Hash, template: Option, _inverse: Option, builder: OpcodeBuilder) { +export function blockLetMacro(params: WireFormat.Core.Params, _hash: WireFormat.Core.Hash, template: Option, _inverse: Option, builder: OpcodeBuilder) { if (template !== null) { if (params !== null) { builder.compileParams(params); From dd76e62bc9a5dc234269d8b641fbb8bb15b049d6 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 10 Jan 2018 11:17:09 -0700 Subject: [PATCH 075/135] Fix custom helper tests --- packages/ember-glimmer/lib/resolver.ts | 11 +++++++++-- packages/ember-glimmer/lib/syntax.ts | 15 +++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 6b5f36126de..96830b972dc 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -164,6 +164,14 @@ export default class RuntimeResolver implements IRuntimeResolver { diff --git a/packages/ember-glimmer/lib/syntax.ts b/packages/ember-glimmer/lib/syntax.ts index dab8e5dc395..ceca5bfce0b 100644 --- a/packages/ember-glimmer/lib/syntax.ts +++ b/packages/ember-glimmer/lib/syntax.ts @@ -1,6 +1,7 @@ import { CompilableBlock, Macros, OpcodeBuilder } from '@glimmer/opcode-compiler'; import { Option } from '@glimmer/util'; import { Core } from '@glimmer/wire-format'; +import { assert } from 'ember-debug'; import { ENV } from 'ember-environment'; import { OwnedTemplateMeta } from 'ember-views'; import { EMBER_TEMPLATE_BLOCK_LET_HELPER } from 'ember/features'; @@ -14,7 +15,14 @@ import { hashToArgs } from './syntax/utils'; import { wrapComponentClassAttribute } from './utils/bindings'; function refineInlineSyntax(name: string, params: Option, hash: Option, builder: OpcodeBuilder): boolean { - // assert(`You attempted to overwrite the built-in helper "${name}" which is not allowed. Please rename the helper.`, !(builder.resolver.resolver.builtInHelpers[name] && builder.resolver.resolver.owner.hasRegistration(`helper:${name}`))); + console.log('fail'); + assert( + `You attempted to overwrite the built-in helper "${name}" which is not allowed. Please rename the helper.`, + !( + builder.resolver.resolver.builtInHelpers[name] && + builder.referrer.owner.hasRegistration(`helper:${name}`) + ) + ); if (name.indexOf('-') === -1) { return false; } @@ -44,7 +52,10 @@ function refineBlockSyntax(name: string, params: Core.Params, hash: Core.Hash, t // assert(`A component or helper named "${name}" could not be found`, builder.resolver.hasHelper(name, builder.referrer)); - // assert(`Helpers may not be used in the block form, for example {{#${name}}}{{/${name}}}. Please use a component, or alternatively use the helper in combination with a built-in Ember helper, for example {{#if (${name})}}{{/if}}.`, !builder.env.hasHelper(name, meta)); + assert( + `Helpers may not be used in the block form, for example {{#${name}}}{{/${name}}}. Please use a component, or alternatively use the helper in combination with a built-in Ember helper, for example {{#if (${name})}}{{/if}}.`, + !builder.resolver.resolver.hasHelper(name, builder.referrer) + ); return false; } From 240dc67e4076818c6baa36f906216639f5b9b538 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Wed, 10 Jan 2018 10:20:52 -0800 Subject: [PATCH 076/135] there are checks in opcode if the handle is falsy so reserve index 0 --- packages/ember-glimmer/lib/resolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 96830b972dc..084301f2758 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -95,7 +95,7 @@ export default class RuntimeResolver implements IRuntimeResolver(); private builtInHelpers: { From 2f135f97081443881bd063cd26ace65ab9f94a6e Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 10 Jan 2018 11:34:50 -0700 Subject: [PATCH 077/135] Remove hasHelper method used only in assertion --- packages/ember-glimmer/lib/resolver.ts | 8 -------- packages/ember-glimmer/lib/syntax.ts | 11 +++++++++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 084301f2758..5952da81a81 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -164,14 +164,6 @@ export default class RuntimeResolver implements IRuntimeResolver, hash: Option, builder: OpcodeBuilder): boolean { - console.log('fail'); assert( `You attempted to overwrite the built-in helper "${name}" which is not allowed. Please rename the helper.`, !( @@ -54,7 +53,15 @@ function refineBlockSyntax(name: string, params: Core.Params, hash: Core.Hash, t assert( `Helpers may not be used in the block form, for example {{#${name}}}{{/${name}}}. Please use a component, or alternatively use the helper in combination with a built-in Ember helper, for example {{#if (${name})}}{{/if}}.`, - !builder.resolver.resolver.hasHelper(name, builder.referrer) + !(() => { + const { resolver } = builder.resolver; + const { owner, moduleName } = builder.referrer; + if (name === 'component' || resolver.builtInHelpers[name]) { + return true; + } + let options = { source: `template:${moduleName}` }; + return owner.hasRegistration(`helper:${name}`, options) || owner.hasRegistration(`helper:${name}`); + })() ); return false; From 75f76f8d14f61dfeff72e30a6ad05019cc67d403 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 10 Jan 2018 14:21:15 -0700 Subject: [PATCH 078/135] normalizeTextValue is important Good thing we have tests --- packages/ember-glimmer/lib/helpers/concat.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/helpers/concat.ts b/packages/ember-glimmer/lib/helpers/concat.ts index 49af7a5f4cf..e779e369082 100644 --- a/packages/ember-glimmer/lib/helpers/concat.ts +++ b/packages/ember-glimmer/lib/helpers/concat.ts @@ -5,6 +5,17 @@ import { } from '@glimmer/runtime'; import { InternalHelperReference } from '../utils/references'; +const isEmpty = (value: any): boolean => { + return value === null || value === undefined || typeof value.toString !== 'function'; +}; + +const normalizeTextValue = (value: any): string => { + if (isEmpty(value)) { + return ''; + } + return String(value); +}; + /** @module ember */ @@ -26,7 +37,7 @@ import { InternalHelperReference } from '../utils/references'; @since 1.13.0 */ function concat({ positional }: CapturedArguments) { - return positional.value().join(''); + return positional.value().map(normalizeTextValue).join(''); } export default function(_vm: VM, args: Arguments) { From f3ed85359760121ce71ab8f61d9167857f4b24bc Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 10 Jan 2018 15:40:44 -0700 Subject: [PATCH 079/135] Add the rest of the tests from #15287 --- .../components/contextual-components-test.js | 72 ++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/packages/ember-glimmer/tests/integration/components/contextual-components-test.js b/packages/ember-glimmer/tests/integration/components/contextual-components-test.js index 6c868b2fde5..36fcb5c5a4a 100644 --- a/packages/ember-glimmer/tests/integration/components/contextual-components-test.js +++ b/packages/ember-glimmer/tests/integration/components/contextual-components-test.js @@ -369,6 +369,76 @@ moduleFor('Components test: contextual components', class extends RenderingTest this.assertText('Hodi Sigmundur 33'); } + ['@test nested components with positional params at middle layer are partially overwriten by hash parameters']() { + this.registerComponent('-looked-up', { + ComponentClass: Component.extend().reopenClass({ + positionalParams: ['greeting', 'name', 'age'] + }), + + template: '{{greeting}} {{name}} {{age}}' + }); + + this.render(strip` + {{#with (component "-looked-up" greeting="Hola" name="Dolores" age=33) as |first|}} + {{#with (component first "Hej" "Sigmundur") as |second|}} + {{component second greeting=model.greeting}} + {{/with}} + {{/with}}`, { + model: { + greeting: 'Hodi' + } + }); + + this.assertText('Hodi Sigmundur 33'); + + this.runTask(() => this.rerender()); + + this.assertText('Hodi Sigmundur 33'); + + this.runTask(() => this.context.set('model.greeting', 'Kaixo')); + + this.assertText('Kaixo Sigmundur 33'); + + this.runTask(() => this.context.set('model', { greeting: 'Hodi' })); + + this.assertText('Hodi Sigmundur 33'); + } + + ['@test nested components with positional params at invocation override earlier hash parameters']() { + this.registerComponent('-looked-up', { + ComponentClass: Component.extend().reopenClass({ + positionalParams: ['greeting', 'name', 'age'] + }), + + template: '{{greeting}} {{name}} {{age}}' + }); + + this.render(strip` + {{#with (component "-looked-up" greeting="Hola" name="Dolores" age=33) as |first|}} + {{#with (component first greeting="Hej" name="Sigmundur") as |second|}} + {{component second model.greeting}} + {{/with}} + {{/with}}`, { + model: { + greeting: 'Hodi' + } + }); + + this.assertText('Hodi Sigmundur 33'); + + this.runTask(() => this.rerender()); + + this.assertText('Hodi Sigmundur 33'); + + this.runTask(() => this.context.set('model.greeting', 'Kaixo')); + + this.assertText('Kaixo Sigmundur 33'); + + this.runTask(() => this.context.set('model', { greeting: 'Hodi' })); + + this.assertText('Hodi Sigmundur 33'); + } + ['@test nested components overwrite hash parameters']() { this.registerComponent('-looked-up', { template: '{{greeting}} {{name}} {{age}}' @@ -502,7 +572,7 @@ moduleFor('Components test: contextual components', class extends RenderingTest }, 'You cannot specify both a positional param (at position 0) and the hash argument `name`.'); } - ['@test conflicting positional and hash parameters raise and assertion if in the same component context with prior curried positional params']() { + ['@test conflicting positional and hash parameters raise an assertion if in the same component context with prior curried positional params']() { this.registerComponent('-looked-up', { ComponentClass: Component.extend().reopenClass({ positionalParams: ['name'] From 129ee6487769bbd5c2bfd3864014588928f78844 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 10 Jan 2018 16:07:31 -0700 Subject: [PATCH 080/135] Component not found assert in resolver It used to be in the dynamic component reference, but that's gone now. --- packages/ember-glimmer/lib/resolver.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 5952da81a81..dede0159478 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -48,6 +48,7 @@ import ActionModifierManager from './modifiers/action'; import { populateMacros } from './syntax'; import { OwnedTemplate } from './template'; import { ClassBasedHelperReference, SimpleHelperReference } from './utils/references'; +import { assert } from 'ember-debug'; function instrumentationPayload(name: string) { return { object: `component:${name}` }; @@ -117,7 +118,10 @@ export default class RuntimeResolver implements IRuntimeResolver { let handle = this.lookupComponentDefinition(name, meta); - if (handle === null) return null; + 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); } From abf3db1b78a708515c5b3ee58e9c1756dd527cef Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 11 Jan 2018 12:51:53 -0800 Subject: [PATCH 081/135] Simplify outlet and fix stability. --- .../lib/component-managers/outlet.ts | 104 +++++------ packages/ember-glimmer/lib/helpers/outlet.ts | 79 +++++--- packages/ember-glimmer/lib/renderer.ts | 38 ++-- packages/ember-glimmer/lib/utils/outlet.ts | 170 ++++++++++++++++++ packages/ember-glimmer/lib/views/outlet.ts | 158 +++------------- tests/node/helpers/component-module.js | 1 - 6 files changed, 304 insertions(+), 246 deletions(-) create mode 100644 packages/ember-glimmer/lib/utils/outlet.ts diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index 2ee04c8b0d5..59d6cb0b38c 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -26,32 +26,35 @@ import RuntimeResolver from '../resolver'; import { OwnedTemplate, } from '../template'; +import { OutletState } from '../utils/outlet'; import { RootReference } from '../utils/references'; -import { default as OutletView, OutletState } from '../views/outlet'; +import OutletView from '../views/outlet'; import AbstractManager from './abstract'; -function instrumentationPayload({ render: { name, outlet } }: {render: {name: string, outlet: string}}) { - return { object: `${name}:${outlet}` }; +function instrumentationPayload(def: OutletDefinitionState) { + return { object: `${def.name}:${def.outlet}` }; } -function NOOP() {/**/} - -class OutletInstanceState { - public finalizer: () => void; - - constructor(public outletState: VersionedPathReference) { - this.instrument(); - } +interface OutletInstanceState { + tag: Tag; + controller: any | undefined; + finalize: () => void; +} - instrument() { - this.finalizer = _instrumentStart('render.outlet', instrumentationPayload, this.outletState.value()); - } +function createInstanceState(definition: OutletDefinitionState): OutletInstanceState { + return { + tag: definition.ref.tag, + controller: definition.controller, + finalize: _instrumentStart('render.outlet', instrumentationPayload, definition), + }; +} - finalize() { - let { finalizer } = this; - finalizer(); - this.finalizer = NOOP; - } +export interface OutletDefinitionState { + ref: VersionedPathReference; + name: string; + outlet: string; + template: OwnedTemplate; + controller: any | undefined; } export const CAPABILITIES: ComponentCapabilities = { @@ -63,27 +66,25 @@ export const CAPABILITIES: ComponentCapabilities = { elementHook: false }; -class OutletComponentManager extends AbstractManager - implements WithStaticLayout { +class OutletComponentManager extends AbstractManager + implements WithStaticLayout { create(environment: Environment, - definition: OutletComponentDefinitionState, + definition: OutletDefinitionState, _args: Arguments, dynamicScope: DynamicScope) { if (DEBUG) { this._pushToDebugStack(`template:${definition.template.referrer.moduleName}`, environment); } - // TODO revisit missing outletName - let outletStateReference = dynamicScope.outletState = - dynamicScope.outletState.get('outlets').get(definition.outletName!) as VersionedPathReference; - return new OutletInstanceState(outletStateReference); + dynamicScope.outletState = definition.ref; + return createInstanceState(definition); } - layoutFor(_state: OutletComponentDefinitionState, _component: OutletInstanceState, _env: Environment): Unique<'Handle'> { + layoutFor(_state: OutletDefinitionState, _component: OutletInstanceState, _env: Environment): Unique<'Handle'> { throw new Error('Method not implemented.'); } - getLayout(state: OutletComponentDefinitionState, _resolver: RuntimeResolver): Invocation { + getLayout(state: OutletDefinitionState, _resolver: RuntimeResolver): Invocation { // The router has already resolved the template const layout = state.template.asLayout(); return { @@ -96,22 +97,20 @@ class OutletComponentManager extends AbstractManager); - } - getCapabilities(): ComponentCapabilities { if (EMBER_GLIMMER_REMOVE_APPLICATION_TEMPLATE_WRAPPER) { return CAPABILITIES; @@ -183,33 +174,20 @@ class TopLevelOutletComponentManager extends OutletComponentManager const TOP_MANAGER = new TopLevelOutletComponentManager(); -export interface TopOutletComponentDefinitionState { - template: OwnedTemplate; -} - -export class TopLevelOutletComponentDefinition implements ComponentDefinition { - public state: TopOutletComponentDefinitionState; +export class TopLevelOutletComponentDefinition implements ComponentDefinition { + public state: OutletDefinitionState; public manager: TopLevelOutletComponentManager = TOP_MANAGER; constructor(instance: OutletView) { - this.state = { - template: instance.template as OwnedTemplate, - }; + this.state = instance.state; } } const OUTLET_MANAGER = new OutletComponentManager(); -export interface OutletComponentDefinitionState { - outletName: string; - template: OwnedTemplate; -} - -export class OutletComponentDefinition implements ComponentDefinition { - public state: OutletComponentDefinitionState; +export class OutletComponentDefinition implements ComponentDefinition { public manager: OutletComponentManager = OUTLET_MANAGER; - constructor(outletName: string, template: OwnedTemplate) { - this.state = { outletName, template }; + constructor(public state: OutletDefinitionState) { } } diff --git a/packages/ember-glimmer/lib/helpers/outlet.ts b/packages/ember-glimmer/lib/helpers/outlet.ts index d865cc4cae6..63822852d5e 100644 --- a/packages/ember-glimmer/lib/helpers/outlet.ts +++ b/packages/ember-glimmer/lib/helpers/outlet.ts @@ -1,4 +1,4 @@ -import { combine, ConstReference, Reference, RevisionTag, TagWrapper, UpdatableTag, VersionedPathReference } from '@glimmer/reference'; +import { ConstReference, Reference, Tag, VersionedPathReference } from '@glimmer/reference'; import { Arguments, CurriedComponentDefinition, @@ -6,51 +6,74 @@ import { UNDEFINED_REFERENCE, VM, } from '@glimmer/runtime'; -import { OutletComponentDefinition } from '../component-managers/outlet'; +import { OutletComponentDefinition, OutletDefinitionState } from '../component-managers/outlet'; import { DynamicScope } from '../renderer'; -import { OutletState } from '../views/outlet'; +import { OutletReference, OutletState } from '../utils/outlet'; export default function outlet(vm: VM, args: Arguments) { let scope = vm.dynamicScope() as DynamicScope; - let outletNameRef: Reference; + let nameRef: Reference; if (args.positional.length === 0) { - outletNameRef = new ConstReference('main'); + nameRef = new ConstReference('main'); } else { - outletNameRef = args.positional.at>(0); + nameRef = args.positional.at>(0); } - return new OutletComponentReference(outletNameRef, scope.outletState); + return new OutletComponentReference(new OutletReference(scope.outletState, nameRef)); } class OutletComponentReference implements VersionedPathReference { - public tag: TagWrapper; - private outletStateTag: TagWrapper; - private definition: any | null; - private lastState: any | null; + public tag: Tag; + private definition: CurriedComponentDefinition | null; + private lastState: OutletDefinitionState | null; - constructor(private outletNameRef: Reference, - private parentOutletStateRef: VersionedPathReference) { - this.outletNameRef = outletNameRef; - this.parentOutletStateRef = parentOutletStateRef; + constructor(private outletRef: VersionedPathReference) { this.definition = null; this.lastState = null; - let outletStateTag = this.outletStateTag = UpdatableTag.create(parentOutletStateRef.tag); - this.tag = combine([outletStateTag, outletNameRef.tag]); + // The router always dirties the root state. + this.tag = outletRef.tag; } value(): CurriedComponentDefinition | null { - let outletName = this.outletNameRef.value(); - let parentState = this.parentOutletStateRef.value(); - if (!parentState) return null; - let outletState = parentState.outlets[outletName]; - if (!outletState) return null; - let renderState = outletState.render; - if (!renderState) return null; - let template = renderState.template; - if (!template) return null; - return curry(new OutletComponentDefinition(outletName, template)); + let state = stateFor(this.outletRef); + if (validate(state, this.lastState)) { + return this.definition; + } + this.lastState = state; + let definition = null; + if (state !== null) { + definition = curry(new OutletComponentDefinition(state)); + } + return this.definition = definition; } get(_key: string) { return UNDEFINED_REFERENCE; } -} \ No newline at end of file +} + +function stateFor(ref: VersionedPathReference): OutletDefinitionState | null { + let outlet = ref.value(); + if (outlet === undefined) return null; + let render = outlet.render; + if (render === undefined) return null; + let template = render.template; + if (template === undefined) return null; + return { + ref, + name: render.name, + outlet: render.outlet, + template, + controller: render.controller, + }; +} + +function validate(state: OutletDefinitionState | null, lastState: OutletDefinitionState | null) { + if (state === null) { + return lastState === null; + } + if (lastState === null) { + return false; + } + return state.template === lastState.template && + state.controller === lastState.controller; +} diff --git a/packages/ember-glimmer/lib/renderer.ts b/packages/ember-glimmer/lib/renderer.ts index 06221aa7e6f..8201306218c 100644 --- a/packages/ember-glimmer/lib/renderer.ts +++ b/packages/ember-glimmer/lib/renderer.ts @@ -1,4 +1,4 @@ -import { Option, Simple } from '@glimmer/interfaces'; +import { Simple } from '@glimmer/interfaces'; import { CURRENT_TAG, VersionedPathReference } from '@glimmer/reference'; import { clientBuilder, @@ -6,8 +6,8 @@ import { curry, DynamicScope as GlimmerDynamicScope, IteratorResult, - NULL_REFERENCE, RenderResult, + UNDEFINED_REFERENCE, } from '@glimmer/runtime'; import { Opaque } from '@glimmer/util'; import { assert } from 'ember-debug'; @@ -29,36 +29,30 @@ import { RootComponentDefinition } from './component-managers/root'; import Environment from './environment'; import { OwnedTemplate } from './template'; import { Component } from './utils/curly-component-state-bucket'; +import { OutletState } from './utils/outlet'; import { UnboundReference } from './utils/references'; -import OutletView, { OutletState, RootOutletStateReference } from './views/outlet'; +import OutletView from './views/outlet'; const { backburner } = run; export class DynamicScope implements GlimmerDynamicScope { - outletState: VersionedPathReference>; - rootOutletState: RootOutletStateReference | undefined; - constructor( public view: Component | null, - outletState: VersionedPathReference>, - rootOutletState?: RootOutletStateReference) { - this.outletState = outletState; - this.rootOutletState = rootOutletState; + public outletState: VersionedPathReference, + public rootOutletState: VersionedPathReference) { } child() { - return new DynamicScope( - this.view, this.outletState, this.rootOutletState, - ); + return new DynamicScope(this.view, this.outletState, this.rootOutletState); } - get(key: 'outletState'): VersionedPathReference> { + get(key: 'outletState'): VersionedPathReference { // tslint:disable-next-line:max-line-length assert(`Using \`-get-dynamic-scope\` is only supported for \`outletState\` (you used \`${key}\`).`, key === 'outletState'); return this.outletState; } - set(key: 'outletState', value: VersionedPathReference>) { + set(key: 'outletState', value: VersionedPathReference) { // tslint:disable-next-line:max-line-length assert(`Using \`-with-dynamic-scope\` is only supported for \`outletState\` (you used \`${key}\`).`, key === 'outletState'); this.outletState = value; @@ -269,25 +263,21 @@ export abstract class Renderer { appendOutletView(view: OutletView, target: Simple.Element) { let definition = new TopLevelOutletComponentDefinition(view); - let outletStateReference = view.toReference(); - - this._appendDefinition(view, curry(definition), target, outletStateReference); + this._appendDefinition(view, curry(definition), target); } appendTo(view: Component, target: Simple.Element) { - let def = new RootComponentDefinition(view); - this._appendDefinition(view, curry(def), target); + let definition = new RootComponentDefinition(view); + this._appendDefinition(view, curry(definition), target); } _appendDefinition( root: OutletView | Component, definition: CurriedComponentDefinition, - target: Simple.Element, - outletStateReference?: RootOutletStateReference) { + target: Simple.Element) { let self = new UnboundReference(definition); - let dynamicScope = new DynamicScope(null, outletStateReference || NULL_REFERENCE, outletStateReference); + let dynamicScope = new DynamicScope(null, UNDEFINED_REFERENCE, UNDEFINED_REFERENCE); let rootState = new RootState(root, this._env, this._rootTemplate, self, target, dynamicScope); - this._renderRoot(rootState); } diff --git a/packages/ember-glimmer/lib/utils/outlet.ts b/packages/ember-glimmer/lib/utils/outlet.ts new file mode 100644 index 00000000000..c859c55e336 --- /dev/null +++ b/packages/ember-glimmer/lib/utils/outlet.ts @@ -0,0 +1,170 @@ +import { Opaque } from '@glimmer/interfaces'; +import { combine, DirtyableTag, Reference, Tag, VersionedPathReference } from '@glimmer/reference'; +import { Owner } from 'ember-utils'; +import { OwnedTemplate } from '../template'; + +export interface RenderState { + /** + * Not sure why this is here, we use the owner of the template for lookups. + * + * Maybe this is for the render helper? + */ + owner: Owner; + + /** + * The name of the parent outlet state. + */ + into: string | undefined; + + /* + * The outlet name in the parent outlet state's outlets. + */ + outlet: string; + + /** + * The name of the route/template + */ + name: string; + + /** + * The controller (the self of the outlet component) + */ + controller: any | undefined; + + /** + * template (the layout of the outlet component) + */ + template: OwnedTemplate | undefined; +} + +export interface Outlets { + [name: string]: OutletState | undefined; +} + +export interface OutletState { + /** + * Nested outlet connections. + */ + outlets: Outlets; + + /** + * Represents what was rendered into this outlet. + */ + render: RenderState | undefined; + + /** + * Has to do with render helper and orphan outlets. + * Whether outlet state was rendered. + */ + wasUsed?: boolean; +} + +/** + * Represents the root outlet. + */ +export class RootOutletReference implements VersionedPathReference { + tag = DirtyableTag.create(); + + constructor(public outletState: OutletState) { + } + + get(key: string): VersionedPathReference { + return new PathReference(this, key); + } + + value(): OutletState { + return this.outletState; + } + + update(state: OutletState) { + this.outletState.outlets.main = state; + this.tag.inner.dirty(); + } +} + +/** + * Represents the connected outlet. + */ +export class OutletReference implements VersionedPathReference { + tag: Tag; + + constructor(public parentStateRef: VersionedPathReference, + public outletNameRef: Reference) { + this.tag = combine([parentStateRef.tag, outletNameRef.tag]); + } + + value(): OutletState | undefined { + let outletState = this.parentStateRef.value(); + let outlets = outletState === undefined ? undefined : outletState.outlets; + return outlets === undefined ? undefined : outlets[this.outletNameRef.value()]; + } + + get(key: string): VersionedPathReference { + return new PathReference(this, key); + } +} + +/** + * Outlet state is dirtied from root. + * This just using the parent tag for dirtiness. + */ +class PathReference implements VersionedPathReference { + public parent: VersionedPathReference; + public key: string; + public tag: Tag; + + constructor(parent: VersionedPathReference, key: string) { + this.parent = parent; + this.key = key; + this.tag = parent.tag; + } + + get(key: string): VersionedPathReference { + return new PathReference(this, key); + } + + value(): Opaque { + let parent = this.parent.value(); + return parent && parent[this.key]; + } +} + +/** + * So this is a relic of the past that SHOULD go away + * in 3.0. Preferably it is deprecated in the release that + * follows the Glimmer release. + */ +export class OrphanedOutletReference implements VersionedPathReference { + public tag: Tag; + + constructor(public root: VersionedPathReference, public name: string) { + this.tag = root.tag; + } + + value(): OutletState | undefined { + let rootState = this.root.value(); + let outletState = rootState && rootState.outlets.main; + let outlets = outletState && outletState.outlets; + outletState = outlets && outlets.__ember_orphans__; + outlets = outletState && outletState.outlets; + + if (outlets === undefined) { + return; + } + + let matched = outlets[this.name]; + + if (matched === undefined || matched.render === undefined) { + return; + } + + let state = Object.create(null); + state[matched.render.outlet] = matched; + matched.wasUsed = true; + return { outlets: state, render: undefined }; + } + + get(key: string): VersionedPathReference { + return new PathReference(this, key); + } +} diff --git a/packages/ember-glimmer/lib/views/outlet.ts b/packages/ember-glimmer/lib/views/outlet.ts index a4480558c1a..5e7d388435a 100644 --- a/packages/ember-glimmer/lib/views/outlet.ts +++ b/packages/ember-glimmer/lib/views/outlet.ts @@ -1,107 +1,11 @@ import { Simple } from '@glimmer/interfaces'; -import { DirtyableTag, Tag, TagWrapper, VersionedPathReference } from '@glimmer/reference'; -import { Opaque, Option } from '@glimmer/util'; import { environment } from 'ember-environment'; import { run } from 'ember-metal'; import { assign, OWNER, Owner } from 'ember-utils'; +import { OutletDefinitionState } from '../component-managers/outlet'; import { Renderer } from '../renderer'; import { OwnedTemplate } from '../template'; - -export class RootOutletStateReference implements VersionedPathReference> { - tag: Tag; - - constructor(public outletView: OutletView) { - this.tag = outletView._tag; - } - - get(key: string): VersionedPathReference { - return new ChildOutletStateReference(this, key); - } - - value(): Option { - return this.outletView.outletState; - } - - getOrphan(name: string): VersionedPathReference> { - return new OrphanedOutletStateReference(this, name); - } - - update(state: OutletState) { - this.outletView.setOutletState(state); - } -} - -// So this is a relic of the past that SHOULD go away -// in 3.0. Preferably it is deprecated in the release that -// follows the Glimmer release. -class OrphanedOutletStateReference extends RootOutletStateReference { - public root: any; - public name: string; - - constructor(root: RootOutletStateReference, name: string) { - super(root.outletView); - this.root = root; - this.name = name; - } - - value(): Option { - let rootState = this.root.value(); - - let orphans = rootState.outlets.main.outlets.__ember_orphans__; - - if (!orphans) { - return null; - } - - let matched = orphans.outlets[this.name]; - - if (!matched) { - return null; - } - - let state = Object.create(null); - state[matched.render.outlet] = matched; - matched.wasUsed = true; - return { outlets: state, render: undefined }; - } -} - -class ChildOutletStateReference implements VersionedPathReference { - public parent: VersionedPathReference; - public key: string; - public tag: Tag; - - constructor(parent: VersionedPathReference, key: string) { - this.parent = parent; - this.key = key; - this.tag = parent.tag; - } - - get(key: string): VersionedPathReference { - return new ChildOutletStateReference(this, key); - } - - value(): any { - let parent = this.parent.value(); - return parent && parent[this.key]; - } -} - -export interface RenderState { - owner: Owner | undefined; - into: string | undefined; - outlet: string; - name: string; - controller: Opaque; - template: OwnedTemplate | undefined; -} - -export interface OutletState { - outlets: { - [name: string]: OutletState | undefined; - }; - render: RenderState | undefined; -} +import { OutletState, RootOutletReference } from '../utils/outlet'; export interface BootEnvironment { hasDOM: boolean; @@ -109,14 +13,10 @@ export interface BootEnvironment { options: any; } -export default class OutletView { - private _environment: BootEnvironment; - public renderer: Renderer; - public owner: Owner; - public template: OwnedTemplate; - public outletState: Option; - public _tag: TagWrapper; +const TOP_LEVEL_NAME = '-top-level'; +const TOP_LEVEL_OUTLET = 'main'; +export default class OutletView { static extend(injections: any) { return class extends OutletView { static create(options: any) { @@ -139,13 +39,28 @@ export default class OutletView { return new OutletView(_environment, renderer, owner, template); } - constructor(_environment: BootEnvironment, renderer: Renderer, owner: Owner, template: OwnedTemplate) { - this._environment = _environment; - this.renderer = renderer; - this.owner = owner; - this.template = template; - this.outletState = null; - this._tag = DirtyableTag.create(); + public ref: RootOutletReference; + public state: OutletDefinitionState; + + constructor(private _environment: BootEnvironment, public renderer: Renderer, public owner: Owner, public template: OwnedTemplate) { + let ref = this.ref = new RootOutletReference({ + outlets: { main: undefined }, + render: { + owner: owner, + into: undefined, + outlet: TOP_LEVEL_OUTLET, + name: TOP_LEVEL_NAME, + controller: undefined, + template, + }, + }); + this.state = { + ref, + name: TOP_LEVEL_NAME, + outlet: TOP_LEVEL_OUTLET, + template, + controller: undefined + }; } appendTo(selector: string | Simple.Element) { @@ -164,24 +79,7 @@ export default class OutletView { rerender() { /**/ } setOutletState(state: OutletState) { - this.outletState = { - outlets: { - main: state, - }, - render: { - owner: undefined, - into: undefined, - outlet: 'main', - name: '-top-level', - controller: undefined, - template: undefined, - }, - }; - this._tag.inner.dirty(); - } - - toReference() { - return new RootOutletStateReference(this); + this.ref.update(state); } destroy() { /**/ } diff --git a/tests/node/helpers/component-module.js b/tests/node/helpers/component-module.js index 0a0ab46d0b7..ebdb331b501 100644 --- a/tests/node/helpers/component-module.js +++ b/tests/node/helpers/component-module.js @@ -107,7 +107,6 @@ function render(_template) { name: 'index', controller: this, template: this.owner.lookup(templateFullName), - outlets: { } }; stateToRender.name = 'index'; From 8d57c533a3f3f4eaf2ce325eecfdb12688b1aa08 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 11 Jan 2018 13:16:18 -0800 Subject: [PATCH 082/135] small cleanup of tslint and type errors --- .../lib/component-managers/definition-state.ts | 6 +++--- packages/ember-glimmer/lib/resolver.ts | 2 +- packages/ember-glimmer/lib/syntax.ts | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/definition-state.ts b/packages/ember-glimmer/lib/component-managers/definition-state.ts index 11521bc51cc..f63043edc69 100644 --- a/packages/ember-glimmer/lib/component-managers/definition-state.ts +++ b/packages/ember-glimmer/lib/component-managers/definition-state.ts @@ -6,14 +6,14 @@ import { import { Option } from '@glimmer/util'; +import { Factory } from 'ember-utils'; +import { Component } from '../utils/curly-component-state-bucket'; export default interface DefinitionState { capabilities: ComponentCapabilities; - name: string; - ComponentClass: any; + ComponentClass: Factory; handle: Option; symbolTable?: ProgramSymbolTable; template?: any; - outletName?: string; } diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index dede0159478..db5b9a9c1ed 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -15,6 +15,7 @@ import { PartialDefinition } from '@glimmer/runtime'; import { privatize as P } from 'container'; +import { assert } from 'ember-debug'; import { _instrumentStart } from 'ember-metal'; import { LookupOptions } from 'ember-utils'; import { @@ -48,7 +49,6 @@ import ActionModifierManager from './modifiers/action'; import { populateMacros } from './syntax'; import { OwnedTemplate } from './template'; import { ClassBasedHelperReference, SimpleHelperReference } from './utils/references'; -import { assert } from 'ember-debug'; function instrumentationPayload(name: string) { return { object: `component:${name}` }; diff --git a/packages/ember-glimmer/lib/syntax.ts b/packages/ember-glimmer/lib/syntax.ts index ba4809f92f0..8369c5a2935 100644 --- a/packages/ember-glimmer/lib/syntax.ts +++ b/packages/ember-glimmer/lib/syntax.ts @@ -5,6 +5,7 @@ import { assert } from 'ember-debug'; import { ENV } from 'ember-environment'; import { OwnedTemplateMeta } from 'ember-views'; import { EMBER_TEMPLATE_BLOCK_LET_HELPER } from 'ember/features'; +import CompileTimeLookup from './compile-time-lookup'; import { textAreaMacro } from './syntax/-text-area'; import { inputMacro } from './syntax/input'; import { blockLetMacro } from './syntax/let'; @@ -18,7 +19,7 @@ function refineInlineSyntax(name: string, params: Option, hash: Opt assert( `You attempted to overwrite the built-in helper "${name}" which is not allowed. Please rename the helper.`, !( - builder.resolver.resolver.builtInHelpers[name] && + (builder.resolver as CompileTimeLookup)['resolver']['builtInHelpers'][name] && builder.referrer.owner.hasRegistration(`helper:${name}`) ) ); @@ -54,9 +55,9 @@ function refineBlockSyntax(name: string, params: Core.Params, hash: Core.Hash, t assert( `Helpers may not be used in the block form, for example {{#${name}}}{{/${name}}}. Please use a component, or alternatively use the helper in combination with a built-in Ember helper, for example {{#if (${name})}}{{/if}}.`, !(() => { - const { resolver } = builder.resolver; + const resolver = (builder.resolver as CompileTimeLookup)['resolver']; const { owner, moduleName } = builder.referrer; - if (name === 'component' || resolver.builtInHelpers[name]) { + if (name === 'component' || resolver['builtInHelpers'][name]) { return true; } let options = { source: `template:${moduleName}` }; From af75347d140f9b2f30074230e96ec82246bd5c3c Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Thu, 11 Jan 2018 14:32:39 -0700 Subject: [PATCH 083/135] Assert that helper exists --- packages/ember-glimmer/lib/syntax.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/syntax.ts b/packages/ember-glimmer/lib/syntax.ts index 8369c5a2935..2e2aecbe11d 100644 --- a/packages/ember-glimmer/lib/syntax.ts +++ b/packages/ember-glimmer/lib/syntax.ts @@ -50,7 +50,7 @@ function refineBlockSyntax(name: string, params: Core.Params, hash: Core.Hash, t return true; } - // assert(`A component or helper named "${name}" could not be found`, builder.resolver.hasHelper(name, builder.referrer)); + assert(`A component or helper named "${name}" could not be found`, builder.referrer.owner.hasRegistration(`helper:${name}`)); assert( `Helpers may not be used in the block form, for example {{#${name}}}{{/${name}}}. Please use a component, or alternatively use the helper in combination with a built-in Ember helper, for example {{#if (${name})}}{{/if}}.`, From 63bcdeb0f36f934f7b98216e4e185396032c4ef4 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Thu, 11 Jan 2018 15:51:51 -0700 Subject: [PATCH 084/135] Fix application lifecycle test --- packages/ember/tests/component_context_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember/tests/component_context_test.js b/packages/ember/tests/component_context_test.js index c4499477896..4bd733f1e7b 100644 --- a/packages/ember/tests/component_context_test.js +++ b/packages/ember/tests/component_context_test.js @@ -126,7 +126,7 @@ moduleFor('Application Lifecycle - Component Context', class extends Application ComponentClass: Component.extend({ didInsertElement() { // FIXME: I'm unsure if this is even the right way to access attrs - this.$().html(this.get('attrs.attrs')); + this.$().html(this.get('attrs.attrs').value); } }) }); From 7e29308d07d5c894f8b2666b465f0e95d5fcf0c6 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 11 Jan 2018 14:51:51 -0800 Subject: [PATCH 085/135] more type fixes --- .../lib/component-managers/curly.ts | 83 +------------------ packages/ember-glimmer/lib/component.ts | 2 +- 2 files changed, 2 insertions(+), 83 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 722290d0aeb..bd2e461c3c0 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -9,7 +9,6 @@ import { import { ParsedLayout, TemplateOptions, WrappedBuilder } from '@glimmer/opcode-compiler'; import { combine, - combineTagged, Tag, VersionedPathReference, } from '@glimmer/reference'; @@ -65,7 +64,6 @@ import { } from '../utils/bindings'; import ComponentStateBucket, { Component } from '../utils/curly-component-state-bucket'; import { processComponentArgs } from '../utils/process-args'; -import { PropertyReference } from '../utils/references'; import AbstractManager from './abstract'; import DefinitionState from './definition-state'; @@ -122,24 +120,6 @@ function applyAttributeBindings(element: Simple.Element, attributeBindings: Arra // return vm.getSelf().get('ariaRole'); // } -export class PositionalArgumentReference { - public tag: any; - private _references: any; - - constructor(references: any) { - this.tag = combineTagged(references); - this._references = references; - } - - value() { - return this._references.map((reference: any) => reference.value()); - } - - get(key: string) { - return PropertyReference.create(this, key); - } -} - const DEFAULT_LAYOUT = P`template:components/-default`; export default class CurlyComponentManager extends AbstractManager @@ -253,38 +233,6 @@ export default class CurlyComponentManager extends AbstractManager, hasBlock: boolean): ComponentStateBucket { @@ -351,35 +299,6 @@ export default class CurlyComponentManager extends AbstractManager { return component[ROOT_REF]; } @@ -402,7 +321,7 @@ export default class CurlyComponentManager extends AbstractManager { - let eventDispatcher = getOwner(this).lookup('event_dispatcher:main'); + let eventDispatcher = getOwner(this).lookup('event_dispatcher:main'); let events = (eventDispatcher && eventDispatcher._finalEvents) || {}; // tslint:disable-next-line:forin From a65c874e048adc179ee37176241b849eb2680275 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 11 Jan 2018 16:44:50 -0800 Subject: [PATCH 086/135] More progress on mount and render --- .../lib/component-managers/mount.ts | 74 ++++++++++------- .../lib/component-managers/render.ts | 46 ++++++---- packages/ember-glimmer/lib/helpers/outlet.ts | 79 ------------------ packages/ember-glimmer/lib/resolver.ts | 13 +-- packages/ember-glimmer/lib/syntax.ts | 7 +- packages/ember-glimmer/lib/syntax/mount.ts | 12 ++- packages/ember-glimmer/lib/syntax/outlet.ts | 83 ++++++++++++++++++- packages/ember-glimmer/lib/syntax/render.ts | 21 +++-- 8 files changed, 185 insertions(+), 150 deletions(-) delete mode 100644 packages/ember-glimmer/lib/helpers/outlet.ts diff --git a/packages/ember-glimmer/lib/component-managers/mount.ts b/packages/ember-glimmer/lib/component-managers/mount.ts index cf129b27c77..7d35986d7fc 100644 --- a/packages/ember-glimmer/lib/component-managers/mount.ts +++ b/packages/ember-glimmer/lib/component-managers/mount.ts @@ -1,14 +1,16 @@ import { - ComponentCapabilities, - VMHandle + ComponentCapabilities, Unique, } from '@glimmer/interfaces'; import { + CONSTANT_TAG, Tag, - VersionedPathReference + VersionedPathReference, } from '@glimmer/reference'; import { Arguments, ComponentDefinition, + Invocation, + WithDynamicLayout, } from '@glimmer/runtime'; import { Destroyable, @@ -18,16 +20,17 @@ import { import { DEBUG } from 'ember-env-flags'; import { generateControllerFactory } from 'ember-routing'; +import { OwnedTemplateMeta } from 'ember-views'; import { EMBER_ENGINES_MOUNT_PARAMS } from 'ember/features'; -import { DIRTY_TAG } from '../component'; import Environment from '../environment'; +import RuntimeResolver from '../resolver'; +import { OwnedTemplate } from '../template'; import { Component } from '../utils/curly-component-state-bucket'; import { RootReference } from '../utils/references'; import AbstractManager from './abstract'; -import DefinitionState from './definition-state'; // TODO: remove these stubbed interfaces when better typing is in place -interface EngineType { +interface Engine { boot(): void; destroy(): void; lookup(name: string): any; @@ -35,24 +38,44 @@ interface EngineType { } interface EngineBucket { - engine: EngineType; + engine: Engine; component?: Component; controller?: any; modelReference?: any; modelRevision?: any; } -class MountManager extends AbstractManager { - getCapabilities(state: DefinitionState): ComponentCapabilities { +interface EngineDefinitionState { + name: string; + capabilities: ComponentCapabilities; +} + +class MountManager extends AbstractManager + implements WithDynamicLayout { + + getDynamicLayout(state: EngineBucket, _: RuntimeResolver): Invocation { + let template = state.engine.lookup('template:application') as OwnedTemplate; + let layout = template.asLayout(); + return { + handle: layout.compile(), + symbolTable: layout.symbolTable + }; + } + + layoutFor(_definition: EngineDefinitionState, _component: EngineBucket, _env: Environment): Unique<'Handle'> { + throw new Error('Method not implemented.'); + } + + getCapabilities(state: EngineDefinitionState): ComponentCapabilities { return state.capabilities; } - create(environment: Environment, { name }: DefinitionState, args: Arguments) { + create(environment: Environment, { name }: EngineDefinitionState, args: Arguments) { if (DEBUG) { this._pushEngineToDebugStack(`engine:${name}`, environment); } - let engine = environment.owner.buildChildEngineInstance(name); + let engine = environment.owner.buildChildEngineInstance(name); engine.boot(); @@ -65,13 +88,6 @@ class MountManager extends AbstractManager { return bucket; } - layoutFor(_definition: ComponentDefinition, _bucket: EngineBucket, _env: Environment) { - // let template = engine.lookup(`template:application`); - throw Error('use resolver.lookupTemplate resolver.compileTemplate'); - // needs to use resolver - // return env.getCompiledBlock(CurlyComponentLayoutCompiler, template); - } - getSelf(bucket: EngineBucket): VersionedPathReference { let { engine, modelReference } = bucket; @@ -88,9 +104,8 @@ class MountManager extends AbstractManager { return new RootReference(controller); } - getTag({ component }: EngineBucket): Tag { - // TODO: is this the right tag? - return component![DIRTY_TAG]; + getTag(): Tag { + return CONSTANT_TAG; } getDestructor({ engine }: EngineBucket): Option { @@ -116,21 +131,22 @@ class MountManager extends AbstractManager { } } +const MOUNT_MANAGER = new MountManager(); + export class MountDefinition implements ComponentDefinition { - public state: DefinitionState; + public state: EngineDefinitionState; + public manager = MOUNT_MANAGER; - constructor(public name: string, public manager: MountManager, public ComponentClass: any, public handle: Option) { + constructor(public name: string) { this.state = { name, - ComponentClass, - handle, capabilities: { dynamicLayout: true, - dynamicTag: true, - prepareArgs: true, + dynamicTag: false, + prepareArgs: false, createArgs: true, - attributeHook: true, - elementHook: true + attributeHook: false, + elementHook: false } }; } diff --git a/packages/ember-glimmer/lib/component-managers/render.ts b/packages/ember-glimmer/lib/component-managers/render.ts index f28658a841f..3e81f052b8a 100644 --- a/packages/ember-glimmer/lib/component-managers/render.ts +++ b/packages/ember-glimmer/lib/component-managers/render.ts @@ -2,7 +2,7 @@ import { ComponentCapabilities, VMHandle, } from '@glimmer/interfaces'; import { - Tag + CONSTANT_TAG, Tag } from '@glimmer/reference'; import { Arguments, @@ -12,15 +12,18 @@ import { import { assert } from 'ember-debug'; import { DEBUG } from 'ember-env-flags'; import { generateController, generateControllerFactory } from 'ember-routing'; -import { DIRTY_TAG } from '../component'; import Environment from '../environment'; import { DynamicScope } from '../renderer'; import { OwnedTemplate } from '../template'; import { RootReference } from '../utils/references'; import AbstractManager from './abstract'; -import DefinitionState from './definition-state'; -export abstract class AbstractRenderManager extends AbstractManager { +export interface RenderDefinitionState { + name: string; + template: OwnedTemplate | undefined; +} + +export abstract class AbstractRenderManager extends AbstractManager { layoutFor(definition: RenderDefinition, _bucket: RenderState, _env: Environment): VMHandle { // only curly components can have lazy layout assert('definition is missing a template', !!definition.template); @@ -46,9 +49,18 @@ export interface RenderState { component: any; } +const CAPABILITIES = { + dynamicLayout: false, + dynamicTag: false, + prepareArgs: false, + createArgs: false, + attributeHook: false, + elementHook: false +}; + class SingletonRenderManager extends AbstractRenderManager { create(env: Environment, - definition: DefinitionState, + definition: RenderDefinitionState, _args: Arguments, dynamicScope: DynamicScope) { let { name } = definition; @@ -65,13 +77,13 @@ class SingletonRenderManager extends AbstractRenderManager { return { controller } as RenderState; } - getCapabilities(state: DefinitionState): ComponentCapabilities { - return state.capabilities; + getCapabilities(_: RenderDefinitionState): ComponentCapabilities { + return CAPABILITIES; } - getTag({ component }: RenderState): Tag { - // TODO: is this the right tag? - return component[DIRTY_TAG]; + getTag(): Tag { + // todo this should be the tag of the state args + return CONSTANT_TAG; } getDestructor() { @@ -83,7 +95,7 @@ export const SINGLETON_RENDER_MANAGER = new SingletonRenderManager(); class NonSingletonRenderManager extends AbstractRenderManager { create(environment: Environment, - definition: DefinitionState, + definition: RenderDefinitionState, args: Arguments, dynamicScope: DynamicScope) { let { name, env } = definition; @@ -108,13 +120,12 @@ class NonSingletonRenderManager extends AbstractRenderManager { controller.set('model', model.value()); } - getCapabilities(state: DefinitionState): ComponentCapabilities { - return state.capabilities; + getCapabilities(_: RenderDefinitionState): ComponentCapabilities { + return CAPABILITIES; } - getTag({ component }: RenderState): Tag { - // TODO: is this the right tag? - return component[DIRTY_TAG]; + getTag(): Tag { + return CONSTANT_TAG; } getDestructor({ controller }: RenderState) { @@ -128,11 +139,10 @@ export class RenderDefinition implements ComponentDefinition { public name: string; public template: OwnedTemplate | undefined; public env: Environment; - public state: DefinitionState; + public state: RenderDefinitionState; public manager: SingletonRenderManager | NonSingletonRenderManager; constructor(name: string, template: OwnedTemplate, env: Environment, manager: SingletonRenderManager | NonSingletonRenderManager) { - this.name = name; this.template = template; this.env = env; diff --git a/packages/ember-glimmer/lib/helpers/outlet.ts b/packages/ember-glimmer/lib/helpers/outlet.ts deleted file mode 100644 index 63822852d5e..00000000000 --- a/packages/ember-glimmer/lib/helpers/outlet.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { ConstReference, Reference, Tag, VersionedPathReference } from '@glimmer/reference'; -import { - Arguments, - CurriedComponentDefinition, - curry, - UNDEFINED_REFERENCE, - VM, -} from '@glimmer/runtime'; -import { OutletComponentDefinition, OutletDefinitionState } from '../component-managers/outlet'; -import { DynamicScope } from '../renderer'; -import { OutletReference, OutletState } from '../utils/outlet'; - -export default function outlet(vm: VM, args: Arguments) { - let scope = vm.dynamicScope() as DynamicScope; - let nameRef: Reference; - if (args.positional.length === 0) { - nameRef = new ConstReference('main'); - } else { - nameRef = args.positional.at>(0); - } - return new OutletComponentReference(new OutletReference(scope.outletState, nameRef)); -} - -class OutletComponentReference implements VersionedPathReference { - public tag: Tag; - private definition: CurriedComponentDefinition | null; - private lastState: OutletDefinitionState | null; - - constructor(private outletRef: VersionedPathReference) { - this.definition = null; - this.lastState = null; - // The router always dirties the root state. - this.tag = outletRef.tag; - } - - value(): CurriedComponentDefinition | null { - let state = stateFor(this.outletRef); - if (validate(state, this.lastState)) { - return this.definition; - } - this.lastState = state; - let definition = null; - if (state !== null) { - definition = curry(new OutletComponentDefinition(state)); - } - return this.definition = definition; - } - - get(_key: string) { - return UNDEFINED_REFERENCE; - } -} - -function stateFor(ref: VersionedPathReference): OutletDefinitionState | null { - let outlet = ref.value(); - if (outlet === undefined) return null; - let render = outlet.render; - if (render === undefined) return null; - let template = render.template; - if (template === undefined) return null; - return { - ref, - name: render.name, - outlet: render.outlet, - template, - controller: render.controller, - }; -} - -function validate(state: OutletDefinitionState | null, lastState: OutletDefinitionState | null) { - if (state === null) { - return lastState === null; - } - if (lastState === null) { - return false; - } - return state.template === lastState.template && - state.controller === lastState.controller; -} diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index db5b9a9c1ed..87b3af16c55 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -35,18 +35,17 @@ import { default as concat } from './helpers/concat'; import { default as eachIn } from './helpers/each-in'; import { default as get } from './helpers/get'; import { default as hash } from './helpers/hash'; -import { - inlineIf, - inlineUnless, -} from './helpers/if-unless'; +import { inlineIf, inlineUnless } from './helpers/if-unless'; import { default as log } from './helpers/log'; import { default as mut } from './helpers/mut'; -import { default as outlet } from './helpers/outlet'; 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 { populateMacros } from './syntax'; +import { mountHelper } from './syntax/mount'; +import { outletHelper } from './syntax/outlet'; +import { renderHelper } from './syntax/render'; import { OwnedTemplate } from './template'; import { ClassBasedHelperReference, SimpleHelperReference } from './utils/references'; @@ -76,7 +75,9 @@ const BUILTINS_HELPERS = { '-normalize-class': normalizeClassHelper, '-html-safe': htmlSafeHelper, '-get-dynamic-var': getDynamicVar, - '-outlet': outlet, + '-mount': mountHelper, + '-outlet': outletHelper, + '-render': renderHelper, }; const BUILTIN_MODIFIERS = { diff --git a/packages/ember-glimmer/lib/syntax.ts b/packages/ember-glimmer/lib/syntax.ts index 2e2aecbe11d..47ad705881b 100644 --- a/packages/ember-glimmer/lib/syntax.ts +++ b/packages/ember-glimmer/lib/syntax.ts @@ -2,7 +2,6 @@ import { CompilableBlock, Macros, OpcodeBuilder } from '@glimmer/opcode-compiler import { Option } from '@glimmer/util'; import { Core } from '@glimmer/wire-format'; import { assert } from 'ember-debug'; -import { ENV } from 'ember-environment'; import { OwnedTemplateMeta } from 'ember-views'; import { EMBER_TEMPLATE_BLOCK_LET_HELPER } from 'ember/features'; import CompileTimeLookup from './compile-time-lookup'; @@ -80,11 +79,7 @@ export function registerMacros(macro: any) { export function populateMacros(macros: Macros) { let { inlines, blocks } = macros; inlines.add('outlet', outletMacro); - - if (ENV._ENABLE_RENDER_SUPPORT === true) { - inlines.add('render', renderMacro); - } - + inlines.add('render', renderMacro); inlines.add('mount', mountMacro); inlines.add('input', inputMacro); inlines.add('textarea', textAreaMacro); diff --git a/packages/ember-glimmer/lib/syntax/mount.ts b/packages/ember-glimmer/lib/syntax/mount.ts index 102b886ce23..1f2c1a37b0f 100644 --- a/packages/ember-glimmer/lib/syntax/mount.ts +++ b/packages/ember-glimmer/lib/syntax/mount.ts @@ -3,8 +3,12 @@ */ import { Option } from '@glimmer/interfaces'; import { OpcodeBuilder } from '@glimmer/opcode-compiler'; +import { VersionedPathReference } from '@glimmer/reference'; import { Arguments, + CurriedComponentDefinition, + curry, + UNDEFINED_REFERENCE, VM } from '@glimmer/runtime'; import * as WireFormat from '@glimmer/wire-format'; @@ -14,7 +18,7 @@ import { EMBER_ENGINES_MOUNT_PARAMS } from 'ember/features'; import { MountDefinition } from '../component-managers/mount'; import Environment from '../environment'; -export function mountHelper(vm: VM, args: Arguments, meta: any) { +export function mountHelper(vm: VM, args: Arguments, meta: any): VersionedPathReference { let env = vm.env; let nameRef = args.positional.at(0); @@ -116,7 +120,7 @@ class DynamicEngineReference { this._lastName = nameOrDef; // TODO: maybe I've got the MountDefinition constructor wrong... - this._lastDef = new MountDefinition(nameOrDef); + this._lastDef = curry(new MountDefinition(nameOrDef)); return this._lastDef; } else { @@ -128,4 +132,8 @@ class DynamicEngineReference { return null; } } + + get() { + return UNDEFINED_REFERENCE; + } } diff --git a/packages/ember-glimmer/lib/syntax/outlet.ts b/packages/ember-glimmer/lib/syntax/outlet.ts index 2b546ac6f26..149c60922de 100644 --- a/packages/ember-glimmer/lib/syntax/outlet.ts +++ b/packages/ember-glimmer/lib/syntax/outlet.ts @@ -1,7 +1,18 @@ import { Option } from '@glimmer/interfaces'; import { OpcodeBuilder } from '@glimmer/opcode-compiler'; +import { ConstReference, Reference, Tag, VersionedPathReference } from '@glimmer/reference'; +import { + Arguments, + CurriedComponentDefinition, + curry, + UNDEFINED_REFERENCE, + VM, +} from '@glimmer/runtime'; import * as WireFormat from '@glimmer/wire-format'; import { OwnedTemplateMeta } from 'ember-views'; +import { OutletComponentDefinition, OutletDefinitionState } from '../component-managers/outlet'; +import { DynamicScope } from '../renderer'; +import { OutletReference, OutletState } from '../utils/outlet'; /** The `{{outlet}}` helper lets you specify where a child route will render in @@ -53,8 +64,76 @@ import { OwnedTemplateMeta } from 'ember-views'; @for Ember.Templates.helpers @public */ -export const outletMacro = (_name: string, params: Option, hash: Option, builder: OpcodeBuilder) => { +export function outletHelper(vm: VM, args: Arguments) { + let scope = vm.dynamicScope() as DynamicScope; + let nameRef: Reference; + if (args.positional.length === 0) { + nameRef = new ConstReference('main'); + } else { + nameRef = args.positional.at>(0); + } + return new OutletComponentReference(new OutletReference(scope.outletState, nameRef)); +} + +export function outletMacro(_name: string, params: Option, hash: Option, builder: OpcodeBuilder) { let expr: WireFormat.Expressions.Helper = [WireFormat.Ops.Helper, '-outlet', params || [], hash]; builder.dynamicComponent(expr, [], null, false, null, null); return true; -}; +} + +class OutletComponentReference implements VersionedPathReference { + public tag: Tag; + private definition: CurriedComponentDefinition | null; + private lastState: OutletDefinitionState | null; + + constructor(private outletRef: VersionedPathReference) { + this.definition = null; + this.lastState = null; + // The router always dirties the root state. + this.tag = outletRef.tag; + } + + value(): CurriedComponentDefinition | null { + let state = stateFor(this.outletRef); + if (validate(state, this.lastState)) { + return this.definition; + } + this.lastState = state; + let definition = null; + if (state !== null) { + definition = curry(new OutletComponentDefinition(state)); + } + return this.definition = definition; + } + + get(_key: string) { + return UNDEFINED_REFERENCE; + } +} + +function stateFor(ref: VersionedPathReference): OutletDefinitionState | null { + let outlet = ref.value(); + if (outlet === undefined) return null; + let render = outlet.render; + if (render === undefined) return null; + let template = render.template; + if (template === undefined) return null; + return { + ref, + name: render.name, + outlet: render.outlet, + template, + controller: render.controller, + }; +} + +function validate(state: OutletDefinitionState | null, lastState: OutletDefinitionState | null) { + if (state === null) { + return lastState === null; + } + if (lastState === null) { + return false; + } + return state.template === lastState.template && + state.controller === lastState.controller; +} diff --git a/packages/ember-glimmer/lib/syntax/render.ts b/packages/ember-glimmer/lib/syntax/render.ts index c83b3c9bea5..844aebd4b3d 100644 --- a/packages/ember-glimmer/lib/syntax/render.ts +++ b/packages/ember-glimmer/lib/syntax/render.ts @@ -6,13 +6,15 @@ Remove after 3.4 once _ENABLE_RENDER_SUPPORT flag is no longer needed. import { Option } from '@glimmer/interfaces'; import { OpcodeBuilder } from '@glimmer/opcode-compiler'; -import { ConstReference, isConst } from '@glimmer/reference'; +import { ConstReference, isConst, VersionedPathReference } from '@glimmer/reference'; import { Arguments, + CurriedComponentDefinition, VM, } from '@glimmer/runtime'; import * as WireFormat from '@glimmer/wire-format'; import { assert } from 'ember-debug'; +import { ENV } from 'ember-environment'; import { OwnedTemplateMeta } from 'ember-views'; import { NON_SINGLETON_RENDER_MANAGER, @@ -22,7 +24,7 @@ import { import Environment from '../environment'; import { OwnedTemplate } from '../template'; -export function makeComponentDefinition(vm: VM, args: Arguments) { +export function renderHelper(vm: VM, args: Arguments): VersionedPathReference { let env = vm.env as Environment; let nameRef = args.positional.at(0); @@ -134,10 +136,13 @@ export function makeComponentDefinition(vm: VM, args: Arguments) { @deprecated Use a component instead */ export function renderMacro(_name: string, params: Option, hash: Option, builder: OpcodeBuilder) { - // TODO needs makeComponentDefinition a helper that returns a curried definition - // TODO not sure all args are for definition or component - // likely the controller name should be a arg to create? - let expr: WireFormat.Expressions.Helper = [WireFormat.Ops.Helper, '-render', params || [], hash]; - builder.dynamicComponent(expr, null, null, false, null, null); - return true; + if (ENV._ENABLE_RENDER_SUPPORT === true) { + // TODO needs makeComponentDefinition a helper that returns a curried definition + // TODO not sure all args are for definition or component + // likely the controller name should be a arg to create? + let expr: WireFormat.Expressions.Helper = [WireFormat.Ops.Helper, '-render', params || [], hash]; + builder.dynamicComponent(expr, null, null, false, null, null); + return true; + } + return false; } From b18bee4e8644732d4cf1113282e5ab04574101cf Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 11 Jan 2018 17:01:11 -0800 Subject: [PATCH 087/135] cleanup types on mount syntax --- packages/ember-glimmer/lib/syntax/mount.ts | 49 ++++++++++------------ 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/packages/ember-glimmer/lib/syntax/mount.ts b/packages/ember-glimmer/lib/syntax/mount.ts index 1f2c1a37b0f..e154853af31 100644 --- a/packages/ember-glimmer/lib/syntax/mount.ts +++ b/packages/ember-glimmer/lib/syntax/mount.ts @@ -3,7 +3,7 @@ */ import { Option } from '@glimmer/interfaces'; import { OpcodeBuilder } from '@glimmer/opcode-compiler'; -import { VersionedPathReference } from '@glimmer/reference'; +import { Tag, VersionedPathReference } from '@glimmer/reference'; import { Arguments, CurriedComponentDefinition, @@ -18,11 +18,10 @@ import { EMBER_ENGINES_MOUNT_PARAMS } from 'ember/features'; import { MountDefinition } from '../component-managers/mount'; import Environment from '../environment'; -export function mountHelper(vm: VM, args: Arguments, meta: any): VersionedPathReference { +export function mountHelper(vm: VM, args: Arguments): VersionedPathReference { let env = vm.env; let nameRef = args.positional.at(0); - - return new DynamicEngineReference({ nameRef, env, meta }); + return new DynamicEngineReference({ nameRef, env }); } /** @@ -85,50 +84,48 @@ export function mountMacro(_name: string, params: Option } class DynamicEngineReference { - public tag: any; - public nameRef: any; + public tag: Tag; + public nameRef: VersionedPathReference; public env: Environment; - public meta: any; - private _lastName: any; - private _lastDef: any; - constructor({ nameRef, env, meta }: any) { + private _lastName: string | null; + private _lastDef: CurriedComponentDefinition | null; + constructor({ nameRef, env }: any) { this.tag = nameRef.tag; this.nameRef = nameRef; this.env = env; - this.meta = meta; - this._lastName = undefined; - this._lastDef = undefined; + this._lastName = null; + this._lastDef = null; } value() { - let { env, nameRef /*meta*/ } = this; - let nameOrDef = nameRef.value(); + let { env, nameRef } = this; + let name = nameRef.value(); - if (typeof nameOrDef === 'string') { - if (this._lastName === nameOrDef) { + if (typeof name === 'string') { + if (this._lastName === name) { return this._lastDef; } assert( - `You used \`{{mount '${nameOrDef}'}}\`, but the engine '${nameOrDef}' can not be found.`, - env.owner.hasRegistration(`engine:${nameOrDef}`), + `You used \`{{mount '${name}'}}\`, but the engine '${name}' can not be found.`, + env.owner.hasRegistration(`engine:${name}`), ); - if (!env.owner.hasRegistration(`engine:${nameOrDef}`)) { + if (!env.owner.hasRegistration(`engine:${name}`)) { return null; } - this._lastName = nameOrDef; - // TODO: maybe I've got the MountDefinition constructor wrong... - this._lastDef = curry(new MountDefinition(nameOrDef)); + this._lastName = name; + this._lastDef = curry(new MountDefinition(name)); return this._lastDef; } else { assert( - `Invalid engine name '${nameOrDef}' specified, engine name must be either a string, null or undefined.`, - nameOrDef === null || nameOrDef === undefined, + `Invalid engine name '${name}' specified, engine name must be either a string, null or undefined.`, + name === null || name === undefined, ); - + this._lastDef = null; + this._lastName = null; return null; } } From e6ba0d64a15111077d8276804cd7c0b1a92e0c4c Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 11 Jan 2018 18:48:56 -0800 Subject: [PATCH 088/135] cleanup self and tag for outlet optimize build for EMBER_GLIMMER_REMOVE_APPLICATION_TEMPLATE_WRAPPER --- .../lib/component-managers/outlet.ts | 133 ++++++++---------- packages/ember-glimmer/lib/renderer.ts | 4 +- 2 files changed, 62 insertions(+), 75 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index 59d6cb0b38c..d9a75df72d2 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -1,7 +1,7 @@ import { ComponentCapabilities, Option, Unique } from '@glimmer/interfaces'; import { ParsedLayout, WrappedBuilder } from '@glimmer/opcode-compiler'; import { - Tag, VersionedPathReference + CONSTANT_TAG, Tag, VersionedPathReference } from '@glimmer/reference'; import { Arguments, @@ -10,6 +10,7 @@ import { Environment, Invocation, TopLevelSyntax, + UNDEFINED_REFERENCE, WithDynamicTagName, WithStaticLayout } from '@glimmer/runtime'; @@ -36,19 +37,10 @@ function instrumentationPayload(def: OutletDefinitionState) { } interface OutletInstanceState { - tag: Tag; - controller: any | undefined; + self: VersionedPathReference; finalize: () => void; } -function createInstanceState(definition: OutletDefinitionState): OutletInstanceState { - return { - tag: definition.ref.tag, - controller: definition.controller, - finalize: _instrumentStart('render.outlet', instrumentationPayload, definition), - }; -} - export interface OutletDefinitionState { ref: VersionedPathReference; name: string; @@ -57,7 +49,7 @@ export interface OutletDefinitionState { controller: any | undefined; } -export const CAPABILITIES: ComponentCapabilities = { +const CAPABILITIES: ComponentCapabilities = { dynamicLayout: false, dynamicTag: false, prepareArgs: false, @@ -77,16 +69,21 @@ class OutletComponentManager extends AbstractManager { throw new Error('Method not implemented.'); } - getLayout(state: OutletDefinitionState, _resolver: RuntimeResolver): Invocation { + getLayout({ template }: OutletDefinitionState, _resolver: RuntimeResolver): Invocation { // The router has already resolved the template - const layout = state.template.asLayout(); + const layout = template.asLayout(); return { handle: layout.compile(), symbolTable: layout.symbolTable @@ -97,16 +94,13 @@ class OutletComponentManager extends AbstractManager { +const OUTLET_MANAGER = new OutletComponentManager(); - getTagName(_component: OutletInstanceState) { - return 'div'; +export class OutletComponentDefinition implements ComponentDefinition { + constructor(public state: OutletDefinitionState, public manager: OutletComponentManager = OUTLET_MANAGER) { } +} - getLayout(state: OutletDefinitionState, resolver: RuntimeResolver): Invocation { - // The router has already resolved the template - const template = state.template; - let layout: TopLevelSyntax; - if (EMBER_GLIMMER_REMOVE_APPLICATION_TEMPLATE_WRAPPER) { - layout = template.asLayout(); - } else { +let createRootOutlet: (outletView: OutletView) => OutletComponentDefinition; + +if (EMBER_GLIMMER_REMOVE_APPLICATION_TEMPLATE_WRAPPER) { + createRootOutlet = (outletView: OutletView) => new OutletComponentDefinition(outletView.state); +} else { + const WRAPPED_CAPABILITIES = Object.assign({}, CAPABILITIES, { + dynamicTag: true, + elementHook: true, + }); + + const WrappedOutletComponentManager = class extends OutletComponentManager + implements WithDynamicTagName { + + getTagName(_component: OutletInstanceState) { + return 'div'; + } + + getLayout(state: OutletDefinitionState, resolver: RuntimeResolver): Invocation { + // The router has already resolved the template + const template = state.template; const compileOptions = Object.assign({}, resolver.templateOptions, { asPartial: false, referrer: template.referrer}); // TODO fix this getting private const parsed: ParsedLayout = (template as any).parsedLayout; - layout = new WrappedBuilder( + const layout = new WrappedBuilder( compileOptions, parsed, - TOP_CAPABILITIES, + WRAPPED_CAPABILITIES, ); + return { + handle: layout.compile(), + symbolTable: layout.symbolTable + }; } - return { - handle: layout.compile(), - symbolTable: layout.symbolTable - }; - } - getCapabilities(): ComponentCapabilities { - if (EMBER_GLIMMER_REMOVE_APPLICATION_TEMPLATE_WRAPPER) { - return CAPABILITIES; + getCapabilities(): ComponentCapabilities { + return WRAPPED_CAPABILITIES; } - return TOP_CAPABILITIES; - } - didCreateElement(_component: OutletInstanceState, _element: Element, _operations: ElementOperations): void { - // to add GUID id and class - _element.setAttribute('class', 'ember-view'); - _element.setAttribute('id', guidFor(_component)); - } -} - -const TOP_MANAGER = new TopLevelOutletComponentManager(); + didCreateElement(component: OutletInstanceState, element: Element, _operations: ElementOperations): void { + // to add GUID id and class + element.setAttribute('class', 'ember-view'); + element.setAttribute('id', guidFor(component)); + } + }; -export class TopLevelOutletComponentDefinition implements ComponentDefinition { - public state: OutletDefinitionState; - public manager: TopLevelOutletComponentManager = TOP_MANAGER; + const WRAPPED_OUTLET_MANAGER = new WrappedOutletComponentManager(); - constructor(instance: OutletView) { - this.state = instance.state; - } + createRootOutlet = (outletView: OutletView) => { + return new OutletComponentDefinition(outletView.state, WRAPPED_OUTLET_MANAGER); + }; } -const OUTLET_MANAGER = new OutletComponentManager(); - -export class OutletComponentDefinition implements ComponentDefinition { - public manager: OutletComponentManager = OUTLET_MANAGER; - - constructor(public state: OutletDefinitionState) { - } -} +export { createRootOutlet }; diff --git a/packages/ember-glimmer/lib/renderer.ts b/packages/ember-glimmer/lib/renderer.ts index 8201306218c..e50a27935ce 100644 --- a/packages/ember-glimmer/lib/renderer.ts +++ b/packages/ember-glimmer/lib/renderer.ts @@ -24,7 +24,7 @@ import { } from 'ember-views'; import RSVP from 'rsvp'; import { BOUNDS } from './component'; -import { TopLevelOutletComponentDefinition } from './component-managers/outlet'; +import { createRootOutlet } from './component-managers/outlet'; import { RootComponentDefinition } from './component-managers/root'; import Environment from './environment'; import { OwnedTemplate } from './template'; @@ -262,7 +262,7 @@ export abstract class Renderer { // renderer HOOKS appendOutletView(view: OutletView, target: Simple.Element) { - let definition = new TopLevelOutletComponentDefinition(view); + let definition = createRootOutlet(view); this._appendDefinition(view, curry(definition), target); } From e99b46927c2393987fb750df60ce89c1e3bcf87f Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 12 Jan 2018 13:25:27 -0500 Subject: [PATCH 089/135] Update to glimmer-vm packages 0.30.4. --- package.json | 12 ++-- yarn.lock | 183 ++++++++++++++++++++++++++------------------------- 2 files changed, 100 insertions(+), 95 deletions(-) diff --git a/package.json b/package.json index 5fd6a4d318e..e53b8353564 100644 --- a/package.json +++ b/package.json @@ -43,12 +43,12 @@ "test:testem": "testem -f testem.dist.js" }, "dependencies": { - "@glimmer/compiler": "^0.30.2", - "@glimmer/node": "^0.30.2", - "@glimmer/program": "^0.30.2", - "@glimmer/reference": "^0.30.2", - "@glimmer/runtime": "^0.30.2", - "@glimmer/vm": "^0.30.2", + "@glimmer/compiler": "^0.30.4", + "@glimmer/node": "^0.30.4", + "@glimmer/program": "^0.30.4", + "@glimmer/reference": "^0.30.4", + "@glimmer/runtime": "^0.30.4", + "@glimmer/vm": "^0.30.4", "broccoli-funnel": "^2.0.1", "broccoli-merge-trees": "^2.0.0", "ember-cli-get-component-path-option": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index 22ec621de74..30021255df7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,117 +2,122 @@ # yarn lockfile v1 -"@glimmer/compiler@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.30.2.tgz#30dd08ca2473ca3b258f9b236e06a1cb7947288f" - dependencies: - "@glimmer/interfaces" "^0.30.2" - "@glimmer/syntax" "^0.30.2" - "@glimmer/util" "^0.30.2" - "@glimmer/wire-format" "^0.30.2" +"@glimmer/compiler@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.30.4.tgz#faafa9940077583b9b987d25ce104c185f61c07f" + dependencies: + "@glimmer/interfaces" "^0.30.4" + "@glimmer/syntax" "^0.30.4" + "@glimmer/util" "^0.30.4" + "@glimmer/wire-format" "^0.30.4" simple-html-tokenizer "^0.4.1" -"@glimmer/encoder@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.30.2.tgz#a9ae83636caa4890fd26fd9c34410cab54e15391" +"@glimmer/encoder@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.30.4.tgz#adce7e163cb69875eded05baa7af9b28df966bac" -"@glimmer/interfaces@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.30.2.tgz#5b34ec121e23ee73e518902f09b6d4f60d3bf507" +"@glimmer/interfaces@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.30.4.tgz#16add8c9e2e8f14c923d016647387acec459bfd5" dependencies: - "@glimmer/wire-format" "^0.30.2" + "@glimmer/wire-format" "^0.30.4" -"@glimmer/node@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.30.2.tgz#de2548558164a03dea2dcc901e6fc6c2c33c83c5" +"@glimmer/low-level@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/low-level/-/low-level-0.30.4.tgz#e045c7a91e17beeb6b19b32e2593d605148f01cd" + +"@glimmer/node@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.30.4.tgz#79acc7e0d379857c4c1e5d2d7bcdd02e192c8d0b" dependencies: - "@glimmer/compiler" "^0.30.2" - "@glimmer/interfaces" "^0.30.2" - "@glimmer/object-reference" "^0.30.2" - "@glimmer/runtime" "^0.30.2" + "@glimmer/compiler" "^0.30.4" + "@glimmer/interfaces" "^0.30.4" + "@glimmer/object-reference" "^0.30.4" + "@glimmer/runtime" "^0.30.4" simple-dom "^0.3.0" -"@glimmer/object-reference@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/object-reference/-/object-reference-0.30.2.tgz#6b08dfd3aabc5279dc137dd8224d145cf1511a01" +"@glimmer/object-reference@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/object-reference/-/object-reference-0.30.4.tgz#576710a678678bb38b83d38cec808d8fdafa9c16" dependencies: - "@glimmer/reference" "^0.30.2" - "@glimmer/util" "^0.30.2" + "@glimmer/reference" "^0.30.4" + "@glimmer/util" "^0.30.4" -"@glimmer/object@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/object/-/object-0.30.2.tgz#b66a2beaa1de28987ff0d4155d8d658527756b82" +"@glimmer/object@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/object/-/object-0.30.4.tgz#95fa3532947dd02ed6d5debfbdb9bd4d3beac177" dependencies: - "@glimmer/object-reference" "^0.30.2" - "@glimmer/util" "^0.30.2" + "@glimmer/object-reference" "^0.30.4" + "@glimmer/util" "^0.30.4" -"@glimmer/opcode-compiler@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/opcode-compiler/-/opcode-compiler-0.30.2.tgz#4fe6f06302af2381e6cfb315c306092c0ea3a34e" +"@glimmer/opcode-compiler@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/opcode-compiler/-/opcode-compiler-0.30.4.tgz#7f8bd7557fc84b6a5ba3cc46d18adc2fcb819dee" dependencies: - "@glimmer/encoder" "^0.30.2" - "@glimmer/interfaces" "^0.30.2" - "@glimmer/program" "^0.30.2" - "@glimmer/syntax" "^0.30.2" - "@glimmer/util" "^0.30.2" - "@glimmer/vm" "^0.30.2" - "@glimmer/wire-format" "^0.30.2" + "@glimmer/encoder" "^0.30.4" + "@glimmer/interfaces" "^0.30.4" + "@glimmer/program" "^0.30.4" + "@glimmer/syntax" "^0.30.4" + "@glimmer/util" "^0.30.4" + "@glimmer/vm" "^0.30.4" + "@glimmer/wire-format" "^0.30.4" simple-html-tokenizer "^0.4.1" -"@glimmer/program@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.30.2.tgz#189ff3fe126a4104d2495b8b35bffda4ef835d04" - dependencies: - "@glimmer/encoder" "^0.30.2" - "@glimmer/interfaces" "^0.30.2" - "@glimmer/util" "^0.30.2" - -"@glimmer/reference@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.30.2.tgz#4a06d3c03b4f490cec38451342fdce8aa7af4d30" - dependencies: - "@glimmer/util" "^0.30.2" - -"@glimmer/runtime@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.30.2.tgz#ef876cec85049c8cef0c4a0a6cee1a93e5be9bb6" - dependencies: - "@glimmer/interfaces" "^0.30.2" - "@glimmer/object" "^0.30.2" - "@glimmer/object-reference" "^0.30.2" - "@glimmer/opcode-compiler" "^0.30.2" - "@glimmer/program" "^0.30.2" - "@glimmer/reference" "^0.30.2" - "@glimmer/util" "^0.30.2" - "@glimmer/vm" "^0.30.2" - "@glimmer/wire-format" "^0.30.2" - -"@glimmer/syntax@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.30.2.tgz#c1acbf44d4c73e7b112192c398e71476cd24e825" - dependencies: - "@glimmer/interfaces" "^0.30.2" - "@glimmer/util" "^0.30.2" +"@glimmer/program@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.30.4.tgz#7a03b28a9aecadaca713969dc9402e92bf974383" + dependencies: + "@glimmer/encoder" "^0.30.4" + "@glimmer/interfaces" "^0.30.4" + "@glimmer/util" "^0.30.4" + +"@glimmer/reference@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.30.4.tgz#5d6b1c0fb5a56154600bf47863c9413895a519a6" + dependencies: + "@glimmer/util" "^0.30.4" + +"@glimmer/runtime@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.30.4.tgz#f34fc52047ce7f89700330c1a37d2f427f18c047" + dependencies: + "@glimmer/interfaces" "^0.30.4" + "@glimmer/low-level" "^0.30.4" + "@glimmer/object" "^0.30.4" + "@glimmer/object-reference" "^0.30.4" + "@glimmer/opcode-compiler" "^0.30.4" + "@glimmer/program" "^0.30.4" + "@glimmer/reference" "^0.30.4" + "@glimmer/util" "^0.30.4" + "@glimmer/vm" "^0.30.4" + "@glimmer/wire-format" "^0.30.4" + +"@glimmer/syntax@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.30.4.tgz#bff250f822fe813f42986b32fadeaafcb0f6e015" + dependencies: + "@glimmer/interfaces" "^0.30.4" + "@glimmer/util" "^0.30.4" handlebars "^4.0.6" simple-html-tokenizer "^0.4.1" -"@glimmer/util@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.30.2.tgz#dd3ed4293b97ce7d89f3b8682381e666c43ba6d7" +"@glimmer/util@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.30.4.tgz#7fbb9e51db17560ac483a33f185acf3ae36838d6" -"@glimmer/vm@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.30.2.tgz#cb2bc6f29ebcfceb6506ecd6d97c832a22aa8106" +"@glimmer/vm@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.30.4.tgz#6069b68f11c178d6911c4105ca07a5a41d435b26" dependencies: - "@glimmer/interfaces" "^0.30.2" - "@glimmer/program" "^0.30.2" - "@glimmer/util" "^0.30.2" + "@glimmer/interfaces" "^0.30.4" + "@glimmer/program" "^0.30.4" + "@glimmer/util" "^0.30.4" -"@glimmer/wire-format@^0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.30.2.tgz#ce4a4c903ada28ee2c62b857b69dfdc06512f53a" +"@glimmer/wire-format@^0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.30.4.tgz#b85c211b59f6b54ee93c2c261db5a03aada3a791" dependencies: - "@glimmer/util" "^0.30.2" + "@glimmer/util" "^0.30.4" "@types/acorn@*": version "4.0.3" From edae558c483e64be8c6c504eaaeb3cc3814199f0 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 12 Jan 2018 13:45:12 -0500 Subject: [PATCH 090/135] Fix a couple contextual component tests. --- .../components/contextual-components-test.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/ember-glimmer/tests/integration/components/contextual-components-test.js b/packages/ember-glimmer/tests/integration/components/contextual-components-test.js index 36fcb5c5a4a..6c09a1a5a70 100644 --- a/packages/ember-glimmer/tests/integration/components/contextual-components-test.js +++ b/packages/ember-glimmer/tests/integration/components/contextual-components-test.js @@ -167,15 +167,15 @@ moduleFor('Components test: contextual components', class extends RenderingTest this.runTask(() => this.context.set('model.greeting', 'Good morning ')); - this.assertText('ZackGood morning '); + this.assertText('Good morning Zack Zack Good morning '); - this.runTask(() => this.context.set('model.name', 'Matthew')); + this.runTask(() => this.context.set('model.name', 'Matthew ')); - this.assertText('MatthewGood morning '); + this.assertText('Good morning Matthew Matthew Good morning '); - this.runTask(() => this.context.set('model', { greeting: 'Gabon ', name: 'Zack' })); + this.runTask(() => this.context.set('model', { greeting: 'Gabon ', name: 'Zack ' })); - this.assertText('ZackGabon '); + this.assertText('Gabon Zack Zack Gabon '); } ['@test renders with component helper with curried params, hash']() { @@ -355,7 +355,7 @@ moduleFor('Components test: contextual components', class extends RenderingTest }); this.assertText('Hodi Sigmundur 33'); - + this.runTask(() => this.rerender()); this.assertText('Hodi Sigmundur 33'); @@ -1234,13 +1234,13 @@ moduleFor('Components test: contextual components', class extends RenderingTest ['@test GH#14632 give useful warning when calling contextual components with input as a name']() { expectAssertion(() => { this.render('{{component (component "input" type="text")}}'); - }, 'You cannot use the input helper as a contextual helper. Please extend TextField or Checkbox to use it as a contextual component.'); + }, 'You cannot use \'input\' as a component name. Component names must contain a hyphen.'); } ['@test GH#14632 give useful warning when calling contextual components with textarea as a name']() { expectAssertion(() => { this.render('{{component (component "textarea" type="text")}}'); - }, 'You cannot use the textarea helper as a contextual helper. Please extend TextArea to use it as a contextual component.'); + }, 'You cannot use \'textarea\' as a component name. Component names must contain a hyphen.'); } }); From bfbd8592a8b545623b0750d42e7513f770891e71 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 12 Jan 2018 13:45:26 -0500 Subject: [PATCH 091/135] Skip (for now) two tests around `(component thingThatDoesnExist)` This pattern is allowed for `{{component` but was previously not allowed for `(component`. It seems reasonable to have parity here, and I believe we should allow `(component somethingNullOrNotFound` to be inert (and not throw an error). --- .../integration/components/contextual-components-test.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/ember-glimmer/tests/integration/components/contextual-components-test.js b/packages/ember-glimmer/tests/integration/components/contextual-components-test.js index 6c09a1a5a70..42117213fca 100644 --- a/packages/ember-glimmer/tests/integration/components/contextual-components-test.js +++ b/packages/ember-glimmer/tests/integration/components/contextual-components-test.js @@ -633,7 +633,8 @@ moduleFor('Components test: contextual components', class extends RenderingTest this.assertText('Hodi Sergio'); } - ['@test raises an asserton when component path is null']() { + ['@skip raises an asserton when component path is null']() { + // TODO: should we change this to be allowed? The test is currently failing because glimmer considers this to be fine... expectAssertion(() => { this.render('{{component (component lookupComponent)}}'); }); @@ -642,10 +643,11 @@ moduleFor('Components test: contextual components', class extends RenderingTest ['@test raises an assertion when component path is not a component name (static)']() { expectAssertion(() => { this.render('{{component (component "not-a-component")}}'); - }, 'The component helper cannot be used without a valid component name. You used "not-a-component" via (component "not-a-component")'); + }, 'Could not find component named \"not-a-component\" (no component or template with that name was found)'); } - ['@test raises an assertion when component path is not a component name (dynamic)']() { + ['@skip raises an assertion when component path is not a component name (dynamic)']() { + // TODO: should we change this to be allowed? The test is currently failing because glimmer considers this to be fine... expectAssertion(() => { this.render('{{component (component compName)}}', { compName: 'not-a-component' From 001b162baa6eeed726d773e0433e21fe347d4e82 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Fri, 12 Jan 2018 14:21:07 -0800 Subject: [PATCH 092/135] Get render working, cleanup typing --- .../component-managers/definition-state.ts | 2 +- .../lib/component-managers/outlet.ts | 1 - .../lib/component-managers/render.ts | 46 ++++++++------ packages/ember-glimmer/lib/helper.ts | 60 +++++++++++++++---- packages/ember-glimmer/lib/resolver.ts | 29 +++++---- packages/ember-glimmer/lib/syntax/render.ts | 15 ++--- .../ember-glimmer/lib/utils/references.ts | 59 +++++++++--------- packages/ember-utils/lib/index.d.ts | 8 +-- packages/ember-views/lib/index.d.ts | 2 +- 9 files changed, 136 insertions(+), 86 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/definition-state.ts b/packages/ember-glimmer/lib/component-managers/definition-state.ts index f63043edc69..adbb69b6987 100644 --- a/packages/ember-glimmer/lib/component-managers/definition-state.ts +++ b/packages/ember-glimmer/lib/component-managers/definition-state.ts @@ -12,7 +12,7 @@ import { Component } from '../utils/curly-component-state-bucket'; export default interface DefinitionState { capabilities: ComponentCapabilities; name: string; - ComponentClass: Factory; + ComponentClass: Factory; handle: Option; symbolTable?: ProgramSymbolTable; template?: any; diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index d9a75df72d2..c408a8ed4cf 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -9,7 +9,6 @@ import { ElementOperations, Environment, Invocation, - TopLevelSyntax, UNDEFINED_REFERENCE, WithDynamicTagName, WithStaticLayout diff --git a/packages/ember-glimmer/lib/component-managers/render.ts b/packages/ember-glimmer/lib/component-managers/render.ts index 3e81f052b8a..bdbcb99b231 100644 --- a/packages/ember-glimmer/lib/component-managers/render.ts +++ b/packages/ember-glimmer/lib/component-managers/render.ts @@ -6,30 +6,40 @@ import { } from '@glimmer/reference'; import { Arguments, - ComponentDefinition + ComponentDefinition, + Invocation, + WithStaticLayout } from '@glimmer/runtime'; -import { assert } from 'ember-debug'; import { DEBUG } from 'ember-env-flags'; import { generateController, generateControllerFactory } from 'ember-routing'; +import { OwnedTemplateMeta } from 'ember-views'; import Environment from '../environment'; import { DynamicScope } from '../renderer'; import { OwnedTemplate } from '../template'; +import { OrphanedOutletReference } from '../utils/outlet'; import { RootReference } from '../utils/references'; import AbstractManager from './abstract'; export interface RenderDefinitionState { name: string; template: OwnedTemplate | undefined; + env: Environment; } -export abstract class AbstractRenderManager extends AbstractManager { - layoutFor(definition: RenderDefinition, _bucket: RenderState, _env: Environment): VMHandle { - // only curly components can have lazy layout - assert('definition is missing a template', !!definition.template); +export abstract class AbstractRenderManager extends AbstractManager + implements WithStaticLayout { - throw Error('use resolver.lookupTemplate resolver.compileTemplate'); - // return env.getCompiledBlock(OutletLayoutCompiler, definition.template!); + getLayout({ template }: RenderDefinitionState): Invocation { + const layout = template!.asLayout(); + return { + handle: layout.compile(), + symbolTable: layout.symbolTable + }; + } + + layoutFor(_definition: RenderDefinition, _bucket: RenderState, _env: Environment): VMHandle { + throw new Error('not implemented'); } getSelf({ controller }: RenderState) { @@ -71,7 +81,7 @@ class SingletonRenderManager extends AbstractRenderManager { } if (dynamicScope.rootOutletState) { - dynamicScope.outletState = dynamicScope.rootOutletState.getOrphan(name); + dynamicScope.outletState = new OrphanedOutletReference(dynamicScope.rootOutletState, name); } return { controller } as RenderState; @@ -110,7 +120,7 @@ class NonSingletonRenderManager extends AbstractRenderManager { } if (dynamicScope.rootOutletState) { - dynamicScope.outletState = dynamicScope.rootOutletState.getOrphan(name); + dynamicScope.outletState = new OrphanedOutletReference(dynamicScope.rootOutletState, name); } return { controller, model: modelRef }; @@ -136,16 +146,14 @@ class NonSingletonRenderManager extends AbstractRenderManager { export const NON_SINGLETON_RENDER_MANAGER = new NonSingletonRenderManager(); export class RenderDefinition implements ComponentDefinition { - public name: string; - public template: OwnedTemplate | undefined; - public env: Environment; + public state: RenderDefinitionState; - public manager: SingletonRenderManager | NonSingletonRenderManager; - constructor(name: string, template: OwnedTemplate, env: Environment, manager: SingletonRenderManager | NonSingletonRenderManager) { - this.name = name; - this.template = template; - this.env = env; - this.manager = manager; + constructor(name: string, template: OwnedTemplate, env: Environment, public manager: SingletonRenderManager | NonSingletonRenderManager) { + this.state = { + name, + template, + env, + }; } } diff --git a/packages/ember-glimmer/lib/helper.ts b/packages/ember-glimmer/lib/helper.ts index 037c56e95f0..c07e237d0cd 100644 --- a/packages/ember-glimmer/lib/helper.ts +++ b/packages/ember-glimmer/lib/helper.ts @@ -2,13 +2,51 @@ @module @ember/component */ +import { Dict, Opaque } from '@glimmer/interfaces'; import { DirtyableTag } from '@glimmer/reference'; -import { Dict, Opaque } from '@glimmer/util'; import { FrameworkObject } from 'ember-runtime'; -import { symbol } from 'ember-utils'; +import { Factory, symbol } from 'ember-utils'; export const RECOMPUTE_TAG = symbol('RECOMPUTE_TAG'); +export type HelperFunction = (positional: Opaque[], named: Dict) => Opaque; + +export type SimpleHelperFactory = Factory; +export type ClassHelperFactory = Factory; + +export type HelperFactory = SimpleHelperFactory | ClassHelperFactory; + +export interface SimpleHelper { + isHelperFactory: true; + isSimpleHelper: true; + + create(): SimpleHelper; + compute: HelperFunction; +} + +export interface HelperStatic { + isHelperFactory: true; + isSimpleHelper: false; + + create(): HelperInstance; +} + +export interface HelperInstance { + compute: HelperFunction; + destroy(): void; +} + +export function isHelperFactory(helper: any | undefined | null): helper is HelperFactory { + return typeof helper === 'object' && + helper !== null && + typeof helper.class === 'function' && + helper.class.isHelperFactory; +} + +export function isSimpleHelper(helper: HelperFactory): helper is SimpleHelperFactory { + return helper.class.isSimpleHelper; +} + /** Ember Helpers are functions that can compute values, and are used in templates. For example, this code calls a helper named `format-currency`: @@ -52,8 +90,6 @@ export const RECOMPUTE_TAG = symbol('RECOMPUTE_TAG'); @since 1.13.0 */ let Helper = FrameworkObject.extend({ - isHelperInstance: true, - init() { this._super(...arguments); this[RECOMPUTE_TAG] = DirtyableTag.create(); @@ -103,14 +139,14 @@ let Helper = FrameworkObject.extend({ Helper.reopenClass({ isHelperFactory: true, + isSimpleHelper: false, }); -export class SimpleHelper { - isHelperFactory = true; - isHelperInstance = true; - isSimpleHelperFactory = true; +class Wrapper implements SimpleHelper { + isHelperFactory: true = true; + isSimpleHelper: true = true; - constructor(public compute: (positional: any[], named: Dict) => any) { } + constructor(public compute: HelperFunction) {} create() { return this; @@ -139,8 +175,8 @@ export class SimpleHelper { @public @since 1.13.0 */ -export function helper(helperFn: (params: any[], hash?: any) => string) { - return new SimpleHelper(helperFn); +export function helper(helperFn: HelperFunction): SimpleHelper { + return new Wrapper(helperFn); } -export default Helper; +export default Helper as HelperStatic; diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 87b3af16c55..22557ed1a31 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -26,6 +26,7 @@ import { import { GLIMMER_CUSTOM_COMPONENT_MANAGER } from 'ember/features'; import CompileTimeLookup from './compile-time-lookup'; import { CurlyComponentDefinition } from './component-managers/curly'; +import { isHelperFactory, isSimpleHelper } from './helper'; import { default as classHelper } from './helpers/-class'; import { default as htmlSafeHelper } from './helpers/-html-safe'; import { default as inputTypeHelper } from './helpers/-input-type'; @@ -183,7 +184,6 @@ export default class RuntimeResolver implements IRuntimeResolver { - const helper = this.builtInHelpers[name]; if (helper !== undefined) { return helper; @@ -193,17 +193,24 @@ export default class RuntimeResolver implements IRuntimeResolver SimpleHelperReference.create(helperFactory, vm, args.capture()); - } else if (helperFactory && helperFactory.class.isHelperFactory) { - return (vm, args) => ClassBasedHelperReference.create(helperFactory, vm, args.capture()); - } else { + if (!isHelperFactory(factory)) { return null; - // throw new Error(`${name} is not a helper`); } + + if (isSimpleHelper(factory)) { + const helper = factory.create().compute; + return (_vm, args) => { + return SimpleHelperReference.create(helper, args.capture()); + }; + } + + return (vm, args) => { + const helper = factory.create(); + vm.newDestroyable(helper); + return ClassBasedHelperReference.create(helper, args.capture()); + }; } private _lookupPartial(name: string, meta: OwnedTemplateMeta): PartialDefinition { @@ -228,12 +235,12 @@ export default class RuntimeResolver implements IRuntimeResolver { let { layout, component } = lookupComponent(meta.owner, name, makeOptions(meta.moduleName)); - let customManager; + let customManager: any | undefined; if (GLIMMER_CUSTOM_COMPONENT_MANAGER) { let managerId = layout && layout.referrer.managerId; if (managerId) { - customManager = meta.owner.factoryFor(`component-manager:${managerId}`).class; + customManager = meta.owner.factoryFor(`component-manager:${managerId}`); } } diff --git a/packages/ember-glimmer/lib/syntax/render.ts b/packages/ember-glimmer/lib/syntax/render.ts index 844aebd4b3d..5a9852bf76f 100644 --- a/packages/ember-glimmer/lib/syntax/render.ts +++ b/packages/ember-glimmer/lib/syntax/render.ts @@ -6,10 +6,11 @@ Remove after 3.4 once _ENABLE_RENDER_SUPPORT flag is no longer needed. import { Option } from '@glimmer/interfaces'; import { OpcodeBuilder } from '@glimmer/opcode-compiler'; -import { ConstReference, isConst, VersionedPathReference } from '@glimmer/reference'; +import { isConst, VersionedPathReference } from '@glimmer/reference'; import { Arguments, CurriedComponentDefinition, + curry, VM, } from '@glimmer/runtime'; import * as WireFormat from '@glimmer/wire-format'; @@ -23,6 +24,7 @@ import { } from '../component-managers/render'; import Environment from '../environment'; import { OwnedTemplate } from '../template'; +import { UnboundReference } from '../utils/references'; export function renderHelper(vm: VM, args: Arguments): VersionedPathReference { let env = vm.env as Environment; @@ -37,7 +39,7 @@ export function renderHelper(vm: VM, args: Arguments): VersionedPathReference(`template:${templateName}`); + let template = env.owner.lookup(`template:${templateName}`); let controllerName: string; @@ -56,11 +58,10 @@ export function renderHelper(vm: VM, args: Arguments): VersionedPathReference any; - public args: any; - - static create(Helper: SimpleHelper, _vm: VM, args: CapturedArguments) { - let helper = Helper.create(); + public helper: HelperFunction; + public args: CapturedArguments; + static create(helper: HelperFunction, args: CapturedArguments) { if (isConst(args)) { let { positional, named } = args; @@ -357,19 +355,14 @@ export class SimpleHelperReference extends CachedReference { maybeFreeze(namedValue); } - let result = helper.compute(positionalValue, namedValue); - - if (typeof result === 'object' && result !== null || typeof result === 'function') { - return new RootReference(result); - } else { - return PrimitiveReference.create(result); - } + let result = helper(positionalValue, namedValue); + return valueToRef(result); } else { - return new SimpleHelperReference(helper.compute, args); + return new SimpleHelperReference(helper, args); } } - constructor(helper: (positionalValue: any, namedValue: any) => any, args: CapturedArguments) { + constructor(helper: HelperFunction, args: CapturedArguments) { super(); this.tag = args.tag; @@ -393,16 +386,14 @@ export class SimpleHelperReference extends CachedReference { } export class ClassBasedHelperReference extends CachedReference { - public instance: any; - public args: any; + public instance: HelperInstance; + public args: CapturedArguments; - static create(helperClass: any, vm: VM, args: CapturedArguments) { - let instance = helperClass.create(); - vm.newDestroyable(instance); + static create(instance: HelperInstance, args: CapturedArguments) { return new ClassBasedHelperReference(instance, args); } - constructor(instance: any, args: CapturedArguments) { + constructor(instance: HelperInstance, args: CapturedArguments) { super(); this.tag = combine([instance[RECOMPUTE_TAG], args.tag]); @@ -445,16 +436,12 @@ export class InternalHelperReference extends CachedReference { // @implements PathReference export class UnboundReference extends ConstReference { - static create(value: T) { - if (typeof value === 'object' && value !== null) { - return new UnboundReference(value); - } else { - return PrimitiveReference.create(value); - } + static create(value: T): VersionedPathReference { + return valueToRef(value, false); } get(key: string) { - return new UnboundReference(get(this.inner, key)); + return valueToRef(get(this.inner, key), false); } } @@ -466,4 +453,16 @@ export function referenceFromParts(root: VersionedPathReference, parts: } return reference; -} \ No newline at end of file +} + +export function valueToRef(value: any | null | undefined, bound = true): VersionedPathReference { + if (value !== null && typeof value === 'object') { + // root of interop with ember objects + return bound ? new RootReference(value) : new UnboundReference(value); + } + // ember doesn't do observing with functions + if (typeof value === 'function') { + return new UnboundReference(value); + } + return PrimitiveReference.create(value); +} diff --git a/packages/ember-utils/lib/index.d.ts b/packages/ember-utils/lib/index.d.ts index a07781dc2a9..f1eb52fda41 100644 --- a/packages/ember-utils/lib/index.d.ts +++ b/packages/ember-utils/lib/index.d.ts @@ -1,7 +1,7 @@ import { Opaque } from '@glimmer/interfaces'; -export interface Factory { - class: any; +export interface Factory { + class: C; fullName: string; normalizedName: string; create(props?: { [prop: string]: any; }): T; @@ -14,8 +14,8 @@ export interface LookupOptions { export interface Owner { lookup(fullName: string, options?: LookupOptions): T; lookup(fullName: string, options?: LookupOptions): any; - factoryFor(fullName: string, options?: LookupOptions): Factory; - factoryFor(fullName: string, options?: LookupOptions): Factory; + factoryFor(fullName: string, options?: LookupOptions): Factory | undefined; + factoryFor(fullName: string, options?: LookupOptions): Factory | undefined; buildChildEngineInstance(name: string): T; hasRegistration(name: string, options?: LookupOptions): boolean; diff --git a/packages/ember-views/lib/index.d.ts b/packages/ember-views/lib/index.d.ts index 6cf1f307d41..cc9cdec7763 100644 --- a/packages/ember-views/lib/index.d.ts +++ b/packages/ember-views/lib/index.d.ts @@ -33,7 +33,7 @@ export function hasPartial(name: string, owner: any): boolean; export function lookupComponent(owner: Owner, name: string, options?: { source?: string }): { layout: Template; - component: Factory; + component: Factory; }; export function lookupPartial(templateName: string, owner: Owner): any; From c7a7bc7665883fa872ebb423bb08c0aea3bf3be8 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 12 Jan 2018 17:29:34 -0500 Subject: [PATCH 093/135] Fix remaining contextual component tests. Issue deprecation when conflicting named and positional params exist (changed from per-layer assert to post-merge deprecation). --- .../lib/component-managers/curly.ts | 6 +- .../components/contextual-components-test.js | 136 ++++++++---------- 2 files changed, 68 insertions(+), 74 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index bd2e461c3c0..2b6a9f2a85e 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -28,6 +28,7 @@ import { Destroyable, EMPTY_ARRAY, Opaque } from '@glimmer/util'; import { privatize as P } from 'container'; import { assert, + deprecate, } from 'ember-debug'; import { DEBUG } from 'ember-env-flags'; import { @@ -223,7 +224,10 @@ export default class CurlyComponentManager extends AbstractManager { + this.render('{{component (component (component "-looked-up" "Sergio" 29) name="Marvin" age=21)}}'); + }, 'You cannot specify both a positional param (at position 1) and the hash argument `age`.'); - this.assertText('Marvin 21'); + this.assertText('Sergio 29'); this.runTask(() => this.rerender()); - this.assertText('Marvin 21'); + this.assertText('Sergio 29'); } - ['@test nested components with positional params at outer layer are overwriten by hash parameters']() { + ['@test nested components with positional params at outer layer are override hash parameters [DEPRECATED]']() { this.registerComponent('-looked-up', { ComponentClass: Component.extend().reopenClass({ positionalParams: ['greeting', 'name', 'age'] @@ -343,33 +345,30 @@ moduleFor('Components test: contextual components', class extends RenderingTest template: '{{greeting}} {{name}} {{age}}' }); - this.render(strip` - {{#with (component "-looked-up" "Hola" "Dolores" 33) as |first|}} - {{#with (component first greeting="Hej" name="Sigmundur") as |second|}} - {{component second greeting=model.greeting}} + expectDeprecation(() => { + this.render( + strip` + {{#with (component "-looked-up" "Hola" "Dolores" 33) as |first|}} + {{#with (component first greeting="Hej" name="Sigmundur") as |second|}} + {{component second greeting=model.greeting}} {{/with}} - {{/with}}`, { + {{/with}}`, + { model: { greeting: 'Hodi' } - }); - - this.assertText('Hodi Sigmundur 33'); - - this.runTask(() => this.rerender()); - - this.assertText('Hodi Sigmundur 33'); - - this.runTask(() => this.context.set('model.greeting', 'Kaixo')); + } + ); + }, 'You cannot specify both a positional param (at position 1) and the hash argument `name`.'); - this.assertText('Kaixo Sigmundur 33'); + this.assertText('Hola Dolores 33'); - this.runTask(() => this.context.set('model', { greeting: 'Hodi' })); + this.runTask(() => this.rerender()); - this.assertText('Hodi Sigmundur 33'); + this.assertText('Hola Dolores 33'); } - ['@test nested components with positional params at middle layer are partially overwriten by hash parameters']() { + ['@test nested components with positional params at middle layer partially override hash parameters [DEPRECATED]']() { this.registerComponent('-looked-up', { ComponentClass: Component.extend().reopenClass({ positionalParams: ['greeting', 'name', 'age'] @@ -378,33 +377,30 @@ moduleFor('Components test: contextual components', class extends RenderingTest template: '{{greeting}} {{name}} {{age}}' }); - this.render(strip` - {{#with (component "-looked-up" greeting="Hola" name="Dolores" age=33) as |first|}} - {{#with (component first "Hej" "Sigmundur") as |second|}} - {{component second greeting=model.greeting}} - {{/with}} - {{/with}}`, { - model: { - greeting: 'Hodi' - } - }); + expectDeprecation(() => { + this.render( + strip` + {{#with (component "-looked-up" greeting="Hola" name="Dolores" age=33) as |first|}} + {{#with (component first "Hej" "Sigmundur") as |second|}} + {{component second greeting=model.greeting}} + {{/with}} + {{/with}}`, + { + model: { + greeting: 'Hodi' + } + } + ); + }, 'You cannot specify both a positional param (at position 0) and the hash argument `greeting`.'); - this.assertText('Hodi Sigmundur 33'); + this.assertText('Hej Sigmundur 33'); this.runTask(() => this.rerender()); - this.assertText('Hodi Sigmundur 33'); - - this.runTask(() => this.context.set('model.greeting', 'Kaixo')); - - this.assertText('Kaixo Sigmundur 33'); - - this.runTask(() => this.context.set('model', { greeting: 'Hodi' })); - - this.assertText('Hodi Sigmundur 33'); + this.assertText('Hej Sigmundur 33'); } - ['@test nested components with positional params at invocation override earlier hash parameters']() { + ['@test nested components with positional params at invocation override earlier hash parameters [DEPRECATED]']() { this.registerComponent('-looked-up', { ComponentClass: Component.extend().reopenClass({ positionalParams: ['greeting', 'name', 'age'] @@ -413,16 +409,21 @@ moduleFor('Components test: contextual components', class extends RenderingTest template: '{{greeting}} {{name}} {{age}}' }); - this.render(strip` - {{#with (component "-looked-up" greeting="Hola" name="Dolores" age=33) as |first|}} - {{#with (component first greeting="Hej" name="Sigmundur") as |second|}} - {{component second model.greeting}} - {{/with}} - {{/with}}`, { - model: { - greeting: 'Hodi' - } - }); + expectDeprecation(() => { + this.render( + strip` + {{#with (component "-looked-up" greeting="Hola" name="Dolores" age=33) as |first|}} + {{#with (component first greeting="Hej" name="Sigmundur") as |second|}} + {{component second model.greeting}} + {{/with}} + {{/with}}`, + { + model: { + greeting: 'Hodi' + } + } + ); + }, 'You cannot specify both a positional param (at position 0) and the hash argument `greeting`.'); this.assertText('Hodi Sigmundur 33'); @@ -559,7 +560,7 @@ moduleFor('Components test: contextual components', class extends RenderingTest this.assertText('Inner 28'); } - ['@test conflicting positional and hash parameters raise an assertion if in the same component context']() { + ['@test conflicting positional and hash parameters trigger a deprecation if in the same component context [DEPRECATED]']() { this.registerComponent('-looked-up', { ComponentClass: Component.extend().reopenClass({ positionalParams: ['name'] @@ -567,24 +568,11 @@ moduleFor('Components test: contextual components', class extends RenderingTest template: '{{greeting}} {{name}}' }); - expectAssertion(() => { + expectDeprecation(() => { this.render('{{component (component "-looked-up" "Hodari" name="Sergio") "Hodari" greeting="Hodi"}}'); }, 'You cannot specify both a positional param (at position 0) and the hash argument `name`.'); } - ['@test conflicting positional and hash parameters raise an assertion if in the same component context with prior curried positional params']() { - this.registerComponent('-looked-up', { - ComponentClass: Component.extend().reopenClass({ - positionalParams: ['name'] - }), - template: '{{greeting}} {{name}}' - }); - - expectAssertion(() => { - this.render('{{component (component "-looked-up" "Hodari") "Sergio" name="Hodi"}}'); - }, 'You cannot specify both a positional param (at position 0) and the hash argument `name`.'); - } - ['@test conflicting positional and hash parameters does not raise an assertion if rerendered']() { // In some cases, rerendering with a positional param used to cause an // assertion. This test checks it does not. @@ -616,7 +604,7 @@ moduleFor('Components test: contextual components', class extends RenderingTest this.assertText('Hodi Hodari'); } - ['@test conflicting positional and hash parameters does not raise an assertion if in different component context']() { + ['@test conflicting positional and hash parameters trigger a deprecation [DEPRECATED]']() { this.registerComponent('-looked-up', { ComponentClass: Component.extend().reopenClass({ positionalParams: ['name'] @@ -624,13 +612,15 @@ moduleFor('Components test: contextual components', class extends RenderingTest template: '{{greeting}} {{name}}' }); - this.render('{{component (component "-looked-up" "Hodari") name="Sergio" greeting="Hodi"}}'); + expectDeprecation(() => { + this.render('{{component (component "-looked-up" "Hodari") name="Sergio" greeting="Hodi"}}'); + }, 'You cannot specify both a positional param (at position 0) and the hash argument `name`.'); - this.assertText('Hodi Sergio'); + this.assertText('Hodi Hodari'); this.runTask(() => this.rerender()); - this.assertText('Hodi Sergio'); + this.assertText('Hodi Hodari'); } ['@skip raises an asserton when component path is null']() { From 9240931232dc8adb99aaf24dce8739421ae44a44 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Fri, 12 Jan 2018 14:50:43 -0800 Subject: [PATCH 094/135] Fix helper and part of render --- packages/ember-glimmer/lib/component-managers/render.ts | 2 +- packages/ember-glimmer/lib/helper.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/render.ts b/packages/ember-glimmer/lib/component-managers/render.ts index bdbcb99b231..9a36ffaa7cd 100644 --- a/packages/ember-glimmer/lib/component-managers/render.ts +++ b/packages/ember-glimmer/lib/component-managers/render.ts @@ -63,7 +63,7 @@ const CAPABILITIES = { dynamicLayout: false, dynamicTag: false, prepareArgs: false, - createArgs: false, + createArgs: true, attributeHook: false, elementHook: false }; diff --git a/packages/ember-glimmer/lib/helper.ts b/packages/ember-glimmer/lib/helper.ts index c07e237d0cd..3121eebfe89 100644 --- a/packages/ember-glimmer/lib/helper.ts +++ b/packages/ember-glimmer/lib/helper.ts @@ -39,8 +39,7 @@ export interface HelperInstance { export function isHelperFactory(helper: any | undefined | null): helper is HelperFactory { return typeof helper === 'object' && helper !== null && - typeof helper.class === 'function' && - helper.class.isHelperFactory; + helper.class && helper.class.isHelperFactory; } export function isSimpleHelper(helper: HelperFactory): helper is SimpleHelperFactory { From 221d6bb595fd46686d30b56dd11d160aff3a35c0 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 12 Jan 2018 17:31:35 -0500 Subject: [PATCH 095/135] Migrate curly test to expectDeprecation for currying conflicts. --- .../tests/integration/components/curly-components-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember-glimmer/tests/integration/components/curly-components-test.js b/packages/ember-glimmer/tests/integration/components/curly-components-test.js index 05176549daa..0771543948a 100644 --- a/packages/ember-glimmer/tests/integration/components/curly-components-test.js +++ b/packages/ember-glimmer/tests/integration/components/curly-components-test.js @@ -1744,7 +1744,7 @@ moduleFor('Components test: curly components', class extends RenderingTest { template: '{{name}}' }); - expectAssertion(() => { + expectDeprecation(() => { this.render('{{sample-component notMyName name=myName}}', { myName: 'Quint', notMyName: 'Sergio' From 41100931f3419b2f33843eae18605baddf266041 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Fri, 12 Jan 2018 15:21:44 -0800 Subject: [PATCH 096/135] remove unused layoutFor and stub only in abstract base. --- .../lib/component-managers/abstract.ts | 5 +---- .../lib/component-managers/curly.ts | 4 ---- .../lib/component-managers/mount.ts | 4 ---- .../lib/component-managers/render.ts | 17 ++++++----------- .../lib/component-managers/template-only.ts | 4 ---- .../custom-component-manager-test.js | 4 ---- 6 files changed, 7 insertions(+), 31 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/abstract.ts b/packages/ember-glimmer/lib/component-managers/abstract.ts index 2b67b86ba58..2a3ea4c72c2 100644 --- a/packages/ember-glimmer/lib/component-managers/abstract.ts +++ b/packages/ember-glimmer/lib/component-managers/abstract.ts @@ -49,10 +49,7 @@ export default abstract class AbstractManager implements ComponentManager< dynamicScope: DynamicScope, caller: VersionedPathReference, hasDefaultBlock: boolean): T; - abstract layoutFor( - definition: any, - component: T, - env: Environment): VMHandle; + abstract getSelf(component: T): VersionedPathReference; abstract getCapabilities(state: U): ComponentCapabilities; diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 2b6a9f2a85e..7326e63a777 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -128,10 +128,6 @@ export default class CurlyComponentManager extends AbstractManager, WithDynamicLayout { - layoutFor(_state: DefinitionState, _component: ComponentStateBucket, _env: Environment): Unique<'Handle'> { - throw new Error('Method not implemented.'); - } - getLayout(state: DefinitionState, _resolver: RuntimeResolver): Invocation { return { // TODO fix diff --git a/packages/ember-glimmer/lib/component-managers/mount.ts b/packages/ember-glimmer/lib/component-managers/mount.ts index 7d35986d7fc..3419540bd9a 100644 --- a/packages/ember-glimmer/lib/component-managers/mount.ts +++ b/packages/ember-glimmer/lib/component-managers/mount.ts @@ -62,10 +62,6 @@ class MountManager extends AbstractManager }; } - layoutFor(_definition: EngineDefinitionState, _component: EngineBucket, _env: Environment): Unique<'Handle'> { - throw new Error('Method not implemented.'); - } - getCapabilities(state: EngineDefinitionState): ComponentCapabilities { return state.capabilities; } diff --git a/packages/ember-glimmer/lib/component-managers/render.ts b/packages/ember-glimmer/lib/component-managers/render.ts index 9a36ffaa7cd..59eb603d7ad 100644 --- a/packages/ember-glimmer/lib/component-managers/render.ts +++ b/packages/ember-glimmer/lib/component-managers/render.ts @@ -2,7 +2,7 @@ import { ComponentCapabilities, VMHandle, } from '@glimmer/interfaces'; import { - CONSTANT_TAG, Tag + CONSTANT_TAG, Tag, VersionedPathReference } from '@glimmer/reference'; import { Arguments, @@ -38,10 +38,6 @@ export abstract class AbstractRenderManager extends AbstractManager; controller: any; - model: any; - component: any; } const CAPABILITIES = { @@ -109,7 +104,7 @@ class NonSingletonRenderManager extends AbstractRenderManager { args: Arguments, dynamicScope: DynamicScope) { let { name, env } = definition; - let modelRef = args.positional.at(0); + let modelRef = args.positional.at(1); let controllerFactory = env.owner.factoryFor(`controller:${name}`); let factory: any = controllerFactory || generateControllerFactory(env.owner, name); @@ -123,7 +118,7 @@ class NonSingletonRenderManager extends AbstractRenderManager { dynamicScope.outletState = new OrphanedOutletReference(dynamicScope.rootOutletState, name); } - return { controller, model: modelRef }; + return { controller, model: modelRef }; } update({ controller, model }: RenderState) { @@ -134,8 +129,8 @@ class NonSingletonRenderManager extends AbstractRenderManager { return CAPABILITIES; } - getTag(): Tag { - return CONSTANT_TAG; + getTag({ model }: RenderState): Tag { + return model.tag; } getDestructor({ controller }: RenderState) { diff --git a/packages/ember-glimmer/lib/component-managers/template-only.ts b/packages/ember-glimmer/lib/component-managers/template-only.ts index f889fe49fb2..e8b81413ec4 100644 --- a/packages/ember-glimmer/lib/component-managers/template-only.ts +++ b/packages/ember-glimmer/lib/component-managers/template-only.ts @@ -22,10 +22,6 @@ export default class TemplateOnlyComponentManager extends AbstractManager return null; } - layoutFor({ template }: TemplateOnlyComponentDefinition, _: null, env: Environment): CompiledDynamicProgram { - return env.getCompiledBlock(TemplateOnlyComponentLayoutCompiler, template); - } - getSelf(): VersionedPathReference { return NULL_REFERENCE; } diff --git a/packages/ember-glimmer/tests/integration/custom-component-manager-test.js b/packages/ember-glimmer/tests/integration/custom-component-manager-test.js index 9bdf23cbbde..abdc11da1d3 100644 --- a/packages/ember-glimmer/tests/integration/custom-component-manager-test.js +++ b/packages/ember-glimmer/tests/integration/custom-component-manager-test.js @@ -35,10 +35,6 @@ if (GLIMMER_CUSTOM_COMPONENT_MANAGER) { return definition.ComponentClass.create(); } - layoutFor(definition, bucket, env) { - return env.getCompiledBlock(TestLayoutCompiler, definition.template); - } - getDestructor(component) { return component; } From 135d84b7ad494cc04e34f512b58a117d271d1fd5 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Fri, 12 Jan 2018 15:23:04 -0800 Subject: [PATCH 097/135] Fix args for model --- packages/ember-glimmer/lib/syntax/render.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/ember-glimmer/lib/syntax/render.ts b/packages/ember-glimmer/lib/syntax/render.ts index 5a9852bf76f..709f3540b88 100644 --- a/packages/ember-glimmer/lib/syntax/render.ts +++ b/packages/ember-glimmer/lib/syntax/render.ts @@ -58,10 +58,14 @@ export function renderHelper(vm: VM, args: Arguments): VersionedPathReference Date: Fri, 12 Jan 2018 15:23:59 -0800 Subject: [PATCH 098/135] remove unused thing --- .../custom-component-manager-test.js | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/packages/ember-glimmer/tests/integration/custom-component-manager-test.js b/packages/ember-glimmer/tests/integration/custom-component-manager-test.js index abdc11da1d3..f1dfac2f74b 100644 --- a/packages/ember-glimmer/tests/integration/custom-component-manager-test.js +++ b/packages/ember-glimmer/tests/integration/custom-component-manager-test.js @@ -1,6 +1,3 @@ -import { - PrimitiveReference -} from '@glimmer/runtime'; import { moduleFor, RenderingTest } from '../utils/test-case'; import { GLIMMER_CUSTOM_COMPONENT_MANAGER @@ -8,25 +5,6 @@ import { import { AbstractComponentManager } from 'ember-glimmer'; if (GLIMMER_CUSTOM_COMPONENT_MANAGER) { - /* - Custom layout compiler. Exists mostly to inject - class and attributes for testing purposes. - */ - class TestLayoutCompiler { - constructor(template) { - this.template = template; - } - - compile(builder) { - builder.wrapLayout(this.template); - builder.tag.dynamic(() => { - return PrimitiveReference.create('p'); - }); - builder.attrs.static('class', 'hey-oh-lets-go'); - builder.attrs.static('manager-id', 'test'); - } - } - /* Implementation of custom component manager, `ComponentManager` interface */ From 424bf82f2823b88aa9b504e7c0853b5cde6885d7 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Fri, 12 Jan 2018 15:56:43 -0800 Subject: [PATCH 099/135] more cleanup --- .../lib/component-managers/abstract.ts | 1 - .../lib/component-managers/curly.ts | 1 - .../lib/component-managers/mount.ts | 2 +- .../lib/component-managers/render.ts | 104 +++++++++--------- packages/ember-glimmer/lib/syntax/render.ts | 4 +- 5 files changed, 56 insertions(+), 56 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/abstract.ts b/packages/ember-glimmer/lib/component-managers/abstract.ts index 2a3ea4c72c2..d07d9626011 100644 --- a/packages/ember-glimmer/lib/component-managers/abstract.ts +++ b/packages/ember-glimmer/lib/component-managers/abstract.ts @@ -1,7 +1,6 @@ import { ComponentCapabilities, Simple, - VMHandle } from '@glimmer/interfaces'; import { Tag, VersionedPathReference } from '@glimmer/reference'; import { diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 7326e63a777..c0866acebae 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -3,7 +3,6 @@ import { Option, ProgramSymbolTable, Simple, - Unique, VMHandle } from '@glimmer/interfaces'; import { ParsedLayout, TemplateOptions, WrappedBuilder } from '@glimmer/opcode-compiler'; diff --git a/packages/ember-glimmer/lib/component-managers/mount.ts b/packages/ember-glimmer/lib/component-managers/mount.ts index 3419540bd9a..414f88fc789 100644 --- a/packages/ember-glimmer/lib/component-managers/mount.ts +++ b/packages/ember-glimmer/lib/component-managers/mount.ts @@ -1,5 +1,5 @@ import { - ComponentCapabilities, Unique, + ComponentCapabilities, } from '@glimmer/interfaces'; import { CONSTANT_TAG, diff --git a/packages/ember-glimmer/lib/component-managers/render.ts b/packages/ember-glimmer/lib/component-managers/render.ts index 59eb603d7ad..774781c3b6e 100644 --- a/packages/ember-glimmer/lib/component-managers/render.ts +++ b/packages/ember-glimmer/lib/component-managers/render.ts @@ -1,5 +1,5 @@ import { - ComponentCapabilities, VMHandle, + ComponentCapabilities, } from '@glimmer/interfaces'; import { CONSTANT_TAG, Tag, VersionedPathReference @@ -13,6 +13,7 @@ import { import { DEBUG } from 'ember-env-flags'; import { generateController, generateControllerFactory } from 'ember-routing'; +import { Owner } from 'ember-utils'; import { OwnedTemplateMeta } from 'ember-views'; import Environment from '../environment'; import { DynamicScope } from '../renderer'; @@ -23,12 +24,30 @@ import AbstractManager from './abstract'; export interface RenderDefinitionState { name: string; - template: OwnedTemplate | undefined; - env: Environment; + template: OwnedTemplate; } -export abstract class AbstractRenderManager extends AbstractManager - implements WithStaticLayout { +export abstract class AbstractRenderManager extends AbstractManager + implements WithStaticLayout { + + create(env: Environment, + definition: RenderDefinitionState, + args: Arguments, + dynamicScope: DynamicScope): T { + let { name } = definition; + + if (DEBUG) { + this._pushToDebugStack(`controller:${name} (with the render helper)`, env); + } + + if (dynamicScope.rootOutletState) { + dynamicScope.outletState = new OrphanedOutletReference(dynamicScope.rootOutletState, name); + } + + return this.createRenderState(args, env.owner, name); + } + + abstract createRenderState(args: Arguments, owner: Owner, name: string): T; getLayout({ template }: RenderDefinitionState): Invocation { const layout = template!.asLayout(); @@ -38,7 +57,7 @@ export abstract class AbstractRenderManager extends AbstractManager; controller: any; } +export interface RenderStateWithModel extends RenderState { + model: VersionedPathReference; +} + const CAPABILITIES = { dynamicLayout: false, dynamicTag: false, prepareArgs: false, - createArgs: true, + createArgs: false, attributeHook: false, elementHook: false }; -class SingletonRenderManager extends AbstractRenderManager { - create(env: Environment, - definition: RenderDefinitionState, - _args: Arguments, - dynamicScope: DynamicScope) { - let { name } = definition; - let controller = env.owner.lookup(`controller:${name}`) || generateController(env.owner, name); - - if (DEBUG) { - this._pushToDebugStack(`controller:${name} (with the render helper)`, env); - } - - if (dynamicScope.rootOutletState) { - dynamicScope.outletState = new OrphanedOutletReference(dynamicScope.rootOutletState, name); - } - - return { controller } as RenderState; +class SingletonRenderManager extends AbstractRenderManager { + createRenderState(_args: Arguments, owner: Owner, name: string) { + let controller = owner.lookup(`controller:${name}`) || generateController(owner, name); + return { controller }; } getCapabilities(_: RenderDefinitionState): ComponentCapabilities { @@ -98,42 +107,36 @@ class SingletonRenderManager extends AbstractRenderManager { export const SINGLETON_RENDER_MANAGER = new SingletonRenderManager(); -class NonSingletonRenderManager extends AbstractRenderManager { - create(environment: Environment, - definition: RenderDefinitionState, - args: Arguments, - dynamicScope: DynamicScope) { - let { name, env } = definition; - let modelRef = args.positional.at(1); - let controllerFactory = env.owner.factoryFor(`controller:${name}`); - - let factory: any = controllerFactory || generateControllerFactory(env.owner, name); - let controller = factory.create({ model: modelRef.value() }); - - if (DEBUG) { - this._pushToDebugStack(`controller:${name} (with the render helper)`, environment); - } - - if (dynamicScope.rootOutletState) { - dynamicScope.outletState = new OrphanedOutletReference(dynamicScope.rootOutletState, name); - } +const NONSINGLETON_CAPABILITIES = { + dynamicLayout: false, + dynamicTag: false, + prepareArgs: false, + createArgs: true, + attributeHook: false, + elementHook: false +}; - return { controller, model: modelRef }; +class NonSingletonRenderManager extends AbstractRenderManager { + createRenderState(args: Arguments, owner: Owner, name: string) { + let model = args.positional.at(1); + let factory = owner.factoryFor(`controller:${name}`) || generateControllerFactory(owner, `controller:${name}`); + let controller = factory.create({ model: model.value() }); + return { controller, model }; } - update({ controller, model }: RenderState) { + update({ controller, model }: RenderStateWithModel) { controller.set('model', model.value()); } getCapabilities(_: RenderDefinitionState): ComponentCapabilities { - return CAPABILITIES; + return NONSINGLETON_CAPABILITIES; } - getTag({ model }: RenderState): Tag { + getTag({ model }: RenderStateWithModel): Tag { return model.tag; } - getDestructor({ controller }: RenderState) { + getDestructor({ controller }: RenderStateWithModel) { return controller; } } @@ -144,11 +147,10 @@ export class RenderDefinition implements ComponentDefinition { public state: RenderDefinitionState; - constructor(name: string, template: OwnedTemplate, env: Environment, public manager: SingletonRenderManager | NonSingletonRenderManager) { + constructor(name: string, template: OwnedTemplate, public manager: SingletonRenderManager | NonSingletonRenderManager) { this.state = { name, template, - env, }; } } diff --git a/packages/ember-glimmer/lib/syntax/render.ts b/packages/ember-glimmer/lib/syntax/render.ts index 709f3540b88..e873462d254 100644 --- a/packages/ember-glimmer/lib/syntax/render.ts +++ b/packages/ember-glimmer/lib/syntax/render.ts @@ -59,10 +59,10 @@ export function renderHelper(vm: VM, args: Arguments): VersionedPathReference Date: Fri, 12 Jan 2018 19:53:04 -0800 Subject: [PATCH 100/135] fix router render into outlet in render helper --- packages/ember-glimmer/lib/component-managers/outlet.ts | 6 ++++++ packages/ember-glimmer/lib/renderer.ts | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index c408a8ed4cf..33dd8a2a987 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -68,6 +68,12 @@ class OutletComponentManager extends AbstractManager, - public rootOutletState: VersionedPathReference) { + public rootOutletState?: VersionedPathReference) { } child() { @@ -276,7 +276,7 @@ export abstract class Renderer { definition: CurriedComponentDefinition, target: Simple.Element) { let self = new UnboundReference(definition); - let dynamicScope = new DynamicScope(null, UNDEFINED_REFERENCE, UNDEFINED_REFERENCE); + let dynamicScope = new DynamicScope(null, UNDEFINED_REFERENCE); let rootState = new RootState(root, this._env, this._rootTemplate, self, target, dynamicScope); this._renderRoot(rootState); } From abf7bd3727cd1ce12d06b68a2410c44d5404d998 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Sat, 13 Jan 2018 12:52:10 -0800 Subject: [PATCH 101/135] Fix model with model param --- .../lib/component-managers/mount.ts | 123 ++++++++++-------- packages/ember-glimmer/lib/syntax/mount.ts | 15 ++- 2 files changed, 78 insertions(+), 60 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/mount.ts b/packages/ember-glimmer/lib/component-managers/mount.ts index 414f88fc789..cdcbbbaaeb6 100644 --- a/packages/ember-glimmer/lib/component-managers/mount.ts +++ b/packages/ember-glimmer/lib/component-managers/mount.ts @@ -25,7 +25,6 @@ import { EMBER_ENGINES_MOUNT_PARAMS } from 'ember/features'; import Environment from '../environment'; import RuntimeResolver from '../resolver'; import { OwnedTemplate } from '../template'; -import { Component } from '../utils/curly-component-state-bucket'; import { RootReference } from '../utils/references'; import AbstractManager from './abstract'; @@ -37,23 +36,36 @@ interface Engine { factoryFor(name: string): any; } -interface EngineBucket { +interface EngineState { engine: Engine; - component?: Component; - controller?: any; - modelReference?: any; - modelRevision?: any; + controller: any; + self: RootReference; + tag: Tag; +} + +interface EngineWithModelState extends EngineState { + modelRef: VersionedPathReference; + modelRev: number; } interface EngineDefinitionState { name: string; - capabilities: ComponentCapabilities; + modelRef: VersionedPathReference | undefined; } -class MountManager extends AbstractManager - implements WithDynamicLayout { +const CAPABILITIES = { + dynamicLayout: true, + dynamicTag: false, + prepareArgs: false, + createArgs: false, + attributeHook: false, + elementHook: false +}; + +class MountManager extends AbstractManager + implements WithDynamicLayout { - getDynamicLayout(state: EngineBucket, _: RuntimeResolver): Invocation { + getDynamicLayout(state: EngineState, _: RuntimeResolver): Invocation { let template = state.engine.lookup('template:application') as OwnedTemplate; let layout = template.asLayout(); return { @@ -62,49 +74,63 @@ class MountManager extends AbstractManager }; } - getCapabilities(state: EngineDefinitionState): ComponentCapabilities { - return state.capabilities; + getCapabilities(): ComponentCapabilities { + return CAPABILITIES; } - create(environment: Environment, { name }: EngineDefinitionState, args: Arguments) { + create(environment: Environment, state: EngineDefinitionState) { if (DEBUG) { - this._pushEngineToDebugStack(`engine:${name}`, environment); + this._pushEngineToDebugStack(`engine:${state.name}`, environment); } - let engine = environment.owner.buildChildEngineInstance(name); - - engine.boot(); - - let bucket: EngineBucket = { engine }; + // TODO + // mount is a runtime helper, this shouldn't use dynamic layout + // we should resolve the engine app template in the helper + // it also should use the owner that looked up the mount helper. - if (EMBER_ENGINES_MOUNT_PARAMS) { - bucket.modelReference = args.named.get('model'); - } + let engine = environment.owner.buildChildEngineInstance(state.name); - return bucket; - } - - getSelf(bucket: EngineBucket): VersionedPathReference { - let { engine, modelReference } = bucket; + engine.boot(); let applicationFactory = engine.factoryFor(`controller:application`); let controllerFactory = applicationFactory || generateControllerFactory(engine, 'application'); - let controller = bucket.controller = controllerFactory.create(); - + let controller: any; + let self: RootReference; + let bucket: EngineState | EngineWithModelState; + let tag: Tag; if (EMBER_ENGINES_MOUNT_PARAMS) { - let model = modelReference.value(); - bucket.modelRevision = modelReference.tag.value(); - controller.set('model', model); + let modelRef = state.modelRef; + if (modelRef === undefined) { + controller = controllerFactory.create(); + self = new RootReference(controller); + tag = CONSTANT_TAG; + bucket = { engine, controller, self, tag }; + } else { + let model = modelRef.value(); + let modelRev = modelRef.tag.value(); + controller = controllerFactory.create({ model }); + self = new RootReference(controller); + tag = modelRef.tag; + bucket = { engine, controller, self, tag, modelRef, modelRev }; + } + } else { + controller = controllerFactory.create(); + self = new RootReference(controller); + tag = CONSTANT_TAG; + bucket = { engine, controller, self, tag }; } + return bucket; + } - return new RootReference(controller); + getSelf({ self }: EngineState): VersionedPathReference { + return self; } - getTag(): Tag { - return CONSTANT_TAG; + getTag(state: EngineState | EngineWithModelState): Tag { + return state.tag; } - getDestructor({ engine }: EngineBucket): Option { + getDestructor({ engine }: EngineState): Option { return engine; } @@ -114,13 +140,12 @@ class MountManager extends AbstractManager } } - update(bucket: EngineBucket): void { + update(bucket: EngineWithModelState): void { if (EMBER_ENGINES_MOUNT_PARAMS) { - let { controller, modelReference, modelRevision } = bucket; - - if (!modelReference.tag.validate(modelRevision)) { - let model = modelReference.value(); - bucket.modelRevision = modelReference.tag.value(); + let { controller, modelRef, modelRev } = bucket; + if (!modelRef.tag.validate(modelRev!)) { + let model = modelRef.value(); + bucket.modelRev = modelRef.tag.value(); controller.set('model', model); } } @@ -133,17 +158,7 @@ export class MountDefinition implements ComponentDefinition { public state: EngineDefinitionState; public manager = MOUNT_MANAGER; - constructor(public name: string) { - this.state = { - name, - capabilities: { - dynamicLayout: true, - dynamicTag: false, - prepareArgs: false, - createArgs: true, - attributeHook: false, - elementHook: false - } - }; + constructor(name: string, modelRef: VersionedPathReference | undefined) { + this.state = { name, modelRef }; } } diff --git a/packages/ember-glimmer/lib/syntax/mount.ts b/packages/ember-glimmer/lib/syntax/mount.ts index e154853af31..c5af68482dc 100644 --- a/packages/ember-glimmer/lib/syntax/mount.ts +++ b/packages/ember-glimmer/lib/syntax/mount.ts @@ -1,7 +1,7 @@ /** @module ember */ -import { Option } from '@glimmer/interfaces'; +import { Option, Opaque } from '@glimmer/interfaces'; import { OpcodeBuilder } from '@glimmer/opcode-compiler'; import { Tag, VersionedPathReference } from '@glimmer/reference'; import { @@ -19,9 +19,10 @@ import { MountDefinition } from '../component-managers/mount'; import Environment from '../environment'; export function mountHelper(vm: VM, args: Arguments): VersionedPathReference { - let env = vm.env; + let env = vm.env as Environment; let nameRef = args.positional.at(0); - return new DynamicEngineReference({ nameRef, env }); + let modelRef = args.named.has('model') ? args.named.get('model') : undefined; + return new DynamicEngineReference(nameRef, env, modelRef); } /** @@ -86,19 +87,21 @@ export function mountMacro(_name: string, params: Option class DynamicEngineReference { public tag: Tag; public nameRef: VersionedPathReference; + public modelRef: VersionedPathReference | undefined; public env: Environment; private _lastName: string | null; private _lastDef: CurriedComponentDefinition | null; - constructor({ nameRef, env }: any) { + constructor(nameRef: VersionedPathReference, env: Environment, modelRef: VersionedPathReference | undefined) { this.tag = nameRef.tag; this.nameRef = nameRef; + this.modelRef = modelRef; this.env = env; this._lastName = null; this._lastDef = null; } value() { - let { env, nameRef } = this; + let { env, nameRef, modelRef } = this; let name = nameRef.value(); if (typeof name === 'string') { @@ -116,7 +119,7 @@ class DynamicEngineReference { } this._lastName = name; - this._lastDef = curry(new MountDefinition(name)); + this._lastDef = curry(new MountDefinition(name, modelRef)); return this._lastDef; } else { From 66f9dbec191db2ee19ba0c05a90822bcdbbadd3c Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 16 Jan 2018 10:29:53 -0800 Subject: [PATCH 102/135] fix module unification lookup --- packages/ember-glimmer/lib/component-managers/mount.ts | 1 - packages/ember-views/lib/utils/lookup-component.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/mount.ts b/packages/ember-glimmer/lib/component-managers/mount.ts index cdcbbbaaeb6..836da32e4e5 100644 --- a/packages/ember-glimmer/lib/component-managers/mount.ts +++ b/packages/ember-glimmer/lib/component-managers/mount.ts @@ -7,7 +7,6 @@ import { VersionedPathReference, } from '@glimmer/reference'; import { - Arguments, ComponentDefinition, Invocation, WithDynamicLayout, diff --git a/packages/ember-views/lib/utils/lookup-component.js b/packages/ember-views/lib/utils/lookup-component.js index 09a4e3aea4f..a0798d1c558 100644 --- a/packages/ember-views/lib/utils/lookup-component.js +++ b/packages/ember-views/lib/utils/lookup-component.js @@ -12,7 +12,7 @@ function lookupModuleUnificationComponentPair(componentLookup, owner, name, opti let globalLayout = componentLookup.layoutFor(name, owner); let localAndUniqueComponent = !!localComponent && (!globalComponent || localComponent.class !== globalComponent.class); - let localAndUniqueLayout = !!localLayout && (!globalLayout || localLayout.meta.moduleName !== globalLayout.meta.moduleName); + let localAndUniqueLayout = !!localLayout && (!globalLayout || localLayout.referrer.moduleName !== globalLayout.referrer.moduleName); if (localAndUniqueComponent && localAndUniqueLayout) { return { layout: localLayout, component: localComponent }; From 5c9c617615be2e4418e007edcc670eb7eef7aba0 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 16 Jan 2018 11:39:37 -0800 Subject: [PATCH 103/135] fix ! usage --- packages/ember-glimmer/lib/syntax/input.ts | 52 +++++++++++----------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/packages/ember-glimmer/lib/syntax/input.ts b/packages/ember-glimmer/lib/syntax/input.ts index d0dfc7b8741..1ad85050fee 100644 --- a/packages/ember-glimmer/lib/syntax/input.ts +++ b/packages/ember-glimmer/lib/syntax/input.ts @@ -152,35 +152,33 @@ function buildSyntax(type: string, params: any[], hash: any, builder: OpcodeBuil */ export function inputMacro(_name: string, params: Option, hash: Option, builder: OpcodeBuilder) { - let keys: WireFormat.Core.Expression[] | undefined; - let values: WireFormat.Core.Expression[] | undefined; - let typeIndex = -1; - let valueIndex = -1; - - if (hash) { - keys = hash[0]; - values = hash[1]; - typeIndex = keys.indexOf('type'); - valueIndex = keys.indexOf('value'); + if (params === null) { + params = []; } - - if (!params) { params = []; } - - if (typeIndex > -1) { - let typeArg = values![typeIndex]; - if (Array.isArray(typeArg)) { - throw new Error('TODO convert to component invoke'); - // return dynamicComponentMacro(params, hash, null, null, builder); - } else if (typeArg === 'checkbox') { - assert( - '{{input type=\'checkbox\'}} does not support setting `value=someBooleanValue`; ' + - 'you must use `checked=someBooleanValue` instead.', - valueIndex === -1, - ); - wrapComponentClassAttribute(hash); - return buildSyntax('-checkbox', params, hash, builder); + if (hash !== null) { + let keys = hash[0]; + let values = hash[1]; + let typeIndex = keys.indexOf('type'); + + if (typeIndex > -1) { + let typeArg = values[typeIndex]; + if (Array.isArray(typeArg)) { + // there is an AST plugin that converts this to an expression + // it really should just compile in the component call too. + let inputTypeExpr = params.shift() as WireFormat.Expression; + builder.dynamicComponent(inputTypeExpr, params, hash, true, null, null); + return true; + } + if (typeArg === 'checkbox') { + assert( + '{{input type=\'checkbox\'}} does not support setting `value=someBooleanValue`; ' + + 'you must use `checked=someBooleanValue` instead.', + keys.indexOf('value') === -1, + ); + wrapComponentClassAttribute(hash); + return buildSyntax('-checkbox', params, hash, builder); + } } } - return buildSyntax('-text-field', params, hash, builder); } From 08ca4e8119247d21f9e88ebe9b48dc273897b63d Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 16 Jan 2018 12:23:48 -0800 Subject: [PATCH 104/135] Fix template only component feature flag. --- .../lib/component-managers/template-only.ts | 49 ++++++++++++------- packages/ember-glimmer/lib/resolver.ts | 7 ++- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/template-only.ts b/packages/ember-glimmer/lib/component-managers/template-only.ts index e8b81413ec4..b4acceb5d4a 100644 --- a/packages/ember-glimmer/lib/component-managers/template-only.ts +++ b/packages/ember-glimmer/lib/component-managers/template-only.ts @@ -1,31 +1,46 @@ -import { VersionedPathReference } from '@glimmer/reference'; -import { CompiledDynamicProgram, ComponentDefinition, NULL_REFERENCE } from '@glimmer/runtime'; -import { Opaque } from '@glimmer/util'; -import Environment from '../environment'; -import { OwnedTemplate, WrappedTemplateFactory } from '../template'; +import { ComponentCapabilities } from '@glimmer/interfaces'; +import { CONSTANT_TAG } from '@glimmer/reference'; +import { ComponentDefinition, Invocation, NULL_REFERENCE, WithStaticLayout } from '@glimmer/runtime'; +import { OwnedTemplateMeta } from 'ember-views'; +import RuntimeResolver from '../resolver'; +import { OwnedTemplate } from '../template'; import AbstractManager from './abstract'; -class TemplateOnlyComponentLayoutCompiler { - static id = 'template-only'; - constructor(public template: WrappedTemplateFactory) { +const CAPABILITIES: ComponentCapabilities = { + dynamicLayout: false, + dynamicTag: false, + prepareArgs: false, + createArgs: false, + attributeHook: false, + elementHook: false +}; + +export default class TemplateOnlyComponentManager extends AbstractManager implements WithStaticLayout { + getLayout(template: OwnedTemplate): Invocation { + const layout = template.asLayout(); + return { + handle: layout.compile(), + symbolTable: layout.symbolTable + }; } - compile(builder: any) { - // TODO: use fromLayout - builder.wrapLayout(this.template); + getCapabilities(): ComponentCapabilities { + return CAPABILITIES; } -} -export default class TemplateOnlyComponentManager extends AbstractManager { create(): null { return null; } - getSelf(): VersionedPathReference { + getSelf() { return NULL_REFERENCE; } + getTag() { + return CONSTANT_TAG; + } + getDestructor() { return null; } @@ -33,8 +48,8 @@ export default class TemplateOnlyComponentManager extends AbstractManager const MANAGER = new TemplateOnlyComponentManager(); -export class TemplateOnlyComponentDefinition extends ComponentDefinition { - constructor(name: string, public template: OwnedTemplate) { - super(name, MANAGER, null); +export class TemplateOnlyComponentDefinition implements ComponentDefinition { + manager = MANAGER; + constructor(public state: OwnedTemplate) { } } diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 22557ed1a31..f01861c8c4f 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -23,9 +23,10 @@ import { lookupPartial, OwnedTemplateMeta, } from 'ember-views'; -import { GLIMMER_CUSTOM_COMPONENT_MANAGER } from 'ember/features'; +import { EMBER_GLIMMER_TEMPLATE_ONLY_COMPONENTS, GLIMMER_CUSTOM_COMPONENT_MANAGER } from 'ember/features'; import CompileTimeLookup from './compile-time-lookup'; import { CurlyComponentDefinition } from './component-managers/curly'; +import { TemplateOnlyComponentDefinition } from './component-managers/template-only'; import { isHelperFactory, isSimpleHelper } from './helper'; import { default as classHelper } from './helpers/-class'; import { default as htmlSafeHelper } from './helpers/-html-safe'; @@ -235,6 +236,10 @@ export default class RuntimeResolver implements IRuntimeResolver { let { layout, component } = lookupComponent(meta.owner, name, makeOptions(meta.moduleName)); + if (EMBER_GLIMMER_TEMPLATE_ONLY_COMPONENTS) { + return new TemplateOnlyComponentDefinition(layout); + } + let customManager: any | undefined; if (GLIMMER_CUSTOM_COMPONENT_MANAGER) { let managerId = layout && layout.referrer.managerId; From 53a386573c7d5cd3930c7ddf0715f51687879130 Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Tue, 16 Jan 2018 13:33:24 -0700 Subject: [PATCH 105/135] Make sure there is no component for template only --- packages/ember-glimmer/lib/resolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index f01861c8c4f..f04175bdd18 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -236,7 +236,7 @@ export default class RuntimeResolver implements IRuntimeResolver { let { layout, component } = lookupComponent(meta.owner, name, makeOptions(meta.moduleName)); - if (EMBER_GLIMMER_TEMPLATE_ONLY_COMPONENTS) { + if (layout && !component && EMBER_GLIMMER_TEMPLATE_ONLY_COMPONENTS) { return new TemplateOnlyComponentDefinition(layout); } From 21e2eae7903eab8fbfa90cd92a58db301e922973 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 16 Jan 2018 13:33:18 -0800 Subject: [PATCH 106/135] fix experimental syntax --- .../tests/integration/syntax/experimental-syntax-test.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/ember-glimmer/tests/integration/syntax/experimental-syntax-test.js b/packages/ember-glimmer/tests/integration/syntax/experimental-syntax-test.js index 42c46e43c07..1cf132eb61c 100644 --- a/packages/ember-glimmer/tests/integration/syntax/experimental-syntax-test.js +++ b/packages/ember-glimmer/tests/integration/syntax/experimental-syntax-test.js @@ -1,7 +1,6 @@ import { moduleFor, RenderingTest } from '../../utils/test-case'; import { strip } from '../../utils/abstract-test-case'; import { _registerMacros, _experimentalMacros } from 'ember-glimmer'; -import { compileExpression } from '@glimmer/runtime'; moduleFor('registerMacros', class extends RenderingTest { constructor() { @@ -9,8 +8,8 @@ moduleFor('registerMacros', class extends RenderingTest { _registerMacros(blocks => { blocks.add('-let', (params, hash, _default, inverse, builder) => { - compileExpression(params[0], builder); - builder.invokeStatic(_default, 1); + builder.compileParams(params); + builder.invokeStaticBlock(_default, params.length); }); }); From 8e779f65e47e95845e3295d0b6deb847608f9331 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 16 Jan 2018 14:41:24 -0800 Subject: [PATCH 107/135] cleanup test case class this stuff is already setup by base class --- packages/internal-test-helpers/lib/test-cases/rendering.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/internal-test-helpers/lib/test-cases/rendering.js b/packages/internal-test-helpers/lib/test-cases/rendering.js index 3c4a44b05f7..51721a65840 100644 --- a/packages/internal-test-helpers/lib/test-cases/rendering.js +++ b/packages/internal-test-helpers/lib/test-cases/rendering.js @@ -1,5 +1,3 @@ -import { ComponentLookup } from 'ember-views'; - import AbstractRenderingTestCase from './abstract-rendering'; export default class RenderingTestCase extends AbstractRenderingTestCase { @@ -8,8 +6,5 @@ export default class RenderingTestCase extends AbstractRenderingTestCase { let { owner } = this; this.env = owner.lookup('service:-glimmer-environment'); - owner.register('component-lookup:main', ComponentLookup); - owner.registerOptionsForType('helper', { instantiate: false }); - owner.registerOptionsForType('component', { singleton: false }); } } From dd1fc5b1645626b8e3b276638ba8a219af74871e Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 16 Jan 2018 14:47:32 -0800 Subject: [PATCH 108/135] cleanup unused --- packages/ember-glimmer/lib/resolver.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index f04175bdd18..f6c3f7973e4 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -141,10 +141,6 @@ export default class RuntimeResolver implements IRuntimeResolver) => Invocation): Invocation { - return create(template, this.templateOptions); - } - /** * Called by CompileTimeLookup compiling Unknown or Helper OpCode */ From ac0542b3d3577c4cde09e2b59ab28c6a79cebfac Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 16 Jan 2018 15:34:56 -0800 Subject: [PATCH 109/135] root curlies (aka component.appendTo) don't have args. --- packages/ember-glimmer/lib/component-managers/root.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index ea756543e36..32306b4b3df 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -8,6 +8,7 @@ import { _instrumentStart, peekMeta, } from 'ember-metal'; +import { DIRTY_TAG } from '../component'; import Environment from '../environment'; import { DynamicScope } from '../renderer'; import RuntimeResolver from '../resolver'; @@ -70,8 +71,8 @@ class RootComponentManager extends CurlyComponentManager { export const ROOT_CAPABILITIES: ComponentCapabilities = { dynamicLayout: true, dynamicTag: true, - prepareArgs: true, - createArgs: true, + prepareArgs: false, + createArgs: false, attributeHook: true, elementHook: true }; @@ -91,4 +92,8 @@ export class RootComponentDefinition implements ComponentDefinition { handle: null, }; } + + getTag({ component }: ComponentStateBucket) { + return component[DIRTY_TAG]; + } } From 9c0caaea4cd745409721311d8cfb479efa605c56 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 16 Jan 2018 15:35:10 -0800 Subject: [PATCH 110/135] cleanup commented out --- .../ember-glimmer/lib/component-managers/curly.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index c0866acebae..c49d2db1961 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -108,18 +108,6 @@ function applyAttributeBindings(element: Simple.Element, attributeBindings: Arra } } -// TODO there is a hook for dynamic attributes -// function tagName(vm: VM) { -// let dynamicScope: DynamicScope = vm.dynamicScope() as DynamicScope; -// // tslint:disable-next-line:no-shadowed-variable -// let { tagName } = dynamicScope.view!; -// return PrimitiveReference.create(tagName === '' ? null : tagName || 'div'); -// } - -// function ariaRole(vm: VM) { -// return vm.getSelf().get('ariaRole'); -// } - const DEFAULT_LAYOUT = P`template:components/-default`; export default class CurlyComponentManager extends AbstractManager From 6dfacd986511f4ae2584e781939a5e3f92941647 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 16 Jan 2018 15:48:28 -0800 Subject: [PATCH 111/135] fix linting --- .../lib/component-managers/template-only.ts | 1 - packages/ember-glimmer/lib/helpers/loc.ts | 2 +- packages/ember-glimmer/lib/modifiers/action.ts | 2 +- packages/ember-glimmer/lib/resolver.ts | 2 -- packages/ember-glimmer/lib/syntax/-text-area.ts | 12 ++++++------ packages/ember-glimmer/lib/syntax/mount.ts | 2 +- packages/ember-glimmer/lib/utils/process-args.ts | 2 +- tsconfig.json | 8 +++----- 8 files changed, 13 insertions(+), 18 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/template-only.ts b/packages/ember-glimmer/lib/component-managers/template-only.ts index b4acceb5d4a..ecfb0df68f8 100644 --- a/packages/ember-glimmer/lib/component-managers/template-only.ts +++ b/packages/ember-glimmer/lib/component-managers/template-only.ts @@ -6,7 +6,6 @@ import RuntimeResolver from '../resolver'; import { OwnedTemplate } from '../template'; import AbstractManager from './abstract'; - const CAPABILITIES: ComponentCapabilities = { dynamicLayout: false, dynamicTag: false, diff --git a/packages/ember-glimmer/lib/helpers/loc.ts b/packages/ember-glimmer/lib/helpers/loc.ts index 78b55d807de..270279078a5 100644 --- a/packages/ember-glimmer/lib/helpers/loc.ts +++ b/packages/ember-glimmer/lib/helpers/loc.ts @@ -3,8 +3,8 @@ @module ember */ -import { helper } from '../helper'; import { String as StringUtils } from 'ember-runtime'; +import { helper } from '../helper'; /** Calls [loc](/api/classes/Ember.String.html#method_loc) with the diff --git a/packages/ember-glimmer/lib/modifiers/action.ts b/packages/ember-glimmer/lib/modifiers/action.ts index 034115c8dad..7f51e19c68e 100644 --- a/packages/ember-glimmer/lib/modifiers/action.ts +++ b/packages/ember-glimmer/lib/modifiers/action.ts @@ -2,7 +2,7 @@ import { Simple } from '@glimmer/interfaces'; import { - TagWrapper, RevisionTag + RevisionTag, TagWrapper } from '@glimmer/reference'; import { Arguments, diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index f6c3f7973e4..e3556010883 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -10,7 +10,6 @@ import { LazyConstants, Program } from '@glimmer/program'; import { getDynamicVar, Helper, - Invocation, ModifierManager, PartialDefinition } from '@glimmer/runtime'; @@ -48,7 +47,6 @@ import { populateMacros } from './syntax'; import { mountHelper } from './syntax/mount'; import { outletHelper } from './syntax/outlet'; import { renderHelper } from './syntax/render'; -import { OwnedTemplate } from './template'; import { ClassBasedHelperReference, SimpleHelperReference } from './utils/references'; function instrumentationPayload(name: string) { diff --git a/packages/ember-glimmer/lib/syntax/-text-area.ts b/packages/ember-glimmer/lib/syntax/-text-area.ts index c7b8e4be6c7..b670b734610 100644 --- a/packages/ember-glimmer/lib/syntax/-text-area.ts +++ b/packages/ember-glimmer/lib/syntax/-text-area.ts @@ -1,13 +1,13 @@ -import { - LazyOpcodeBuilder, - TemplateMeta -} from '@glimmer/opcode-compiler'; +import { Option } from '@glimmer/interfaces'; +import { OpcodeBuilder } from '@glimmer/opcode-compiler'; +import * as WireFormat from '@glimmer/wire-format'; +import { OwnedTemplateMeta } from 'ember-views'; import { wrapComponentClassAttribute } from '../utils/bindings'; import { hashToArgs } from './utils'; -export function textAreaMacro(_name: string, params: any[], hash: any, builder: LazyOpcodeBuilder) { +export function textAreaMacro(_name: string, params: Option, hash: Option, builder: OpcodeBuilder) { let definition = builder.resolver.lookupComponentDefinition('-text-area', builder.referrer); wrapComponentClassAttribute(hash); - builder.component.static(definition!, [params, hashToArgs(hash), null, null]); + builder.component.static(definition!, [params || [], hashToArgs(hash), null, null]); return true; } diff --git a/packages/ember-glimmer/lib/syntax/mount.ts b/packages/ember-glimmer/lib/syntax/mount.ts index c5af68482dc..1d2d77af890 100644 --- a/packages/ember-glimmer/lib/syntax/mount.ts +++ b/packages/ember-glimmer/lib/syntax/mount.ts @@ -1,7 +1,7 @@ /** @module ember */ -import { Option, Opaque } from '@glimmer/interfaces'; +import { Opaque, Option } from '@glimmer/interfaces'; import { OpcodeBuilder } from '@glimmer/opcode-compiler'; import { Tag, VersionedPathReference } from '@glimmer/reference'; import { diff --git a/packages/ember-glimmer/lib/utils/process-args.ts b/packages/ember-glimmer/lib/utils/process-args.ts index 7a875b86249..65fbd455622 100644 --- a/packages/ember-glimmer/lib/utils/process-args.ts +++ b/packages/ember-glimmer/lib/utils/process-args.ts @@ -1,6 +1,6 @@ +import { CapturedNamedArguments } from '@glimmer/runtime'; import { symbol } from 'ember-utils'; import { MUTABLE_CELL } from 'ember-views'; -import { CapturedNamedArguments } from '@glimmer/runtime'; import { ARGS } from '../component'; import { ACTION } from '../helpers/action'; import { UPDATE } from './references'; diff --git a/tsconfig.json b/tsconfig.json index e318fb334c3..e2b0b442e85 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,14 +14,12 @@ "moduleResolution": "node", // Enhance Strictness - "noImplicitAny": true, + "strict": true, + "noImplicitReturns": true, + "allowUnreachableCode": false, "suppressImplicitAnyIndexErrors": true, "noUnusedLocals": true, "noUnusedParameters": true, - "allowUnreachableCode": false, - "strictNullChecks": true, - "noImplicitReturns": true, - "noImplicitThis": true, "newLine": "LF", "noEmit": true, From 670d490146e04577ac8799ba2c7f3d5d9f8a76a6 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 16 Jan 2018 17:22:46 -0800 Subject: [PATCH 112/135] Get everything that needs to be cached into place --- .../lib/component-managers/curly.ts | 30 +++------ packages/ember-glimmer/lib/resolver.ts | 62 ++++++++++++++----- 2 files changed, 54 insertions(+), 38 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index c49d2db1961..eb9b9f726a7 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -5,7 +5,6 @@ import { Simple, VMHandle } from '@glimmer/interfaces'; -import { ParsedLayout, TemplateOptions, WrappedBuilder } from '@glimmer/opcode-compiler'; import { combine, Tag, @@ -37,7 +36,6 @@ import { String as StringUtils } from 'ember-runtime'; import { getOwner, guidFor, - setOwner } from 'ember-utils'; import { OwnedTemplateMeta, setViewElement } from 'ember-views'; import { @@ -52,7 +50,6 @@ import { DynamicScope } from '../renderer'; import RuntimeResolver from '../resolver'; import { Factory as TemplateFactory, - Injections, OwnedTemplate } from '../template'; import { @@ -123,17 +120,15 @@ export default class CurlyComponentManager extends AbstractManager): OwnedTemplate { - let Template = get(component, 'layout') as TemplateFactory | OwnedTemplate | undefined; - if (Template !== undefined) { + templateFor(component: Component, resolver: RuntimeResolver): OwnedTemplate { + let layout = get(component, 'layout') as TemplateFactory | OwnedTemplate | undefined; + if (layout !== undefined) { // This needs to be cached by template.id - if (isTemplateFactory(Template)) { - const injections: Injections = { options }; - setOwner(injections, getOwner(component)); - return Template.create(injections); + if (isTemplateFactory(layout)) { + return resolver.createTemplate(layout, getOwner(component)); } else { // we were provided an instance already - return Template; + return layout; } } let owner = getOwner(component); @@ -148,17 +143,8 @@ export default class CurlyComponentManager extends AbstractManager = (template as any).parsedLayout; - const layout = new WrappedBuilder( - compileOptions, - parsed, - CURLY_CAPABILITIES, - ); + const template = this.templateFor(component, resolver); + const layout = resolver.getWrappedLayout(template, CURLY_CAPABILITIES); // NEEDS TO BE CACHED return { handle: layout.compile(), diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index e3556010883..271f6c52d96 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -3,9 +3,10 @@ import { Opaque, Option, RuntimeResolver as IRuntimeResolver, - VMHandle + VMHandle, + ComponentCapabilities } from '@glimmer/interfaces'; -import { LazyOpcodeBuilder, Macros, OpcodeBuilderConstructor, TemplateOptions } from '@glimmer/opcode-compiler'; +import { LazyOpcodeBuilder, Macros, OpcodeBuilderConstructor, ParsedLayout, TemplateOptions, WrappedBuilder } from '@glimmer/opcode-compiler'; import { LazyConstants, Program } from '@glimmer/program'; import { getDynamicVar, @@ -16,7 +17,7 @@ import { import { privatize as P } from 'container'; import { assert } from 'ember-debug'; import { _instrumentStart } from 'ember-metal'; -import { LookupOptions } from 'ember-utils'; +import { LookupOptions, Owner, setOwner } from 'ember-utils'; import { lookupComponent, lookupPartial, @@ -24,7 +25,7 @@ import { } from 'ember-views'; import { EMBER_GLIMMER_TEMPLATE_ONLY_COMPONENTS, GLIMMER_CUSTOM_COMPONENT_MANAGER } from 'ember/features'; import CompileTimeLookup from './compile-time-lookup'; -import { CurlyComponentDefinition } from './component-managers/curly'; +import { CURLY_CAPABILITIES, CurlyComponentDefinition } from './component-managers/curly'; import { TemplateOnlyComponentDefinition } from './component-managers/template-only'; import { isHelperFactory, isSimpleHelper } from './helper'; import { default as classHelper } from './helpers/-class'; @@ -47,6 +48,7 @@ import { populateMacros } from './syntax'; import { mountHelper } from './syntax/mount'; import { outletHelper } from './syntax/outlet'; import { renderHelper } from './syntax/render'; +import { Factory as TemplateFactory, Injections, OwnedTemplate } from './template'; import { ClassBasedHelperReference, SimpleHelperReference } from './utils/references'; function instrumentationPayload(name: string) { @@ -92,12 +94,9 @@ export default class RuntimeResolver implements IRuntimeResolver(); private builtInHelpers: { @@ -126,11 +125,6 @@ export default class RuntimeResolver implements IRuntimeResolver { - let partial = this._lookupPartial(name, meta); - return this.handle(partial); - } - /** * Called by RuntimeConstants to lookup unresolved handles. */ @@ -163,9 +157,45 @@ export default class RuntimeResolver implements IRuntimeResolver { return this.handle(this._lookupModifier(name)); } + + /** + * Called by CompileTimeLookup to lookup partial + */ + lookupPartial(name: string, meta: OwnedTemplateMeta): Option { + let partial = this._lookupPartial(name, meta); + return this.handle(partial); + } + // end CompileTimeLookup - // needed for latebound + // TODO implement caching for the follow hooks + + /** + * Creates a directly imported template with injections. + * @param templateFactory the direct imported template factory + * @param owner the owner to set + */ + createTemplate(factory: TemplateFactory, owner: Owner) { + const injections: Injections = { options: this.templateOptions }; + setOwner(injections, owner); + // TODO cache by owner and template.id + return factory.create(injections); + } + + /** + * Returns a wrapped layout for the specified layout. + * @param template the layout to wrap. + */ + getWrappedLayout(template: OwnedTemplate, capabilities: ComponentCapabilities) { + const compileOptions = Object.assign({}, + this.templateOptions, { asPartial: false, referrer: template.referrer}); + // TODO fix this getting private + const parsed: ParsedLayout = (template as any).parsedLayout; + // TODO cache by template instance and capabilities + return new WrappedBuilder(compileOptions, parsed, capabilities); + } + + // needed for lazy compile time lookup private handle(obj: any | null | undefined) { if (obj === undefined || obj === null) { return null; From ad880289144f3721fbdbd1e71167875f6a326abb Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 17 Jan 2018 06:24:10 -0700 Subject: [PATCH 113/135] Begin fixing the custom component manager test --- packages/ember-glimmer/lib/index.ts | 2 +- packages/ember-glimmer/lib/resolver.ts | 2 +- .../custom-component-manager-test.js | 31 +++++++++++++++++-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/packages/ember-glimmer/lib/index.ts b/packages/ember-glimmer/lib/index.ts index 1b7f35a6738..b3942b735cc 100644 --- a/packages/ember-glimmer/lib/index.ts +++ b/packages/ember-glimmer/lib/index.ts @@ -266,7 +266,7 @@ export { default as Checkbox } from './components/checkbox'; export { default as TextField } from './components/text_field'; export { default as TextArea } from './components/text_area'; export { default as LinkComponent } from './components/link-to'; -export { default as Component } from './component'; +export { default as Component, ROOT_REF } from './component'; export { default as Helper, helper } from './helper'; export { default as Environment } from './environment'; export { diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 271f6c52d96..2a24d1e520d 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -269,7 +269,7 @@ export default class RuntimeResolver implements IRuntimeResolver Date: Wed, 17 Jan 2018 11:00:58 -0700 Subject: [PATCH 114/135] Skip the custom component manager tests for now. Per @rwjblue, we will add this feature and test back after the upgrade lands --- packages/ember-glimmer/lib/resolver.ts | 15 +++------ .../custom-component-manager-test.js | 33 +++---------------- 2 files changed, 8 insertions(+), 40 deletions(-) diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 2a24d1e520d..82a56fdda77 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -1,10 +1,10 @@ import { + ComponentCapabilities, ComponentDefinition, Opaque, Option, RuntimeResolver as IRuntimeResolver, - VMHandle, - ComponentCapabilities + VMHandle } from '@glimmer/interfaces'; import { LazyOpcodeBuilder, Macros, OpcodeBuilderConstructor, ParsedLayout, TemplateOptions, WrappedBuilder } from '@glimmer/opcode-compiler'; import { LazyConstants, Program } from '@glimmer/program'; @@ -23,9 +23,9 @@ import { lookupPartial, OwnedTemplateMeta, } from 'ember-views'; -import { EMBER_GLIMMER_TEMPLATE_ONLY_COMPONENTS, GLIMMER_CUSTOM_COMPONENT_MANAGER } from 'ember/features'; +import { EMBER_GLIMMER_TEMPLATE_ONLY_COMPONENTS } from 'ember/features'; import CompileTimeLookup from './compile-time-lookup'; -import { CURLY_CAPABILITIES, CurlyComponentDefinition } from './component-managers/curly'; +import { CurlyComponentDefinition } from './component-managers/curly'; import { TemplateOnlyComponentDefinition } from './component-managers/template-only'; import { isHelperFactory, isSimpleHelper } from './helper'; import { default as classHelper } from './helpers/-class'; @@ -265,13 +265,6 @@ export default class RuntimeResolver implements IRuntimeResolver; diff --git a/packages/ember-glimmer/tests/integration/custom-component-manager-test.js b/packages/ember-glimmer/tests/integration/custom-component-manager-test.js index b36183808c4..e89506ab63d 100644 --- a/packages/ember-glimmer/tests/integration/custom-component-manager-test.js +++ b/packages/ember-glimmer/tests/integration/custom-component-manager-test.js @@ -1,10 +1,8 @@ -import { CONSTANT_TAG } from '@glimmer/reference'; -import { PrimitiveReference } from '@glimmer/runtime'; import { moduleFor, RenderingTest } from '../utils/test-case'; import { GLIMMER_CUSTOM_COMPONENT_MANAGER } from 'ember/features'; -import { AbstractComponentManager, ROOT_REF } from 'ember-glimmer'; +import { AbstractComponentManager } from 'ember-glimmer'; if (GLIMMER_CUSTOM_COMPONENT_MANAGER) { /* @@ -19,36 +17,13 @@ if (GLIMMER_CUSTOM_COMPONENT_MANAGER) { return component; } - getSelf(component) { - return component[ROOT_REF]; - } - getCapabilities() { - return { - dynamicLayout: false - }; - } - getLayout(state) { - return { - handle: state.handle, - symbolTable: state.symbolTable - }; - } - didCreateElement(bucket, element, operations) { - operations.setAttribute('class', PrimitiveReference.create('hey-oh-lets-go')); - operations.setAttribute('manager-id', PrimitiveReference.create('test')); - } - // TODO: uncomment this when the cause of the infinite loop is discovered and resolved - // getTagName() { return 'p'; } - getTag() { - return CONSTANT_TAG; - } - getDestructor() { - return { destroy() {} } + getSelf() { + return null; } } moduleFor('Components test: curly components with custom manager', class extends RenderingTest { - ['@test it can render a basic component with custom component manager'](assert) { + ['@skip it can render a basic component with custom component manager'](assert) { let managerId = 'test'; this.owner.register(`component-manager:${managerId}`, new TestComponentManager()); this.registerComponent('foo-bar', { From b20f825562fd7f9ed89bf9ecf850d28932de5c53 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Wed, 17 Jan 2018 13:05:42 -0500 Subject: [PATCH 115/135] Add tests for usage of null/undefined with contextual components. --- .../components/contextual-components-test.js | 92 ++++++++++++++++--- 1 file changed, 81 insertions(+), 11 deletions(-) diff --git a/packages/ember-glimmer/tests/integration/components/contextual-components-test.js b/packages/ember-glimmer/tests/integration/components/contextual-components-test.js index bb33d0a24cc..4fb35490a79 100644 --- a/packages/ember-glimmer/tests/integration/components/contextual-components-test.js +++ b/packages/ember-glimmer/tests/integration/components/contextual-components-test.js @@ -623,11 +623,84 @@ moduleFor('Components test: contextual components', class extends RenderingTest this.assertText('Hodi Hodari'); } - ['@skip raises an asserton when component path is null']() { - // TODO: should we change this to be allowed? The test is currently failing because glimmer considers this to be fine... - expectAssertion(() => { - this.render('{{component (component lookupComponent)}}'); - }); + ['@test component with dynamic component name resolving to undefined, then an existing component']() { + this.registerComponent('foo-bar', { template: 'hello {{name}}' }); + + this.render('{{component (component componentName name=name)}}', { componentName: undefined, name: 'Alex' }); + + this.assertText(''); + + this.runTask(() => this.rerender()); + + this.assertText(''); + + this.runTask(() => this.context.set('componentName', 'foo-bar')); + + this.assertText('hello Alex'); + + this.runTask(() => this.context.set('componentName', undefined)); + + this.assertText(''); + } + + ['@test component with dynamic component name resolving to a component, then undefined']() { + this.registerComponent('foo-bar', { template: 'hello {{name}}' }); + + this.render('{{component (component componentName name=name)}}', { componentName: 'foo-bar', name: 'Alex' }); + + this.assertText('hello Alex'); + + this.runTask(() => this.rerender()); + + this.assertText('hello Alex'); + + this.runTask(() => this.context.set('componentName', undefined)); + + this.assertText(''); + + this.runTask(() => this.context.set('componentName', 'foo-bar')); + + this.assertText('hello Alex'); + } + + ['@test component with dynamic component name resolving to null, then an existing component']() { + this.registerComponent('foo-bar', { template: 'hello {{name}}' }); + + this.render('{{component (component componentName name=name)}}', { componentName: null, name: 'Alex' }); + + this.assertText(''); + + this.runTask(() => this.rerender()); + + this.assertText(''); + + this.runTask(() => this.context.set('componentName', 'foo-bar')); + + this.assertText('hello Alex'); + + this.runTask(() => this.context.set('componentName', null)); + + this.assertText(''); + } + + ['@test component with dynamic component name resolving to a component, then null']() { + this.registerComponent('foo-bar', { template: 'hello {{name}}' }); + + this.render('{{component (component componentName name=name)}}', { componentName: 'foo-bar', name: 'Alex' }); + + this.assertText('hello Alex'); + + this.runTask(() => this.rerender()); + + this.assertText('hello Alex'); + + this.runTask(() => this.context.set('componentName', null)); + + this.assertText(''); + + this.runTask(() => this.context.set('componentName', 'foo-bar')); + + this.assertText('hello Alex'); } ['@test raises an assertion when component path is not a component name (static)']() { @@ -636,13 +709,10 @@ moduleFor('Components test: contextual components', class extends RenderingTest }, 'Could not find component named \"not-a-component\" (no component or template with that name was found)'); } - ['@skip raises an assertion when component path is not a component name (dynamic)']() { - // TODO: should we change this to be allowed? The test is currently failing because glimmer considers this to be fine... + ['@test raises an assertion when component path is not a component name (dynamic)']() { expectAssertion(() => { - this.render('{{component (component compName)}}', { - compName: 'not-a-component' - }); - }, /The component helper cannot be used without a valid component name. You used "not-a-component" via \(component .*\)/); + this.render('{{component (component compName)}}', { compName: "not-a-component" }); + }, 'Could not find component named \"not-a-component\" (no component or template with that name was found)'); } ['@test renders with dot path']() { From 2890c7a3a17d5f30d4e0977a2271207ef6f21937 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Wed, 17 Jan 2018 11:46:35 -0800 Subject: [PATCH 116/135] Fix caching instance for directly imported factories on Component layout property. --- packages/ember-glimmer/lib/resolver.ts | 30 ++++++++++++++----- .../tests/unit/template-factory-test.js | 21 ++++++------- .../lib/test-cases/rendering.js | 4 +++ 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 82a56fdda77..401db38a7c7 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -107,6 +107,11 @@ export default class RuntimeResolver implements IRuntimeResolver; } = BUILTIN_MODIFIERS; + // supports directly imported late bound layouts on component.prototype.layout + private templateCache: WeakMap> = new WeakMap(); + private templateCacheHits = 0; + private templateCacheMisses = 0; + constructor() { populateMacros(this.templateOptions.macros); } @@ -175,11 +180,23 @@ export default class RuntimeResolver implements IRuntimeResolver; let definition = (layout || component) ? new CurlyComponentDefinition( name, customManager, component || meta.owner.factoryFor(P`component:-default`), - layoutHandle, + null, layout ) : null; diff --git a/packages/ember-glimmer/tests/unit/template-factory-test.js b/packages/ember-glimmer/tests/unit/template-factory-test.js index bd6775d0c0b..39ba3701631 100644 --- a/packages/ember-glimmer/tests/unit/template-factory-test.js +++ b/packages/ember-glimmer/tests/unit/template-factory-test.js @@ -6,6 +6,7 @@ import { Component } from '../utils/helpers'; moduleFor('Template factory test', class extends RenderingTest { ['@test the template factory returned from precompile is the same as compile'](assert) { let { env } = this; + let { resolver } = this; let templateStr = 'Hello {{name}}'; let options = { moduleName: 'some-module' }; @@ -25,18 +26,18 @@ moduleFor('Template factory test', class extends RenderingTest { assert.equal(typeof Compiled.create, 'function', 'compiled is a factory'); assert.ok(Compiled.id, 'compiled has id'); - assert.equal(env._templateCache.misses, 0, 'misses 0'); - assert.equal(env._templateCache.hits, 0, 'hits 0'); + assert.equal(resolver.templateCacheMisses, 0, 'misses 0'); + assert.equal(resolver.templateCacheHits, 0, 'hits 0'); - let precompiled = env.getTemplate(Precompiled, env.owner); + let precompiled = resolver.createTemplate(Precompiled, env.owner); - assert.equal(env._templateCache.misses, 1, 'misses 1'); - assert.equal(env._templateCache.hits, 0, 'hits 0'); + assert.equal(resolver.templateCacheMisses, 1, 'misses 1'); + assert.equal(resolver.templateCacheHits, 0, 'hits 0'); - let compiled = env.getTemplate(Compiled, env.owner); + let compiled = resolver.createTemplate(Compiled, env.owner); - assert.equal(env._templateCache.misses, 2, 'misses 2'); - assert.equal(env._templateCache.hits, 0, 'hits 0'); + assert.equal(resolver.templateCacheMisses, 2, 'misses 2'); + assert.equal(resolver.templateCacheHits, 0, 'hits 0'); assert.ok(typeof precompiled.spec !== 'string', 'Spec has been parsed'); assert.ok(typeof compiled.spec !== 'string', 'Spec has been parsed'); @@ -55,8 +56,8 @@ moduleFor('Template factory test', class extends RenderingTest { this.render('{{x-precompiled name="precompiled"}} {{x-compiled name="compiled"}}'); - assert.equal(env._templateCache.misses, 2, 'misses 2'); - assert.equal(env._templateCache.hits, 2, 'hits 2'); + assert.equal(resolver.templateCacheMisses, 2, 'misses 2'); + assert.equal(resolver.templateCacheHits, 2, 'hits 2'); this.assertText('Hello precompiled Hello compiled'); } diff --git a/packages/internal-test-helpers/lib/test-cases/rendering.js b/packages/internal-test-helpers/lib/test-cases/rendering.js index 51721a65840..8e5072432ef 100644 --- a/packages/internal-test-helpers/lib/test-cases/rendering.js +++ b/packages/internal-test-helpers/lib/test-cases/rendering.js @@ -1,4 +1,5 @@ import AbstractRenderingTestCase from './abstract-rendering'; +import { privatize as P } from 'container'; export default class RenderingTestCase extends AbstractRenderingTestCase { constructor() { @@ -6,5 +7,8 @@ export default class RenderingTestCase extends AbstractRenderingTestCase { let { owner } = this; this.env = owner.lookup('service:-glimmer-environment'); + let templateOptions = owner.lookup(P`template-options:main`); + // get the runtime/lazy resolver from the compiler resolver; + this.resolver = templateOptions.resolver.resolver; } } From 5d01bb0de2b0457995f348861c455bc7638e4b3f Mon Sep 17 00:00:00 2001 From: Steven Footea Date: Wed, 17 Jan 2018 13:25:15 -0700 Subject: [PATCH 117/135] Add a resolver setter to local lookup test case Since RenderingTestCase is setting `resolver` in its constructor, a setter is necessary, even if it doesn't do anything. --- .../tests/integration/components/local-lookup-test.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/ember-glimmer/tests/integration/components/local-lookup-test.js b/packages/ember-glimmer/tests/integration/components/local-lookup-test.js index e04e88f05fc..15fe3222ae1 100644 --- a/packages/ember-glimmer/tests/integration/components/local-lookup-test.js +++ b/packages/ember-glimmer/tests/integration/components/local-lookup-test.js @@ -258,6 +258,10 @@ if (EMBER_MODULE_UNIFICATION) { get resolver() { return this.owner.__registry__.fallback.resolver; } + set resolver(resolver) { + // `resolver` needs a setter because RenderingTestCase sets `resolver` in + // its constructor + } getResolver() { return new LocalLookupTestResolver(); From 078d6188563bbee800359686eea8f9975e2a25dc Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 18 Jan 2018 14:32:34 -0800 Subject: [PATCH 118/135] Implement layout wrapper caching --- .../lib/component-managers/curly.ts | 7 +- .../lib/component-managers/root.ts | 9 +- packages/ember-glimmer/lib/resolver.ts | 55 ++-- .../components/local-lookup-test.js | 4 - .../tests/unit/layout-cache-test.js | 252 +++++++++--------- .../tests/unit/template-factory-test.js | 24 +- .../lib/test-cases/rendering.js | 6 +- 7 files changed, 183 insertions(+), 174 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index eb9b9f726a7..8faecd9510c 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -142,20 +142,15 @@ export default class CurlyComponentManager extends AbstractManager(DEFAULT_LAYOUT); } - compileDynamicLayout(component: Component, resolver: RuntimeResolver): Invocation { + getDynamicLayout({ component }: ComponentStateBucket, resolver: RuntimeResolver): Invocation { const template = this.templateFor(component, resolver); const layout = resolver.getWrappedLayout(template, CURLY_CAPABILITIES); - // NEEDS TO BE CACHED return { handle: layout.compile(), symbolTable: layout.symbolTable, }; } - getDynamicLayout(state: ComponentStateBucket, resolver: RuntimeResolver): Invocation { - return this.compileDynamicLayout(state.component, resolver); - } - getTagName(state: ComponentStateBucket): Option { const { component } = state; if (component.tagName === '') { diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index 32306b4b3df..da96ed9e5e5 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -28,7 +28,12 @@ class RootComponentManager extends CurlyComponentManager { } getLayout(_state: DefinitionState, resolver: RuntimeResolver) { - return this.compileDynamicLayout(this.component, resolver); + const template = this.templateFor(this.component, resolver); + const layout = resolver.getWrappedLayout(template, ROOT_CAPABILITIES); + return { + handle: layout.compile(), + symbolTable: layout.symbolTable, + }; } create(environment: Environment, @@ -69,7 +74,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: ComponentCapabilities = { - dynamicLayout: true, + dynamicLayout: false, dynamicTag: true, prepareArgs: false, createArgs: false, diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 401db38a7c7..130f4883d57 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -3,8 +3,7 @@ import { ComponentDefinition, Opaque, Option, - RuntimeResolver as IRuntimeResolver, - VMHandle + RuntimeResolver as IRuntimeResolver } from '@glimmer/interfaces'; import { LazyOpcodeBuilder, Macros, OpcodeBuilderConstructor, ParsedLayout, TemplateOptions, WrappedBuilder } from '@glimmer/opcode-compiler'; import { LazyConstants, Program } from '@glimmer/program'; @@ -12,7 +11,8 @@ import { getDynamicVar, Helper, ModifierManager, - PartialDefinition + PartialDefinition, + TopLevelSyntax, } from '@glimmer/runtime'; import { privatize as P } from 'container'; import { assert } from 'ember-debug'; @@ -109,8 +109,13 @@ export default class RuntimeResolver implements IRuntimeResolver> = new WeakMap(); - private templateCacheHits = 0; - private templateCacheMisses = 0; + + public templateCacheHits = 0; + public templateCacheMisses = 0; + + private wrapperCache: WeakMap> = new WeakMap(); + public wrapperCacheHits = 0; + public wrapperCacheMisses = 0; constructor() { populateMacros(this.templateOptions.macros); @@ -173,12 +178,10 @@ export default class RuntimeResolver implements IRuntimeResolver = (template as any).parsedLayout; - // TODO cache by template instance and capabilities - return new WrappedBuilder(compileOptions, parsed, capabilities); + // TODO fix this getting private + const parsed: ParsedLayout = (template as any).parsedLayout; + wrapper = new WrappedBuilder(compileOptions, parsed, capabilities); + cache.set(capabilities, wrapper); + this.wrapperCacheMisses++; + } else { + this.wrapperCacheHits++; + } + return wrapper; } // needed for lazy compile time lookup @@ -281,13 +302,11 @@ export default class RuntimeResolver implements IRuntimeResolver set(this.context, 'cond', false)); + + this.assertText('Two'); + state = this.expectCacheChanges({ + templateCacheMisses: 1, + wrapperCacheMisses: 1, + }, state, 'component-two first render misses both template cache and wrapper cache'); + + // show component-one again + this.runTask(() => set(this.context, 'cond', true)); + + this.assertText('One'); + state = this.expectCacheChanges({ + wrapperCacheHits: 1, + }, state, 'toggle back to component-one hits wrapper cache'); + + // show component-two again + this.runTask(() => set(this.context, 'cond', false)); + + this.assertText('Two'); + state = this.expectCacheChanges({ + wrapperCacheHits: 1, + templateCacheHits: 1, + }, state, 'toggle back to component-two hits wrapper cache and template cache'); + + // render new root append + let root = rootFactory.create(); + try { + runAppend(root); + this.assertText('TwoOne'); + // roots have different capabilities so this will hit + state = this.expectCacheChanges({ + wrapperCacheMisses: 1, + }, state, 'append root with component-one template misses because different capabilities'); + + // render new root append + let root2 = rootFactory.create(); + try { + runAppend(root2); + this.assertText('TwoOneOne'); + state = this.expectCacheChanges({ + wrapperCacheHits: 1, + }, state, 'append another root hits'); + } finally { + runDestroy(root2); + } + } finally { + runDestroy(root); + } } - ['@test each template/compiler pair is treated as unique'](assert) { - let { env } = this; - - let template = this.templateFor('Hello world!'); - - assert.ok(env.getCompiledBlock(TypeOneCompiler, template) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - assert.strictEqual(COUNTER.get(`type-one+${template.id}`), 1); - assert.strictEqual(COUNTER.get(`type-two+${template.id}`), 0); - assert.strictEqual(COUNTER.total, 1); - - assert.ok(env.getCompiledBlock(TypeOneCompiler, template) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - assert.strictEqual(COUNTER.get(`type-one+${template.id}`), 1); - assert.strictEqual(COUNTER.get(`type-two+${template.id}`), 0); - assert.strictEqual(COUNTER.total, 1); - - assert.ok(env.getCompiledBlock(TypeTwoCompiler, template) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - assert.strictEqual(COUNTER.get(`type-one+${template.id}`), 1); - assert.strictEqual(COUNTER.get(`type-two+${template.id}`), 1); - assert.strictEqual(COUNTER.total, 2); - - assert.ok(env.getCompiledBlock(TypeOneCompiler, template) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - assert.ok(env.getCompiledBlock(TypeOneCompiler, template) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - assert.ok(env.getCompiledBlock(TypeTwoCompiler, template) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - assert.ok(env.getCompiledBlock(TypeOneCompiler, template) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - assert.ok(env.getCompiledBlock(TypeOneCompiler, template) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - assert.ok(env.getCompiledBlock(TypeOneCompiler, template) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - assert.ok(env.getCompiledBlock(TypeTwoCompiler, template) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - assert.ok(env.getCompiledBlock(TypeTwoCompiler, template) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - - assert.strictEqual(COUNTER.get(`type-one+${template.id}`), 1); - assert.strictEqual(COUNTER.get(`type-two+${template.id}`), 1); - assert.strictEqual(COUNTER.total, 2); - } - - ['@test a template instance is returned (ensures templates can be injected into layout property)'](assert) { - let { owner, env } = this; - - let templateInstanceFor = (content) => { - let Factory = this.compile(content); - return Factory.create({ [OWNER]: owner, env }); + getCacheCounters() { + let { runtimeResolver: { + wrapperCacheHits, + wrapperCacheMisses, + templateCacheHits, + templateCacheMisses, + } } = this; + return { + wrapperCacheHits, + wrapperCacheMisses, + templateCacheHits, + templateCacheMisses, }; + } - let template1 = templateInstanceFor('Hello world!'); - let template2 = templateInstanceFor('{{foo}} {{bar}}'); - - assert.ok(env.getCompiledBlock(TypeOneCompiler, template1) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); - assert.ok(env.getCompiledBlock(TypeOneCompiler, template2) instanceof CompiledDynamicTemplate, 'should return a CompiledDynamicTemplate'); + expectCacheChanges(expected, lastState, message) { + let state = this.getCacheCounters(); + let actual = diff(state, lastState); + this.assert.deepEqual(actual, expected, message); + return state; } }); + +function diff(state, lastState) { + let res = {}; + Object.keys(state).forEach(key => { + let delta = state[key] - lastState[key]; + if (delta !== 0) { + res[key] = state[key] - lastState[key]; + } + }); + return res; +} diff --git a/packages/ember-glimmer/tests/unit/template-factory-test.js b/packages/ember-glimmer/tests/unit/template-factory-test.js index 39ba3701631..b5e03c5a500 100644 --- a/packages/ember-glimmer/tests/unit/template-factory-test.js +++ b/packages/ember-glimmer/tests/unit/template-factory-test.js @@ -5,8 +5,8 @@ import { Component } from '../utils/helpers'; moduleFor('Template factory test', class extends RenderingTest { ['@test the template factory returned from precompile is the same as compile'](assert) { - let { env } = this; - let { resolver } = this; + let { owner } = this; + let { runtimeResolver } = this; let templateStr = 'Hello {{name}}'; let options = { moduleName: 'some-module' }; @@ -26,18 +26,18 @@ moduleFor('Template factory test', class extends RenderingTest { assert.equal(typeof Compiled.create, 'function', 'compiled is a factory'); assert.ok(Compiled.id, 'compiled has id'); - assert.equal(resolver.templateCacheMisses, 0, 'misses 0'); - assert.equal(resolver.templateCacheHits, 0, 'hits 0'); + assert.equal(runtimeResolver.templateCacheMisses, 0, 'misses 0'); + assert.equal(runtimeResolver.templateCacheHits, 0, 'hits 0'); - let precompiled = resolver.createTemplate(Precompiled, env.owner); + let precompiled = runtimeResolver.createTemplate(Precompiled, owner); - assert.equal(resolver.templateCacheMisses, 1, 'misses 1'); - assert.equal(resolver.templateCacheHits, 0, 'hits 0'); + assert.equal(runtimeResolver.templateCacheMisses, 1, 'misses 1'); + assert.equal(runtimeResolver.templateCacheHits, 0, 'hits 0'); - let compiled = resolver.createTemplate(Compiled, env.owner); + let compiled = runtimeResolver.createTemplate(Compiled, owner); - assert.equal(resolver.templateCacheMisses, 2, 'misses 2'); - assert.equal(resolver.templateCacheHits, 0, 'hits 0'); + assert.equal(runtimeResolver.templateCacheMisses, 2, 'misses 2'); + assert.equal(runtimeResolver.templateCacheHits, 0, 'hits 0'); assert.ok(typeof precompiled.spec !== 'string', 'Spec has been parsed'); assert.ok(typeof compiled.spec !== 'string', 'Spec has been parsed'); @@ -56,8 +56,8 @@ moduleFor('Template factory test', class extends RenderingTest { this.render('{{x-precompiled name="precompiled"}} {{x-compiled name="compiled"}}'); - assert.equal(resolver.templateCacheMisses, 2, 'misses 2'); - assert.equal(resolver.templateCacheHits, 2, 'hits 2'); + assert.equal(runtimeResolver.templateCacheMisses, 2, 'misses 2'); + assert.equal(runtimeResolver.templateCacheHits, 2, 'hits 2'); this.assertText('Hello precompiled Hello compiled'); } diff --git a/packages/internal-test-helpers/lib/test-cases/rendering.js b/packages/internal-test-helpers/lib/test-cases/rendering.js index 8e5072432ef..22df8187102 100644 --- a/packages/internal-test-helpers/lib/test-cases/rendering.js +++ b/packages/internal-test-helpers/lib/test-cases/rendering.js @@ -7,8 +7,8 @@ export default class RenderingTestCase extends AbstractRenderingTestCase { let { owner } = this; this.env = owner.lookup('service:-glimmer-environment'); - let templateOptions = owner.lookup(P`template-options:main`); - // get the runtime/lazy resolver from the compiler resolver; - this.resolver = templateOptions.resolver.resolver; + this.templateOptions = owner.lookup(P`template-options:main`); + this.compileTimeLookup = this.templateOptions.resolver; + this.runtimeResolver = this.compileTimeLookup.resolver; } } From 39be53cac4bf29b9555f05308fdff43e957ffbdd Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 18 Jan 2018 14:52:43 -0800 Subject: [PATCH 119/135] fix build --- broccoli/to-es5.js | 1 + package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/broccoli/to-es5.js b/broccoli/to-es5.js index 913f084ef53..418c30151f4 100644 --- a/broccoli/to-es5.js +++ b/broccoli/to-es5.js @@ -36,6 +36,7 @@ module.exports = function toES5(tree, _options) { } }], ['transform-es2015-template-literals', {loose: true}], + ['transform-es2015-literals'], ['transform-es2015-arrow-functions'], ['transform-es2015-destructuring', {loose: true}], ['transform-es2015-spread', {loose: true}], diff --git a/package.json b/package.json index 0a2ba467646..f09759291e4 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "babel-plugin-transform-es2015-classes": "^6.24.1", "babel-plugin-transform-es2015-computed-properties": "^6.24.1", "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", "babel-plugin-transform-es2015-modules-amd": "^6.24.1", "babel-plugin-transform-es2015-parameters": "^6.24.1", "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", From 5d2b06d861827d3b0ea55ee5b24a3af16462194a Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 18 Jan 2018 15:12:33 -0800 Subject: [PATCH 120/135] fix root getting factory --- packages/container/lib/index.d.ts | 3 ++- packages/ember-glimmer/lib/component-managers/root.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/container/lib/index.d.ts b/packages/container/lib/index.d.ts index 8dbde3f5450..5e81cd19343 100644 --- a/packages/container/lib/index.d.ts +++ b/packages/container/lib/index.d.ts @@ -15,4 +15,5 @@ interface Container { } export const privatize: any; export const Registry: any; -export const Container: (registry: any, options?: any) => Container; \ No newline at end of file +export const Container: (registry: any, options?: any) => Container; +export const FACTORY_FOR: WeakMap; diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index da96ed9e5e5..4364bf24ecd 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -3,6 +3,7 @@ import { Arguments, ComponentDefinition } from '@glimmer/runtime'; +import { FACTORY_FOR } from 'container'; import { DEBUG } from 'ember-env-flags'; import { _instrumentStart, @@ -89,7 +90,7 @@ export class RootComponentDefinition implements ComponentDefinition { constructor(public component: Component) { let manager = new RootComponentManager(component); this.manager = manager; - let factory = peekMeta(component)._factory; + let factory = FACTORY_FOR.get(component); this.state = { name: factory.fullName.slice(10), capabilities: ROOT_CAPABILITIES, From 96265b11c58b933b87be2a77f99069e3f1a1e699 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 18 Jan 2018 15:55:39 -0800 Subject: [PATCH 121/135] fix Object.assign issues --- .../lib/component-managers/outlet.ts | 16 +++------------- .../ember-glimmer/lib/component-managers/root.ts | 5 +---- packages/ember-glimmer/lib/resolver.ts | 5 ++--- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index 33dd8a2a987..a27f65d2b68 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -1,5 +1,4 @@ import { ComponentCapabilities, Option, Unique } from '@glimmer/interfaces'; -import { ParsedLayout, WrappedBuilder } from '@glimmer/opcode-compiler'; import { CONSTANT_TAG, Tag, VersionedPathReference } from '@glimmer/reference'; @@ -16,7 +15,7 @@ import { import { Destroyable } from '@glimmer/util/dist/types'; import { DEBUG } from 'ember-env-flags'; import { _instrumentStart } from 'ember-metal'; -import { guidFor } from 'ember-utils'; +import { assign, guidFor } from 'ember-utils'; import { OwnedTemplateMeta } from 'ember-views'; import { EMBER_GLIMMER_REMOVE_APPLICATION_TEMPLATE_WRAPPER, @@ -133,7 +132,7 @@ let createRootOutlet: (outletView: OutletView) => OutletComponentDefinition; if (EMBER_GLIMMER_REMOVE_APPLICATION_TEMPLATE_WRAPPER) { createRootOutlet = (outletView: OutletView) => new OutletComponentDefinition(outletView.state); } else { - const WRAPPED_CAPABILITIES = Object.assign({}, CAPABILITIES, { + const WRAPPED_CAPABILITIES = assign({}, CAPABILITIES, { dynamicTag: true, elementHook: true, }); @@ -148,16 +147,7 @@ if (EMBER_GLIMMER_REMOVE_APPLICATION_TEMPLATE_WRAPPER) { getLayout(state: OutletDefinitionState, resolver: RuntimeResolver): Invocation { // The router has already resolved the template const template = state.template; - const compileOptions = Object.assign({}, - resolver.templateOptions, - { asPartial: false, referrer: template.referrer}); - // TODO fix this getting private - const parsed: ParsedLayout = (template as any).parsedLayout; - const layout = new WrappedBuilder( - compileOptions, - parsed, - WRAPPED_CAPABILITIES, - ); + const layout = resolver.getWrappedLayout(template, WRAPPED_CAPABILITIES); return { handle: layout.compile(), symbolTable: layout.symbolTable diff --git a/packages/ember-glimmer/lib/component-managers/root.ts b/packages/ember-glimmer/lib/component-managers/root.ts index 4364bf24ecd..94c3147f057 100644 --- a/packages/ember-glimmer/lib/component-managers/root.ts +++ b/packages/ember-glimmer/lib/component-managers/root.ts @@ -5,10 +5,7 @@ import { } from '@glimmer/runtime'; import { FACTORY_FOR } from 'container'; import { DEBUG } from 'ember-env-flags'; -import { - _instrumentStart, - peekMeta, -} from 'ember-metal'; +import { _instrumentStart } from 'ember-metal'; import { DIRTY_TAG } from '../component'; import Environment from '../environment'; import { DynamicScope } from '../renderer'; diff --git a/packages/ember-glimmer/lib/resolver.ts b/packages/ember-glimmer/lib/resolver.ts index 130f4883d57..a80ed51f69e 100644 --- a/packages/ember-glimmer/lib/resolver.ts +++ b/packages/ember-glimmer/lib/resolver.ts @@ -17,7 +17,7 @@ import { import { privatize as P } from 'container'; import { assert } from 'ember-debug'; import { _instrumentStart } from 'ember-metal'; -import { LookupOptions, Owner, setOwner } from 'ember-utils'; +import { assign, LookupOptions, Owner, setOwner } from 'ember-utils'; import { lookupComponent, lookupPartial, @@ -220,8 +220,7 @@ export default class RuntimeResolver implements IRuntimeResolver = (template as any).parsedLayout; wrapper = new WrappedBuilder(compileOptions, parsed, capabilities); From b4037facb6183d685f3dd327623fd9678d5172c6 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 18 Jan 2018 16:59:43 -0800 Subject: [PATCH 122/135] avoid assign and optimize early common exits from prepareArgs --- .../lib/component-managers/curly.ts | 46 ++++++++----------- .../component-managers/definition-state.ts | 2 +- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index 8faecd9510c..f09b5d5b0f3 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -34,6 +34,7 @@ import { } from 'ember-metal'; import { String as StringUtils } from 'ember-runtime'; import { + assign, getOwner, guidFor, } from 'ember-utils'; @@ -166,41 +167,34 @@ export default class CurlyComponentManager extends AbstractManager { const { positionalParams } = state.ComponentClass.class; - if (typeof positionalParams === 'string') { - if (args.named.has(positionalParams)) { - if (args.positional.length === 0) { - return null; - } else { - assert(`You cannot specify positional parameters and the hash argument \`${positionalParams}\`.`, false); - } - } + // early exits + if (positionalParams === undefined || positionalParams === null || args.positional.length === 0) { + return null; + } + + let named: PreparedArguments['named']; - const named = { - ...args.named.capture().map - }; - named[positionalParams] = args.positional.capture(); - return { positional: EMPTY_ARRAY, named }; - } else if (Array.isArray(positionalParams)) { - const named = { - ...args.named.capture().map - }; + if (typeof positionalParams === 'string') { + assert(`You cannot specify positional parameters and the hash argument \`${positionalParams}\`.`, !args.named.has(positionalParams)); + named = { [positionalParams]: args.positional.capture() }; + assign(named, args.named.capture().map); + } else if (Array.isArray(positionalParams) && positionalParams.length > 0) { const count = Math.min(positionalParams.length, args.positional.length); + named = {}; + assign(named, args.named.capture().map); for (let i=0; i, hasBlock: boolean): ComponentStateBucket { diff --git a/packages/ember-glimmer/lib/component-managers/definition-state.ts b/packages/ember-glimmer/lib/component-managers/definition-state.ts index adbb69b6987..4b0f701703c 100644 --- a/packages/ember-glimmer/lib/component-managers/definition-state.ts +++ b/packages/ember-glimmer/lib/component-managers/definition-state.ts @@ -12,7 +12,7 @@ import { Component } from '../utils/curly-component-state-bucket'; export default interface DefinitionState { capabilities: ComponentCapabilities; name: string; - ComponentClass: Factory; + ComponentClass: Factory; handle: Option; symbolTable?: ProgramSymbolTable; template?: any; From d84f498082260a029ed875055a2dfb3464a2a3b5 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Thu, 18 Jan 2018 17:57:36 -0800 Subject: [PATCH 123/135] still hacky but at least exists in prod too --- packages/ember-glimmer/lib/component-managers/curly.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index f09b5d5b0f3..b2e74f1f0d4 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -283,7 +283,7 @@ export default class CurlyComponentManager extends AbstractManager Date: Thu, 18 Jan 2018 18:29:22 -0800 Subject: [PATCH 124/135] fix linting --- packages/ember-glimmer/lib/component-managers/curly.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ember-glimmer/lib/component-managers/curly.ts b/packages/ember-glimmer/lib/component-managers/curly.ts index b2e74f1f0d4..8e2bebec5fe 100644 --- a/packages/ember-glimmer/lib/component-managers/curly.ts +++ b/packages/ember-glimmer/lib/component-managers/curly.ts @@ -265,7 +265,7 @@ export default class CurlyComponentManager extends AbstractManager Date: Thu, 18 Jan 2018 21:39:04 -0500 Subject: [PATCH 125/135] Increase browser start and total run timeout times. --- testem.dist.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/testem.dist.js b/testem.dist.js index 6088d262f3a..bc1f8e680de 100644 --- a/testem.dist.js +++ b/testem.dist.js @@ -50,38 +50,38 @@ module.exports = { test_page: "dist/tests/index.html?hidepassed&hideskipped&timeout=60000", timeout: 540, reporter: FailureOnlyPerBrowserReporter, - browser_start_timeout: 600, + browser_start_timeout: 1200, parallel: 4, disable_watching: true, launchers: { BS_Chrome_Current: { exe: "node_modules/.bin/browserstack-launch", - args: ["--os", "Windows", "--osv", "10", "--b", "chrome", "--bv", "latest", "-t", "600", "--u", ""], + args: ["--os", "Windows", "--osv", "10", "--b", "chrome", "--bv", "latest", "-t", "1200", "--u", ""], protocol: "browser" }, BS_Firefox_Current: { exe: "node_modules/.bin/browserstack-launch", - args: ["--os", "Windows", "--osv", "10", "--b", "firefox", "--bv", "latest", "-t", "600", "--u", ""], + args: ["--os", "Windows", "--osv", "10", "--b", "firefox", "--bv", "latest", "-t", "1200", "--u", ""], protocol: "browser" }, BS_Safari_Current: { exe: "node_modules/.bin/browserstack-launch", - args: ["--os", "OS X", "--osv", "High Sierra", "--b", "safari", "--bv", "11", "-t", "600", "--u", ""], + args: ["--os", "OS X", "--osv", "High Sierra", "--b", "safari", "--bv", "11", "-t", "1200", "--u", ""], protocol: "browser" }, BS_Safari_Last: { exe: "node_modules/.bin/browserstack-launch", - args: ["--os", "OS X", "--osv", "Sierra", "--b", "safari", "--bv", "10.1", "-t", "600", "--u", ""], + args: ["--os", "OS X", "--osv", "Sierra", "--b", "safari", "--bv", "10.1", "-t", "1200", "--u", ""], protocol: "browser" }, BS_MS_Edge: { exe: "node_modules/.bin/browserstack-launch", - args: ["--os", "Windows", "--osv", "10", "--b", "edge", "--bv", "latest", "-t", "600", "--u", ""], + args: ["--os", "Windows", "--osv", "10", "--b", "edge", "--bv", "latest", "-t", "1200", "--u", ""], protocol: "browser" }, BS_IE_11: { exe: "node_modules/.bin/browserstack-launch", - args: ["--os", "Windows", "--osv", "10", "--b", "ie", "--bv", "11.0", "-t", "600", "--u", ""], + args: ["--os", "Windows", "--osv", "10", "--b", "ie", "--bv", "11.0", "-t", "1200", "--u", ""], protocol: "browser" } }, From 09d9d3fd1030789692fd9a4b7bc7553a322c84c4 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Thu, 18 Jan 2018 22:08:50 -0500 Subject: [PATCH 126/135] Move `@glimmer/*` deps to `devDependencies`. End users of `ember-source` do not need these dependencies... --- package.json | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index caadfbca5d9..c02489bb416 100644 --- a/package.json +++ b/package.json @@ -44,12 +44,6 @@ "test:testem": "testem -f testem.dist.js" }, "dependencies": { - "@glimmer/compiler": "^0.30.4", - "@glimmer/node": "^0.30.4", - "@glimmer/program": "^0.30.4", - "@glimmer/reference": "^0.30.4", - "@glimmer/runtime": "^0.30.4", - "@glimmer/vm": "^0.30.4", "broccoli-funnel": "^2.0.1", "broccoli-merge-trees": "^2.0.0", "ember-cli-get-component-path-option": "^1.0.0", @@ -66,11 +60,12 @@ "resolve": "^1.3.3" }, "devDependencies": { - "@glimmer/compiler": "^0.30.2", - "@glimmer/node": "^0.30.2", - "@glimmer/reference": "^0.30.2", - "@glimmer/runtime": "^0.30.2", - "@glimmer/vm": "^0.30.2", + "@glimmer/compiler": "^0.30.4", + "@glimmer/node": "^0.30.4", + "@glimmer/program": "^0.30.4", + "@glimmer/reference": "^0.30.4", + "@glimmer/runtime": "^0.30.4", + "@glimmer/vm": "^0.30.4", "@types/rsvp": "^4.0.1", "auto-dist-tag": "^0.1.5", "aws-sdk": "^2.46.0", From ac2c603f2ad410e8ee851fccf9af5ba13a24f9bf Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 23 Jan 2018 15:50:08 -0800 Subject: [PATCH 127/135] Fix imports --- packages/ember-glimmer/lib/component-managers/abstract.ts | 6 +++--- packages/ember-glimmer/lib/component-managers/outlet.ts | 2 +- packages/ember-glimmer/lib/template.ts | 2 +- .../ember-glimmer/lib/utils/curly-component-state-bucket.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/abstract.ts b/packages/ember-glimmer/lib/component-managers/abstract.ts index d07d9626011..dacfa154e4e 100644 --- a/packages/ember-glimmer/lib/component-managers/abstract.ts +++ b/packages/ember-glimmer/lib/component-managers/abstract.ts @@ -11,7 +11,7 @@ import { Environment, PreparedArguments, } from '@glimmer/runtime'; -import { IArguments } from '@glimmer/runtime/dist/types/lib/vm/arguments'; +import { Arguments } from '@glimmer/runtime'; import { Destroyable, Opaque, @@ -33,7 +33,7 @@ export default abstract class AbstractManager implements ComponentManager< this.debugStack = undefined; } - prepareArgs(_state: U, _args: IArguments): Option { + prepareArgs(_state: U, _args: Arguments): Option { return null; } @@ -44,7 +44,7 @@ export default abstract class AbstractManager implements ComponentManager< abstract create( env: Environment, definition: U, - args: IArguments, + args: Arguments, dynamicScope: DynamicScope, caller: VersionedPathReference, hasDefaultBlock: boolean): T; diff --git a/packages/ember-glimmer/lib/component-managers/outlet.ts b/packages/ember-glimmer/lib/component-managers/outlet.ts index a27f65d2b68..4de49b46ea9 100644 --- a/packages/ember-glimmer/lib/component-managers/outlet.ts +++ b/packages/ember-glimmer/lib/component-managers/outlet.ts @@ -12,7 +12,7 @@ import { WithDynamicTagName, WithStaticLayout } from '@glimmer/runtime'; -import { Destroyable } from '@glimmer/util/dist/types'; +import { Destroyable } from '@glimmer/util'; import { DEBUG } from 'ember-env-flags'; import { _instrumentStart } from 'ember-metal'; import { assign, guidFor } from 'ember-utils'; diff --git a/packages/ember-glimmer/lib/template.ts b/packages/ember-glimmer/lib/template.ts index 23c8360a5f0..e9cb47cd2e1 100644 --- a/packages/ember-glimmer/lib/template.ts +++ b/packages/ember-glimmer/lib/template.ts @@ -4,7 +4,7 @@ import { templateFactory, TemplateFactory, } from '@glimmer/runtime'; -import { SerializedTemplateWithLazyBlock } from '@glimmer/wire-format/dist/types'; +import { SerializedTemplateWithLazyBlock } from '@glimmer/wire-format'; import { getOwner } from 'ember-utils'; import { OwnedTemplateMeta, StaticTemplateMeta } from 'ember-views'; diff --git a/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts b/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts index 8adfe81d399..56ecb9949e6 100644 --- a/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts +++ b/packages/ember-glimmer/lib/utils/curly-component-state-bucket.ts @@ -1,6 +1,6 @@ import { Revision, VersionedReference } from '@glimmer/reference'; import { CapturedNamedArguments } from '@glimmer/runtime'; -import { Opaque } from '@glimmer/util/dist/types'; +import { Opaque } from '@glimmer/util'; import Environment from '../environment'; export interface Component { From ab647500a4c76a8b2874aac81d8e471598f5e36a Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 23 Jan 2018 15:52:28 -0800 Subject: [PATCH 128/135] Fix glimmer deps --- package.json | 12 ++-- yarn.lock | 191 ++++++++++++++++++++------------------------------- 2 files changed, 82 insertions(+), 121 deletions(-) diff --git a/package.json b/package.json index c02489bb416..518d6e93a6e 100644 --- a/package.json +++ b/package.json @@ -60,12 +60,12 @@ "resolve": "^1.3.3" }, "devDependencies": { - "@glimmer/compiler": "^0.30.4", - "@glimmer/node": "^0.30.4", - "@glimmer/program": "^0.30.4", - "@glimmer/reference": "^0.30.4", - "@glimmer/runtime": "^0.30.4", - "@glimmer/vm": "^0.30.4", + "@glimmer/runtime": "^0.30.5", + "@glimmer/node": "^0.30.5", + "@glimmer/interfaces": "^0.30.5", + "@glimmer/reference": "^0.30.5", + "@glimmer/opcode-compiler": "^0.30.5", + "@glimmer/program": "^0.30.5", "@types/rsvp": "^4.0.1", "auto-dist-tag": "^0.1.5", "aws-sdk": "^2.46.0", diff --git a/yarn.lock b/yarn.lock index 1581810d77d..7434c4bb510 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,122 +2,83 @@ # yarn lockfile v1 -"@glimmer/compiler@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.30.4.tgz#faafa9940077583b9b987d25ce104c185f61c07f" - dependencies: - "@glimmer/interfaces" "^0.30.4" - "@glimmer/syntax" "^0.30.4" - "@glimmer/util" "^0.30.4" - "@glimmer/wire-format" "^0.30.4" - simple-html-tokenizer "^0.4.1" - -"@glimmer/encoder@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.30.4.tgz#adce7e163cb69875eded05baa7af9b28df966bac" - -"@glimmer/interfaces@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.30.4.tgz#16add8c9e2e8f14c923d016647387acec459bfd5" - dependencies: - "@glimmer/wire-format" "^0.30.4" - -"@glimmer/low-level@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/low-level/-/low-level-0.30.4.tgz#e045c7a91e17beeb6b19b32e2593d605148f01cd" - -"@glimmer/node@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.30.4.tgz#79acc7e0d379857c4c1e5d2d7bcdd02e192c8d0b" - dependencies: - "@glimmer/compiler" "^0.30.4" - "@glimmer/interfaces" "^0.30.4" - "@glimmer/object-reference" "^0.30.4" - "@glimmer/runtime" "^0.30.4" +"@glimmer/encoder@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.30.5.tgz#461d81f09215d34294b02e8f18b6cf0e8a2078aa" + +"@glimmer/interfaces@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.30.5.tgz#9fd391ff4b9e4b29cf56495a2c3f5f660e45497a" + dependencies: + "@glimmer/wire-format" "^0.30.5" + +"@glimmer/low-level@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/low-level/-/low-level-0.30.5.tgz#d1e52d4cc5ad753d28ff4168f91d519fc416ff54" + +"@glimmer/node@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/node/-/node-0.30.5.tgz#79ae64537a3046daff0497e586ff29ca712f0821" + dependencies: + "@glimmer/interfaces" "^0.30.5" + "@glimmer/runtime" "^0.30.5" simple-dom "^0.3.0" -"@glimmer/object-reference@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/object-reference/-/object-reference-0.30.4.tgz#576710a678678bb38b83d38cec808d8fdafa9c16" - dependencies: - "@glimmer/reference" "^0.30.4" - "@glimmer/util" "^0.30.4" - -"@glimmer/object@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/object/-/object-0.30.4.tgz#95fa3532947dd02ed6d5debfbdb9bd4d3beac177" - dependencies: - "@glimmer/object-reference" "^0.30.4" - "@glimmer/util" "^0.30.4" - -"@glimmer/opcode-compiler@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/opcode-compiler/-/opcode-compiler-0.30.4.tgz#7f8bd7557fc84b6a5ba3cc46d18adc2fcb819dee" - dependencies: - "@glimmer/encoder" "^0.30.4" - "@glimmer/interfaces" "^0.30.4" - "@glimmer/program" "^0.30.4" - "@glimmer/syntax" "^0.30.4" - "@glimmer/util" "^0.30.4" - "@glimmer/vm" "^0.30.4" - "@glimmer/wire-format" "^0.30.4" - simple-html-tokenizer "^0.4.1" - -"@glimmer/program@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.30.4.tgz#7a03b28a9aecadaca713969dc9402e92bf974383" - dependencies: - "@glimmer/encoder" "^0.30.4" - "@glimmer/interfaces" "^0.30.4" - "@glimmer/util" "^0.30.4" - -"@glimmer/reference@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.30.4.tgz#5d6b1c0fb5a56154600bf47863c9413895a519a6" - dependencies: - "@glimmer/util" "^0.30.4" - -"@glimmer/runtime@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.30.4.tgz#f34fc52047ce7f89700330c1a37d2f427f18c047" - dependencies: - "@glimmer/interfaces" "^0.30.4" - "@glimmer/low-level" "^0.30.4" - "@glimmer/object" "^0.30.4" - "@glimmer/object-reference" "^0.30.4" - "@glimmer/opcode-compiler" "^0.30.4" - "@glimmer/program" "^0.30.4" - "@glimmer/reference" "^0.30.4" - "@glimmer/util" "^0.30.4" - "@glimmer/vm" "^0.30.4" - "@glimmer/wire-format" "^0.30.4" - -"@glimmer/syntax@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.30.4.tgz#bff250f822fe813f42986b32fadeaafcb0f6e015" - dependencies: - "@glimmer/interfaces" "^0.30.4" - "@glimmer/util" "^0.30.4" - handlebars "^4.0.6" - simple-html-tokenizer "^0.4.1" - -"@glimmer/util@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.30.4.tgz#7fbb9e51db17560ac483a33f185acf3ae36838d6" - -"@glimmer/vm@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.30.4.tgz#6069b68f11c178d6911c4105ca07a5a41d435b26" - dependencies: - "@glimmer/interfaces" "^0.30.4" - "@glimmer/program" "^0.30.4" - "@glimmer/util" "^0.30.4" - -"@glimmer/wire-format@^0.30.4": - version "0.30.4" - resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.30.4.tgz#b85c211b59f6b54ee93c2c261db5a03aada3a791" - dependencies: - "@glimmer/util" "^0.30.4" +"@glimmer/opcode-compiler@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/opcode-compiler/-/opcode-compiler-0.30.5.tgz#7a9d15740c2cf17b76a1ea77b69eb66baa8220c9" + dependencies: + "@glimmer/encoder" "^0.30.5" + "@glimmer/interfaces" "^0.30.5" + "@glimmer/program" "^0.30.5" + "@glimmer/util" "^0.30.5" + "@glimmer/vm" "^0.30.5" + "@glimmer/wire-format" "^0.30.5" + +"@glimmer/program@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/program/-/program-0.30.5.tgz#976bcd0a10361f96e0d6d2d2b483c175c767ee26" + dependencies: + "@glimmer/encoder" "^0.30.5" + "@glimmer/interfaces" "^0.30.5" + "@glimmer/util" "^0.30.5" + +"@glimmer/reference@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/reference/-/reference-0.30.5.tgz#71062ea435ea47830b93ab87d4be818865fdc0e6" + dependencies: + "@glimmer/util" "^0.30.5" + +"@glimmer/runtime@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/runtime/-/runtime-0.30.5.tgz#41ffdbd1c1268d56ad8f6b811e4d320abf8359da" + dependencies: + "@glimmer/interfaces" "^0.30.5" + "@glimmer/low-level" "^0.30.5" + "@glimmer/opcode-compiler" "^0.30.5" + "@glimmer/program" "^0.30.5" + "@glimmer/reference" "^0.30.5" + "@glimmer/util" "^0.30.5" + "@glimmer/vm" "^0.30.5" + "@glimmer/wire-format" "^0.30.5" + +"@glimmer/util@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.30.5.tgz#97f3dcd4029f713c503371e1608e129a833a70e1" + +"@glimmer/vm@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/vm/-/vm-0.30.5.tgz#10512f7a8b7505d25cafe726c4a95fce01c67fd1" + dependencies: + "@glimmer/interfaces" "^0.30.5" + "@glimmer/program" "^0.30.5" + "@glimmer/util" "^0.30.5" + +"@glimmer/wire-format@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/wire-format/-/wire-format-0.30.5.tgz#17d79a320b931950ac03887733e56ecc7bbd0a06" + dependencies: + "@glimmer/util" "^0.30.5" "@types/acorn@*": version "4.0.3" @@ -3572,7 +3533,7 @@ growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" -handlebars@^4.0.4, handlebars@^4.0.6: +handlebars@^4.0.4: version "4.0.11" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" dependencies: From 77a81308c61e53028dbc8a4de2cebc9148df42ba Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 23 Jan 2018 15:54:28 -0800 Subject: [PATCH 129/135] forget template compiler needs the compiler --- package.json | 1 + yarn.lock | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 518d6e93a6e..a62771dfdb5 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "resolve": "^1.3.3" }, "devDependencies": { + "@glimmer/compiler": "^0.30.5", "@glimmer/runtime": "^0.30.5", "@glimmer/node": "^0.30.5", "@glimmer/interfaces": "^0.30.5", diff --git a/yarn.lock b/yarn.lock index 7434c4bb510..ba23bc3f060 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,16 @@ # yarn lockfile v1 +"@glimmer/compiler@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/compiler/-/compiler-0.30.5.tgz#b65e377653475b7c401c7eafd0e554cc388103e3" + dependencies: + "@glimmer/interfaces" "^0.30.5" + "@glimmer/syntax" "^0.30.5" + "@glimmer/util" "^0.30.5" + "@glimmer/wire-format" "^0.30.5" + simple-html-tokenizer "^0.4.1" + "@glimmer/encoder@^0.30.5": version "0.30.5" resolved "https://registry.yarnpkg.com/@glimmer/encoder/-/encoder-0.30.5.tgz#461d81f09215d34294b02e8f18b6cf0e8a2078aa" @@ -62,6 +72,15 @@ "@glimmer/vm" "^0.30.5" "@glimmer/wire-format" "^0.30.5" +"@glimmer/syntax@^0.30.5": + version "0.30.5" + resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.30.5.tgz#763a631fccdb5ee2468269becd215752fc2361cc" + dependencies: + "@glimmer/interfaces" "^0.30.5" + "@glimmer/util" "^0.30.5" + handlebars "^4.0.6" + simple-html-tokenizer "^0.4.1" + "@glimmer/util@^0.30.5": version "0.30.5" resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.30.5.tgz#97f3dcd4029f713c503371e1608e129a833a70e1" @@ -3533,7 +3552,7 @@ growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" -handlebars@^4.0.4: +handlebars@^4.0.4, handlebars@^4.0.6: version "4.0.11" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" dependencies: From 17ec6c465938d35ba5106e599067bbfe84766a94 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 23 Jan 2018 17:22:08 -0800 Subject: [PATCH 130/135] fix proxy issue --- .../lib/component-managers/abstract.ts | 2 +- .../ember-runtime/lib/system/core_object.js | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/ember-glimmer/lib/component-managers/abstract.ts b/packages/ember-glimmer/lib/component-managers/abstract.ts index dacfa154e4e..8c67a571a47 100644 --- a/packages/ember-glimmer/lib/component-managers/abstract.ts +++ b/packages/ember-glimmer/lib/component-managers/abstract.ts @@ -4,6 +4,7 @@ import { } from '@glimmer/interfaces'; import { Tag, VersionedPathReference } from '@glimmer/reference'; import { + Arguments, Bounds, ComponentManager, DynamicScope, @@ -11,7 +12,6 @@ import { Environment, PreparedArguments, } from '@glimmer/runtime'; -import { Arguments } from '@glimmer/runtime'; import { Destroyable, Opaque, diff --git a/packages/ember-runtime/lib/system/core_object.js b/packages/ember-runtime/lib/system/core_object.js index f98cb1a47b9..82eeef7aeb3 100644 --- a/packages/ember-runtime/lib/system/core_object.js +++ b/packages/ember-runtime/lib/system/core_object.js @@ -60,6 +60,14 @@ function makeCtor() { constructor() { let self = this; + if (!wasApplied) { + Class.proto(); // prepare prototype... + } + + if (arguments.length > 0) { + initProperties = [arguments[0]]; + } + if (MANDATORY_GETTER && EMBER_METAL_ES5_GETTERS && HAS_NATIVE_PROXY && typeof self.unknownProperty === 'function') { let messageFor = (obj, property) => { return `You attempted to access the \`${String(property)}\` property (of ${obj}).\n` + @@ -76,7 +84,7 @@ function makeCtor() { /* globals Proxy Reflect */ self = new Proxy(this, { get(target, property, receiver) { - if (property === PROXY_CONTENT) { + if (property === PROXY_CONTENT || property === 'didDefineProperty') { return target; } else if (typeof property === 'symbol' || property in target) { return Reflect.get(target, property, receiver); @@ -89,14 +97,6 @@ function makeCtor() { }); } - if (!wasApplied) { - Class.proto(); // prepare prototype... - } - - if (arguments.length > 0) { - initProperties = [arguments[0]]; - } - self.__defineNonEnumerable(GUID_KEY_PROPERTY); let m = meta(self); let proto = m.proto; From c8dd18112cba7bc686283d25a2e3fb48fbc6d644 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 23 Jan 2018 18:11:38 -0800 Subject: [PATCH 131/135] contentFor can now be called before init() this is due to the Proxy issue --- packages/ember-runtime/lib/mixins/-proxy.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/ember-runtime/lib/mixins/-proxy.js b/packages/ember-runtime/lib/mixins/-proxy.js index 43d0f7cd0c4..8541b0ed902 100644 --- a/packages/ember-runtime/lib/mixins/-proxy.js +++ b/packages/ember-runtime/lib/mixins/-proxy.js @@ -37,7 +37,9 @@ function contentPropertyDidChange(content, contentKey) { export function contentFor(proxy, m) { let content = get(proxy, 'content'); let tag = (m === undefined ? meta(proxy) : m).readableTag(); - tag.inner.second.inner.update(tagFor(content)); + if (tag !== undefined) { + tag.inner.second.inner.update(tagFor(content)); + } return content; } From 78e70feca6c8c8bce2a997c419befd6eed76a4d2 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 23 Jan 2018 18:20:20 -0800 Subject: [PATCH 132/135] rollup ember-glimmer --- broccoli/packages.js | 36 ++++++++++++++++++- packages/ember-glimmer/lib/index.ts | 11 ++++++ .../integration/syntax/in-element-test.js | 2 +- .../ember-glimmer/tests/unit/outlet-test.js | 2 +- .../tests/unit/template-factory-test.js | 2 +- .../tests/unit/utils/debug-stack-test.js | 2 +- .../tests/unit/utils/iterable-test.js | 3 +- 7 files changed, 51 insertions(+), 7 deletions(-) diff --git a/broccoli/packages.js b/broccoli/packages.js index 2a43e290edd..983f569ef9d 100644 --- a/broccoli/packages.js +++ b/broccoli/packages.js @@ -86,7 +86,41 @@ module.exports.emberGlimmerES = function _emberGlimmerES() { } }); - return debugTree(funneled, 'ember-glimmer:output'); + let rollup = new Rollup(funneled, { + annotation: 'ember-glimmer', + rollup: { + external: [ + '@glimmer/reference', + '@glimmer/runtime', + '@glimmer/node', + '@glimmer/opcode-compiler', + '@glimmer/program', + '@glimmer/wire-format', + '@glimmer/util', + 'ember-console', + 'ember-debug', + 'ember-env-flags', + 'ember/features', + 'ember-environment', + 'ember-utils', + 'ember-metal', + 'ember-runtime', + 'ember-views', + 'ember-routing', + 'node-module', + 'rsvp', + 'container' + ], + input: 'ember-glimmer/index.js', + output: { + file: 'ember-glimmer.js', + format: 'es', + exports: 'named' + }, + }, + }); + + return debugTree(rollup, 'ember-glimmer:output'); }; module.exports.handlebarsES = function _handlebars() { diff --git a/packages/ember-glimmer/lib/index.ts b/packages/ember-glimmer/lib/index.ts index b3942b735cc..d7ae9537dab 100644 --- a/packages/ember-glimmer/lib/index.ts +++ b/packages/ember-glimmer/lib/index.ts @@ -293,3 +293,14 @@ export { setupEngineRegistry, setupApplicationRegistry } from './setup-registry' export { DOMChanges, NodeDOMTreeConstruction, DOMTreeConstruction } from './dom'; export { registerMacros as _registerMacros, experimentalMacros as _experimentalMacros } from './syntax'; export { default as AbstractComponentManager } from './component-managers/abstract'; + +// needed for test +// TODO just test these through public API +// a lot of these are testing how a problem was solved +// rather than the problem was solved +// DebugStack should just test the assert message +// it supports for example +export { UpdatableReference } from './utils/references'; +export { default as iterableFor } from './utils/iterable'; +export { default as DebugStack } from './utils/debug-stack'; +export { default as OutletView } from './views/outlet'; diff --git a/packages/ember-glimmer/tests/integration/syntax/in-element-test.js b/packages/ember-glimmer/tests/integration/syntax/in-element-test.js index d5743860595..ffd0a6de077 100644 --- a/packages/ember-glimmer/tests/integration/syntax/in-element-test.js +++ b/packages/ember-glimmer/tests/integration/syntax/in-element-test.js @@ -1,7 +1,7 @@ import { moduleFor, RenderingTest } from '../../utils/test-case'; import { equalTokens } from '../../utils/test-helpers'; import { strip } from '../../utils/abstract-test-case'; -import Component from '../../../component'; +import { Component } from 'ember-glimmer'; import { set } from 'ember-metal'; moduleFor('{{in-element}}', class extends RenderingTest { diff --git a/packages/ember-glimmer/tests/unit/outlet-test.js b/packages/ember-glimmer/tests/unit/outlet-test.js index e9cc8d1a237..78f9493073f 100644 --- a/packages/ember-glimmer/tests/unit/outlet-test.js +++ b/packages/ember-glimmer/tests/unit/outlet-test.js @@ -1,4 +1,4 @@ -import OutletView from 'ember-glimmer/views/outlet'; +import { OutletView } from 'ember-glimmer'; import { run } from 'ember-metal'; QUnit.module('Glimmer OutletView'); diff --git a/packages/ember-glimmer/tests/unit/template-factory-test.js b/packages/ember-glimmer/tests/unit/template-factory-test.js index b5e03c5a500..8320c085fa3 100644 --- a/packages/ember-glimmer/tests/unit/template-factory-test.js +++ b/packages/ember-glimmer/tests/unit/template-factory-test.js @@ -1,5 +1,5 @@ import { precompile, compile } from 'ember-template-compiler'; -import { template } from '../../index'; +import { template } from 'ember-glimmer'; import { RenderingTest, moduleFor } from '../utils/test-case'; import { Component } from '../utils/helpers'; diff --git a/packages/ember-glimmer/tests/unit/utils/debug-stack-test.js b/packages/ember-glimmer/tests/unit/utils/debug-stack-test.js index ce70d45d941..601555e555f 100644 --- a/packages/ember-glimmer/tests/unit/utils/debug-stack-test.js +++ b/packages/ember-glimmer/tests/unit/utils/debug-stack-test.js @@ -1,4 +1,4 @@ -import DebugStack from 'ember-glimmer/utils/debug-stack'; +import { DebugStack } from 'ember-glimmer'; import { DEBUG } from 'ember-env-flags'; if (DEBUG) { diff --git a/packages/ember-glimmer/tests/unit/utils/iterable-test.js b/packages/ember-glimmer/tests/unit/utils/iterable-test.js index 859a66c8b58..28797a895dd 100644 --- a/packages/ember-glimmer/tests/unit/utils/iterable-test.js +++ b/packages/ember-glimmer/tests/unit/utils/iterable-test.js @@ -1,7 +1,6 @@ import Ember from 'ember'; import { moduleFor, TestCase } from 'ember-glimmer/tests/utils/test-case'; -import iterableFor from 'ember-glimmer/utils/iterable'; -import { UpdatableReference } from 'ember-glimmer/utils/references'; +import { iterableFor, UpdatableReference } from 'ember-glimmer'; const ITERATOR_KEY_GUID = 'be277757-bbbe-4620-9fcb-213ef433cca2'; From c75e6f7be099d9c3d600e49fdf56bd20fabbb467 Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Tue, 23 Jan 2018 23:13:11 -0800 Subject: [PATCH 133/135] another hack --- packages/ember-runtime/lib/system/core_object.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/ember-runtime/lib/system/core_object.js b/packages/ember-runtime/lib/system/core_object.js index 82eeef7aeb3..e2e809a49e4 100644 --- a/packages/ember-runtime/lib/system/core_object.js +++ b/packages/ember-runtime/lib/system/core_object.js @@ -84,9 +84,14 @@ function makeCtor() { /* globals Proxy Reflect */ self = new Proxy(this, { get(target, property, receiver) { - if (property === PROXY_CONTENT || property === 'didDefineProperty') { + if (property === PROXY_CONTENT) { return target; - } else if (typeof property === 'symbol' || property in target) { + } else if (typeof property === 'symbol' || + property === NAME_KEY || + property === GUID_KEY_PROPERTY || + property === 'toString' || + property === 'toJSON' || + property === 'toStringExtension' || property in target) { return Reflect.get(target, property, receiver); } From e6cbc39ecee745bdb11ce6abc1830d2c9b25af2f Mon Sep 17 00:00:00 2001 From: Kris Selden Date: Wed, 24 Jan 2018 15:09:04 -0800 Subject: [PATCH 134/135] fix tests --- packages/ember-runtime/lib/system/core_object.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/ember-runtime/lib/system/core_object.js b/packages/ember-runtime/lib/system/core_object.js index e2e809a49e4..4e49c8c061e 100644 --- a/packages/ember-runtime/lib/system/core_object.js +++ b/packages/ember-runtime/lib/system/core_object.js @@ -68,6 +68,8 @@ function makeCtor() { initProperties = [arguments[0]]; } + let before = true; + if (MANDATORY_GETTER && EMBER_METAL_ES5_GETTERS && HAS_NATIVE_PROXY && typeof self.unknownProperty === 'function') { let messageFor = (obj, property) => { return `You attempted to access the \`${String(property)}\` property (of ${obj}).\n` + @@ -86,11 +88,12 @@ function makeCtor() { get(target, property, receiver) { if (property === PROXY_CONTENT) { return target; - } else if (typeof property === 'symbol' || + } else if (before || + typeof property === 'symbol' || property === NAME_KEY || property === GUID_KEY_PROPERTY || - property === 'toString' || property === 'toJSON' || + property === 'toString' || property === 'toStringExtension' || property in target) { return Reflect.get(target, property, receiver); } @@ -200,7 +203,7 @@ function makeCtor() { if (ENV._ENABLE_BINDING_SUPPORT) { Mixin.finishPartial(self, m); } - + before = false; self.init(...arguments); self[POST_INIT](); From eeecb9b2c88fb5ec7943bae52950c1e2fa439b42 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Thu, 25 Jan 2018 09:26:54 -0800 Subject: [PATCH 135/135] Fix backwards compat shim for custom AST plugins. --- packages/ember-template-compiler/lib/index.js | 3 +- .../lib/system/compile-options.js | 29 ++++---- .../tests/system/compile_options_test.js | 71 ++++++++++++++++++- 3 files changed, 87 insertions(+), 16 deletions(-) diff --git a/packages/ember-template-compiler/lib/index.js b/packages/ember-template-compiler/lib/index.js index 2120b607e61..9ddffd9582f 100644 --- a/packages/ember-template-compiler/lib/index.js +++ b/packages/ember-template-compiler/lib/index.js @@ -14,7 +14,8 @@ export { default as precompile } from './system/precompile'; export { default as compile } from './system/compile'; export { default as compileOptions, - registerPlugin + registerPlugin, + unregisterPlugin } from './system/compile-options'; export { default as defaultPlugins } from './plugins'; diff --git a/packages/ember-template-compiler/lib/system/compile-options.js b/packages/ember-template-compiler/lib/system/compile-options.js index bb1deaaa862..231b4727a28 100644 --- a/packages/ember-template-compiler/lib/system/compile-options.js +++ b/packages/ember-template-compiler/lib/system/compile-options.js @@ -16,27 +16,24 @@ export default function compileOptions(_options) { options.plugins = { ast: [...USER_PLUGINS, ...PLUGINS] }; } else { let potententialPugins = [...USER_PLUGINS, ...PLUGINS]; + let providedPlugins = options.plugins.ast.map(plugin => wrapLegacyPluginIfNeeded(plugin)); let pluginsToAdd = potententialPugins.filter((plugin) => { return options.plugins.ast.indexOf(plugin) === -1; }); - options.plugins.ast = options.plugins.ast.slice().concat(pluginsToAdd); + options.plugins.ast = providedPlugins.concat(pluginsToAdd); } return options; } -export function registerPlugin(type, _plugin) { - if (type !== 'ast') { - throw new Error(`Attempting to register ${_plugin} as "${type}" which is not a valid Glimmer plugin type.`); - } - - let plugin; +function wrapLegacyPluginIfNeeded(_plugin) { + let plugin = _plugin; if (_plugin.prototype && _plugin.prototype.transform) { plugin = (env) => { return { name: _plugin.constructor && _plugin.constructor.name, - visitors: { + visitor: { Program(node) { let plugin = new _plugin(env); @@ -45,16 +42,24 @@ export function registerPlugin(type, _plugin) { return plugin.transform(node); } } - }; + }; }; - } else { - plugin = _plugin; } + return plugin; +} + +export function registerPlugin(type, _plugin) { + if (type !== 'ast') { + throw new Error(`Attempting to register ${_plugin} as "${type}" which is not a valid Glimmer plugin type.`); + } + + let plugin = wrapLegacyPluginIfNeeded(_plugin); + USER_PLUGINS = [plugin, ...USER_PLUGINS]; } -export function removePlugin(type, PluginClass) { +export function unregisterPlugin(type, PluginClass) { if (type !== 'ast') { throw new Error(`Attempting to unregister ${PluginClass} as "${type}" which is not a valid Glimmer plugin type.`); } diff --git a/packages/ember-template-compiler/tests/system/compile_options_test.js b/packages/ember-template-compiler/tests/system/compile_options_test.js index ec6b86ff4e9..f4c78dc12dd 100644 --- a/packages/ember-template-compiler/tests/system/compile_options_test.js +++ b/packages/ember-template-compiler/tests/system/compile_options_test.js @@ -1,6 +1,5 @@ -import { compileOptions } from '../../index'; -import { defaultPlugins } from '../../index'; -import { moduleFor, AbstractTestCase } from 'internal-test-helpers'; +import { compile, compileOptions, defaultPlugins, registerPlugin, unregisterPlugin } from '../../index'; +import { moduleFor, AbstractTestCase, RenderingTestCase } from 'internal-test-helpers'; moduleFor('ember-template-compiler: default compile options', class extends AbstractTestCase { ['@test default options are a new copy'](assert) { @@ -18,3 +17,69 @@ moduleFor('ember-template-compiler: default compile options', class extends Abst } } }); + +class CustomTransform { + constructor(options) { + this.options = options; + this.syntax = null; + } + + transform(ast) { + let walker = new this.syntax.Walker(); + + walker.visit(ast, node => { + if (node.type !== 'ElementNode') { + return; + } + + for (var i = 0; i < node.attributes.length; i++) { + let attribute = node.attributes[i]; + + if (attribute.name === 'data-test') { + node.attributes.splice(i, 1); + } + } + }); + + return ast; + } +} + +moduleFor('ember-template-compiler: registerPlugin with a custom plugins', class extends RenderingTestCase { + beforeEach() { + registerPlugin('ast', CustomTransform); + } + + afterEach() { + unregisterPlugin('ast', CustomTransform); + } + + ['@test custom plugins can be used']() { + this.render('
'); + this.assertElement(this.firstChild, { + tagName: 'div', + attrs: { class: 'hahaha', 'data-blah': 'derp' }, + content: '' + }); + } +}); + +moduleFor('ember-template-compiler: custom plugins passed to compile', class extends RenderingTestCase { + // override so that we can provide custom AST plugins to compile + compile(templateString) { + return compile(templateString, { + plugins: { + ast: [CustomTransform] + } + }); + } + + ['@test custom plugins can be used']() { + this.render('
'); + this.assertElement(this.firstChild, { + tagName: 'div', + attrs: { class: 'hahaha', 'data-blah': 'derp' }, + content: '' + }); + } +});