Skip to content

Commit

Permalink
Merge pull request #1395 from developit/ie11_remove
Browse files Browse the repository at this point in the history
Fix Element.prototype.remove not available in IE11
  • Loading branch information
marvinhagemeister committed Mar 14, 2019
2 parents a0d8d66 + 07b3370 commit bdfe27b
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 7 deletions.
3 changes: 2 additions & 1 deletion src/diff/children.js
@@ -1,6 +1,7 @@
import { diff, unmount } from './index';
import { coerceToVNode, Fragment } from '../create-element';
import { EMPTY_OBJ, EMPTY_ARR } from '../constants';
import { removeNode } from '../util';

/**
* Diff the children of a virtual node
Expand Down Expand Up @@ -117,7 +118,7 @@ export function diffChildren(parentDom, newParentVNode, oldParentVNode, context,
}

// Remove children that are not part of any vnode. Only used by `hydrate`
if (excessDomChildren!=null && newParentVNode.type!==Fragment) for (i=excessDomChildren.length; i--; ) if (excessDomChildren[i]!=null) excessDomChildren[i].remove();
if (excessDomChildren!=null && newParentVNode.type!==Fragment) for (i=excessDomChildren.length; i--; ) if (excessDomChildren[i]!=null) removeNode(excessDomChildren[i]);

// Remove remaining oldChildren if there are any.
for (i=oldChildrenLength; i--; ) if (oldChildren[i]!=null) unmount(oldChildren[i], ancestorComponent);
Expand Down
12 changes: 7 additions & 5 deletions src/diff/index.js
Expand Up @@ -3,7 +3,7 @@ import { Component, enqueueRender } from '../component';
import { coerceToVNode, Fragment } from '../create-element';
import { diffChildren } from './children';
import { diffProps } from './props';
import { assign } from '../util';
import { assign, removeNode } from '../util';
import options from '../options';

/**
Expand Down Expand Up @@ -297,16 +297,18 @@ export function applyRef(ref, value, ancestorComponent) {
* @param {import('../internal').VNode} vnode The virtual node to unmount
* @param {import('../internal').Component} ancestorComponent The parent
* component to this virtual node
* @param {boolean} skipRemove Flag that indicates that a parent node of the
* current element is already detached from the DOM.
*/
export function unmount(vnode, ancestorComponent) {
export function unmount(vnode, ancestorComponent, skipRemove) {
let r;
if (options.unmount) options.unmount(vnode);

if (r = vnode.ref) {
applyRef(r, null, ancestorComponent);
}

if ((r = vnode._dom)!=null) r.remove();
if (!skipRemove && vnode._lastDomChild==null && (skipRemove = ((r = vnode._dom)!=null))) removeNode(r);

vnode._dom = vnode._lastDomChild = null;

Expand All @@ -321,11 +323,11 @@ export function unmount(vnode, ancestorComponent) {
}

r.base = r._parentDom = null;
if (r = r._prevVNode) unmount(r, ancestorComponent);
if (r = r._prevVNode) unmount(r, ancestorComponent, skipRemove);
}
else if (r = vnode._children) {
for (let i = 0; i < r.length; i++) {
unmount(r[i], ancestorComponent);
unmount(r[i], ancestorComponent, skipRemove);
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/util.js
Expand Up @@ -9,3 +9,14 @@ export function assign(obj, props) {
for (let i in props) obj[i] = props[i];
return /** @type {O & P} */ (obj);
}

/**
* Remove a child node from its parent if attached. This is a workaround for
* IE11 which doesn't support `Element.prototype.remove()`. Using this function
* is smaller than including a dedicated polyfill.
* @param {Node} node The node to remove
*/
export function removeNode(node) {
let parentNode = node.parentNode;
if (parentNode) parentNode.removeChild(node);
}
6 changes: 5 additions & 1 deletion test/_util/logCall.js
Expand Up @@ -28,7 +28,11 @@ export function logCall(obj, method) {
if (c) c += ', ';
c += serialize(args[i]);
}
const operation = `${serialize(this)}.${method}(${c})`;

// Normalize removeChild -> remove to keep output clean and readable
const operation = method!='removeChild'
? `${serialize(this)}.${method}(${c})`
: `${serialize(c)}.remove()`;
log.push(operation);
return old.apply(this, args);
};
Expand Down
1 change: 1 addition & 0 deletions test/browser/hydrate.test.js
Expand Up @@ -14,6 +14,7 @@ describe('hydrate()', () => {
before(() => {
logCall(Element.prototype, 'appendChild');
logCall(Element.prototype, 'insertBefore');
logCall(Element.prototype, 'removeChild');
logCall(Element.prototype, 'remove');
logCall(Element.prototype, 'setAttribute');
logCall(Element.prototype, 'removeAttribute');
Expand Down
1 change: 1 addition & 0 deletions test/browser/keys.test.js
Expand Up @@ -52,6 +52,7 @@ describe('keys', () => {
before(() => {
logCall(Element.prototype, 'appendChild');
logCall(Element.prototype, 'insertBefore');
logCall(Element.prototype, 'removeChild');
logCall(Element.prototype, 'remove');
});

Expand Down

0 comments on commit bdfe27b

Please sign in to comment.