diff --git a/lib/less/environment/abstract-plugin-loader.js b/lib/less/environment/abstract-plugin-loader.js index 2a51d354..09b361b7 100644 --- a/lib/less/environment/abstract-plugin-loader.js +++ b/lib/less/environment/abstract-plugin-loader.js @@ -52,8 +52,8 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, pluginOp registry = functionRegistry.create(); try { - loader = new Function("module", "require", "functions", "tree", "fileInfo", "less", contents); - pluginObj = loader(localModule, this.require, registry, this.less.tree, fileInfo, this.less); + loader = new Function("module", "require", "functions", "tree", "fileInfo", contents); + pluginObj = loader(localModule, this.require, registry, this.less.tree, fileInfo); if (!pluginObj) { pluginObj = localModule.exports; diff --git a/lib/less/functions/function-caller.js b/lib/less/functions/function-caller.js index d5358b3f..ba8a9e98 100644 --- a/lib/less/functions/function-caller.js +++ b/lib/less/functions/function-caller.js @@ -11,8 +11,8 @@ var functionCaller = function(name, context, index, currentFileInfo) { functionCaller.prototype.isValid = function() { return Boolean(this.func); }; -functionCaller.prototype.call = function(args) { +functionCaller.prototype.call = function(args) { // This code is terrible and should be replaced as per this issue... // https://github.com/less/less.js/issues/2477 if (Array.isArray(args)) { diff --git a/lib/less/tree/anonymous.js b/lib/less/tree/anonymous.js index ec4f3130..3b013cd0 100644 --- a/lib/less/tree/anonymous.js +++ b/lib/less/tree/anonymous.js @@ -2,9 +2,9 @@ var Node = require("./node"); var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, visibilityInfo) { this.value = value; - this.index = index; + this._index = index; + this._fileInfo = currentFileInfo; this.mapLines = mapLines; - this.currentFileInfo = currentFileInfo; this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike; this.allowRoot = true; this.copyVisibilityInfo(visibilityInfo); @@ -12,7 +12,7 @@ var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, Anonymous.prototype = new Node(); Anonymous.prototype.type = "Anonymous"; Anonymous.prototype.eval = function () { - return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo()); + return new Anonymous(this.value, this._index, this._fileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo()); }; Anonymous.prototype.compare = function (other) { return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined; @@ -21,6 +21,6 @@ Anonymous.prototype.isRulesetLike = function() { return this.rulesetLike; }; Anonymous.prototype.genCSS = function (context, output) { - output.add(this.value, this.currentFileInfo, this.index, this.mapLines); + output.add(this.value, this._fileInfo, this._index, this.mapLines); }; module.exports = Anonymous; diff --git a/lib/less/tree/atrule.js b/lib/less/tree/atrule.js index 4a512d4e..178ce8de 100644 --- a/lib/less/tree/atrule.js +++ b/lib/less/tree/atrule.js @@ -12,14 +12,15 @@ var AtRule = function (name, value, rules, index, currentFileInfo, debugInfo, is this.rules = rules; } else { this.rules = [rules]; - this.rules[0].selectors = (new Selector([], null, null, this.index, currentFileInfo)).createEmptySelectors(); + this.rules[0].selectors = (new Selector([], null, null, index, currentFileInfo)).createEmptySelectors(); } for (i = 0; i < this.rules.length; i++) { this.rules[i].allowImports = true; } + this.setParent(this.rules, this); } - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; this.debugInfo = debugInfo; this.isRooted = isRooted || false; this.copyVisibilityInfo(visibilityInfo); @@ -45,7 +46,7 @@ AtRule.prototype.isCharset = function() { }; AtRule.prototype.genCSS = function (context, output) { var value = this.value, rules = this.rules; - output.add(this.name, this.currentFileInfo, this.index); + output.add(this.name, this.fileInfo(), this.getIndex()); if (value) { output.add(' '); value.genCSS(context, output); @@ -80,7 +81,7 @@ AtRule.prototype.eval = function (context) { context.mediaBlocks = mediaBlocksBackup; return new AtRule(this.name, value, rules, - this.index, this.currentFileInfo, this.debugInfo, this.isRooted, this.visibilityInfo()); + this.getIndex(), this.fileInfo(), this.debugInfo, this.isRooted, this.visibilityInfo()); }; AtRule.prototype.variable = function (name) { if (this.rules) { diff --git a/lib/less/tree/call.js b/lib/less/tree/call.js index d95c9496..f6604e24 100644 --- a/lib/less/tree/call.js +++ b/lib/less/tree/call.js @@ -6,8 +6,8 @@ var Node = require("./node"), var Call = function (name, args, index, currentFileInfo) { this.name = name; this.args = args; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; }; Call.prototype = new Node(); Call.prototype.type = "Call"; @@ -29,8 +29,8 @@ Call.prototype.accept = function (visitor) { // Call.prototype.eval = function (context) { var args = this.args.map(function (a) { return a.eval(context); }), - result, funcCaller = new FunctionCaller(this.name, context, this.index, this.currentFileInfo); - + result, funcCaller = new FunctionCaller(this.name, context, this.getIndex(), this.fileInfo()); + if (funcCaller.isValid()) { try { result = funcCaller.call(args); @@ -39,24 +39,24 @@ Call.prototype.eval = function (context) { type: e.type || "Runtime", message: "error evaluating function `" + this.name + "`" + (e.message ? ': ' + e.message : ''), - index: this.index, - filename: this.currentFileInfo.filename, + index: this.getIndex(), + filename: this.fileInfo().filename, line: e.lineNumber, column: e.columnNumber }; } if (result != null) { - result.index = this.index; - result.currentFileInfo = this.currentFileInfo; + result._index = this._index; + result._fileInfo = this._fileInfo; return result; } } - return new Call(this.name, args, this.index, this.currentFileInfo); + return new Call(this.name, args, this.getIndex(), this.fileInfo()); }; Call.prototype.genCSS = function (context, output) { - output.add(this.name + "(", this.currentFileInfo, this.index); + output.add(this.name + "(", this.fileInfo(), this.getIndex()); for (var i = 0; i < this.args.length; i++) { this.args[i].genCSS(context, output); diff --git a/lib/less/tree/color.js b/lib/less/tree/color.js index a694d5ff..4218b950 100644 --- a/lib/less/tree/color.js +++ b/lib/less/tree/color.js @@ -99,7 +99,7 @@ Color.prototype.toCSS = function (context, doNotCompress) { // we create a new Color node to hold the result. // Color.prototype.operate = function (context, op, other) { - var rgb = []; + var rgb = new Array(3); var alpha = this.alpha * (1 - other.alpha) + other.alpha; for (var c = 0; c < 3; c++) { rgb[c] = this._operate(context, op, this.rgb[c], other.rgb[c]); diff --git a/lib/less/tree/comment.js b/lib/less/tree/comment.js index b08c422a..a3cbfdca 100644 --- a/lib/less/tree/comment.js +++ b/lib/less/tree/comment.js @@ -4,15 +4,15 @@ var Node = require("./node"), var Comment = function (value, isLineComment, index, currentFileInfo) { this.value = value; this.isLineComment = isLineComment; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; this.allowRoot = true; }; Comment.prototype = new Node(); Comment.prototype.type = "Comment"; Comment.prototype.genCSS = function (context, output) { if (this.debugInfo) { - output.add(getDebugInfo(context, this), this.currentFileInfo, this.index); + output.add(getDebugInfo(context, this), this.fileInfo(), this.getIndex()); } output.add(this.value); }; diff --git a/lib/less/tree/condition.js b/lib/less/tree/condition.js index 6b2b5365..4c893089 100644 --- a/lib/less/tree/condition.js +++ b/lib/less/tree/condition.js @@ -4,7 +4,7 @@ var Condition = function (op, l, r, i, negate) { this.op = op.trim(); this.lvalue = l; this.rvalue = r; - this.index = i; + this._index = i; this.negate = negate; }; Condition.prototype = new Node(); diff --git a/lib/less/tree/declaration.js b/lib/less/tree/declaration.js index f8f063bf..f4a4e3a8 100644 --- a/lib/less/tree/declaration.js +++ b/lib/less/tree/declaration.js @@ -7,12 +7,13 @@ var Declaration = function (name, value, important, merge, index, currentFileInf this.value = (value instanceof Node) ? value : new Value([value]); //value instanceof tree.Value || value instanceof tree.Ruleset ?? this.important = important ? ' ' + important.trim() : ''; this.merge = merge; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; this.inline = inline || false; this.variable = (variable !== undefined) ? variable : (name.charAt && (name.charAt(0) === '@')); this.allowRoot = true; + this.setParent(this.value, this); }; function evalName(context, name) { @@ -27,16 +28,16 @@ function evalName(context, name) { Declaration.prototype = new Node(); Declaration.prototype.type = "Declaration"; Declaration.prototype.genCSS = function (context, output) { - output.add(this.name + (context.compress ? ':' : ': '), this.currentFileInfo, this.index); + output.add(this.name + (context.compress ? ':' : ': '), this.fileInfo(), this.getIndex()); try { this.value.genCSS(context, output); } catch(e) { - e.index = this.index; - e.filename = this.currentFileInfo.filename; + e.index = this._index; + e.filename = this._fileInfo.filename; throw e; } - output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? "" : ";"), this.currentFileInfo, this.index); + output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? "" : ";"), this._fileInfo, this._index); }; Declaration.prototype.eval = function (context) { var strictMathBypass = false, name = this.name, evaldValue, variable = this.variable; @@ -57,7 +58,7 @@ Declaration.prototype.eval = function (context) { if (!this.variable && evaldValue.type === "DetachedRuleset") { throw { message: "Rulesets cannot be evaluated on a property.", - index: this.index, filename: this.currentFileInfo.filename }; + index: this.getIndex(), filename: this.fileInfo().filename }; } var important = this.important, importantResult = context.importantScope.pop(); @@ -69,13 +70,13 @@ Declaration.prototype.eval = function (context) { evaldValue, important, this.merge, - this.index, this.currentFileInfo, this.inline, + this.getIndex(), this.fileInfo(), this.inline, variable); } catch(e) { if (typeof e.index !== 'number') { - e.index = this.index; - e.filename = this.currentFileInfo.filename; + e.index = this.getIndex(); + e.filename = this.fileInfo().filename; } throw e; } @@ -90,7 +91,7 @@ Declaration.prototype.makeImportant = function () { this.value, "!important", this.merge, - this.index, this.currentFileInfo, this.inline); + this.getIndex(), this.fileInfo(), this.inline); }; module.exports = Declaration; \ No newline at end of file diff --git a/lib/less/tree/detached-ruleset.js b/lib/less/tree/detached-ruleset.js index 01bbbc75..2805809f 100644 --- a/lib/less/tree/detached-ruleset.js +++ b/lib/less/tree/detached-ruleset.js @@ -1,9 +1,11 @@ var Node = require("./node"), - contexts = require("../contexts"); + contexts = require("../contexts"), + utils = require("../utils"); var DetachedRuleset = function (ruleset, frames) { this.ruleset = ruleset; this.frames = frames; + this.setParent(this.ruleset, this); }; DetachedRuleset.prototype = new Node(); DetachedRuleset.prototype.type = "DetachedRuleset"; @@ -12,7 +14,7 @@ DetachedRuleset.prototype.accept = function (visitor) { this.ruleset = visitor.visit(this.ruleset); }; DetachedRuleset.prototype.eval = function (context) { - var frames = this.frames || context.frames.slice(0); + var frames = this.frames || utils.copyArray(context.frames); return new DetachedRuleset(this.ruleset, frames); }; DetachedRuleset.prototype.callEval = function (context) { diff --git a/lib/less/tree/dimension.js b/lib/less/tree/dimension.js index e3ce27ef..db979a93 100644 --- a/lib/less/tree/dimension.js +++ b/lib/less/tree/dimension.js @@ -10,6 +10,7 @@ var Dimension = function (value, unit) { this.value = parseFloat(value); this.unit = (unit && unit instanceof Unit) ? unit : new Unit(unit ? [unit] : undefined); + this.setParent(this.unit, this); }; Dimension.prototype = new Node(); diff --git a/lib/less/tree/element.js b/lib/less/tree/element.js index 4daf5295..c759f97f 100644 --- a/lib/less/tree/element.js +++ b/lib/less/tree/element.js @@ -2,7 +2,7 @@ var Node = require("./node"), Paren = require("./paren"), Combinator = require("./combinator"); -var Element = function (combinator, value, index, currentFileInfo, info) { +var Element = function (combinator, value, index, currentFileInfo, visibilityInfo) { this.combinator = combinator instanceof Combinator ? combinator : new Combinator(combinator); @@ -13,9 +13,10 @@ var Element = function (combinator, value, index, currentFileInfo, info) { } else { this.value = ""; } - this.index = index; - this.currentFileInfo = currentFileInfo; - this.copyVisibilityInfo(info); + this._index = index; + this._fileInfo = currentFileInfo; + this.copyVisibilityInfo(visibilityInfo); + this.setParent(this.combinator, this); }; Element.prototype = new Node(); Element.prototype.type = "Element"; @@ -29,17 +30,17 @@ Element.prototype.accept = function (visitor) { Element.prototype.eval = function (context) { return new Element(this.combinator, this.value.eval ? this.value.eval(context) : this.value, - this.index, - this.currentFileInfo, this.visibilityInfo()); + this.getIndex(), + this.fileInfo(), this.visibilityInfo()); }; Element.prototype.clone = function () { return new Element(this.combinator, this.value, - this.index, - this.currentFileInfo, this.visibilityInfo()); + this.getIndex(), + this.fileInfo(), this.visibilityInfo()); }; Element.prototype.genCSS = function (context, output) { - output.add(this.toCSS(context), this.currentFileInfo, this.index); + output.add(this.toCSS(context), this.fileInfo(), this.getIndex()); }; Element.prototype.toCSS = function (context) { context = context || {}; diff --git a/lib/less/tree/extend.js b/lib/less/tree/extend.js index e91fbf77..b3e8d49c 100644 --- a/lib/less/tree/extend.js +++ b/lib/less/tree/extend.js @@ -4,10 +4,10 @@ var Node = require("./node"), var Extend = function Extend(selector, option, index, currentFileInfo, visibilityInfo) { this.selector = selector; this.option = option; - this.index = index; this.object_id = Extend.next_id++; this.parent_ids = [this.object_id]; - this.currentFileInfo = currentFileInfo || {}; + this._index = index; + this._fileInfo = currentFileInfo; this.copyVisibilityInfo(visibilityInfo); this.allowRoot = true; @@ -21,6 +21,7 @@ var Extend = function Extend(selector, option, index, currentFileInfo, visibilit this.allowAfter = false; break; } + this.setParent(this.selector, this); }; Extend.next_id = 0; @@ -30,10 +31,10 @@ Extend.prototype.accept = function (visitor) { this.selector = visitor.visit(this.selector); }; Extend.prototype.eval = function (context) { - return new Extend(this.selector.eval(context), this.option, this.index, this.currentFileInfo, this.visibilityInfo()); + return new Extend(this.selector.eval(context), this.option, this.getIndex(), this.fileInfo(), this.visibilityInfo()); }; Extend.prototype.clone = function (context) { - return new Extend(this.selector, this.option, this.index, this.currentFileInfo, this.visibilityInfo()); + return new Extend(this.selector, this.option, this.getIndex(), this.fileInfo(), this.visibilityInfo()); }; //it concatenates (joins) all selectors in selector array Extend.prototype.findSelfSelectors = function (selectors) { diff --git a/lib/less/tree/import.js b/lib/less/tree/import.js index ef9636a9..03c122b0 100644 --- a/lib/less/tree/import.js +++ b/lib/less/tree/import.js @@ -3,7 +3,8 @@ var Node = require("./node"), URL = require("./url"), Quoted = require("./quoted"), Ruleset = require("./ruleset"), - Anonymous = require("./anonymous"); + Anonymous = require("./anonymous"), + utils = require("../utils"); // // CSS @import node @@ -19,10 +20,10 @@ var Node = require("./node"), // var Import = function (path, features, options, index, currentFileInfo, visibilityInfo) { this.options = options; - this.index = index; + this._index = index; + this._fileInfo = currentFileInfo; this.path = path; this.features = features; - this.currentFileInfo = currentFileInfo; this.allowRoot = true; if (this.options.less !== undefined || this.options.inline) { @@ -34,6 +35,8 @@ var Import = function (path, features, options, index, currentFileInfo, visibili } } this.copyVisibilityInfo(visibilityInfo); + this.setParent(this.features, this); + this.setParent(this.path, this); }; // @@ -57,8 +60,8 @@ Import.prototype.accept = function (visitor) { } }; Import.prototype.genCSS = function (context, output) { - if (this.css && this.path.currentFileInfo.reference === undefined) { - output.add("@import ", this.currentFileInfo, this.index); + if (this.css && this.path._fileInfo.reference === undefined) { + output.add("@import ", this._fileInfo, this._index); this.path.genCSS(context, output); if (this.features) { output.add(" "); @@ -89,11 +92,11 @@ Import.prototype.evalForImport = function (context) { path = path.value; } - return new Import(path.eval(context), this.features, this.options, this.index, this.currentFileInfo, this.visibilityInfo()); + return new Import(path.eval(context), this.features, this.options, this._index, this._fileInfo, this.visibilityInfo()); }; Import.prototype.evalPath = function (context) { var path = this.path.eval(context); - var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + var rootpath = this._fileInfo && this._fileInfo.rootpath; if (!(path instanceof URL)) { if (rootpath) { @@ -149,18 +152,18 @@ Import.prototype.doEval = function (context) { var contents = new Anonymous(this.root, 0, { filename: this.importedFilename, - reference: this.path.currentFileInfo && this.path.currentFileInfo.reference + reference: this.path._fileInfo && this.path._fileInfo.reference }, true, true); return this.features ? new Media([contents], this.features.value) : [contents]; } else if (this.css) { - var newImport = new Import(this.evalPath(context), features, this.options, this.index); + var newImport = new Import(this.evalPath(context), features, this.options, this._index); if (!newImport.css && this.error) { throw this.error; } return newImport; } else { - ruleset = new Ruleset(null, this.root.rules.slice(0)); + ruleset = new Ruleset(null, utils.copyArray(this.root.rules)); ruleset.evalImports(context); return this.features ? new Media(ruleset.rules, this.features.value) : ruleset.rules; diff --git a/lib/less/tree/javascript.js b/lib/less/tree/javascript.js index 15773827..e2ee0137 100644 --- a/lib/less/tree/javascript.js +++ b/lib/less/tree/javascript.js @@ -6,8 +6,8 @@ var JsEvalNode = require("./js-eval-node"), var JavaScript = function (string, escaped, index, currentFileInfo) { this.escaped = escaped; this.expression = string; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; }; JavaScript.prototype = new JsEvalNode(); JavaScript.prototype.type = "JavaScript"; @@ -17,7 +17,7 @@ JavaScript.prototype.eval = function(context) { if (typeof result === 'number') { return new Dimension(result); } else if (typeof result === 'string') { - return new Quoted('"' + result + '"', result, this.escaped, this.index); + return new Quoted('"' + result + '"', result, this.escaped, this._index); } else if (Array.isArray(result)) { return new Anonymous(result.join(', ')); } else { diff --git a/lib/less/tree/js-eval-node.js b/lib/less/tree/js-eval-node.js index a4410b23..b5e37bbe 100644 --- a/lib/less/tree/js-eval-node.js +++ b/lib/less/tree/js-eval-node.js @@ -12,20 +12,20 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { if (!context.javascriptEnabled) { throw { message: "Inline JavaScript is not enabled. Is it set in your options?", - filename: this.currentFileInfo.filename, - index: this.index }; + filename: this.fileInfo().filename, + index: this.getIndex() }; } expression = expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return that.jsify(new Variable('@' + name, that.index, that.currentFileInfo).eval(context)); + return that.jsify(new Variable('@' + name, that.getIndex(), that.fileInfo()).eval(context)); }); try { expression = new Function('return (' + expression + ')'); } catch (e) { throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" , - filename: this.currentFileInfo.filename, - index: this.index }; + filename: this.fileInfo().filename, + index: this.getIndex() }; } var variables = context.frames[0].variables(); @@ -45,8 +45,8 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { result = expression.call(evalContext); } catch (e) { throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" , - filename: this.currentFileInfo.filename, - index: this.index }; + filename: this.fileInfo().filename, + index: this.getIndex() }; } return result; }; diff --git a/lib/less/tree/media.js b/lib/less/tree/media.js index bfba0e36..0ef4db2c 100644 --- a/lib/less/tree/media.js +++ b/lib/less/tree/media.js @@ -3,19 +3,23 @@ var Ruleset = require("./ruleset"), Selector = require("./selector"), Anonymous = require("./anonymous"), Expression = require("./expression"), - AtRule = require("./atrule"); + AtRule = require("./atrule"), + utils = require("../utils"); var Media = function (value, features, index, currentFileInfo, visibilityInfo) { - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; - var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors(); + var selectors = (new Selector([], null, null, this._index, this._fileInfo)).createEmptySelectors(); this.features = new Value(features); this.rules = [new Ruleset(selectors, value)]; this.rules[0].allowImports = true; this.copyVisibilityInfo(visibilityInfo); this.allowRoot = true; + this.setParent(selectors, this); + this.setParent(this.features, this); + this.setParent(this.rules, this); }; Media.prototype = new AtRule(); Media.prototype.type = "Media"; @@ -29,7 +33,7 @@ Media.prototype.accept = function (visitor) { } }; Media.prototype.genCSS = function (context, output) { - output.add('@media ', this.currentFileInfo, this.index); + output.add('@media ', this._fileInfo, this._index); this.features.genCSS(context, output); this.outputRuleset(context, output, this.rules); }; @@ -39,7 +43,7 @@ Media.prototype.eval = function (context) { context.mediaPath = []; } - var media = new Media(null, [], this.index, this.currentFileInfo, this.visibilityInfo()); + var media = new Media(null, [], this._index, this._fileInfo, this.visibilityInfo()); if (this.debugInfo) { this.rules[0].debugInfo = this.debugInfo; media.debugInfo = this.debugInfo; @@ -76,10 +80,11 @@ Media.prototype.evalTop = function (context) { // Render all dependent Media blocks. if (context.mediaBlocks.length > 1) { - var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors(); + var selectors = (new Selector([], null, null, this.getIndex(), this.fileInfo())).createEmptySelectors(); result = new Ruleset(selectors, context.mediaBlocks); result.multiMedia = true; result.copyVisibilityInfo(this.visibilityInfo()); + this.setParent(result, this); } delete context.mediaBlocks; @@ -116,6 +121,7 @@ Media.prototype.evalNested = function (context) { return new Expression(path); })); + this.setParent(this.features, this); // Fake a tree-node that doesn't output anything. return new Ruleset([], []); @@ -140,6 +146,7 @@ Media.prototype.bubbleSelectors = function (selectors) { if (!selectors) { return; } - this.rules = [new Ruleset(selectors.slice(0), [this.rules[0]])]; + this.rules = [new Ruleset(utils.copyArray(selectors), [this.rules[0]])]; + this.setParent(this.rules, this); }; module.exports = Media; diff --git a/lib/less/tree/mixin-call.js b/lib/less/tree/mixin-call.js index 5864a0c3..7b1d0c0b 100644 --- a/lib/less/tree/mixin-call.js +++ b/lib/less/tree/mixin-call.js @@ -6,10 +6,11 @@ var Node = require("./node"), var MixinCall = function (elements, args, index, currentFileInfo, important) { this.selector = new Selector(elements); this.arguments = args || []; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; this.important = important; this.allowRoot = true; + this.setParent(this.selector, this); }; MixinCall.prototype = new Node(); MixinCall.prototype.type = "MixinCall"; @@ -117,7 +118,7 @@ MixinCall.prototype.eval = function (context) { if ((count[defTrue] + count[defFalse]) > 1) { throw { type: 'Runtime', message: 'Ambiguous use of `default()` found when matching for `' + this.format(args) + '`', - index: this.index, filename: this.currentFileInfo.filename }; + index: this.getIndex(), filename: this.fileInfo().filename }; } } @@ -135,7 +136,7 @@ MixinCall.prototype.eval = function (context) { this._setVisibilityToReplacement(newRules); Array.prototype.push.apply(rules, newRules); } catch (e) { - throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + throw { message: e.message, index: this.getIndex(), filename: this.fileInfo().filename, stack: e.stack }; } } } @@ -148,11 +149,11 @@ MixinCall.prototype.eval = function (context) { if (isOneFound) { throw { type: 'Runtime', message: 'No matching definition was found for `' + this.format(args) + '`', - index: this.index, filename: this.currentFileInfo.filename }; + index: this.getIndex(), filename: this.fileInfo().filename }; } else { throw { type: 'Name', message: this.selector.toCSS().trim() + " is undefined", - index: this.index, filename: this.currentFileInfo.filename }; + index: this.getIndex(), filename: this.fileInfo().filename }; } }; diff --git a/lib/less/tree/mixin-definition.js b/lib/less/tree/mixin-definition.js index d2c366c0..3437cec6 100644 --- a/lib/less/tree/mixin-definition.js +++ b/lib/less/tree/mixin-definition.js @@ -3,11 +3,12 @@ var Selector = require("./selector"), Ruleset = require("./ruleset"), Declaration = require("./declaration"), Expression = require("./expression"), - contexts = require("../contexts"); + contexts = require("../contexts"), + utils = require("../utils"); var Definition = function (name, params, rules, condition, variadic, frames, visibilityInfo) { this.name = name; - this.selectors = [new Selector([new Element(null, name, this.index, this.currentFileInfo)])]; + this.selectors = [new Selector([new Element(null, name, this._index, this._fileInfo)])]; this.params = params; this.condition = condition; this.variadic = variadic; @@ -45,7 +46,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume /*jshint boss:true */ var frame = new Ruleset(null, null), varargs, arg, - params = this.params.slice(0), + params = utils.copyArray(this.params), i, j, val, name, isNamedFound, argIndex, argsLength = 0; if (mixinEnv.frames && mixinEnv.frames[0] && mixinEnv.frames[0].functionRegistry) { @@ -54,7 +55,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume mixinEnv = new contexts.Eval(mixinEnv, [frame].concat(mixinEnv.frames)); if (args) { - args = args.slice(0); + args = utils.copyArray(args); argsLength = args.length; for (i = 0; i < argsLength; i++) { @@ -132,7 +133,7 @@ Definition.prototype.makeImportant = function() { return result; }; Definition.prototype.eval = function (context) { - return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || context.frames.slice(0)); + return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || utils.copyArray(context.frames)); }; Definition.prototype.evalCall = function (context, args, important) { var _arguments = [], @@ -142,7 +143,7 @@ Definition.prototype.evalCall = function (context, args, important) { frame.prependRule(new Declaration('@arguments', new Expression(_arguments).eval(context))); - rules = this.rules.slice(0); + rules = utils.copyArray(this.rules); ruleset = new Ruleset(null, rules); ruleset.originalRuleset = this; diff --git a/lib/less/tree/node.js b/lib/less/tree/node.js index 50e122a2..2b89ea25 100644 --- a/lib/less/tree/node.js +++ b/lib/less/tree/node.js @@ -1,4 +1,35 @@ var Node = function() { + this.parent = null; + this.visibilityBlocks = undefined; + this.nodeVisible = undefined; + + var self = this; + Object.defineProperty(this, "currentFileInfo", { + get: function() { return self.fileInfo(); } + }); + Object.defineProperty(this, "index", { + get: function() { return self.getIndex(); } + }); + +}; +Node.prototype.setParent = function(nodes, parent) { + function set(node) { + if (node && node instanceof Node) { + node.parent = parent; + } + } + if (Array.isArray(nodes)) { + nodes.forEach(set); + } + else { + set(nodes); + } +}; +Node.prototype.getIndex = function() { + return this._index || (this.parent && this.parent.getIndex()) || 0; +}; +Node.prototype.fileInfo = function() { + return this._fileInfo || (this.parent && this.parent.fileInfo()) || {}; }; Node.prototype.toCSS = function (context) { var strs = []; diff --git a/lib/less/tree/quoted.js b/lib/less/tree/quoted.js index e1be87d1..07d5d1bd 100644 --- a/lib/less/tree/quoted.js +++ b/lib/less/tree/quoted.js @@ -6,14 +6,14 @@ var Quoted = function (str, content, escaped, index, currentFileInfo) { this.escaped = (escaped == null) ? true : escaped; this.value = content || ''; this.quote = str.charAt(0); - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; }; Quoted.prototype = new JsEvalNode(); Quoted.prototype.type = "Quoted"; Quoted.prototype.genCSS = function (context, output) { if (!this.escaped) { - output.add(this.quote, this.currentFileInfo, this.index); + output.add(this.quote, this.fileInfo(), this.getIndex()); } output.add(this.value); if (!this.escaped) { @@ -29,7 +29,7 @@ Quoted.prototype.eval = function (context) { return String(that.evaluateJavaScript(exp, context)); }; var interpolationReplacement = function (_, name) { - var v = new Variable('@' + name, that.index, that.currentFileInfo).eval(context, true); + var v = new Variable('@' + name, that.getIndex(), that.fileInfo()).eval(context, true); return (v instanceof Quoted) ? v.value : v.toCSS(); }; function iterativeReplace(value, regexp, replacementFnc) { @@ -42,7 +42,7 @@ Quoted.prototype.eval = function (context) { } value = iterativeReplace(value, /`([^`]+)`/g, javascriptReplacement); value = iterativeReplace(value, /@\{([\w-]+)\}/g, interpolationReplacement); - return new Quoted(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo); + return new Quoted(this.quote + value + this.quote, value, this.escaped, this.getIndex(), this.fileInfo()); }; Quoted.prototype.compare = function (other) { // when comparing quoted strings allow the quote to differ diff --git a/lib/less/tree/ruleset.js b/lib/less/tree/ruleset.js index 08dc53b5..dc8a530b 100644 --- a/lib/less/tree/ruleset.js +++ b/lib/less/tree/ruleset.js @@ -6,7 +6,8 @@ var Node = require("./node"), contexts = require("../contexts"), globalFunctionRegistry = require("../functions/function-registry"), defaultFunc = require("../functions/default"), - getDebugInfo = require("./debug-info"); + getDebugInfo = require("./debug-info"), + utils = require("../utils"); var Ruleset = function (selectors, rules, strictImports, visibilityInfo) { this.selectors = selectors; @@ -15,6 +16,11 @@ var Ruleset = function (selectors, rules, strictImports, visibilityInfo) { this.strictImports = strictImports; this.copyVisibilityInfo(visibilityInfo); this.allowRoot = true; + this.setParent(this.selectors, this); + this.setParent(this.rules, this); + + this.types = Object.create(null); + }; Ruleset.prototype = new Node(); Ruleset.prototype.type = "Ruleset"; @@ -35,14 +41,14 @@ Ruleset.prototype.eval = function (context) { selCnt, selector, i, hasOnePassingSelector = false; if (thisSelectors && (selCnt = thisSelectors.length)) { - selectors = []; + selectors = new Array(selCnt); defaultFunc.error({ type: "Syntax", message: "it is currently only allowed in parametric mixin guards," }); for (i = 0; i < selCnt; i++) { selector = thisSelectors[i].eval(context); - selectors.push(selector); + selectors[i] = selector; if (selector.evaldCondition) { hasOnePassingSelector = true; } @@ -52,7 +58,7 @@ Ruleset.prototype.eval = function (context) { hasOnePassingSelector = true; } - var rules = this.rules ? this.rules.slice(0) : null, + var rules = this.rules ? utils.copyArray(this.rules) : null, ruleset = new Ruleset(selectors, rules, this.strictImports, this.visibilityInfo()), rule, subRule; @@ -281,6 +287,7 @@ Ruleset.prototype.prependRule = function (rule) { } else { this.rules = [ rule ]; } + this.setParent(rule, this); }; Ruleset.prototype.find = function (selector, self, filter) { self = self || this; @@ -453,9 +460,9 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { if (elementsToPak.length === 0) { replacementParen = new Paren(elementsToPak[0]); } else { - var insideParent = []; + var insideParent = new Array(elementsToPak.length); for (j = 0; j < elementsToPak.length; j++) { - insideParent.push(new Element(null, elementsToPak[j], originalElement.index, originalElement.currentFileInfo)); + insideParent[j] = new Element(null, elementsToPak[j], originalElement._index, originalElement._fileInfo); } replacementParen = new Paren(new Selector(insideParent)); } @@ -464,7 +471,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { function createSelector(containedElement, originalElement) { var element, selector; - element = new Element(null, containedElement, originalElement.index, originalElement.currentFileInfo); + element = new Element(null, containedElement, originalElement._index, originalElement._fileInfo); selector = new Selector([element]); return selector; } @@ -480,9 +487,9 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { //construct the joined selector - if & is the first thing this will be empty, // if not newJoinedSelector will be the last set of elements in the selector if (beginningPath.length > 0) { - newSelectorPath = beginningPath.slice(0); + newSelectorPath = utils.copyArray(beginningPath); lastSelector = newSelectorPath.pop(); - newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0)); + newJoinedSelector = originalSelector.createDerived(utils.copyArray(lastSelector.elements)); } else { newJoinedSelector = originalSelector.createDerived([]); @@ -498,7 +505,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { combinator = parentEl.combinator; } // join the elements so far with the first part of the parent - newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo)); + newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement._index, replacedElement._fileInfo)); newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1)); } @@ -635,7 +642,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { // the combinator used on el should now be applied to the next element instead so that // it is not lost if (sel.length > 0) { - sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo)); + sel[0].elements.push(new Element(el.combinator, '', el._index, el._fileInfo)); } selectorsMultiplied.push(sel); } @@ -667,7 +674,6 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { paths.push(newSelectors[i]); lastSelector = newSelectors[i][length - 1]; newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList); - //newSelectors[i][length - 1].copyVisibilityInfo(inSelector.visibilityInfo()); } } @@ -690,12 +696,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { if (context.length > 0) { newPaths = []; for (i = 0; i < context.length; i++) { - //var concatenated = []; - //context[i].forEach(function(entry) { - // var newEntry = entry.createDerived(entry.elements, entry.extendList, entry.evaldCondition); - // newEntry.copyVisibilityInfo(selector.visibilityInfo()); - // concatenated.push(newEntry); - //}, this); + var concatenated = context[i].map(deriveSelector.bind(this, selector.visibilityInfo())); concatenated.push(selector); diff --git a/lib/less/tree/selector.js b/lib/less/tree/selector.js index cb5beee1..20bd9401 100644 --- a/lib/less/tree/selector.js +++ b/lib/less/tree/selector.js @@ -5,11 +5,13 @@ var Selector = function (elements, extendList, condition, index, currentFileInfo this.elements = elements; this.extendList = extendList; this.condition = condition; - this.currentFileInfo = currentFileInfo || {}; + this._index = index; + this._fileInfo = currentFileInfo; if (!condition) { this.evaldCondition = true; } this.copyVisibilityInfo(visibilityInfo); + this.setParent(this.elements, this); }; Selector.prototype = new Node(); Selector.prototype.type = "Selector"; @@ -27,14 +29,14 @@ Selector.prototype.accept = function (visitor) { Selector.prototype.createDerived = function(elements, extendList, evaldCondition) { var info = this.visibilityInfo(); evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition; - var newSelector = new Selector(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, info); + var newSelector = new Selector(elements, extendList || this.extendList, null, this.getIndex(), this.fileInfo(), info); newSelector.evaldCondition = evaldCondition; newSelector.mediaEmpty = this.mediaEmpty; return newSelector; }; Selector.prototype.createEmptySelectors = function() { - var el = new Element('', '&', this.index, this.currentFileInfo), - sels = [new Selector([el], null, null, this.index, this.currentFileInfo)]; + var el = new Element('', '&', this._index, this._fileInfo), + sels = [new Selector([el], null, null, this._index, this._fileInfo)]; sels[0].mediaEmpty = true; return sels; }; @@ -95,7 +97,7 @@ Selector.prototype.eval = function (context) { Selector.prototype.genCSS = function (context, output) { var i, element; if ((!context || !context.firstSelector) && this.elements[0].combinator.value === "") { - output.add(' ', this.currentFileInfo, this.index); + output.add(' ', this.fileInfo(), this.getIndex()); } if (!this._css) { //TODO caching? speed comparison? diff --git a/lib/less/tree/unit.js b/lib/less/tree/unit.js index aa53124d..b94a795b 100644 --- a/lib/less/tree/unit.js +++ b/lib/less/tree/unit.js @@ -1,9 +1,10 @@ var Node = require("./node"), - unitConversions = require("../data/unit-conversions"); + unitConversions = require("../data/unit-conversions"), + utils = require("../utils"); var Unit = function (numerator, denominator, backupUnit) { - this.numerator = numerator ? numerator.slice(0).sort() : []; - this.denominator = denominator ? denominator.slice(0).sort() : []; + this.numerator = numerator ? utils.copyArray(numerator).sort() : []; + this.denominator = denominator ? utils.copyArray(denominator).sort() : []; if (backupUnit) { this.backupUnit = backupUnit; } else if (numerator && numerator.length) { @@ -14,7 +15,7 @@ var Unit = function (numerator, denominator, backupUnit) { Unit.prototype = new Node(); Unit.prototype.type = "Unit"; Unit.prototype.clone = function () { - return new Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + return new Unit(utils.copyArray(this.numerator), utils.copyArray(this.denominator), this.backupUnit); }; Unit.prototype.genCSS = function (context, output) { // Dimension checks the unit is singular and throws an error if in strict math mode. diff --git a/lib/less/tree/url.js b/lib/less/tree/url.js index 65347af4..fa0d4c87 100644 --- a/lib/less/tree/url.js +++ b/lib/less/tree/url.js @@ -2,8 +2,8 @@ var Node = require("./node"); var URL = function (val, index, currentFileInfo, isEvald) { this.value = val; - this.currentFileInfo = currentFileInfo; - this.index = index; + this._index = index; + this._fileInfo = currentFileInfo; this.isEvald = isEvald; }; URL.prototype = new Node(); @@ -22,7 +22,7 @@ URL.prototype.eval = function (context) { if (!this.isEvald) { // Add the base path if the URL is relative - rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + rootpath = this.fileInfo() && this.fileInfo().rootpath; if (rootpath && typeof val.value === "string" && context.isPathRelative(val.value)) { @@ -49,6 +49,6 @@ URL.prototype.eval = function (context) { } } - return new URL(val, this.index, this.currentFileInfo, true); + return new URL(val, this.getIndex(), this.fileInfo(), true); }; module.exports = URL; diff --git a/lib/less/tree/variable.js b/lib/less/tree/variable.js index 9d109192..553526e9 100644 --- a/lib/less/tree/variable.js +++ b/lib/less/tree/variable.js @@ -2,8 +2,8 @@ var Node = require("./node"); var Variable = function (name, index, currentFileInfo) { this.name = name; - this.index = index; - this.currentFileInfo = currentFileInfo || {}; + this._index = index; + this._fileInfo = currentFileInfo; }; Variable.prototype = new Node(); Variable.prototype.type = "Variable"; @@ -11,14 +11,14 @@ Variable.prototype.eval = function (context) { var variable, name = this.name; if (name.indexOf('@@') === 0) { - name = '@' + new Variable(name.slice(1), this.index, this.currentFileInfo).eval(context).value; + name = '@' + new Variable(name.slice(1), this.getIndex(), this.fileInfo()).eval(context).value; } if (this.evaluating) { throw { type: 'Name', message: "Recursive variable definition for " + name, - filename: this.currentFileInfo.filename, - index: this.index }; + filename: this.fileInfo().filename, + index: this.getIndex() }; } this.evaluating = true; @@ -39,8 +39,8 @@ Variable.prototype.eval = function (context) { } else { throw { type: 'Name', message: "variable " + name + " is undefined", - filename: this.currentFileInfo.filename, - index: this.index }; + filename: this.fileInfo().filename, + index: this.getIndex() }; } }; Variable.prototype.find = function (obj, fun) { diff --git a/lib/less/utils.js b/lib/less/utils.js index 6efdb21b..d32a7e92 100644 --- a/lib/less/utils.js +++ b/lib/less/utils.js @@ -16,5 +16,14 @@ module.exports = { line: line, column: column }; + }, + copyArray: function(arr) { + var i, length = arr.length, + copy = new Array(length); + + for (i = 0; i < length; i++) { + copy[i] = arr[i]; + } + return copy; } }; diff --git a/lib/less/visitors/extend-visitor.js b/lib/less/visitors/extend-visitor.js index 1d757ddb..37df534a 100644 --- a/lib/less/visitors/extend-visitor.js +++ b/lib/less/visitors/extend-visitor.js @@ -1,6 +1,7 @@ var tree = require("../tree"), Visitor = require("./visitor"), - logger = require("../logger"); + logger = require("../logger"), + utils = require("../utils"); /*jshint loopfunc:true */ @@ -46,7 +47,7 @@ ExtendFinderVisitor.prototype = { selector = selectorPath[selectorPath.length - 1], selExtendList = selector.extendList; - extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList) + extendList = selExtendList ? utils.copyArray(selExtendList).concat(allSelectorsExtendList) : allSelectorsExtendList; if (extendList) { @@ -166,7 +167,7 @@ ProcessExtendsVisitor.prototype = { newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector, extend.isVisible()); // but now we create a new extend from it - newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.currentFileInfo, info); + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.fileInfo(), info); newExtend.selfSelectors = newSelector; // add the extend onto the list of extends for that selector @@ -384,8 +385,8 @@ ProcessExtendsVisitor.prototype = { firstElement = new tree.Element( match.initialCombinator, replacementSelector.elements[0].value, - replacementSelector.elements[0].index, - replacementSelector.elements[0].currentFileInfo + replacementSelector.elements[0].getIndex(), + replacementSelector.elements[0].fileInfo() ); if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { diff --git a/lib/less/visitors/import-visitor.js b/lib/less/visitors/import-visitor.js index 803f89b4..7bbbc93b 100644 --- a/lib/less/visitors/import-visitor.js +++ b/lib/less/visitors/import-visitor.js @@ -1,6 +1,7 @@ var contexts = require("../contexts"), Visitor = require("./visitor"), - ImportSequencer = require("./import-sequencer"); + ImportSequencer = require("./import-sequencer"), + utils = require("../utils"); var ImportVisitor = function(importer, finish) { @@ -39,7 +40,7 @@ ImportVisitor.prototype = { if (!importNode.css || inlineCSS) { - var context = new contexts.Eval(this.context, this.context.frames.slice(0)); + var context = new contexts.Eval(this.context, utils.copyArray(this.context.frames)); var importParent = context.frames[0]; this.importCount++; @@ -58,7 +59,7 @@ ImportVisitor.prototype = { try { evaldImportNode = importNode.evalForImport(context); } catch(e) { - if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + if (!e.filename) { e.index = importNode.getIndex(); e.filename = importNode.fileInfo().filename; } // attempt to eval properly and treat as css importNode.css = true; // if that fails, this error will be thrown @@ -84,7 +85,7 @@ ImportVisitor.prototype = { var onImported = this.onImported.bind(this, evaldImportNode, context), sequencedOnImported = this._sequencer.addImport(onImported); - this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo, + this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.fileInfo(), evaldImportNode.options, sequencedOnImported); } else { this.importCount--; @@ -96,7 +97,7 @@ ImportVisitor.prototype = { onImported: function (importNode, context, e, root, importedAtRoot, fullPath) { if (e) { if (!e.filename) { - e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; + e.index = importNode.getIndex(); e.filename = importNode.fileInfo().filename; } this.error = e; } diff --git a/lib/less/visitors/to-css-visitor.js b/lib/less/visitors/to-css-visitor.js index a4eefdc9..d418f6ca 100644 --- a/lib/less/visitors/to-css-visitor.js +++ b/lib/less/visitors/to-css-visitor.js @@ -207,15 +207,15 @@ ToCSSVisitor.prototype = { var ruleNode = rules[i]; if (isRoot && ruleNode instanceof tree.Declaration && !ruleNode.variable) { throw { message: "Properties must be inside selector blocks. They cannot be in the root", - index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; + index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } if (ruleNode instanceof tree.Call) { throw { message: "Function '" + ruleNode.name + "' is undefined", - index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; + index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } if (ruleNode.type && !ruleNode.allowRoot) { throw { message: ruleNode.type + " node returned by a function is not valid here", - index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; + index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } } }, diff --git a/test/less/plugin/plugin-transitive.js b/test/less/plugin/plugin-transitive.js index 1da1864c..18d96c64 100644 --- a/test/less/plugin/plugin-transitive.js +++ b/test/less/plugin/plugin-transitive.js @@ -1,5 +1,6 @@ functions.addMultiple({ "test-transitive" : function() { - return new tree.Anonymous( "transitive" ); + var anon = new tree.Anonymous( "transitive" ); + return anon; } });