Skip to content

Commit 10663a9

Browse files
committed
improve in element support
1 parent bbe6e11 commit 10663a9

File tree

1 file changed

+91
-153
lines changed

1 file changed

+91
-153
lines changed

ember_debug/libs/render-tree.js

+91-153
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@ class InElementSupportProvider {
66
constructor(owner) {
77
this.nodeMap = new Map();
88
this.remoteRoots = [];
9-
this.currentNode = null;
10-
this.nodeStack = [];
11-
this.remoteNodeStack = [];
129
this.runtime = this.require('@glimmer/runtime');
10+
this.reference = this.require('@glimmer/reference');
1311
try {
1412
this.Wormhole = requireModule('ember-wormhole/components/ember-wormhole');
1513
} catch (e) {
@@ -27,115 +25,105 @@ class InElementSupportProvider {
2725
reset() {
2826
this.nodeMap.clear();
2927
this.remoteRoots.length = 0;
30-
this.nodeStack.length = 0;
31-
this.remoteNodeStack.length = 0;
32-
this.currentRemoteNode = null;
33-
this.currentNode = null;
34-
}
35-
36-
buildInElementNode(node) {
37-
const obj = Object.create(null);
38-
obj.index = this.currentNode?.refs?.size || 0;
39-
obj.name = 'in-element';
40-
obj.type = 'component';
41-
obj.template = null;
42-
obj.isRemote = true;
43-
obj.args = {
44-
positional: [],
45-
named: {
46-
destination: node,
47-
},
48-
};
49-
obj.instance = {
50-
args: obj.args.named,
51-
constructor: {
52-
name: 'InElement',
53-
},
54-
};
55-
obj.bounds = {
56-
firstNode: node,
57-
lastNode: node,
58-
parentElement: node.parentElement,
59-
};
60-
obj.children = [];
61-
return obj;
6228
}
6329

6430
patch() {
6531
const self = this;
6632

67-
const captureNode = this.debugRenderTree.captureNode;
68-
this.debugRenderTree.captureNode = function (...args) {
69-
const capture = captureNode.call(this, ...args);
70-
const [id, state] = args;
71-
const node = this.nodeFor(state);
72-
self.setupNodeRemotes(node, id, capture);
73-
return capture;
74-
};
75-
76-
const enter = this.debugRenderTree.enter;
77-
this.debugRenderTree.enter = function (...args) {
78-
const state = args[0];
79-
self.enter(this.nodeFor(state));
80-
return enter.call(this, ...args);
81-
};
82-
83-
const exit = this.debugRenderTree.exit;
84-
this.debugRenderTree.exit = function (...args) {
85-
self.exit();
86-
return exit.call(this, ...args);
87-
};
88-
8933
const NewElementBuilder = this.NewElementBuilder;
34+
const remoteStack = [];
35+
9036
const didAppendNode = NewElementBuilder.prototype.didAppendNode;
9137
NewElementBuilder.prototype.didAppendNode = function (...args) {
92-
args[0].__emberInspectorParentNode = self.currentNode;
38+
const debugRenderTree =
39+
this.env?.debugRenderTree || this.env?.extra?.debugRenderTree;
40+
const parent = debugRenderTree.stack.current;
41+
args[0].__emberInspectorParentNode = debugRenderTree.nodeFor(parent);
9342
return didAppendNode.call(this, ...args);
9443
};
9544

9645
const pushElement = NewElementBuilder.prototype.pushElement;
9746
NewElementBuilder.prototype.pushElement = function (...args) {
98-
args[0].__emberInspectorParentNode = self.currentNode;
47+
const debugRenderTree =
48+
this.env?.debugRenderTree || this.env?.extra?.debugRenderTree;
49+
// for first push element, .env is not yet set...
50+
if (debugRenderTree) {
51+
const parent = debugRenderTree.stack.current;
52+
args[0].__emberInspectorParentNode = debugRenderTree.nodeFor(parent);
53+
}
9954
return pushElement.call(this, ...args);
10055
};
10156

10257
const pushRemoteElement = NewElementBuilder.prototype.pushRemoteElement;
10358
NewElementBuilder.prototype.pushRemoteElement = function (...args) {
104-
const block = pushRemoteElement.call(this, ...args);
105-
self.registerRemote(block, ...args);
106-
self.nodeStack.push(self.currentNode);
107-
self.remoteNodeStack.push(self.currentNode);
108-
self.currentRemoteNode = self.currentNode;
109-
return block;
59+
const element = args[0];
60+
remoteStack.push({});
61+
let capturedArgs, ref;
62+
if (self.reference.createUnboundRef) {
63+
ref = self.reference.createUnboundRef?.(element);
64+
capturedArgs = {
65+
positional: [],
66+
named: {
67+
destination: ref,
68+
},
69+
};
70+
} else {
71+
ref = new self.reference.ConstReference(() => element);
72+
capturedArgs = {
73+
value() {
74+
return {
75+
positional: [],
76+
named: {
77+
destination: ref,
78+
},
79+
};
80+
},
81+
};
82+
}
83+
const debugRenderTree =
84+
this.env?.debugRenderTree || this.env?.extra?.debugRenderTree;
85+
debugRenderTree?.create(remoteStack.at(-1), {
86+
type: 'remote-element',
87+
name: 'in-element',
88+
args: capturedArgs,
89+
instance: {
90+
args: {
91+
destination: element,
92+
},
93+
constructor: {
94+
name: 'InElement',
95+
},
96+
},
97+
});
98+
return pushRemoteElement.call(this, ...args);
11099
};
111100

112101
const popRemoteElement = NewElementBuilder.prototype.popRemoteElement;
113102
NewElementBuilder.prototype.popRemoteElement = function (...args) {
114-
const block = popRemoteElement.call(this, ...args);
115-
self.remoteNodeStack.pop();
116-
self.nodeStack.pop();
117-
self.currentRemoteNode =
118-
self.remoteNodeStack[self.remoteNodeStack.length - 1];
119-
return block;
103+
const element = this.element;
104+
const debugRenderTree =
105+
this.env?.debugRenderTree || this.env?.extra?.debugRenderTree;
106+
debugRenderTree?.didRender(remoteStack.at(-1), {
107+
parentElement: () => element.parentElement,
108+
firstNode: () => element,
109+
lastNode: () => element,
110+
});
111+
remoteStack.pop();
112+
return popRemoteElement.call(this, ...args);
120113
};
121114

122-
this.debugRenderTreeFunctions = {
123-
exit,
124-
enter,
125-
captureNode,
126-
};
127115
this.NewElementBuilderFunctions = {
128116
pushElement,
129117
pushRemoteElement,
118+
popRemoteElement,
130119
didAppendNode,
131120
};
132121
}
133122

134123
teardown() {
135-
if (!this.debugRenderTreeFunctions) {
124+
if (!this.NewElementBuilderFunctions) {
136125
return;
137126
}
138-
Object.assign(this.debugRenderTree, this.debugRenderTreeFunctions);
139127
Object.assign(
140128
this.NewElementBuilder.prototype,
141129
this.NewElementBuilderFunctions
@@ -147,81 +135,6 @@ class InElementSupportProvider {
147135
? requireModule(req)
148136
: EmberLoader.require(req);
149137
}
150-
151-
enter(node) {
152-
if (this.currentNode && this.currentNode === this.currentRemoteNode) {
153-
this.currentRemoteNode.children.push(node);
154-
node.remoteParent = this.currentRemoteNode;
155-
}
156-
this.currentNode = node;
157-
this.nodeStack.push(this.currentNode);
158-
}
159-
160-
exit() {
161-
this.nodeStack.pop();
162-
this.currentNode = this.nodeStack[this.nodeStack.length - 1];
163-
}
164-
165-
registerRemote(block, node) {
166-
const obj = this.buildInElementNode(node);
167-
if (this.currentNode) {
168-
if (!this.currentNode.remotes) {
169-
Object.defineProperty(this.currentNode, 'remotes', {
170-
value: [],
171-
});
172-
}
173-
this.currentNode.remotes.push(obj);
174-
}
175-
this.remoteRoots.push(obj);
176-
this.currentNode = obj;
177-
}
178-
179-
setupNodeRemotes(node, id, capture) {
180-
capture.isInRemote = !!node.remoteParent;
181-
this.nodeMap.set(node, id);
182-
if (node.remoteParent) {
183-
const idx = node.remoteParent.children.indexOf(node);
184-
if (idx >= 0) {
185-
node.remoteParent.children[idx] = capture;
186-
}
187-
}
188-
capture.children = capture.children.filter((c) => !c.isInRemote);
189-
node.remotes?.forEach((remote) => {
190-
remote.id = 'remote-render-node:' + this.remoteRoots.length;
191-
this.nodeMap.set(remote, remote.id);
192-
this.remoteRoots.push(remote);
193-
capture.children.splice(remote.index, 0, remote);
194-
});
195-
if (capture.instance?.__emberInspectorTargetNode) {
196-
Object.defineProperty(capture, 'bounds', {
197-
get() {
198-
return {
199-
firstNode: capture.instance.__emberInspectorTargetNode,
200-
lastNode: capture.instance.__emberInspectorTargetNode,
201-
parentElement:
202-
capture.instance.__emberInspectorTargetNode.parentElement,
203-
};
204-
},
205-
});
206-
}
207-
if (this.Wormhole && capture.instance instanceof this.Wormhole.default) {
208-
this.remoteRoots.push(capture);
209-
const bounds = capture.bounds;
210-
Object.defineProperty(capture, 'bounds', {
211-
get() {
212-
if (capture.instance._destination) {
213-
return {
214-
firstNode: capture.instance._destination,
215-
lastNode: capture.instance._destination,
216-
parentElement: capture.instance._destination.parentElement,
217-
};
218-
}
219-
return bounds;
220-
},
221-
});
222-
}
223-
return capture;
224-
}
225138
}
226139

227140
export default class RenderTree {
@@ -496,6 +409,31 @@ export default class RenderTree {
496409

497410
if (serialized === undefined) {
498411
this.nodes[node.id] = node;
412+
if (node.type === 'remote-element') {
413+
node.type = 'component';
414+
this.inElementSupport?.nodeMap.set(node, node.id);
415+
this.inElementSupport?.remoteRoots.push(node);
416+
}
417+
418+
if (
419+
this.inElementSupport?.Wormhole &&
420+
node.instance instanceof this.inElementSupport.Wormhole.default
421+
) {
422+
this.inElementSupport?.remoteRoots.push(node);
423+
const bounds = node.bounds;
424+
Object.defineProperty(node, 'bounds', {
425+
get() {
426+
if (node.instance._destination) {
427+
return {
428+
firstNode: node.instance._destination,
429+
lastNode: node.instance._destination,
430+
parentElement: node.instance._destination.parentElement,
431+
};
432+
}
433+
return bounds;
434+
},
435+
});
436+
}
499437

500438
if (parentNode) {
501439
this.parentNodes[node.id] = parentNode;

0 commit comments

Comments
 (0)