mirror of
https://github.com/less/less.js.git
synced 2026-05-01 03:00:22 -04:00
Add visitor.js array-based function cache for faster lookups. perf / #1615
This commit is contained in:
@@ -1,7 +1,39 @@
|
||||
(function (tree) {
|
||||
|
||||
var _visitArgs = { visitDeeper: true },
|
||||
_hasIndexed = false;
|
||||
|
||||
function _noop(node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
function indexNodeTypes(parent, ticker) {
|
||||
// add .typeIndex to tree node types for lookup table
|
||||
var key, child;
|
||||
for (key in parent) {
|
||||
child = parent[key];
|
||||
switch (typeof child) {
|
||||
case "function":
|
||||
if (child.prototype.type) {
|
||||
child.prototype.typeIndex = ticker++;
|
||||
}
|
||||
break;
|
||||
case "object":
|
||||
ticker = indexNodeTypes(child, ticker);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ticker;
|
||||
}
|
||||
|
||||
tree.visitor = function(implementation) {
|
||||
this._implementation = implementation;
|
||||
this._visitFnCache = [];
|
||||
|
||||
if (!_hasIndexed) {
|
||||
indexNodeTypes(tree, 1);
|
||||
_hasIndexed = true;
|
||||
}
|
||||
};
|
||||
|
||||
tree.visitor.prototype = {
|
||||
@@ -11,27 +43,48 @@
|
||||
return this.visitArray(node);
|
||||
}
|
||||
|
||||
if (!node || !node.type) {
|
||||
if (!node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
var funcName = "visit" + node.type,
|
||||
func = this._implementation[funcName],
|
||||
visitArgs, newNode;
|
||||
if (func) {
|
||||
visitArgs = {visitDeeper: true};
|
||||
newNode = func.call(this._implementation, node, visitArgs);
|
||||
if (this._implementation.isReplacing) {
|
||||
var nodeTypeIndex = node.typeIndex;
|
||||
if (!nodeTypeIndex) {
|
||||
return node;
|
||||
}
|
||||
|
||||
var visitFnCache = this._visitFnCache,
|
||||
impl = this._implementation,
|
||||
aryIndx = nodeTypeIndex << 1,
|
||||
func = visitFnCache[aryIndx],
|
||||
funcOut = visitFnCache[aryIndx | 1],
|
||||
visitArgs = _visitArgs, noop = _noop,
|
||||
fnName;
|
||||
|
||||
visitArgs.visitDeeper = true;
|
||||
|
||||
if (!func) {
|
||||
fnName = "visit" + node.type;
|
||||
func = impl[fnName] || noop;
|
||||
funcOut = impl[fnName + "Out"] || noop;
|
||||
visitFnCache[aryIndx] = func;
|
||||
visitFnCache[aryIndx | 1] = funcOut;
|
||||
}
|
||||
|
||||
if (func != noop) {
|
||||
var newNode = func.call(impl, node, visitArgs);
|
||||
if (impl.isReplacing) {
|
||||
node = newNode;
|
||||
}
|
||||
}
|
||||
if ((!visitArgs || visitArgs.visitDeeper) && node && node.accept) {
|
||||
|
||||
if (visitArgs.visitDeeper && node && node.accept) {
|
||||
node.accept(this);
|
||||
}
|
||||
funcName = funcName + "Out";
|
||||
if (this._implementation[funcName]) {
|
||||
this._implementation[funcName](node);
|
||||
|
||||
if (funcOut != noop) {
|
||||
funcOut.call(impl, node);
|
||||
}
|
||||
|
||||
return node;
|
||||
},
|
||||
visitArray: function(nodes) {
|
||||
|
||||
Reference in New Issue
Block a user