Skip to content

Commit ed002cc

Browse files
Merge pull request #1560 from patricklx/add-in-element-debug-render-tree
add in element to debug render tree
2 parents 92e150d + b472b00 commit ed002cc

File tree

7 files changed

+91
-15
lines changed

7 files changed

+91
-15
lines changed

packages/@glimmer-workspace/integration-tests/test/debug-render-tree-test.ts

+49-1
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,54 @@ class DebugRenderTreeTest extends RenderTest {
283283
]);
284284
}
285285

286+
@test 'in-element in tree'() {
287+
this.registerComponent('Glimmer', 'HiWorld', 'Hi World');
288+
this.registerComponent(
289+
'Glimmer',
290+
'HelloWorld',
291+
'{{#in-element this.destinationElement}}<HiWorld />{{/in-element}}',
292+
class extends GlimmerishComponent {
293+
get destinationElement() {
294+
return document.getElementById('target');
295+
}
296+
}
297+
);
298+
299+
this.render(`<div id='target'></div><HelloWorld @arg="first"/>`);
300+
301+
this.assertRenderTree([
302+
{
303+
type: 'component',
304+
name: 'HelloWorld',
305+
args: { positional: [], named: { arg: 'first' } },
306+
instance: (instance: GlimmerishComponent) => instance.args['arg'] === 'first',
307+
template: '(unknown template module)',
308+
bounds: this.nodeBounds(this.element.firstChild!.nextSibling),
309+
children: [
310+
{
311+
type: 'keyword',
312+
name: 'in-element',
313+
args: { positional: [this.element.firstChild], named: {} },
314+
instance: (instance: GlimmerishComponent) => instance === null,
315+
template: null,
316+
bounds: this.elementBounds(this.element.firstChild! as unknown as Element),
317+
children: [
318+
{
319+
type: 'component',
320+
name: 'HiWorld',
321+
args: { positional: [], named: {} },
322+
instance: (instance: GlimmerishComponent) => instance,
323+
template: '(unknown template module)',
324+
bounds: this.nodeBounds(this.element.firstChild!.firstChild),
325+
children: [],
326+
},
327+
],
328+
},
329+
],
330+
},
331+
]);
332+
}
333+
286334
@test 'getDebugCustomRenderTree works'() {
287335
let bucket1 = {};
288336
let instance1 = {};
@@ -532,7 +580,7 @@ class DebugRenderTreeTest extends RenderTest {
532580
this.assertRenderNode(actualNode, expected, `${actualNode.type}:${actualNode.name}`);
533581
});
534582
} else {
535-
this.assert.deepEqual(actual, [], path);
583+
this.assert.deepEqual(actual, expectedNodes, path);
536584
}
537585
}
538586

packages/@glimmer/interfaces/lib/dom/attributes.d.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ export interface DOMStack {
3737
element: SimpleElement,
3838
guid: string,
3939
insertBefore: Maybe<SimpleNode>
40-
): Nullable<RemoteLiveBlock>;
41-
popRemoteElement(): void;
40+
): RemoteLiveBlock;
41+
popRemoteElement(): RemoteLiveBlock;
4242
popElement(): void;
4343
openElement(tag: string, _operations?: ElementOperations): SimpleElement;
4444
flushElement(modifiers: Nullable<ModifierInstance[]>): void;

packages/@glimmer/interfaces/lib/runtime/debug-render-tree.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { SimpleElement, SimpleNode } from '@simple-dom/interface';
33
import type { Bounds } from '../dom/bounds.js';
44
import type { Arguments, CapturedArguments } from './arguments.js';
55

6-
export type RenderNodeType = 'outlet' | 'engine' | 'route-template' | 'component';
6+
export type RenderNodeType = 'outlet' | 'engine' | 'route-template' | 'component' | 'keyword';
77

88
export interface RenderNode {
99
type: RenderNodeType;

packages/@glimmer/node/lib/serialize-builder.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class SerializeBuilder extends NewElementBuilder implements ElementBuilder {
129129
element: SimpleElement,
130130
cursorId: string,
131131
insertBefore: Maybe<SimpleNode> = null
132-
): Nullable<RemoteLiveBlock> {
132+
): RemoteLiveBlock {
133133
let { dom } = this;
134134
let script = dom.createElement('script');
135135
script.setAttribute('glmr', cursorId);

packages/@glimmer/runtime/lib/compiled/opcodes/dom.ts

+29-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
CheckOption,
2020
CheckString,
2121
} from '@glimmer/debug';
22-
import { associateDestroyableChild, destroy } from '@glimmer/destroyable';
22+
import { associateDestroyableChild, destroy, registerDestructor } from '@glimmer/destroyable';
2323
import { getInternalModifierManager } from '@glimmer/manager';
2424
import { createComputeRef, isConstRef, valueForRef } from '@glimmer/reference';
2525
import { debugToString, expect, isObject } from '@glimmer/util';
@@ -32,6 +32,7 @@ import type { DynamicAttribute } from '../../vm/attributes/dynamic';
3232
import { isCurriedType, resolveCurriedValue } from '../../curried-value';
3333
import { APPEND_OPCODES } from '../../opcodes';
3434
import { CONSTANTS } from '../../symbols';
35+
import { createCapturedArgs } from '../../vm/arguments';
3536
import { CheckArguments, CheckOperations, CheckReference } from './-debug-strip';
3637
import { Assert } from './vm';
3738

@@ -71,10 +72,36 @@ APPEND_OPCODES.add(Op.PushRemoteElement, (vm) => {
7172

7273
let block = vm.elements().pushRemoteElement(element, guid, insertBefore);
7374
if (block) vm.associateDestroyable(block);
75+
76+
if (vm.env.debugRenderTree !== undefined) {
77+
// Note that there is nothing to update – when the args for an
78+
// {{#in-element}} changes it gets torn down and a new one is
79+
// re-created/rendered in its place (see the `Assert`s above)
80+
let args = createCapturedArgs(
81+
insertBefore === undefined ? {} : { insertBefore: insertBeforeRef },
82+
[elementRef]
83+
);
84+
85+
vm.env.debugRenderTree.create(block, {
86+
type: 'keyword',
87+
name: 'in-element',
88+
args,
89+
instance: null,
90+
});
91+
92+
registerDestructor(block, () => {
93+
vm.env.debugRenderTree?.willDestroy(block);
94+
});
95+
}
7496
});
7597

7698
APPEND_OPCODES.add(Op.PopRemoteElement, (vm) => {
77-
vm.elements().popRemoteElement();
99+
let bounds = vm.elements().popRemoteElement();
100+
101+
if (vm.env.debugRenderTree !== undefined) {
102+
// The RemoteLiveBlock is also its bounds
103+
vm.env.debugRenderTree.didRender(bounds, bounds);
104+
}
78105
});
79106

80107
APPEND_OPCODES.add(Op.FlushElement, (vm) => {

packages/@glimmer/runtime/lib/vm/element-builder.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ export class NewElementBuilder implements ElementBuilder {
100100

101101
constructor(env: Environment, parentNode: SimpleElement, nextSibling: Nullable<SimpleNode>) {
102102
this.pushElement(parentNode, nextSibling);
103-
104103
this.env = env;
105104
this.dom = env.getAppendOperations();
106105
this.updateOperations = env.getDOM();
@@ -214,15 +213,15 @@ export class NewElementBuilder implements ElementBuilder {
214213
element: SimpleElement,
215214
guid: string,
216215
insertBefore: Maybe<SimpleNode>
217-
): Nullable<RemoteLiveBlock> {
216+
): RemoteLiveBlock {
218217
return this.__pushRemoteElement(element, guid, insertBefore);
219218
}
220219

221220
__pushRemoteElement(
222221
element: SimpleElement,
223222
_guid: string,
224223
insertBefore: Maybe<SimpleNode>
225-
): Nullable<RemoteLiveBlock> {
224+
): RemoteLiveBlock {
226225
this.pushElement(element, insertBefore);
227226

228227
if (insertBefore === undefined) {
@@ -236,12 +235,14 @@ export class NewElementBuilder implements ElementBuilder {
236235
return this.pushLiveBlock(block, true);
237236
}
238237

239-
popRemoteElement() {
240-
this.popBlock();
238+
popRemoteElement(): RemoteLiveBlock {
239+
const block = this.popBlock();
240+
assert(block instanceof RemoteLiveBlock, '[BUG] expecting a RemoteLiveBlock');
241241
this.popElement();
242+
return block;
242243
}
243244

244-
protected pushElement(element: SimpleElement, nextSibling: Maybe<SimpleNode> = null) {
245+
protected pushElement(element: SimpleElement, nextSibling: Maybe<SimpleNode> = null): void {
245246
this[CURSOR_STACK].push(new CursorImpl(element, nextSibling));
246247
}
247248

@@ -268,7 +269,7 @@ export class NewElementBuilder implements ElementBuilder {
268269
return element;
269270
}
270271

271-
willCloseElement() {
272+
willCloseElement(): void {
272273
this.block().closeElement();
273274
}
274275

packages/@glimmer/runtime/lib/vm/rehydrate-builder.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ export class RehydrateBuilder extends NewElementBuilder implements ElementBuilde
455455
element: SimpleElement,
456456
cursorId: string,
457457
insertBefore: Maybe<SimpleNode>
458-
): Nullable<RemoteLiveBlock> {
458+
): RemoteLiveBlock {
459459
const marker = this.getMarker(castToBrowser(element, 'HTML'), cursorId);
460460

461461
assert(

0 commit comments

Comments
 (0)