From 052ed5f7ab049a0864bbe059c7861efbc80f2c69 Mon Sep 17 00:00:00 2001 From: Anthony Gubler Date: Fri, 29 May 2020 17:11:36 +0100 Subject: [PATCH 1/4] preserve dom nodes when keyed virtual nodes are moved --- src/core/vdom.ts | 121 ++++++++++++++++++++++++--------- tests/core/unit/vdom.tsx | 142 +++++++++++++++++++++++++-------------- 2 files changed, 182 insertions(+), 81 deletions(-) diff --git a/src/core/vdom.ts b/src/core/vdom.ts index 20c72270a..3b268c313 100644 --- a/src/core/vdom.ts +++ b/src/core/vdom.ts @@ -151,6 +151,7 @@ export interface BaseNodeWrapper { hasAnimations?: boolean; parentId: string; childDomWrapperId?: string; + reparent?: string; } export interface WNodeWrapper extends BaseNodeWrapper { @@ -234,6 +235,7 @@ interface ProcessMeta { mergeNodes?: Node[]; oldIndex?: number; newIndex?: number; + currentKeyMap?: Map; } interface InvalidationQueueItem { @@ -1417,7 +1419,8 @@ export function renderer(renderer: () => RenderResult): Renderer { parentId: parent.id, requiresInsertBefore: insertBefore, hasParentWNode, - namespace: namespace + namespace: namespace, + reparent: hasParentWNode ? parent.reparent : undefined } as DNodeWrapper; if (isVNode(renderedItem)) { if (renderedItem.deferredPropertiesCallback) { @@ -1501,12 +1504,17 @@ export function renderer(renderer: () => RenderResult): Renderer { } if (nextSibling.childDomWrapperId) { const childWrapper = _idToWrapperMap.get(nextSibling.childDomWrapperId); - if (childWrapper && !isBodyWrapper(childWrapper) && !isHeadWrapper(childWrapper)) { + if ( + childWrapper && + !childWrapper.reparent && + !isBodyWrapper(childWrapper) && + !isHeadWrapper(childWrapper) + ) { domNode = childWrapper.domNode; } } } - if (domNode && domNode.parentNode) { + if (!nextSibling.reparent && domNode && domNode.parentNode) { insertBefore = domNode; break; } @@ -1900,6 +1908,7 @@ export function renderer(renderer: () => RenderResult): Renderer { } } item.next.inserted = true; + item.next.reparent = undefined; } else if (item.type === 'update') { const { next, @@ -1973,39 +1982,39 @@ export function renderer(renderer: () => RenderResult): Renderer { checkDistinguishable(childNodes, index, parentWNodeWrapper); } - function createKeyMap(wrappers: DNodeWrapper[]): (string | number)[] | false { - const keys: (string | number)[] = []; + function createKeyMap(wrappers: DNodeWrapper[]): Map { + const keys = new Map(); for (let i = 0; i < wrappers.length; i++) { const wrapper = wrappers[i]; if (wrapper.node.properties.key != null) { - keys.push(wrapper.node.properties.key); - } else { - return false; + keys.set(wrapper.node.properties.key, wrapper); } } return keys; } function _process(current: DNodeWrapper[], next: DNodeWrapper[], meta: ProcessMeta = {}): void { - let { mergeNodes = [], oldIndex = 0, newIndex = 0 } = meta; - const currentLength = current.length; + let { mergeNodes = [], oldIndex = 0, newIndex = 0, currentKeyMap } = meta; + let currentLength = current.length; const nextLength = next.length; const hasPreviousSiblings = currentLength > 1 || (currentLength > 0 && currentLength < nextLength); let instructions: Instruction[] = []; let replace = false; - if (oldIndex === 0 && newIndex === 0 && currentLength) { - const currentKeys = createKeyMap(current); - if (currentKeys) { - const nextKeys = createKeyMap(next); - if (nextKeys) { - for (let i = 0; i < currentKeys.length; i++) { - if (nextKeys.indexOf(currentKeys[i]) !== -1) { + if (!currentKeyMap) { + currentKeyMap = createKeyMap(current); + if (currentKeyMap.size === currentLength) { + const nextKeyMap = createKeyMap(next); + if (nextKeyMap.size === nextLength) { + const currentEntries = [...currentKeyMap.entries()]; + for (let i = 0; i < currentEntries.length; i++) { + const [key, value] = currentEntries[i]; + if (nextKeyMap.has(key)) { instructions = []; replace = false; break; } replace = true; - instructions.push({ current: current[i], next: undefined }); + instructions.push({ current: value, next: undefined }); } } } @@ -2020,18 +2029,32 @@ export function renderer(renderer: () => RenderResult): Renderer { let currentWrapper = oldIndex < currentLength ? current[oldIndex] : undefined; const nextWrapper = next[newIndex]; nextWrapper.hasPreviousSiblings = hasPreviousSiblings; - _processMergeNodes(nextWrapper, mergeNodes); - if (currentWrapper && same(currentWrapper, nextWrapper)) { oldIndex++; newIndex++; if (isVNodeWrapper(currentWrapper) && isVNodeWrapper(nextWrapper)) { nextWrapper.inserted = currentWrapper.inserted; } - instructions.push({ current: currentWrapper, next: nextWrapper }); + if (isVNodeWrapper(currentWrapper) && isVNodeWrapper(nextWrapper) && nextWrapper.reparent) { + nextWrapper.domNode = currentWrapper.domNode; + nextWrapper.reparent = currentWrapper.id; + currentWrapper.reparent = currentWrapper.id; + instructions.push({ current: currentWrapper, next: undefined }); + instructions.push({ current: undefined, next: nextWrapper }); + } else { + instructions.push({ current: currentWrapper, next: nextWrapper }); + } } else if (!currentWrapper || findIndexOfChild(current, nextWrapper, oldIndex + 1) === -1) { has('dojo-debug') && current.length && distinguishableCheck(next, newIndex); + const foundWrapper = currentKeyMap.get(nextWrapper.node.properties.key); + if (foundWrapper && same(foundWrapper, nextWrapper)) { + nextWrapper.domNode = foundWrapper.domNode; + current.splice(current.indexOf(foundWrapper), 1); + currentLength--; + currentKeyMap.delete(nextWrapper.node.properties.key); + nextWrapper.reparent = foundWrapper.id; + } instructions.push({ current: undefined, next: nextWrapper }); newIndex++; } else if (findIndexOfChild(next, currentWrapper, newIndex + 1) === -1) { @@ -2041,6 +2064,15 @@ export function renderer(renderer: () => RenderResult): Renderer { } else { has('dojo-debug') && distinguishableCheck(next, newIndex); has('dojo-debug') && distinguishableCheck(current, oldIndex); + const foundWrapper = currentKeyMap.get(nextWrapper.node.properties.key); + if (foundWrapper && same(foundWrapper, nextWrapper)) { + nextWrapper.domNode = foundWrapper.domNode; + nextWrapper.reparent = foundWrapper.id; + foundWrapper.reparent = foundWrapper.id; + currentWrapper.reparent = foundWrapper.id; + currentKeyMap.delete(nextWrapper.node.properties.key); + instructions.push({ current: foundWrapper, next: undefined }); + } instructions.push({ current: currentWrapper, next: undefined }); instructions.push({ current: undefined, next: nextWrapper }); oldIndex++; @@ -2048,9 +2080,14 @@ export function renderer(renderer: () => RenderResult): Renderer { } } if (newIndex < nextLength) { - _processQueue.push({ current, next, meta: { mergeNodes, oldIndex, newIndex } }); + _processQueue.push({ + current, + next, + meta: { mergeNodes, oldIndex, newIndex, currentKeyMap } + }); } if (currentLength > oldIndex && newIndex >= nextLength) { + currentKeyMap.clear(); for (let i = oldIndex; i < currentLength; i++) { has('dojo-debug') && distinguishableCheck(current, i); instructions.push({ current: current[i], next: undefined }); @@ -2252,9 +2289,16 @@ export function renderer(renderer: () => RenderResult): Renderer { if (!parentInvalidate && !(Constructor as any).isWNodeWrapper) { parentInvalidate = invalidate; } + let currentChildren: undefined | DNodeWrapper[] = undefined; + if (next.reparent) { + currentChildren = _idToChildrenWrappers.get(next.reparent); + _idToChildrenWrappers.delete(next.reparent); + next.reparent = undefined; + } return { item: { + current: currentChildren, next: children, meta: { mergeNodes: next.mergeNodes } }, @@ -2357,14 +2401,17 @@ export function renderer(renderer: () => RenderResult): Renderer { _idToWrapperMap.delete(current.id); const meta = widgetMetaMap.get(current.id); let currentChildren = _idToChildrenWrappers.get(current.id); - _idToChildrenWrappers.delete(current.id); _wrapperSiblingMap.delete(current); - let processResult: ProcessResult = { - item: { - current: currentChildren, - meta: {} - } - }; + let processResult: ProcessResult = {}; + if (!current.reparent) { + _idToChildrenWrappers.delete(current.id); + processResult = { + item: { + current: currentChildren, + meta: {} + } + }; + } if (meta) { meta.registryHandler && meta.registryHandler.destroy(); destroyHandles(meta); @@ -2451,15 +2498,22 @@ export function renderer(renderer: () => RenderResult): Renderer { parentDomNode: parentDomNode, type: 'create' }; - if (children) { + + let currentChildren: DNodeWrapper[] | undefined = undefined; + if (next.reparent) { + currentChildren = _idToChildrenWrappers.get(next.reparent); + _idToChildrenWrappers.delete(next.reparent); + } + + if (children || currentChildren) { return { item: { - current: [], + current: currentChildren, next: children, meta: { mergeNodes } }, dom, - widget: isVirtual ? { type: 'attach', id: (next as any).id, attached: false } : undefined + widget: isVirtual ? { type: 'attach', id: next.id, attached: false } : undefined }; } return { dom }; @@ -2491,6 +2545,9 @@ export function renderer(renderer: () => RenderResult): Renderer { } function _removeDom({ current }: RemoveDomInstruction): ProcessResult { + if (current.reparent) { + return {}; + } const isSpecial = isSpecialWrapper(current); const children = _idToChildrenWrappers.get(current.id); _idToChildrenWrappers.delete(current.id); diff --git a/tests/core/unit/vdom.tsx b/tests/core/unit/vdom.tsx index 8bd2918a2..bdfb41f2b 100644 --- a/tests/core/unit/vdom.tsx +++ b/tests/core/unit/vdom.tsx @@ -2,6 +2,7 @@ const { afterEach, beforeEach, describe, it } = intern.getInterface('bdd'); const { assert } = intern.getPlugin('chai'); const { describe: jsdomDescribe } = intern.getPlugin('jsdom'); import global from '../../../src/shim/global'; +import { from as arrayFrom } from '../../../src/shim/array'; import { spy, stub, SinonSpy, SinonStub } from 'sinon'; import { add } from '../../../src/core/has'; import { createResolvers } from './../support/util'; @@ -2349,7 +2350,7 @@ jsdomDescribe('vdom', () => { } render() { - return [w(Qux, { key: '1' }), v('div', [w(Qux, { key: '2' })])]; + return [w(Qux, { key: '1' }), v('div', { id: 'dovvy', key: 'divvy' }, [w(Qux, { key: '2' })])]; } } @@ -6312,10 +6313,10 @@ jsdomDescribe('vdom', () => { it('can distinguish between falsy keys when replacing', () => { const [Widget, meta] = getWidget( v('div', [ - v('span', { key: false as any }), - v('span', { key: null as any }), - v('span', { key: '' }), - v('span', {}) + v('span', { id: 'false', key: false as any }), + v('span', { id: 'null', key: null as any }), + v('span', { id: 'empty', key: '' }), + v('span', { id: 'none' }) ]) ); const r = renderer(() => w(Widget, {})); @@ -6330,7 +6331,7 @@ jsdomDescribe('vdom', () => { const thirdSpan = root.childNodes[2]; const fourthSpan = root.childNodes[3]; - meta.setRenderResult(v('div', [v('span', { key: 0 })])); + meta.setRenderResult(v('div', [v('span', { id: 'zero', key: 0 })])); assert.lengthOf(root.childNodes, 1); const newSpan = root.childNodes[0]; @@ -6381,21 +6382,44 @@ jsdomDescribe('vdom', () => { }); it('does not reorder nodes based on keys', () => { - const [Widget, meta] = getWidget(v('div', [v('span', { key: 'a' }), v('span', { key: 'b' })])); + const [Widget, meta] = getWidget( + v('div', [ + v('span', { key: 'a', id: 'a' }), + v('span', { key: '1', id: '1' }), + v('span', { key: '2', id: '2' }), + v('span', { key: '3', id: '3' }), + v('span', { key: '4', id: '4' }), + v('span', { key: '5', id: '5' }), + v('span', { key: '6', id: '6' }), + v('span', { key: '7', id: '7' }), + v('span', { key: 'b', id: 'b' }) + ]) + ); const r = renderer(() => w(Widget, {})); const div = document.createElement('div'); r.mount({ domNode: div, sync: true }); const root = div.childNodes[0] as HTMLElement; - assert.lengthOf(root.childNodes, 2); - const firstSpan = root.childNodes[0]; - const lastSpan = root.childNodes[1]; - - meta.setRenderResult(v('div', [v('span', { key: 'b' }), v('span', { key: 'a' })])); + assert.lengthOf(root.childNodes, 9); + const firstSpan = root.firstChild; + const lastSpan = root.lastChild; - assert.lengthOf(root.childNodes, 2); - assert.notStrictEqual(root.childNodes[0], lastSpan); - assert.notStrictEqual(root.childNodes[1], firstSpan); + meta.setRenderResult( + v('div', [ + v('span', { key: 'b', id: 'b' }), + v('span', { key: '1', id: '1' }), + v('span', { key: '2', id: '2' }), + v('span', { key: '3', id: '3' }), + v('span', { key: '4', id: '4' }), + v('span', { key: '5', id: '5' }), + v('span', { key: '6', id: '6' }), + v('span', { key: '7', id: '7' }), + v('span', { key: 'a', id: 'a' }) + ]) + ); + assert.lengthOf(root.childNodes, 9); + assert.strictEqual(root.firstChild, lastSpan); + assert.strictEqual(root.lastChild, firstSpan); }); it('can insert text nodes', () => { @@ -6417,7 +6441,17 @@ jsdomDescribe('vdom', () => { assert.strictEqual(root.childNodes[2], lastSpan); }); - it('Can update, insert and remove only affected nodes', () => { + it('Can update, insert and remove only affected vnodes', () => { + let onDetachStub = stub(); + class Other extends WidgetBase { + onDetach() { + onDetachStub(); + } + render() { + const { key } = this.properties; + return v('div', { key }); + } + } const [Widget, meta] = getWidget( v('div', [ v('span', { key: '1', id: '1' }), @@ -6427,7 +6461,7 @@ jsdomDescribe('vdom', () => { v('span', { key: '5', id: '5' }), v('span', { key: '6', id: '6' }), v('span', { key: '7', id: '7' }), - v('span', { key: '8', id: '8' }), + v('span', { key: '8', id: '8' }, [w(Other, { key: 'widget-8' })]), v('span', { key: '9', id: '9' }), v('span', { key: '10', id: '10' }), v('span', { key: '11', id: '11' }), @@ -6473,32 +6507,37 @@ jsdomDescribe('vdom', () => { assert.lengthOf(root.childNodes, 16); assert.strictEqual(root.childNodes[0], childOne); - assert.notEqual(root.childNodes[1], childTwo); - assert.notEqual(root.childNodes[1], childEight); - assert.notEqual(root.childNodes[2], childThree); - assert.notEqual(root.childNodes[2], childNine); - assert.notEqual(root.childNodes[3], childFour); - assert.notEqual(root.childNodes[3], childTen); - assert.isNull(childFive.parentNode); + assert.strictEqual(root.childNodes[1], childEight); + assert.strictEqual(root.childNodes[2], childNine); + assert.strictEqual(root.childNodes[3], childTen); assert.strictEqual(root.childNodes[4], childSix); assert.strictEqual(root.childNodes[9], childSeven); assert.strictEqual((root.childNodes[9] as HTMLElement).getAttribute('href'), 'href'); - assert.notEqual(root.childNodes[10], childEight); - assert.notEqual(root.childNodes[10], childTwo); - assert.notEqual(root.childNodes[11], childNine); - assert.notEqual(root.childNodes[11], childThree); - assert.notEqual(root.childNodes[12], childTen); - assert.notEqual(root.childNodes[12], childFour); + assert.strictEqual(root.childNodes[10], childTwo); + assert.strictEqual(root.childNodes[11], childThree); + assert.strictEqual(root.childNodes[12], childFour); + assert.isNull(childFive.parentNode); assert.strictEqual(root.childNodes[13], childEleven); assert.strictEqual(root.childNodes[14], childTwelve); + assert.strictEqual(onDetachStub.callCount, 1); }); it('Can update, insert and remove only affected nodes from widgets', () => { - class Foo extends WidgetBase<{ id?: string; href?: string }> { + class Other extends WidgetBase { render() { - const { key, id, href } = this.properties; + const { key } = this.properties; + return v('div', { key }); + } + } + + class Foo extends WidgetBase<{ id?: string; href?: string; show?: boolean }> { + render() { + const { key, id, href, show = true } = this.properties; + if (!show) { + return null; + } let properties = href ? { key, id, href } : { key, id }; - return v('span', properties); + return v('span', properties, [v('span', { id: `child-${id}` }), w(Other, { key: `widget-${id}` })]); } } @@ -6520,7 +6559,7 @@ jsdomDescribe('vdom', () => { ); const r = renderer(() => w(Widget, {})); const div = document.createElement('div'); - r.mount({ domNode: div, sync: true }); + r.mount({ domNode: div }); const root = div.childNodes[0] as HTMLElement; const childOne = root.childNodes[0] as HTMLSpanElement; const childTwo = root.childNodes[1] as HTMLSpanElement; @@ -6555,27 +6594,32 @@ jsdomDescribe('vdom', () => { w(Foo, { key: '13', id: '13' }) ]) ); - + resolvers.resolve(); + resolvers.resolve(); assert.lengthOf(root.childNodes, 16); assert.strictEqual(root.childNodes[0], childOne); - assert.notEqual(root.childNodes[1], childTwo); - assert.notEqual(root.childNodes[1], childEight); - assert.notEqual(root.childNodes[2], childThree); - assert.notEqual(root.childNodes[2], childNine); - assert.notEqual(root.childNodes[3], childFour); - assert.notEqual(root.childNodes[3], childTen); - assert.isNull(childFive.parentNode); + assert.strictEqual(root.childNodes[0].childNodes, childOne.childNodes); + assert.strictEqual(root.childNodes[1], childEight); + assert.strictEqual(root.childNodes[1].childNodes, childEight.childNodes); + assert.strictEqual(root.childNodes[2], childNine); + assert.strictEqual(root.childNodes[2].childNodes, childNine.childNodes); + assert.strictEqual(root.childNodes[3], childTen); + assert.strictEqual(root.childNodes[3].childNodes, childTen.childNodes); assert.strictEqual(root.childNodes[4], childSix); + assert.strictEqual(root.childNodes[4].childNodes, childSix.childNodes); assert.strictEqual(root.childNodes[9], childSeven); - assert.strictEqual((root.childNodes[9] as HTMLElement).getAttribute('href'), 'href'); - assert.notEqual(root.childNodes[10], childEight); - assert.notEqual(root.childNodes[10], childTwo); - assert.notEqual(root.childNodes[11], childNine); - assert.notEqual(root.childNodes[11], childThree); - assert.notEqual(root.childNodes[12], childTen); - assert.notEqual(root.childNodes[12], childFour); + assert.strictEqual(root.childNodes[9].childNodes, childSeven.childNodes); + assert.strictEqual(root.childNodes[10], childTwo); + assert.strictEqual(root.childNodes[10].childNodes, childTwo.childNodes); + assert.strictEqual(root.childNodes[11], childThree); + assert.strictEqual(root.childNodes[11].childNodes, childThree.childNodes); + assert.strictEqual(root.childNodes[12], childFour); + assert.strictEqual(root.childNodes[12].childNodes, childFour.childNodes); assert.strictEqual(root.childNodes[13], childEleven); + assert.strictEqual(root.childNodes[13].childNodes, childEleven.childNodes); assert.strictEqual(root.childNodes[14], childTwelve); + assert.strictEqual(root.childNodes[14].childNodes, childTwelve.childNodes); + assert.notDeepInclude(arrayFrom(root.children), childFive); }); it('Can insert new nodes in a widget that returns an array from render', () => { From 42afce14c3ce24032194ce87656fda757fd86334 Mon Sep 17 00:00:00 2001 From: Anthony Gubler Date: Mon, 1 Jun 2020 14:22:44 +0100 Subject: [PATCH 2/4] clean up --- src/core/vdom.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/core/vdom.ts b/src/core/vdom.ts index 3b268c313..2b4b2a853 100644 --- a/src/core/vdom.ts +++ b/src/core/vdom.ts @@ -1982,7 +1982,7 @@ export function renderer(renderer: () => RenderResult): Renderer { checkDistinguishable(childNodes, index, parentWNodeWrapper); } - function createKeyMap(wrappers: DNodeWrapper[]): Map { + function createKeyMap(wrappers: DNodeWrapper[]): Map { const keys = new Map(); for (let i = 0; i < wrappers.length; i++) { const wrapper = wrappers[i]; @@ -1995,7 +1995,7 @@ export function renderer(renderer: () => RenderResult): Renderer { function _process(current: DNodeWrapper[], next: DNodeWrapper[], meta: ProcessMeta = {}): void { let { mergeNodes = [], oldIndex = 0, newIndex = 0, currentKeyMap } = meta; - let currentLength = current.length; + const currentLength = current.length; const nextLength = next.length; const hasPreviousSiblings = currentLength > 1 || (currentLength > 0 && currentLength < nextLength); let instructions: Instruction[] = []; @@ -2021,7 +2021,7 @@ export function renderer(renderer: () => RenderResult): Renderer { } if (replace || (currentLength === 0 && !_mountOptions.merge)) { - for (let i = 0; i < next.length; i++) { + for (let i = 0; i < nextLength; i++) { instructions.push({ current: undefined, next: next[i] }); } } else { @@ -2046,14 +2046,13 @@ export function renderer(renderer: () => RenderResult): Renderer { instructions.push({ current: currentWrapper, next: nextWrapper }); } } else if (!currentWrapper || findIndexOfChild(current, nextWrapper, oldIndex + 1) === -1) { - has('dojo-debug') && current.length && distinguishableCheck(next, newIndex); + has('dojo-debug') && currentLength && distinguishableCheck(next, newIndex); const foundWrapper = currentKeyMap.get(nextWrapper.node.properties.key); if (foundWrapper && same(foundWrapper, nextWrapper)) { - nextWrapper.domNode = foundWrapper.domNode; - current.splice(current.indexOf(foundWrapper), 1); - currentLength--; + const { domNode, id } = foundWrapper; + nextWrapper.domNode = domNode; + nextWrapper.reparent = id; currentKeyMap.delete(nextWrapper.node.properties.key); - nextWrapper.reparent = foundWrapper.id; } instructions.push({ current: undefined, next: nextWrapper }); newIndex++; @@ -2066,10 +2065,11 @@ export function renderer(renderer: () => RenderResult): Renderer { has('dojo-debug') && distinguishableCheck(current, oldIndex); const foundWrapper = currentKeyMap.get(nextWrapper.node.properties.key); if (foundWrapper && same(foundWrapper, nextWrapper)) { - nextWrapper.domNode = foundWrapper.domNode; - nextWrapper.reparent = foundWrapper.id; - foundWrapper.reparent = foundWrapper.id; - currentWrapper.reparent = foundWrapper.id; + const { domNode, id } = foundWrapper; + nextWrapper.domNode = domNode; + nextWrapper.reparent = id; + foundWrapper.reparent = id; + currentWrapper.reparent = id; currentKeyMap.delete(nextWrapper.node.properties.key); instructions.push({ current: foundWrapper, next: undefined }); } From 641725da7edbb47567d078fd4de438270816cd66 Mon Sep 17 00:00:00 2001 From: Anthony Gubler Date: Mon, 3 Aug 2020 12:37:55 +0100 Subject: [PATCH 3/4] package lock --- package-lock.json | 215 ++++++++++++++++------------------------------ 1 file changed, 75 insertions(+), 140 deletions(-) diff --git a/package-lock.json b/package-lock.json index 002c186d8..d0763f84d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,9 +28,9 @@ } }, "@sinonjs/commons": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.0.tgz", - "integrity": "sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", + "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -98,9 +98,9 @@ } }, "@types/babel-types": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.7.tgz", - "integrity": "sha512-dBtBbrc+qTHy1WdfHYjBwRln4+LWqASWakLHsWHR2NWHIFkv4W3O070IGoGLEBrJBvct3r0L1BUPuvURi7kYUQ==", + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.8.tgz", + "integrity": "sha512-jvu8g4LR7+p6ao30RhTREnEhHxmP4/R9D9/rOR/Kq14FztORty9SKgtOZUNZNMB9CXLxZ54EWu4dArUE8WdTsw==", "dev": true }, "@types/benchmark": { @@ -172,9 +172,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.7.tgz", - "integrity": "sha512-EMgTj/DF9qpgLXyc+Btimg+XoH7A2liE8uKul8qSmMTHCeNYzydDKFdsJskDvw42UsesCnhO63dO0Grbj8J4Dw==", + "version": "4.17.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.9.tgz", + "integrity": "sha512-DG0BYg6yO+ePW+XoDENYz8zhNGC3jDDEpComMYn7WJc4mY1Us8Rw9ax2YhJXxpyk2SF47PQAoQ0YyVT1a0bEkA==", "dev": true, "requires": { "@types/node": "*", @@ -237,9 +237,9 @@ } }, "@types/jquery": { - "version": "3.3.38", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.38.tgz", - "integrity": "sha512-nkDvmx7x/6kDM5guu/YpXkGZ/Xj/IwGiLDdKM99YA5Vag7pjGyTJ8BNUh/6hxEn/sEu5DKtyRgnONJ7EmOoKrA==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.1.tgz", + "integrity": "sha512-Tyctjh56U7eX2b9udu3wG853ASYP0uagChJcQJXLUXEU6C/JiW5qt5dl8ao01VRj1i5pgXPAf8f1mq4+FDLRQg==", "dev": true, "requires": { "@types/sizzle": "*" @@ -256,9 +256,9 @@ } }, "@types/mime": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz", - "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", + "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", "dev": true }, "@types/multer": { @@ -277,9 +277,9 @@ "dev": true }, "@types/qs": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz", - "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==", + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==", "dev": true }, "@types/ramda": { @@ -301,9 +301,9 @@ "dev": true }, "@types/serve-static": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz", - "integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.5.tgz", + "integrity": "sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ==", "dev": true, "requires": { "@types/express-serve-static-core": "*", @@ -381,9 +381,9 @@ "dev": true }, "ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -1460,13 +1460,10 @@ "dev": true }, "commander": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "component-emitter": { "version": "1.3.0", @@ -2008,9 +2005,9 @@ } }, "entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.2.tgz", - "integrity": "sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" }, "error-ex": { "version": "1.3.2", @@ -2022,22 +2019,22 @@ } }, "es-abstract": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", - "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", "object-inspect": "^1.7.0", "object-keys": "^1.1.1", "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" } }, "es-to-primitive": { @@ -2122,9 +2119,9 @@ "dev": true }, "escodegen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz", - "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", "dev": true, "requires": { "esprima": "^4.0.1", @@ -2353,9 +2350,9 @@ "dev": true }, "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "fast-json-stable-stringify": { @@ -2709,12 +2706,6 @@ "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, "handlebars": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", @@ -2734,12 +2725,12 @@ "dev": true }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, @@ -3100,9 +3091,9 @@ "dev": true }, "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", "dev": true }, "is-ci": { @@ -3300,12 +3291,12 @@ "dev": true }, "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", + "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", "dev": true, "requires": { - "has": "^1.0.3" + "has-symbols": "^1.0.1" } }, "is-regexp": { @@ -3710,12 +3701,6 @@ "stringify-object": "^3.2.0" }, "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, "execa": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", @@ -3971,9 +3956,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true }, "lodash.get": { @@ -4309,9 +4294,9 @@ "dev": true }, "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, "next-tick": { @@ -4469,14 +4454,6 @@ "commander": "^2.9.0", "npm-path": "^2.0.2", "which": "^1.2.10" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } } }, "nth-check": { @@ -4534,9 +4511,9 @@ } }, "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", "dev": true }, "object-keys": { @@ -4907,9 +4884,9 @@ } }, "platform": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", - "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", "dev": true }, "posix-character-classes": { @@ -5633,12 +5610,12 @@ "dev": true }, "seek-bzip": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", - "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", "dev": true, "requires": { - "commander": "~2.8.1" + "commander": "^2.8.1" } }, "selenium-webdriver": { @@ -6106,28 +6083,6 @@ "es-abstract": "^1.17.5" } }, - "string.prototype.trimleft": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", - "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimstart": "^1.0.0" - } - }, - "string.prototype.trimright": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", - "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimend": "^1.0.0" - } - }, "string.prototype.trimstart": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", @@ -6399,14 +6354,6 @@ "semver": "^5.3.0", "tslib": "^1.8.0", "tsutils": "^2.27.2" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } } }, "tslint-language-service": { @@ -6485,23 +6432,11 @@ "dev": true }, "uglify-js": { - "version": "3.9.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.3.tgz", - "integrity": "sha512-r5ImcL6QyzQGVimQoov3aL2ZScywrOgBXGndbWrdehKoSvGe/RmiE5Jpw/v+GvxODt6l2tpBXwA7n+qZVlHBMA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.1.tgz", + "integrity": "sha512-RjxApKkrPJB6kjJxQS3iZlf///REXWYxYJxO/MpmlQzVkDWVI3PSnCBWezMecmTU/TRkNxrl8bmsfFQCp+LO+Q==", "dev": true, - "optional": true, - "requires": { - "commander": "~2.20.3" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "optional": true - } - } + "optional": true }, "unbzip2-stream": { "version": "1.4.3", From ea2ed7b99d0aacea288482c543c2a6878e43af1c Mon Sep 17 00:00:00 2001 From: Anthony Gubler Date: Mon, 3 Aug 2020 13:23:52 +0100 Subject: [PATCH 4/4] fix tests for ie11 --- tests/core/unit/vdom.tsx | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/tests/core/unit/vdom.tsx b/tests/core/unit/vdom.tsx index bdfb41f2b..4613dfb99 100644 --- a/tests/core/unit/vdom.tsx +++ b/tests/core/unit/vdom.tsx @@ -6598,27 +6598,38 @@ jsdomDescribe('vdom', () => { resolvers.resolve(); assert.lengthOf(root.childNodes, 16); assert.strictEqual(root.childNodes[0], childOne); - assert.strictEqual(root.childNodes[0].childNodes, childOne.childNodes); + assert.strictEqual(root.childNodes[0].childNodes[0], childOne.childNodes[0]); + assert.strictEqual(root.childNodes[0].childNodes[1], childOne.childNodes[1]); assert.strictEqual(root.childNodes[1], childEight); - assert.strictEqual(root.childNodes[1].childNodes, childEight.childNodes); + assert.strictEqual(root.childNodes[1].childNodes[0], childEight.childNodes[0]); + assert.strictEqual(root.childNodes[1].childNodes[1], childEight.childNodes[1]); assert.strictEqual(root.childNodes[2], childNine); - assert.strictEqual(root.childNodes[2].childNodes, childNine.childNodes); + assert.strictEqual(root.childNodes[2].childNodes[0], childNine.childNodes[0]); + assert.strictEqual(root.childNodes[2].childNodes[1], childNine.childNodes[1]); assert.strictEqual(root.childNodes[3], childTen); - assert.strictEqual(root.childNodes[3].childNodes, childTen.childNodes); + assert.strictEqual(root.childNodes[3].childNodes[0], childTen.childNodes[0]); + assert.strictEqual(root.childNodes[3].childNodes[1], childTen.childNodes[1]); assert.strictEqual(root.childNodes[4], childSix); - assert.strictEqual(root.childNodes[4].childNodes, childSix.childNodes); + assert.strictEqual(root.childNodes[4].childNodes[0], childSix.childNodes[0]); + assert.strictEqual(root.childNodes[4].childNodes[1], childSix.childNodes[1]); assert.strictEqual(root.childNodes[9], childSeven); - assert.strictEqual(root.childNodes[9].childNodes, childSeven.childNodes); + assert.strictEqual(root.childNodes[9].childNodes[0], childSeven.childNodes[0]); + assert.strictEqual(root.childNodes[9].childNodes[1], childSeven.childNodes[1]); assert.strictEqual(root.childNodes[10], childTwo); - assert.strictEqual(root.childNodes[10].childNodes, childTwo.childNodes); + assert.strictEqual(root.childNodes[10].childNodes[0], childTwo.childNodes[0]); + assert.strictEqual(root.childNodes[10].childNodes[1], childTwo.childNodes[1]); assert.strictEqual(root.childNodes[11], childThree); - assert.strictEqual(root.childNodes[11].childNodes, childThree.childNodes); + assert.strictEqual(root.childNodes[11].childNodes[0], childThree.childNodes[0]); + assert.strictEqual(root.childNodes[11].childNodes[1], childThree.childNodes[1]); assert.strictEqual(root.childNodes[12], childFour); - assert.strictEqual(root.childNodes[12].childNodes, childFour.childNodes); + assert.strictEqual(root.childNodes[12].childNodes[0], childFour.childNodes[0]); + assert.strictEqual(root.childNodes[12].childNodes[1], childFour.childNodes[1]); assert.strictEqual(root.childNodes[13], childEleven); - assert.strictEqual(root.childNodes[13].childNodes, childEleven.childNodes); + assert.strictEqual(root.childNodes[13].childNodes[0], childEleven.childNodes[0]); + assert.strictEqual(root.childNodes[13].childNodes[1], childEleven.childNodes[1]); assert.strictEqual(root.childNodes[14], childTwelve); - assert.strictEqual(root.childNodes[14].childNodes, childTwelve.childNodes); + assert.strictEqual(root.childNodes[14].childNodes[0], childTwelve.childNodes[0]); + assert.strictEqual(root.childNodes[14].childNodes[1], childTwelve.childNodes[1]); assert.notDeepInclude(arrayFrom(root.children), childFive); });