Skip to content

Commit

Permalink
improve in element support
Browse files Browse the repository at this point in the history
  • Loading branch information
patricklx committed Feb 5, 2024
1 parent bbe6e11 commit 2c44415
Showing 1 changed file with 66 additions and 153 deletions.
219 changes: 66 additions & 153 deletions ember_debug/libs/render-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ class InElementSupportProvider {
constructor(owner) {
this.nodeMap = new Map();
this.remoteRoots = [];
this.currentNode = null;
this.nodeStack = [];
this.remoteNodeStack = [];
this.runtime = this.require('@glimmer/runtime');
this.reference = this.require('@glimmer/reference');
try {
this.Wormhole = requireModule('ember-wormhole/components/ember-wormhole');
} catch (e) {
Expand All @@ -27,115 +25,80 @@ class InElementSupportProvider {
reset() {
this.nodeMap.clear();
this.remoteRoots.length = 0;
this.nodeStack.length = 0;
this.remoteNodeStack.length = 0;
this.currentRemoteNode = null;
this.currentNode = null;
}

buildInElementNode(node) {
const obj = Object.create(null);
obj.index = this.currentNode?.refs?.size || 0;
obj.name = 'in-element';
obj.type = 'component';
obj.template = null;
obj.isRemote = true;
obj.args = {
positional: [],
named: {
destination: node,
},
};
obj.instance = {
args: obj.args.named,
constructor: {
name: 'InElement',
},
};
obj.bounds = {
firstNode: node,
lastNode: node,
parentElement: node.parentElement,
};
obj.children = [];
return obj;
}

patch() {
const self = this;

const captureNode = this.debugRenderTree.captureNode;
this.debugRenderTree.captureNode = function (...args) {
const capture = captureNode.call(this, ...args);
const [id, state] = args;
const node = this.nodeFor(state);
self.setupNodeRemotes(node, id, capture);
return capture;
};

const enter = this.debugRenderTree.enter;
this.debugRenderTree.enter = function (...args) {
const state = args[0];
self.enter(this.nodeFor(state));
return enter.call(this, ...args);
};

const exit = this.debugRenderTree.exit;
this.debugRenderTree.exit = function (...args) {
self.exit();
return exit.call(this, ...args);
};

const NewElementBuilder = this.NewElementBuilder;
const remoteStack = [];

const didAppendNode = NewElementBuilder.prototype.didAppendNode;
NewElementBuilder.prototype.didAppendNode = function (...args) {
args[0].__emberInspectorParentNode = self.currentNode;
const parent = this.env.debugRenderTree.stack.current;
args[0].__emberInspectorParentNode =
this.env.debugRenderTree.nodeFor(parent);
return didAppendNode.call(this, ...args);
};

const pushElement = NewElementBuilder.prototype.pushElement;
NewElementBuilder.prototype.pushElement = function (...args) {
args[0].__emberInspectorParentNode = self.currentNode;
const parent = this.env?.debugRenderTree.stack.current;
args[0].__emberInspectorParentNode =
this.env?.debugRenderTree.nodeFor(parent);
return pushElement.call(this, ...args);
};

const pushRemoteElement = NewElementBuilder.prototype.pushRemoteElement;
NewElementBuilder.prototype.pushRemoteElement = function (...args) {
const block = pushRemoteElement.call(this, ...args);
self.registerRemote(block, ...args);
self.nodeStack.push(self.currentNode);
self.remoteNodeStack.push(self.currentNode);
self.currentRemoteNode = self.currentNode;
return block;
const element = args[0];
remoteStack.push({});
const ref = self.reference.createUnboundRef(element);
this.env.debugRenderTree?.create(remoteStack.at(-1), {
type: 'remote-element',
name: 'in-element',
args: {
positional: [],
named: {
destination: ref,
},
},
instance: {
args: {
destination: ref,
},
constructor: {
name: 'InElement',
},
},
});
return pushRemoteElement.call(this, ...args);
};

const popRemoteElement = NewElementBuilder.prototype.popRemoteElement;
NewElementBuilder.prototype.popRemoteElement = function (...args) {
const block = popRemoteElement.call(this, ...args);
self.remoteNodeStack.pop();
self.nodeStack.pop();
self.currentRemoteNode =
self.remoteNodeStack[self.remoteNodeStack.length - 1];
return block;
const element = this.element;
this.env.debugRenderTree?.didRender(remoteStack.at(-1), {
parentElement: () => element.parentElement,
firstNode: () => element,
lastNode: () => element,
});
remoteStack.pop();
return popRemoteElement.call(this, ...args);
};

this.debugRenderTreeFunctions = {
exit,
enter,
captureNode,
};
this.NewElementBuilderFunctions = {
pushElement,
pushRemoteElement,
popRemoteElement,
didAppendNode,
};
}

teardown() {
if (!this.debugRenderTreeFunctions) {
if (!this.NewElementBuilderFunctions) {
return;
}
Object.assign(this.debugRenderTree, this.debugRenderTreeFunctions);
Object.assign(
this.NewElementBuilder.prototype,
this.NewElementBuilderFunctions
Expand All @@ -147,81 +110,6 @@ class InElementSupportProvider {
? requireModule(req)
: EmberLoader.require(req);
}

enter(node) {
if (this.currentNode && this.currentNode === this.currentRemoteNode) {
this.currentRemoteNode.children.push(node);
node.remoteParent = this.currentRemoteNode;
}
this.currentNode = node;
this.nodeStack.push(this.currentNode);
}

exit() {
this.nodeStack.pop();
this.currentNode = this.nodeStack[this.nodeStack.length - 1];
}

registerRemote(block, node) {
const obj = this.buildInElementNode(node);
if (this.currentNode) {
if (!this.currentNode.remotes) {
Object.defineProperty(this.currentNode, 'remotes', {
value: [],
});
}
this.currentNode.remotes.push(obj);
}
this.remoteRoots.push(obj);
this.currentNode = obj;
}

setupNodeRemotes(node, id, capture) {
capture.isInRemote = !!node.remoteParent;
this.nodeMap.set(node, id);
if (node.remoteParent) {
const idx = node.remoteParent.children.indexOf(node);
if (idx >= 0) {
node.remoteParent.children[idx] = capture;
}
}
capture.children = capture.children.filter((c) => !c.isInRemote);
node.remotes?.forEach((remote) => {
remote.id = 'remote-render-node:' + this.remoteRoots.length;
this.nodeMap.set(remote, remote.id);
this.remoteRoots.push(remote);
capture.children.splice(remote.index, 0, remote);
});
if (capture.instance?.__emberInspectorTargetNode) {
Object.defineProperty(capture, 'bounds', {
get() {
return {
firstNode: capture.instance.__emberInspectorTargetNode,
lastNode: capture.instance.__emberInspectorTargetNode,
parentElement:
capture.instance.__emberInspectorTargetNode.parentElement,
};
},
});
}
if (this.Wormhole && capture.instance instanceof this.Wormhole.default) {
this.remoteRoots.push(capture);
const bounds = capture.bounds;
Object.defineProperty(capture, 'bounds', {
get() {
if (capture.instance._destination) {
return {
firstNode: capture.instance._destination,
lastNode: capture.instance._destination,
parentElement: capture.instance._destination.parentElement,
};
}
return bounds;
},
});
}
return capture;
}
}

export default class RenderTree {
Expand Down Expand Up @@ -496,6 +384,31 @@ export default class RenderTree {

if (serialized === undefined) {
this.nodes[node.id] = node;
if (node.type === 'remote-element') {
node.type = 'component';
this.inElementSupport?.nodeMap.set(node, node.id);
this.inElementSupport?.remoteRoots.push(node);
}

if (
this.inElementSupport?.Wormhole &&
node.instance instanceof this.inElementSupport.Wormhole.default
) {
this.inElementSupport?.remoteRoots.push(node);
const bounds = node.bounds;
Object.defineProperty(node, 'bounds', {
get() {
if (node.instance._destination) {
return {
firstNode: node.instance._destination,
lastNode: node.instance._destination,
parentElement: node.instance._destination.parentElement,
};
}
return bounds;
},
});
}

if (parentNode) {
this.parentNodes[node.id] = parentNode;
Expand Down

0 comments on commit 2c44415

Please sign in to comment.