Skip to content

Commit

Permalink
Merge 28658e4 into 1784e2d
Browse files Browse the repository at this point in the history
  • Loading branch information
tbranyen committed Feb 11, 2016
2 parents 1784e2d + 28658e4 commit 7c2d7f3
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 113 deletions.
86 changes: 32 additions & 54 deletions dist/diffhtml.js
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,9 @@ function make(node) {
// Set a lowercased (normalized) version of the element's nodeName.
entry.nodeName = node.nodeName.toLowerCase();

// Keep consistent with our internal HTML parser and set the nodeType.
entry.nodeType = node.nodeType;

// If the element is a text node set the nodeValue.
if (nodeType === 3) {
entry.nodeValue = node.textContent;
Expand Down Expand Up @@ -675,7 +678,7 @@ function make(node) {
var childNodesLength = childNodes.length;

// If the element has child nodes, convert them all to virtual nodes.
if (node.nodeType !== 3 && childNodes) {
if (entry.nodeType !== 3 && childNodesLength) {
for (var i = 0; i < childNodesLength; i++) {
var newNode = make(childNodes[i]);

Expand Down Expand Up @@ -1997,7 +2000,7 @@ function cleanMemory(makeNode) {
// Clean out unused elements.
if (makeNode && makeNode.nodes) {
for (var uuid in makeNode.nodes) {
if (!pools.elementObject.cache.uuid[uuid]) {
if (!pools.elementObject.cache.uuid.has(uuid)) {
delete makeNode.nodes[uuid];
}
}
Expand Down Expand Up @@ -2396,9 +2399,9 @@ function createPool(name, opts) {

var cache = {
free: [],
allocated: [],
protected: [],
uuid: {}
allocated: new Set(),
protected: new Set(),
uuid: new Set()
};

// Prime the cache with n objects.
Expand All @@ -2410,70 +2413,45 @@ function createPool(name, opts) {
cache: cache,

get: function get() {
var obj = null;
var freeLength = cache.free.length;
var minusOne = freeLength - 1;

if (freeLength) {
obj = cache.free[minusOne];
cache.free.length = minusOne;
} else {
obj = fill();
}

cache.allocated.push(obj);

return obj;
var value = cache.free.pop() || fill();
cache.allocated.add(value);
return value;
},
protect: function protect(value) {
var idx = cache.allocated.indexOf(value);
cache.allocated.delete(value);
cache.protected.add(value);

// Move the value out of allocated, since we need to protect this from
// being free'd accidentally.
if (cache.protected.indexOf(value) === -1) {
cache.protected.push(idx === -1 ? value : cache.allocated.splice(idx, 1)[0]);
}

// If we're protecting an element object, push the uuid into a lookup
// table.
if (name === 'elementObject') {
cache.uuid[value.uuid] = value;
cache.uuid.add(value.uuid);
}
},
unprotect: function unprotect(value) {
var idx = cache.protected.indexOf(value);

if (idx !== -1) {
var obj = cache.protected.splice(idx, 1)[0];

if (obj) {
cache.free.push(obj);
}
if (cache.protected.has(value)) {
cache.protected.delete(value);
cache.free.push(value);
}

if (name === 'elementObject') {
delete cache.uuid[value.uuid];
}
if (name === 'elementObject') {
cache.uuid.delete(value.uuid);
}
},
freeAll: function freeAll() {
var freeLength = cache.free.length;
var minusOne = freeLength - 1;
var reAlloc = cache.allocated.slice(0, size - minusOne);
// All of this could go away if we could figure out `Array.from` within
// a PhantomJS web-worker.
cache.allocated.forEach(function (value) {
cache.free.push(value);

cache.free.push.apply(cache.free, reAlloc);
cache.allocated.length = 0;
if (name === 'elementObject') {
cache.uuid.delete(value.uuid);
}
});

if (name === 'elementObject') {
reAlloc.forEach(function (element) {
return delete cache.uuid[element.uuid];
});
}
cache.allocated.clear();
cache.free.length = size;
},
free: function free(value) {
var idx = cache.allocated.indexOf(value);

// Already freed.
if (idx === -1) {
if (!cache.allocated.has(value)) {
return;
}

Expand All @@ -2482,7 +2460,7 @@ function createPool(name, opts) {
cache.free.push(value);
}

cache.allocated.splice(idx, 1);
cache.allocated.delete(value);
}
};
}
Expand Down
2 changes: 1 addition & 1 deletion lib/util/memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function cleanMemory(makeNode) {
// Clean out unused elements.
if (makeNode && makeNode.nodes) {
for (let uuid in makeNode.nodes) {
if (!pools.elementObject.cache.uuid[uuid]) {
if (!pools.elementObject.cache.uuid.has(uuid)) {
delete makeNode.nodes[uuid];
}
}
Expand Down
80 changes: 27 additions & 53 deletions lib/util/pools.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export function createPool(name, opts) {
var { size, fill } = opts;
var cache = {
free: [],
allocated: [],
protected: [],
uuid: {}
allocated: new Set(),
protected: new Set(),
uuid: new Set(),
};

// Prime the cache with n objects.
Expand All @@ -29,82 +29,56 @@ export function createPool(name, opts) {
cache,

get() {
var obj = null;
var freeLength = cache.free.length;
var minusOne = freeLength - 1;

if (freeLength) {
obj = cache.free[minusOne];
cache.free.length = minusOne;
}
else {
obj = fill();
}

cache.allocated.push(obj);

return obj;
var value = cache.free.pop() || fill();
cache.allocated.add(value);
return value;
},

protect(value) {
let idx = cache.allocated.indexOf(value);

// Move the value out of allocated, since we need to protect this from
// being free'd accidentally.
if (cache.protected.indexOf(value) === -1) {
cache.protected.push(
idx === -1 ? value : cache.allocated.splice(idx, 1)[0]
);
}
cache.allocated.delete(value);
cache.protected.add(value);

// If we're protecting an element object, push the uuid into a lookup
// table.
if (name === 'elementObject') {
cache.uuid[value.uuid] = value;
cache.uuid.add(value.uuid);
}
},

unprotect(value) {
let idx = cache.protected.indexOf(value);

if (idx !== -1) {
let obj = cache.protected.splice(idx, 1)[0];

if (obj) {
cache.free.push(obj);
}
if (cache.protected.has(value)) {
cache.protected.delete(value);
cache.free.push(value);
}

if (name === 'elementObject') {
delete cache.uuid[value.uuid];
}
if (name === 'elementObject') {
cache.uuid.delete(value.uuid);
}
},

freeAll() {
let freeLength = cache.free.length;
let minusOne = freeLength - 1;
let reAlloc = cache.allocated.slice(0, size - minusOne);
// All of this could go away if we could figure out `Array.from` within
// a PhantomJS web-worker.
cache.allocated.forEach(value => {
cache.free.push(value);

cache.free.push.apply(cache.free, reAlloc);
cache.allocated.length = 0;
if (name === 'elementObject') {
cache.uuid.delete(value.uuid);
}
});

if (name === 'elementObject') {
reAlloc.forEach(element => delete cache.uuid[element.uuid]);
}
cache.allocated.clear();
cache.free.length = size;
},

free(value) {
let idx = cache.allocated.indexOf(value);

// Already freed.
if (idx === -1) { return; }
if (!cache.allocated.has(value)) { return; }

// Only put back into the free queue if we're under the size.
if (cache.free.length < size) {
cache.free.push(value);
}

cache.allocated.splice(idx, 1);
cache.allocated.delete(value);
}
};
}
Expand Down
4 changes: 2 additions & 2 deletions test/integration/memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ describe('Integration: Memory management', function() {

it('can allocate/deallocate uuids', function() {
diff.innerHTML(this.fixture, '<p></p>');
assert.equal(Object.keys(pools.elementObject.cache.uuid).length, 2);
assert.equal(pools.elementObject.cache.uuid.size, 2);

diff.innerHTML(this.fixture, '');
assert.equal(Object.keys(pools.elementObject.cache.uuid).length, 1);
assert.equal(pools.elementObject.cache.uuid.size, 1);
});
});
6 changes: 3 additions & 3 deletions test/util/validateMemory.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import makeNode from '../../lib/node/make';
* Validates that the memory has been successfully cleaned per render.
*/
export default function validateMemory() {
assert.equal(pools.elementObject.cache.protected.length, 0,
assert.equal(pools.elementObject.cache.protected.size, 0,
'Should not leave leftover protected elements');

assert.equal(pools.elementObject.cache.allocated.length, 0,
assert.equal(pools.elementObject.cache.allocated.size, 0,
'Should not leave leftover allocations');

assert.equal(Object.keys(pools.elementObject.cache.uuid).length, 0,
assert.equal(pools.elementObject.cache.uuid.size, 0,
'All UUIDs should be unprotected');

assert.equal(Object.keys(makeNode.nodes).length, 0,
Expand Down

0 comments on commit 7c2d7f3

Please sign in to comment.