Skip to content

Commit c1cc192

Browse files
NullVoxPopuliclaude
andcommitted
Remove layout/layoutName from classic Component
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>
1 parent 70ceeef commit c1cc192

File tree

16 files changed

+141
-373
lines changed

16 files changed

+141
-373
lines changed

packages/@ember/-internals/glimmer/lib/component-managers/curly.ts

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import type {
1919
Environment,
2020
InternalComponentCapabilities,
2121
PreparedArguments,
22-
TemplateFactory,
2322
VMArguments,
2423
WithCreateInstance,
2524
WithDynamicLayout,
@@ -42,7 +41,7 @@ import {
4241
import type Component from '../component';
4342
import type { DynamicScope } from '../renderer';
4443
import type RuntimeResolver from '../resolver';
45-
import { isTemplateFactory } from '../template';
44+
import { getComponentTemplate } from '@glimmer/manager';
4645
import {
4746
createClassNameBindingRef,
4847
createSimpleClassNameBindingRef,
@@ -132,24 +131,12 @@ export default class CurlyComponentManager
132131
WithDynamicTagName<ComponentStateBucket>
133132
{
134133
protected templateFor(component: Component): CompilableProgram | null {
135-
let { layout, layoutName } = component;
136134
let owner = getOwner(component);
137135
assert('Component is unexpectedly missing an owner', owner);
138136

139-
let factory: TemplateFactory;
137+
let factory = getComponentTemplate(component.constructor as object);
140138

141-
if (layout === undefined) {
142-
if (layoutName !== undefined) {
143-
let _factory = owner.lookup(`template:${layoutName}`) as TemplateFactory;
144-
assert(`Layout \`${layoutName}\` not found!`, _factory !== undefined);
145-
factory = _factory;
146-
} else {
147-
return null;
148-
}
149-
} else if (isTemplateFactory(layout)) {
150-
factory = layout;
151-
} else {
152-
// no layout was found, use the default layout
139+
if (factory === undefined) {
153140
return null;
154141
}
155142

packages/@ember/-internals/glimmer/lib/component.ts

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
import { guidFor } from '@ember/-internals/utils';
2121
import { assert } from '@ember/debug';
2222
import { DEBUG } from '@glimmer/env';
23-
import type { Environment, Template, TemplateFactory } from '@glimmer/interfaces';
23+
import type { Environment } from '@glimmer/interfaces';
2424
import { setInternalComponentManager } from '@glimmer/manager';
2525
import { isUpdatableRef, updateRef } from '@glimmer/reference';
2626
import { normalizeProperty } from '@glimmer/runtime';
@@ -202,7 +202,6 @@ interface ComponentMethods {
202202
@type String
203203
@public
204204
*/
205-
layoutName?: string;
206205
}
207206

208207
// A zero-runtime-overhead private symbol to use in branding the component to
@@ -1268,25 +1267,6 @@ class Component<S = unknown>
12681267
*/
12691268
declare static positionalParams: string | string[];
12701269

1271-
/**
1272-
Layout can be used to wrap content in a component.
1273-
@property layout
1274-
@type Function
1275-
@public
1276-
*/
1277-
declare layout?: TemplateFactory | Template;
1278-
1279-
/**
1280-
The name of the layout to lookup if no layout is provided.
1281-
By default `Component` will lookup a template with this name in
1282-
`Ember.TEMPLATES` (a shared global object).
1283-
@property layoutName
1284-
@type String
1285-
@default undefined
1286-
@private
1287-
*/
1288-
declare layoutName?: string;
1289-
12901270
/**
12911271
The WAI-ARIA role of the control represented by this view. For example, a
12921272
button may have a role of type 'button', or a pane may have a role of

packages/@ember/-internals/glimmer/tests/integration/application/engine-test.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,8 @@ moduleFor(
235235

236236
let sharedLayout = precompileTemplate('{{ambiguous-curlies}}');
237237

238-
let sharedComponent = class extends Component {
239-
layout = sharedLayout;
240-
};
238+
let sharedComponent = class extends Component {};
239+
setComponentTemplate(sharedLayout, sharedComponent);
241240

242241
this.add(
243242
'template:application',

packages/@ember/-internals/glimmer/tests/integration/components/append-test.js

Lines changed: 87 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ class AbstractAppendTest extends RenderingTestCase {
285285
let componentsByName = {};
286286

287287
// TODO: refactor/combine with other life-cycle tests
288-
let registerLoggerComponent = (name, { ComponentClass, resolveableTemplate }) => {
288+
let registerLoggerComponent = (name, { ComponentClass, compiledTemplate }) => {
289289
function pushHook(hookName) {
290290
hooks.push([name, hookName]);
291291
}
@@ -351,19 +351,17 @@ class AbstractAppendTest extends RenderingTestCase {
351351
}
352352
};
353353

354-
this.owner.register(`component:${name}`, ExtendedClass);
355-
356-
if (resolveableTemplate) {
357-
this.owner.register(`template:components/${name}`, resolveableTemplate);
354+
if (compiledTemplate) {
355+
setComponentTemplate(compiledTemplate, ExtendedClass);
358356
}
357+
358+
this.owner.register(`component:${name}`, ExtendedClass);
359359
};
360360

361361
registerLoggerComponent('x-parent', {
362-
ComponentClass: class extends Component {
363-
layoutName = 'components/x-parent';
364-
},
362+
ComponentClass: class extends Component {},
365363

366-
resolveableTemplate: precompileTemplate(
364+
compiledTemplate: precompileTemplate(
367365
'[parent: {{this.foo}}]{{#x-child bar=this.foo}}[yielded: {{this.foo}}]{{/x-child}}'
368366
),
369367
});
@@ -373,7 +371,7 @@ class AbstractAppendTest extends RenderingTestCase {
373371
tagName = '';
374372
},
375373

376-
resolveableTemplate: precompileTemplate('[child: {{this.bar}}]{{yield}}'),
374+
compiledTemplate: precompileTemplate('[child: {{this.bar}}]{{yield}}'),
377375
});
378376

379377
let XParent;
@@ -530,17 +528,18 @@ class AbstractAppendTest extends RenderingTestCase {
530528
let willDestroyCalled = 0;
531529

532530
let XParentClass = class extends Component {
533-
layoutName = 'components/x-parent';
534531
willDestroyElement() {
535532
willDestroyCalled++;
536533
}
537534
};
538535

539-
this.owner.register('component:x-parent', XParentClass);
540536
this.owner.register(
541-
'template:components/x-parent',
542-
precompileTemplate(
543-
'[parent: {{this.foo}}]{{#x-child bar=this.foo}}[yielded: {{this.foo}}]{{/x-child}}'
537+
'component:x-parent',
538+
setComponentTemplate(
539+
precompileTemplate(
540+
'[parent: {{this.foo}}]{{#x-child bar=this.foo}}[yielded: {{this.foo}}]{{/x-child}}'
541+
),
542+
XParentClass
544543
)
545544
);
546545

@@ -639,28 +638,25 @@ class AbstractAppendTest extends RenderingTestCase {
639638
let willDestroyCalled = 0;
640639

641640
let XFirstClass = class extends Component {
642-
layoutName = 'components/x-first';
643-
644641
willDestroyElement() {
645642
willDestroyCalled++;
646643
}
647644
};
648645

649-
this.owner.register('component:x-first', XFirstClass);
650-
this.owner.register('template:components/x-first', precompileTemplate('x-first {{this.foo}}!'));
646+
this.owner.register(
647+
'component:x-first',
648+
setComponentTemplate(precompileTemplate('x-first {{this.foo}}!'), XFirstClass)
649+
);
651650

652651
let XSecondClass = class extends Component {
653-
layoutName = 'components/x-second';
654-
655652
willDestroyElement() {
656653
willDestroyCalled++;
657654
}
658655
};
659656

660-
this.owner.register('component:x-second', XSecondClass);
661657
this.owner.register(
662-
'template:components/x-second',
663-
precompileTemplate('x-second {{this.bar}}!')
658+
'component:x-second',
659+
setComponentTemplate(precompileTemplate('x-second {{this.bar}}!'), XSecondClass)
664660
);
665661

666662
let First, Second;
@@ -777,31 +773,25 @@ class AbstractAppendTest extends RenderingTestCase {
777773
};
778774

779775
let element1, element2;
780-
this.owner.register(
781-
'component:first-component',
782-
class extends Component {
783-
layout = precompileTemplate('component-one');
784-
785-
didInsertElement() {
786-
element1 = this.element;
776+
let FirstComponentClass = class extends Component {
777+
didInsertElement() {
778+
element1 = this.element;
787779

788-
let SecondComponent = owner.factoryFor('component:second-component');
780+
let SecondComponent = owner.factoryFor('component:second-component');
789781

790-
append(SecondComponent.create());
791-
}
782+
append(SecondComponent.create());
792783
}
793-
);
794-
795-
this.owner.register(
796-
'component:second-component',
797-
class extends Component {
798-
layout = precompileTemplate(`component-two`);
784+
};
785+
setComponentTemplate(precompileTemplate('component-one'), FirstComponentClass);
786+
this.owner.register('component:first-component', FirstComponentClass);
799787

800-
didInsertElement() {
801-
element2 = this.element;
802-
}
788+
let SecondComponentClass = class extends Component {
789+
didInsertElement() {
790+
element2 = this.element;
803791
}
804-
);
792+
};
793+
setComponentTemplate(precompileTemplate('component-two'), SecondComponentClass);
794+
this.owner.register('component:second-component', SecondComponentClass);
805795

806796
let FirstComponent = this.owner.factoryFor('component:first-component');
807797

@@ -819,84 +809,75 @@ class AbstractAppendTest extends RenderingTestCase {
819809
};
820810

821811
let element1, element2, element3, element4, component1, component2;
822-
this.owner.register(
823-
'component:foo-bar',
824-
class extends Component {
825-
layout = precompileTemplate('foo-bar');
826-
827-
init() {
828-
super.init(...arguments);
829-
component1 = this;
830-
}
831-
832-
didInsertElement() {
833-
element1 = this.element;
812+
let FooBarComponent = class extends Component {
813+
init() {
814+
super.init(...arguments);
815+
component1 = this;
816+
}
834817

835-
let OtherRoot = owner.factoryFor('component:other-root');
818+
didInsertElement() {
819+
element1 = this.element;
836820

837-
this._instance = OtherRoot.create({
838-
didInsertElement() {
839-
element2 = this.element;
840-
},
841-
});
821+
let OtherRoot = owner.factoryFor('component:other-root');
842822

843-
append(this._instance);
844-
}
823+
this._instance = OtherRoot.create({
824+
didInsertElement() {
825+
element2 = this.element;
826+
},
827+
});
845828

846-
willDestroy() {
847-
this._instance.destroy();
848-
}
829+
append(this._instance);
849830
}
850-
);
851831

852-
this.owner.register(
853-
'component:baz-qux',
854-
class extends Component {
855-
layout = precompileTemplate('baz-qux');
832+
willDestroy() {
833+
this._instance.destroy();
834+
}
835+
};
836+
setComponentTemplate(precompileTemplate('foo-bar'), FooBarComponent);
837+
this.owner.register('component:foo-bar', FooBarComponent);
856838

857-
init() {
858-
super.init(...arguments);
859-
component2 = this;
860-
}
839+
let BazQuxComponent = class extends Component {
840+
init() {
841+
super.init(...arguments);
842+
component2 = this;
843+
}
861844

862-
didInsertElement() {
863-
element3 = this.element;
845+
didInsertElement() {
846+
element3 = this.element;
864847

865-
let OtherRoot = owner.factoryFor('component:other-root');
848+
let OtherRoot = owner.factoryFor('component:other-root');
866849

867-
this._instance = OtherRoot.create({
868-
didInsertElement() {
869-
element4 = this.element;
870-
},
871-
});
850+
this._instance = OtherRoot.create({
851+
didInsertElement() {
852+
element4 = this.element;
853+
},
854+
});
872855

873-
append(this._instance);
874-
}
856+
append(this._instance);
857+
}
875858

876-
willDestroy() {
877-
this._instance.destroy();
878-
}
859+
willDestroy() {
860+
this._instance.destroy();
879861
}
880-
);
862+
};
863+
setComponentTemplate(precompileTemplate('baz-qux'), BazQuxComponent);
864+
this.owner.register('component:baz-qux', BazQuxComponent);
881865

882866
let instantiatedRoots = 0;
883867
let destroyedRoots = 0;
884-
this.owner.register(
885-
'component:other-root',
886-
class extends Component {
887-
layout = precompileTemplate(`fake-thing: {{this.counter}}`);
888-
889-
init() {
890-
super.init(...arguments);
891-
this.counter = instantiatedRoots++;
892-
}
868+
let OtherRootComponent = class extends Component {
869+
init() {
870+
super.init(...arguments);
871+
this.counter = instantiatedRoots++;
872+
}
893873

894-
willDestroy() {
895-
destroyedRoots++;
896-
super.willDestroy(...arguments);
897-
}
874+
willDestroy() {
875+
destroyedRoots++;
876+
super.willDestroy(...arguments);
898877
}
899-
);
878+
};
879+
setComponentTemplate(precompileTemplate('fake-thing: {{this.counter}}'), OtherRootComponent);
880+
this.owner.register('component:other-root', OtherRootComponent);
900881

901882
this.render(
902883
strip`
@@ -954,12 +935,10 @@ moduleFor(
954935
}
955936

956937
['@test raises an assertion when the target does not exist in the DOM'](assert) {
957-
let FooBarClass = class extends Component {
958-
layoutName = 'components/foo-bar';
959-
};
938+
let FooBarClass = class extends Component {};
939+
setComponentTemplate(precompileTemplate('FOO BAR!'), FooBarClass);
960940

961941
this.owner.register('component:foo-bar', FooBarClass);
962-
this.owner.register('template:components/foo-bar', precompileTemplate('FOO BAR!'));
963942

964943
let FooBar = this.owner.factoryFor('component:foo-bar');
965944

0 commit comments

Comments
 (0)