Avoid unnecessary array allocations in dangerouslyRenderMarkup.
Ben Newman committed
Sep 9, 2013 at 14:55 UTC
cd7d863f205dbeac5f6b43b947a139ce51eb0a6e
1 file changed
+32
-20
src/dom/Danger.js
+32
-20
@@ -31,6 +31,9 @@ var mutateHTMLNodeWithMarkup = require('mutateHTMLNodeWithMarkup');
31
32
var COMMENT_NODE_TYPE = 8;
33
34
+// This buffer will be reused in dangerouslyRenderMarkup to avoid unnecessary
35
+// array allocations.
36
+var reusableBuffer = [];
37
38
/**
39
* Extracts the `nodeName` from a string of markup.
@@ -50,9 +53,9 @@ function getNodeName(markup) {
53
var Danger = {
54
55
/**
53
- * Renders markup into an array of nodes. The markup is expected to
54
- * render into a list of root nodes. Also, the length of `resultList`
55
- * and `markupList` should be the same.
56
+ * Renders markup into an array of nodes. The markup is expected to render
57
+ * into a list of root nodes. Also, the length of `resultList` and
58
+ * `markupList` should be the same.
59
*
60
* @param {array<string>} markupList List of markup strings to render.
61
* @return {array<DOMElement>} List of rendered nodes.
@@ -86,15 +89,17 @@ var Danger = {
89
}
90
var markupListByNodeName = markupByNodeName[nodeName];
91
89
- var commentedMarkupList = [];
90
- // This for-in loop skips the holes of the sparse array. The order
91
- // of iteration should follow the order of assignment, which happens
92
- // to match numerical index order, but we don't rely on that.
92
+ var commentedMarkupList = reusableBuffer;
93
+ commentedMarkupList.length = 0;
94
+
95
+ // This for-in loop skips the holes of the sparse array. The order of
96
+ // iteration should follow the order of assignment, which happens to match
97
+ // numerical index order, but we don't rely on that.
98
for (var resultIndex in markupListByNodeName) {
99
if (markupListByNodeName.hasOwnProperty(resultIndex)) {
100
// Push the requested markup followed by a sentinel HTML
96
- // comment. Comments are a good choice for sentinels because
97
- // they can appear as children of any HTML node.
101
+ // comment. Comments are a good choice for sentinels because they can
102
+ // appear as children of any HTML node.
103
commentedMarkupList.push(
104
markupListByNodeName[resultIndex],
105
// This resultIndex will be parsed back out below.
@@ -103,14 +108,15 @@ var Danger = {
108
}
109
}
110
106
- // Render each group of markup with similar wrapping `nodeName`,
107
- // with sentinel comments interspersed.
111
+ // Render each group of markup with similar wrapping `nodeName`, with
112
+ // sentinel comments interspersed.
113
var renderNodes = createNodesFromMarkup(
114
commentedMarkupList.join(''),
115
emptyFunction // Do nothing special with <script> tags.
116
);
117
113
- var renderBuffer = [];
118
+ var renderBuffer = reusableBuffer;
119
+ renderBuffer.length = 0;
120
121
for (i = 0; i < renderNodes.length; ++i) {
122
var renderNode = renderNodes[i];
@@ -137,8 +143,8 @@ var Danger = {
143
"rendered as " + renderBuffer.length + " nodes instead of 1:"
144
];
145
140
- // Pass the nodes as arguments to console.error so that
141
- // they can be inspected in the browser.
146
+ // Pass the nodes as arguments to console.error so that they can
147
+ // be inspected in the browser.
148
args.push.apply(args, renderBuffer);
149
150
// Use console.error instead of throwing so that we don't
@@ -151,13 +157,13 @@ var Danger = {
157
// resultList[resultIndex];
158
renderBuffer.length = 0;
159
154
- // This should match resultList.length and markupList.length
155
- // when we're done.
160
+ // This should match resultList.length and markupList.length when
161
+ // we're done.
162
resultListAssignmentCount += 1;
163
164
} else {
159
- // It's some other kind of comment that we didn't create.
160
- // Weirder things have happened.
165
+ // It's some other kind of comment that we didn't create. Weirder
166
+ // things have happened.
167
renderBuffer.push(renderNode);
168
console.warn(
169
'Danger: Markup unexpectedly rendered a comment node:',
@@ -168,8 +174,14 @@ var Danger = {
174
}
175
}
176
171
- // Although resultList was populated out of order, it should now be a
172
- // dense array.
177
+ invariant(
178
+ reusableBuffer.length === 0,
179
+ 'Danger: Rendered malformed markup: %s.',
180
+ reusableBuffer
181
+ );
182
+
183
+ // Although resultList was populated out of order, it should now be a dense
184
+ // array.
185
invariant(
186
resultListAssignmentCount === resultList.length,
187
'Danger: Did not assign to every index of resultList.'