Skip to content

Commit

Permalink
Merge pull request #14967 from status200/mount-syntax-refactor
Browse files Browse the repository at this point in the history
Refactor {{mount}} syntax
  • Loading branch information
rwjblue authored Mar 2, 2017
2 parents 3e30b50 + a2b1684 commit 4d0a17b
Showing 1 changed file with 54 additions and 18 deletions.
72 changes: 54 additions & 18 deletions packages/ember-glimmer/lib/syntax/mount.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ import { OutletLayoutCompiler } from './outlet';
import { FACTORY_FOR } from 'container';
import AbstractManager from './abstract-manager';

function dynamicEngineFor(vm, symbolTable) {
let env = vm.env;
let args = vm.getArgs();
let nameRef = args.positional.at(0);

return new DynamicEngineReference({ nameRef, env, symbolTable });
}

/**
The `{{mount}}` helper lets you embed a routeless engine in a template.
Mounting an engine will cause an instance to be booted and its `application`
Expand All @@ -39,45 +47,74 @@ export function mountMacro(path, params, hash, builder) {
params.length === 1 && hash === null
);

let name = params[0];

assert(
'The first argument of {{mount}} must be quoted, e.g. {{mount "chat-engine"}}.',
typeof name === 'string'
);

assert(
`You used \`{{mount '${name}'}}\`, but the engine '${name}' can not be found.`,
builder.env.owner.hasRegistration(`engine:${name}`)
typeof params[0] === 'string'
);

builder.component.static(new MountDefinition(name, builder.env), [params, hash, null, null], builder.symbolTable);
let definitionArgs = [params.slice(0, 1), null, null, null];
let args = [null, null, null, null];
builder.component.dynamic(definitionArgs, dynamicEngineFor, args, builder.symbolTable);
return true;
}

class DynamicEngineReference {
constructor({ nameRef, env, symbolTable, args }) {
this.tag = nameRef.tag;
this.nameRef = nameRef;
this.env = env;
this.symbolTable = symbolTable;
this._lastName = undefined;
this._lastDef = undefined;
}

value() {
let { env, nameRef, /*symbolTable*/ } = this;
let nameOrDef = nameRef.value();

if (this._lastName === nameOrDef) {
return this._lastDef;
}

assert(
`You used \`{{mount '${nameOrDef}'}}\`, but the engine '${nameOrDef}' can not be found.`,
env.owner.hasRegistration(`engine:${nameOrDef}`)
);

if (!env.owner.hasRegistration(`engine:${nameOrDef}`)) {
return null;
}

this._lastName = nameOrDef;
this._lastDef = new MountDefinition(nameOrDef);

return this._lastDef;
}
}

class MountManager extends AbstractManager {
prepareArgs(definition, args) {
return args;
}

create(environment, { name, env }, args, dynamicScope) {
runInDebug(() => this._pushEngineToDebugStack(`engine:${name}`, env));
create(environment, { name }, args, dynamicScope) {
runInDebug(() => this._pushEngineToDebugStack(`engine:${name}`, environment));

dynamicScope.outletState = UNDEFINED_REFERENCE;

let engine = env.owner.buildChildEngineInstance(name);
let engine = environment.owner.buildChildEngineInstance(name);

engine.boot();

return { engine };
return engine;
}

layoutFor(definition, { engine }, env) {
layoutFor(definition, engine, env) {
let template = engine.lookup(`template:application`);
return env.getCompiledBlock(OutletLayoutCompiler, template);
}

getSelf({ engine }) {
getSelf(engine) {
let applicationFactory = engine[FACTORY_FOR](`controller:application`);
let factory = applicationFactory || generateControllerFactory(engine, 'application');
return new RootReference(factory.create());
Expand All @@ -87,7 +124,7 @@ class MountManager extends AbstractManager {
return null;
}

getDestructor({ engine }) {
getDestructor(engine) {
return engine;
}

Expand All @@ -106,8 +143,7 @@ class MountManager extends AbstractManager {
const MOUNT_MANAGER = new MountManager();

class MountDefinition extends ComponentDefinition {
constructor(name, env) {
constructor(name) {
super(name, MOUNT_MANAGER, null);
this.env = env;
}
}

0 comments on commit 4d0a17b

Please sign in to comment.