diff --git a/packages/ember-application/lib/system/application-instance.js b/packages/ember-application/lib/system/application-instance.js index 295438c0b4f..25ff8e1a1fc 100644 --- a/packages/ember-application/lib/system/application-instance.js +++ b/packages/ember-application/lib/system/application-instance.js @@ -283,18 +283,9 @@ ApplicationInstance.reopenClass({ */ setupRegistry(registry, options = new BootOptions()) { registry.register('-environment:main', options.toEnvironment(), { instantiate: false }); - registry.injection('view', '_environment', '-environment:main'); - registry.injection('route', '_environment', '-environment:main'); - registry.register('service:-document', options.document, { instantiate: false }); - if (options.isInteractive) { - registry.injection('view', 'renderer', 'renderer:-dom'); - registry.injection('component', 'renderer', 'renderer:-dom'); - } else { - registry.injection('view', 'renderer', 'renderer:-inert'); - registry.injection('component', 'renderer', 'renderer:-inert'); - } + this._super(registry, options); } }); diff --git a/packages/ember-application/lib/system/engine-instance.js b/packages/ember-application/lib/system/engine-instance.js index 6475f642650..a792b04c236 100644 --- a/packages/ember-application/lib/system/engine-instance.js +++ b/packages/ember-application/lib/system/engine-instance.js @@ -74,7 +74,7 @@ const EngineInstance = EmberObject.extend(RegistryProxy, ContainerProxy, { @param options {Object} @return {Promise} */ - boot(options = {}) { + boot(options) { if (this._bootPromise) { return this._bootPromise; } this._bootPromise = new RSVP.Promise(resolve => resolve(this._bootSync(options))); @@ -105,6 +105,8 @@ const EngineInstance = EmberObject.extend(RegistryProxy, ContainerProxy, { this.cloneParentDependencies(); } + this.setupRegistry(options); + this.base.runInstanceInitializers(this); this._booted = true; @@ -112,6 +114,10 @@ const EngineInstance = EmberObject.extend(RegistryProxy, ContainerProxy, { return this; }, + setupRegistry(options = this.__container__.lookup('-environment:main')) { + this.constructor.setupRegistry(this.__registry__, options); + }, + /** Unregister a factory. @@ -136,6 +142,30 @@ const EngineInstance = EmberObject.extend(RegistryProxy, ContainerProxy, { } }); +EngineInstance.reopenClass({ + /** + @private + @method setupRegistry + @param {Registry} registry + @param {BootOptions} options + */ + setupRegistry(registry, options) { + // when no options/environment is present, do nothing + if (!options) { return; } + + registry.injection('view', '_environment', '-environment:main'); + registry.injection('route', '_environment', '-environment:main'); + + if (options.isInteractive) { + registry.injection('view', 'renderer', 'renderer:-dom'); + registry.injection('component', 'renderer', 'renderer:-dom'); + } else { + registry.injection('view', 'renderer', 'renderer:-inert'); + registry.injection('component', 'renderer', 'renderer:-inert'); + } + } +}); + if (isEnabled('ember-application-engines')) { EngineInstance.reopen({ /** diff --git a/packages/ember-glimmer/lib/environment.js b/packages/ember-glimmer/lib/environment.js index 0eefb4d8276..3ec6a8cf310 100644 --- a/packages/ember-glimmer/lib/environment.js +++ b/packages/ember-glimmer/lib/environment.js @@ -272,7 +272,7 @@ export default class Environment extends GlimmerEnvironment { let name = path[0]; let blockMeta = symbolTable.getMeta(); let owner = blockMeta.owner; - let source = `template:${blockMeta.moduleName}`; + let source = blockMeta.moduleName && `template:${blockMeta.moduleName}`; return this._definitionCache.get({ name, source, owner }); } diff --git a/packages/ember-glimmer/lib/setup-registry.js b/packages/ember-glimmer/lib/setup-registry.js index eea23851f79..c7390c7bcf0 100644 --- a/packages/ember-glimmer/lib/setup-registry.js +++ b/packages/ember-glimmer/lib/setup-registry.js @@ -6,6 +6,7 @@ import TextField from './components/text_field'; import TextArea from './components/text_area'; import Checkbox from './components/checkbox'; import LinkToComponent from './components/link-to'; +import Component from './component'; import ComponentTemplate from './templates/component'; import RootTemplate from './templates/root'; import OutletTemplate from './templates/outlet'; @@ -50,4 +51,5 @@ export function setupEngineRegistry(registry) { registry.register('component:-text-area', TextArea); registry.register('component:-checkbox', Checkbox); registry.register('component:link-to', LinkToComponent); + registry.register(P`component:-default`, Component); } diff --git a/packages/ember-glimmer/lib/syntax/curly-component.js b/packages/ember-glimmer/lib/syntax/curly-component.js index 44c905b5435..13d50acf2ba 100644 --- a/packages/ember-glimmer/lib/syntax/curly-component.js +++ b/packages/ember-glimmer/lib/syntax/curly-component.js @@ -8,7 +8,6 @@ import assign from 'ember-metal/assign'; import get from 'ember-metal/property_get'; import { _instrumentStart } from 'ember-metal/instrumentation'; import { ComponentDefinition } from 'glimmer-runtime'; -import Component from '../component'; import { OWNER } from 'container/owner'; const DEFAULT_LAYOUT = P`template:components/-default`; @@ -188,7 +187,6 @@ class CurlyComponentManager { aliasIdToElementId(args, props); props.parentView = parentView; - props.renderer = parentView.renderer; props[HAS_BLOCK] = hasBlock; // dynamicScope here is inherited from the parent dynamicScope, @@ -370,7 +368,7 @@ function ariaRole(vm) { export class CurlyComponentDefinition extends ComponentDefinition { constructor(name, ComponentClass, template, args) { - super(name, MANAGER, ComponentClass || Component); + super(name, MANAGER, ComponentClass); this.template = template; this.args = args; } diff --git a/packages/ember-glimmer/tests/integration/application/engine-test.js b/packages/ember-glimmer/tests/integration/application/engine-test.js index c3bbcd40d03..2b8a9ba57e9 100644 --- a/packages/ember-glimmer/tests/integration/application/engine-test.js +++ b/packages/ember-glimmer/tests/integration/application/engine-test.js @@ -4,6 +4,7 @@ import { strip } from '../../utils/abstract-test-case'; import { compile } from '../../utils/helpers'; import Controller from 'ember-runtime/controllers/controller'; import Engine from 'ember-application/system/engine'; +import Route from 'ember-routing/system/route'; import isEnabled from 'ember-metal/features'; // only run these tests for ember-glimmer when the feature is enabled, or for @@ -56,5 +57,41 @@ if (shouldRun) { this.assertText('ApplicationController Data!EngineComponent!'); }); } + + ['@test can use shouldRender: false'](assert) { + this.assert.expect(2); + let hooks = []; + + this.registerRoute('application', Route.extend({ + model() { + hooks.push('application - application'); + } + })); + + this.router.map(function() { + this.mount('blog'); + }); + this.application.register('route-map:blog', function() { }); + + this.registerEngine('blog', Engine.extend({ + init() { + this._super(...arguments); + + this.register('route:application', Route.extend({ + model() { + hooks.push('engine - application'); + } + })); + } + })); + + return this.visit('/blog', { shouldRender: false }).then(() => { + this.assertText(''); + this.assert.deepEqual(hooks, [ + 'application - application', + 'engine - application' + ], 'the expected model hooks were fired'); + }); + } }); } 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 5b3e2f1da39..8024a5fa341 100644 --- a/packages/ember-glimmer/tests/integration/components/curly-components-test.js +++ b/packages/ember-glimmer/tests/integration/components/curly-components-test.js @@ -28,6 +28,18 @@ moduleFor('Components test: curly components', class extends RenderingTest { this.assertComponentElement(this.firstChild, { content: 'hello' }); } + ['@test it can render a template only component']() { + this.registerComponent('foo-bar', { template: 'hello' }); + + this.render('{{foo-bar}}'); + + this.assertComponentElement(this.firstChild, { content: 'hello' }); + + this.runTask(() => this.rerender()); + + this.assertComponentElement(this.firstChild, { content: 'hello' }); + } + ['@test it can have a custom id and it is not bound']() { this.registerComponent('foo-bar', { template: '{{id}} {{elementId}}' }); diff --git a/packages/ember-glimmer/tests/utils/abstract-test-case.js b/packages/ember-glimmer/tests/utils/abstract-test-case.js index 346a559c7d8..88c4533c140 100644 --- a/packages/ember-glimmer/tests/utils/abstract-test-case.js +++ b/packages/ember-glimmer/tests/utils/abstract-test-case.js @@ -266,13 +266,13 @@ export class AbstractApplicationTest extends TestCase { runDestroy(this.application); } - visit(url) { + visit(url, options) { let { applicationInstance } = this; if (applicationInstance) { - return run(applicationInstance, 'visit', url); + return run(applicationInstance, 'visit', url, options); } else { - return run(this.application, 'visit', url).then(instance => { + return run(this.application, 'visit', url, options).then(instance => { this.applicationInstance = instance; }); } diff --git a/packages/ember-htmlbars/lib/setup-registry.js b/packages/ember-htmlbars/lib/setup-registry.js index 2bb9a4afe27..3c5ef274700 100644 --- a/packages/ember-htmlbars/lib/setup-registry.js +++ b/packages/ember-htmlbars/lib/setup-registry.js @@ -1,15 +1,16 @@ +import { privatize as P } from 'container/registry'; import { InteractiveRenderer, InertRenderer } from 'ember-htmlbars/renderer'; import HTMLBarsDOMHelper from 'ember-htmlbars/system/dom-helper'; import topLevelViewTemplate from 'ember-htmlbars/templates/top-level-view'; import { OutletView as HTMLBarsOutletView } from 'ember-htmlbars/views/outlet'; import EmberView from 'ember-views/views/view'; +import Component from 'ember-htmlbars/component'; import TextField from 'ember-htmlbars/components/text_field'; import TextArea from 'ember-htmlbars/components/text_area'; import Checkbox from 'ember-htmlbars/components/checkbox'; import LinkToComponent from 'ember-htmlbars/components/link-to'; import TemplateSupport from 'ember-views/mixins/template_support'; - export function setupApplicationRegistry(registry) { registry.register('renderer:-dom', InteractiveRenderer); registry.register('renderer:-inert', InertRenderer); @@ -32,4 +33,6 @@ export function setupEngineRegistry(registry) { registry.register('component:-text-area', TextArea); registry.register('component:-checkbox', Checkbox); registry.register('component:link-to', LinkToComponent); + + registry.register(P`component:-default`, Component); } diff --git a/packages/ember-views/lib/utils/lookup-component.js b/packages/ember-views/lib/utils/lookup-component.js index a182a5c2450..0521c921d8e 100644 --- a/packages/ember-views/lib/utils/lookup-component.js +++ b/packages/ember-views/lib/utils/lookup-component.js @@ -1,10 +1,16 @@ +import { privatize as P } from 'container/registry'; + function lookupComponentPair(componentLookup, owner, name, options) { let component = componentLookup.componentFor(name, owner, options); let layout = componentLookup.layoutFor(name, owner, options); - return { - component, - layout - }; + + let result = { layout, component }; + + if (layout && !component) { + result.component = owner._lookupFactory(P`component:-default`); + } + + return result; } export default function lookupComponent(owner, name, options) {