Skip to content

Commit 15c6cee

Browse files
committed
add tests
add in element to debug render tree My learnings from hacking on this in inspector https://github.com/emberjs/ember-inspector/pull/2549/files Adding modifiers is also easy, will add it in another pr
1 parent dc76897 commit 15c6cee

File tree

3 files changed

+92
-3
lines changed

3 files changed

+92
-3
lines changed

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

+51-1
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,56 @@ class DebugRenderTreeTest extends RenderTest {
253253
]);
254254
}
255255

256+
@test 'in-element in tree'() {
257+
this.registerComponent(
258+
'Glimmer',
259+
'HiWorld',
260+
'Hi World'
261+
);
262+
this.registerComponent(
263+
'Glimmer',
264+
'HelloWorld',
265+
'{{#in-element this.destinationElement}}<HiWorld />{{/in-element}}',
266+
class extends GlimmerishComponent {
267+
get destinationElement() {
268+
return document.getElementById('target');
269+
}
270+
}
271+
);
272+
273+
this.render(`<div id='target'></div><HelloWorld @arg="first"/>`);
274+
275+
this.assertRenderTree([
276+
{
277+
type: 'component',
278+
name: 'HelloWorld',
279+
args: { positional: [], named: { arg: 'first' } },
280+
instance: (instance: GlimmerishComponent) => instance.args['arg'] === 'first',
281+
template: '(unknown template module)',
282+
bounds: this.nodeBounds(this.element.firstChild!.nextSibling),
283+
children: [
284+
{
285+
type: 'remote-element',
286+
name: 'in-element',
287+
args: { positional: [], named: { destination: this.element.firstChild } },
288+
instance: (instance: GlimmerishComponent) => instance.constructor.name === 'InElement',
289+
template: null,
290+
bounds: this.nodeBounds(this.element.firstChild),
291+
children: [{
292+
type: 'component',
293+
name: 'HiWorld',
294+
args: { positional: [], named: {} },
295+
instance: (instance: GlimmerishComponent) => instance,
296+
template: '(unknown template module)',
297+
bounds: this.nodeBounds(this.element.firstChild!.firstChild),
298+
children: []
299+
}],
300+
},
301+
],
302+
},
303+
]);
304+
}
305+
256306
@test 'getDebugCustomRenderTree works'() {
257307
let bucket1 = {};
258308
let instance1 = {};
@@ -502,7 +552,7 @@ class DebugRenderTreeTest extends RenderTest {
502552
this.assertRenderNode(actualNode, expected, `${actualNode.type}:${actualNode.name}`);
503553
});
504554
} else {
505-
this.assert.deepEqual(actual, [], path);
555+
this.assert.deepEqual(actual, expectedNodes, path);
506556
}
507557
}
508558

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ 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 =
7+
| 'outlet'
8+
| 'engine'
9+
| 'route-template'
10+
| 'component'
11+
| 'remote-element';
712

813
export interface RenderNode {
914
type: RenderNodeType;

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

+35-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import type {
2020
UpdatableBlock,
2121
} from '@glimmer/interfaces';
2222
import { destroy, registerDestructor } from '@glimmer/destroyable';
23+
import { createUnboundRef } from '@glimmer/reference';
2324
import { assert, expect, Stack } from '@glimmer/util';
2425

2526
import type { DynamicAttribute } from './attributes/dynamic';
@@ -83,6 +84,7 @@ export class NewElementBuilder implements ElementBuilder {
8384
[CURSOR_STACK] = new Stack<Cursor>();
8485
private modifierStack = new Stack<Nullable<ModifierInstance[]>>();
8586
private blockStack = new Stack<LiveBlock>();
87+
private remoteStateStack: Object[];
8688

8789
static forInitialRender(env: Environment, cursor: CursorImpl) {
8890
return new this(env, cursor.element, cursor.nextSibling).initialize();
@@ -100,10 +102,10 @@ export class NewElementBuilder implements ElementBuilder {
100102

101103
constructor(env: Environment, parentNode: SimpleElement, nextSibling: Nullable<SimpleNode>) {
102104
this.pushElement(parentNode, nextSibling);
103-
104105
this.env = env;
105106
this.dom = env.getAppendOperations();
106107
this.updateOperations = env.getDOM();
108+
this.remoteStateStack = [];
107109
}
108110

109111
protected initialize(): this {
@@ -215,6 +217,29 @@ export class NewElementBuilder implements ElementBuilder {
215217
guid: string,
216218
insertBefore: Maybe<SimpleNode>
217219
): Nullable<RemoteLiveBlock> {
220+
if (this.env.debugRenderTree) {
221+
const state = {};
222+
this.remoteStateStack.push(state);
223+
const ref = createUnboundRef(element, false);
224+
this.env.debugRenderTree.create(state, {
225+
type: 'remote-element',
226+
name: 'in-element',
227+
args: {
228+
positional: [],
229+
named: {
230+
destination: ref,
231+
},
232+
} as any,
233+
instance: {
234+
args: {
235+
destination: ref,
236+
},
237+
constructor: {
238+
name: 'InElement',
239+
},
240+
},
241+
});
242+
}
218243
return this.__pushRemoteElement(element, guid, insertBefore);
219244
}
220245

@@ -237,6 +262,15 @@ export class NewElementBuilder implements ElementBuilder {
237262
}
238263

239264
popRemoteElement() {
265+
if (this.env.debugRenderTree) {
266+
const state = this.remoteStateStack.pop();
267+
const element = this.element;
268+
this.env.debugRenderTree?.didRender(state!, {
269+
parentElement: () => (element as any).parentElement,
270+
firstNode: () => element,
271+
lastNode: () => element,
272+
});
273+
}
240274
this.popBlock();
241275
this.popElement();
242276
}

0 commit comments

Comments
 (0)