Two more fixes for document.createElement mode

Is this all of them? I hope so.

- Set text content after creating hierarchy, like the text is a child. I should've done this originally but I guessed it wouldn't matter. I was wrong (~20% perf difference in IE11).
- IE throws when setting an enum-like property to an invalid value. I tried setting every property to the string 'a' and changed the ones that threw to be MUST_USE_ATTRIBUTE. I think these are all correct -- encType is the most suspicious one based on the existing comments but I tested in IE8 and it works fine as an attribute.
This commit is contained in:
Ben Alpert
2015-10-23 22:46:02 -07:00
parent 8aaa66c292
commit 6269ef62cf
5 changed files with 34 additions and 27 deletions
@@ -11,6 +11,8 @@
'use strict';
var setTextContent = require('setTextContent');
/**
* In IE (8-11) and Edge, appending nodes with no children is dramatically
* faster than appending a full subtree, so we essentially queue up the
@@ -43,6 +45,8 @@ function insertTreeChildren(tree) {
}
} else if (tree.html != null) {
node.innerHTML = tree.html;
} else if (tree.text != null) {
setTextContent(node, tree.text);
}
}
@@ -72,11 +76,20 @@ function queueHTML(tree, html) {
}
}
function queueText(tree, text) {
if (enableLazy) {
tree.text = text;
} else {
setTextContent(tree.node, text);
}
}
function DOMLazyTree(node) {
return {
node: node,
children: [],
html: null,
text: null,
};
}
@@ -84,5 +97,6 @@ DOMLazyTree.insertTreeBefore = insertTreeBefore;
DOMLazyTree.replaceChildWithTree = replaceChildWithTree;
DOMLazyTree.queueChild = queueChild;
DOMLazyTree.queueHTML = queueHTML;
DOMLazyTree.queueText = queueText;
module.exports = DOMLazyTree;
@@ -58,8 +58,8 @@ var HTMLDOMPropertyConfig = {
// autoFocus: HAS_BOOLEAN_VALUE,
autoPlay: HAS_BOOLEAN_VALUE,
capture: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
cellPadding: null,
cellSpacing: null,
cellPadding: MUST_USE_ATTRIBUTE,
cellSpacing: MUST_USE_ATTRIBUTE,
charSet: MUST_USE_ATTRIBUTE,
challenge: MUST_USE_ATTRIBUTE,
checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
@@ -71,9 +71,9 @@ var HTMLDOMPropertyConfig = {
// regardless of whether the element is HTML or SVG.
className: hasSVG ? MUST_USE_ATTRIBUTE : MUST_USE_PROPERTY,
cols: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
colSpan: null,
colSpan: MUST_USE_ATTRIBUTE,
content: null,
contentEditable: null,
contentEditable: MUST_USE_ATTRIBUTE,
contextMenu: MUST_USE_ATTRIBUTE,
controls: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
coords: null,
@@ -82,11 +82,11 @@ var HTMLDOMPropertyConfig = {
dateTime: MUST_USE_ATTRIBUTE,
default: HAS_BOOLEAN_VALUE,
defer: HAS_BOOLEAN_VALUE,
dir: null,
dir: MUST_USE_ATTRIBUTE,
disabled: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
download: HAS_OVERLOADED_BOOLEAN_VALUE,
draggable: null,
encType: null,
encType: MUST_USE_ATTRIBUTE,
form: MUST_USE_ATTRIBUTE,
formAction: MUST_USE_ATTRIBUTE,
formEncType: MUST_USE_ATTRIBUTE,
@@ -112,16 +112,16 @@ var HTMLDOMPropertyConfig = {
label: null,
lang: null,
list: MUST_USE_ATTRIBUTE,
loop: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
loop: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
low: null,
manifest: MUST_USE_ATTRIBUTE,
marginHeight: null,
marginWidth: null,
marginHeight: MUST_USE_ATTRIBUTE,
marginWidth: MUST_USE_ATTRIBUTE,
max: null,
maxLength: MUST_USE_ATTRIBUTE,
media: MUST_USE_ATTRIBUTE,
mediaGroup: null,
method: null,
method: MUST_USE_ATTRIBUTE,
min: null,
minLength: MUST_USE_ATTRIBUTE,
multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
@@ -140,23 +140,23 @@ var HTMLDOMPropertyConfig = {
required: HAS_BOOLEAN_VALUE,
role: MUST_USE_ATTRIBUTE,
rows: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
rowSpan: null,
rowSpan: MUST_USE_ATTRIBUTE | HAS_NUMERIC_VALUE,
sandbox: null,
scope: null,
scoped: HAS_BOOLEAN_VALUE,
scrolling: null,
scrolling: MUST_USE_ATTRIBUTE,
seamless: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
shape: null,
size: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
sizes: MUST_USE_ATTRIBUTE,
span: HAS_POSITIVE_NUMERIC_VALUE,
span: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
spellCheck: null,
src: null,
srcDoc: MUST_USE_PROPERTY,
srcLang: null,
srcSet: MUST_USE_ATTRIBUTE,
start: HAS_NUMERIC_VALUE,
start: MUST_USE_ATTRIBUTE | HAS_NUMERIC_VALUE,
step: null,
style: null,
summary: null,
@@ -169,7 +169,7 @@ var HTMLDOMPropertyConfig = {
value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS,
width: MUST_USE_ATTRIBUTE,
wmode: MUST_USE_ATTRIBUTE,
wrap: null,
wrap: MUST_USE_ATTRIBUTE,
/**
* RDFa Properties
@@ -225,9 +225,6 @@ var HTMLDOMPropertyConfig = {
autoFocus: 'autofocus',
autoPlay: 'autoplay',
autoSave: 'autosave',
// `encoding` is equivalent to `enctype`, IE8 lacks an `enctype` setter.
// http://www.w3.org/TR/html5/forms.html#dom-fs-encoding
encType: 'encoding',
hrefLang: 'hreflang',
radioGroup: 'radiogroup',
spellCheck: 'spellcheck',
@@ -42,7 +42,6 @@ var escapeTextContentForBrowser = require('escapeTextContentForBrowser');
var invariant = require('invariant');
var isEventSupported = require('isEventSupported');
var keyOf = require('keyOf');
var setTextContent = require('setTextContent');
var shallowEqual = require('shallowEqual');
var validateDOMNesting = require('validateDOMNesting');
var warning = require('warning');
@@ -828,7 +827,7 @@ ReactDOMComponent.Mixin = {
var childrenToUse = contentToUse != null ? null : props.children;
if (contentToUse != null) {
// TODO: Validate that text is allowed as a child of this node
setTextContent(lazyTree.node, contentToUse);
DOMLazyTree.queueText(lazyTree, contentToUse);
} else if (childrenToUse != null) {
var mountImages = this.mountChildren(
childrenToUse,
@@ -21,7 +21,6 @@ var ReactMount = require('ReactMount');
var assign = require('Object.assign');
var escapeTextContentForBrowser = require('escapeTextContentForBrowser');
var setTextContent = require('setTextContent');
var validateDOMNesting = require('validateDOMNesting');
function getNode(inst) {
@@ -106,8 +105,9 @@ assign(ReactDOMTextComponent.prototype, {
DOMPropertyOperations.setAttributeForID(el, rootID);
// Populate node cache
ReactMount.getID(el);
setTextContent(el, this._stringText);
return DOMLazyTree(el);
var lazyTree = DOMLazyTree(el);
DOMLazyTree.queueText(lazyTree, this._stringText);
return lazyTree;
} else {
var escapedText = escapeTextContentForBrowser(this._stringText);
@@ -432,10 +432,7 @@ describe('ReactDOMComponent', function() {
var node = ReactDOM.render(<div />, container);
var setter = mocks.getMockFunction();
Object.defineProperty(node, 'dir', {
get: function() {},
set: setter,
});
node.setAttribute = setter;
ReactDOM.render(<div dir={null} />, container);
ReactDOM.render(<div dir={undefined} />, container);