Skip to content

[DRAFT] Explore removing templateFor from curly component manager#21285

Closed
NullVoxPopuli-ai-agent wants to merge 2 commits intoemberjs:mainfrom
NullVoxPopuli-ai-agent:nvp/remove-templateFor-dynamic-layout
Closed

[DRAFT] Explore removing templateFor from curly component manager#21285
NullVoxPopuli-ai-agent wants to merge 2 commits intoemberjs:mainfrom
NullVoxPopuli-ai-agent:nvp/remove-templateFor-dynamic-layout

Conversation

@NullVoxPopuli-ai-agent
Copy link
Copy Markdown
Contributor

Investigation

Explored removing getDynamicLayout/templateFor from the curly component manager.

Finding

getDynamicLayout cannot be fully removed because it's needed for the root component rendered via runAppend(), which bypasses the resolver entirely.

The template resolution flow for curly components has two paths:

  1. Named components (e.g. <FooBar /> in a template): The resolver's lookupComponentPair calls getComponentTemplate(component.class) and returns the template as part of the component definition. The VM uses this directly — getDynamicLayout is never called.

  2. Root component (via runAppend in this.render()): The component is created directly and passed to runAppend, bypassing the resolver. The VM has no template from the resolver, so it falls back to getDynamicLayoutgetComponentTemplate(component.constructor).

What changed

  • Removed the separate templateFor() method, inlined logic into getDynamicLayout
  • Added comments explaining why getDynamicLayout is still needed

What would be needed to fully remove it

  • runAppend would need to go through the resolver, OR
  • The VM would need to check getComponentTemplate() directly when no template is provided, OR
  • this.render() in tests would need to stop using runAppend with classic components

Builds on #21284.

🤖 Generated with Claude Code

The curly component manager now uses getComponentTemplate() to resolve
templates, aligning with how Glimmer components work. The layout and
layoutName properties are removed from Component.

Changes:
- curly.ts: templateFor() uses getComponentTemplate(component.constructor)
  instead of layout/layoutName properties
- component.ts: remove layout and layoutName property declarations
- rendering.ts, router-non-application.ts: render() uses template() from
  @ember/template-compiler/runtime instead of compile + layoutName
- abstract-application.ts: remove compile method
- Tests using layoutName rewritten to use setComponentTemplate
- Tests specifically testing layout/layoutName behavior removed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@NullVoxPopuli-ai-agent NullVoxPopuli-ai-agent force-pushed the nvp/remove-templateFor-dynamic-layout branch 2 times, most recently from fbbde80 to 5601996 Compare April 3, 2026 13:13
manager: RootComponentManager;
capabilities = capabilityFlagsFrom(ROOT_CAPABILITIES);
compilable = null;
compilable: CompilableProgram;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need to be here? a some point we need to stop unwrapping templates

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — the unwrapTemplate chain is tech debt. For now it's needed because the VM's compilable field requires CompilableProgram, and getComponentTemplate returns a TemplateFactory. Removing the unwrap would mean changing the VM to accept template factories directly.

tagName: '',
layoutName: '-top-level',
let TopLevel = template(templateStr, {
component: Component.extend(Object.assign({}, context, { tagName: '' })),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we c an probably just use templateOnly() here / omit component entirely. This value isn't doing anything for us

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried using templateOnly() but the container's owner.lookup calls .create() on the registered factory, which templateOnly() doesn't have. Kept Component.extend({ tagName: '' }) but removed the unused context parameter since this render method is never called with one.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so we update that, too

@NullVoxPopuli-ai-agent NullVoxPopuli-ai-agent force-pushed the nvp/remove-templateFor-dynamic-layout branch from 5601996 to b98dfff Compare April 3, 2026 14:08
…agers

Fully removes the dynamicLayout capability and getDynamicLayout from
curly and root component managers.

curly.ts:
- Removed getDynamicLayout, templateFor, WithDynamicLayout interface
- Set dynamicLayout: false in CURLY_CAPABILITIES
- Removed unused imports (getOwner, getComponentTemplate, unwrapTemplate,
  CompilableProgram, RuntimeResolver)

root.ts:
- RootComponentDefinition eagerly resolves template via getComponentTemplate()
- Uses a default empty template (precompileTemplate('')) when no template
  is set, so compilable is never null
- Set dynamicLayout: false in ROOT_CAPABILITIES
- Removed getDynamicLayout from RootComponentManager

Template resolution for curly components now has one path: the resolver
provides it via getComponentTemplate() at lookup time. Root components
get their template eagerly in the definition constructor.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@NullVoxPopuli-ai-agent NullVoxPopuli-ai-agent force-pushed the nvp/remove-templateFor-dynamic-layout branch from b98dfff to 252e9f4 Compare April 3, 2026 14:36
@NullVoxPopuli
Copy link
Copy Markdown
Contributor

once we deprecate @ember/component, we can revisit this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants