Skip to content

Commit 6f06291

Browse files
committed
Ensure childDomWrapperId is available to insert nodes in the correct order (dojo#642)
* Failing unit test for issue 641 * Ensure childDomWrapperId is available to insert nodes in the correct order
1 parent 194a7cf commit 6f06291

File tree

2 files changed

+74
-9
lines changed

2 files changed

+74
-9
lines changed

src/core/vdom.ts

+19-9
Original file line numberDiff line numberDiff line change
@@ -1080,10 +1080,15 @@ export function renderer(renderer: () => RenderResult): Renderer {
10801080
const nextSibling = _wrapperSiblingMap.get(searchNode);
10811081
if (nextSibling) {
10821082
let domNode = nextSibling.domNode;
1083-
if ((isWNodeWrapper(nextSibling) || isVirtualWrapper(nextSibling)) && nextSibling.childDomWrapperId) {
1084-
const childWrapper = _idToWrapperMap.get(nextSibling.childDomWrapperId);
1085-
if (childWrapper) {
1086-
domNode = childWrapper.domNode;
1083+
if (isWNodeWrapper(nextSibling) || isVirtualWrapper(nextSibling)) {
1084+
if (!nextSibling.childDomWrapperId) {
1085+
nextSibling.childDomWrapperId = findDomNodeOnParentWrapper(nextSibling);
1086+
}
1087+
if (nextSibling.childDomWrapperId) {
1088+
const childWrapper = _idToWrapperMap.get(nextSibling.childDomWrapperId);
1089+
if (childWrapper && !isBodyWrapper(childWrapper)) {
1090+
domNode = childWrapper.domNode;
1091+
}
10871092
}
10881093
}
10891094
if (domNode && domNode.parentNode) {
@@ -1896,16 +1901,14 @@ export function renderer(renderer: () => RenderResult): Renderer {
18961901
return processResult;
18971902
}
18981903

1899-
function setDomNodeOnParentWrapper(id: string) {
1900-
let wrapper = _idToWrapperMap.get(id)!;
1901-
let children = [...(_idToChildrenWrappers.get(id) || [])];
1904+
function findDomNodeOnParentWrapper(wrapper: DNodeWrapper): string | undefined {
1905+
let children = [...(_idToChildrenWrappers.get(wrapper.id) || [])];
19021906
let child: DNodeWrapper | undefined;
19031907
while (children.length && !wrapper.domNode) {
19041908
child = children.shift();
19051909
if (child) {
19061910
if (child.domNode) {
1907-
wrapper.childDomWrapperId = child.id;
1908-
break;
1911+
return child.id;
19091912
}
19101913
let nextChildren = _idToChildrenWrappers.get(child.id);
19111914
if (nextChildren) {
@@ -1915,6 +1918,13 @@ export function renderer(renderer: () => RenderResult): Renderer {
19151918
}
19161919
}
19171920

1921+
function setDomNodeOnParentWrapper(id: string) {
1922+
let wrapper = _idToWrapperMap.get(id);
1923+
if (wrapper) {
1924+
wrapper.childDomWrapperId = findDomNodeOnParentWrapper(wrapper);
1925+
}
1926+
}
1927+
19181928
function _createDom({ next }: CreateDomInstruction): ProcessResult {
19191929
const parentDomNode = findParentDomNode(next)!;
19201930
const isVirtual = isVirtualWrapper(next);

tests/core/unit/vdom.tsx

+55
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,61 @@ jsdomDescribe('vdom', () => {
14941494
assert.strictEqual(div.outerHTML, '<div><div><foobar></foobar><baz></baz><qux></qux></div></div>');
14951495
});
14961496

1497+
it('should insert widgets in the correct position when the nested widgets domNode is not initially rendered', () => {
1498+
const root = document.createElement('div');
1499+
1500+
let invalidateApp: any[] = [];
1501+
let renderA = false;
1502+
let renderB = false;
1503+
1504+
class VirtualFoo extends WidgetBase<{ render: boolean }> {
1505+
constructor() {
1506+
super();
1507+
invalidateApp.push(() => {
1508+
this.invalidate();
1509+
});
1510+
}
1511+
1512+
render() {
1513+
return w(Foo, {
1514+
key: this.properties.key,
1515+
render: this.properties.key === 'a' ? renderA : renderB
1516+
});
1517+
}
1518+
}
1519+
1520+
class Foo extends WidgetBase<{ render: boolean }> {
1521+
render() {
1522+
if (this.properties.render) {
1523+
return v('div', [`${this.properties.key}`]);
1524+
}
1525+
return null;
1526+
}
1527+
}
1528+
1529+
class App extends WidgetBase {
1530+
render() {
1531+
return v('div', [
1532+
w(VirtualFoo, { key: 'a', render: renderA }),
1533+
w(VirtualFoo, { key: 'b', render: renderB })
1534+
]);
1535+
}
1536+
}
1537+
1538+
const r = renderer(() => w(App, {}));
1539+
r.mount({ domNode: root });
1540+
resolvers.resolve();
1541+
assert.strictEqual(root.innerHTML, '<div></div>');
1542+
renderB = true;
1543+
invalidateApp[1]();
1544+
resolvers.resolve();
1545+
assert.strictEqual(root.innerHTML, '<div><div>b</div></div>');
1546+
renderA = true;
1547+
invalidateApp[0]();
1548+
resolvers.resolve();
1549+
assert.strictEqual(root.innerHTML, '<div><div>a</div><div>b</div></div>');
1550+
});
1551+
14971552
it('Should insert result from widget in correct position', () => {
14981553
class Menu extends WidgetBase {
14991554
render() {

0 commit comments

Comments
 (0)