From b59017b5430e085db8bc88cd94dcac8600ea03d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Flaventin=20Hauchecorne?= Date: Tue, 14 Jun 2022 18:46:56 +0200 Subject: [PATCH 1/3] Scope nodes.filename changes --- lib/parser.js | 46 +++++++++++++++-------- lib/renderer.js | 2 - lib/visitor/evaluator.js | 79 +++++++++++++++++++++++----------------- 3 files changed, 76 insertions(+), 51 deletions(-) diff --git a/lib/parser.js b/lib/parser.js index 89e3b2654..e2cdd65e1 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -161,7 +161,15 @@ var Parser = module.exports = function Parser(str, options) { this.lexer = new Lexer(str, options); } this.prefix = options.prefix || ''; - this.root = options.root || new nodes.Root; + this.filename = options.filename || null; + var previousFilename = nodes.filename; + nodes.filename = options.filename; + try{ + this.root = options.root || new nodes.Root; + } + finally{ + nodes.filename = previousFilename; + } this.state = ['root']; this.stash = []; this.parens = 0; @@ -227,23 +235,29 @@ Parser.prototype = { */ parse: function(){ - var block = this.parent = this.root; - if (Parser.cache.has(this.hash)) { - block = Parser.cache.get(this.hash); - // normalize cached imports - if ('block' == block.nodeName) block.constructor = nodes.Root; - } else { - while ('eos' != this.peek().type) { - this.skipWhitespace(); - if ('eos' == this.peek().type) break; - var stmt = this.statement(); - this.accept(';'); - if (!stmt) this.error('unexpected token {peek}, not allowed at the root level'); - block.push(stmt); + var previousFilename = nodes.filename; + nodes.filename = this.filename; + try{ + var block = this.parent = this.root; + if (Parser.cache.has(this.hash)) { + block = Parser.cache.get(this.hash); + // normalize cached imports + if ('block' == block.nodeName) block.constructor = nodes.Root; + } else { + while ('eos' != this.peek().type) { + this.skipWhitespace(); + if ('eos' == this.peek().type) break; + var stmt = this.statement(); + this.accept(';'); + if (!stmt) this.error('unexpected token {peek}, not allowed at the root level'); + block.push(stmt); + } + Parser.cache.set(this.hash, block); } - Parser.cache.set(this.hash, block); + return block; + } finally { + nodes.filename = previousFilename; } - return block; }, /** diff --git a/lib/renderer.js b/lib/renderer.js index dd478b3fb..ec05527fb 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -75,7 +75,6 @@ Renderer.prototype.render = function(fn){ } try { - nodes.filename = this.options.filename; // parse var ast = parser.parse(); @@ -133,7 +132,6 @@ Renderer.prototype.deps = function(filename){ , parser = new Parser(this.str, opts); try { - nodes.filename = opts.filename; // parse var ast = parser.parse() , resolver = new DepsResolver(ast, opts); diff --git a/lib/visitor/evaluator.js b/lib/visitor/evaluator.js index d60ddfcad..4230b2eac 100644 --- a/lib/visitor/evaluator.js +++ b/lib/visitor/evaluator.js @@ -62,45 +62,51 @@ function importFile(node, file, literal) { // Parse the file importStack.push(file); + var previousFilename = nodes.filename; nodes.filename = file; + try{ + if (literal) { + literal = new nodes.Literal(str.replace(/\r\n?/g, '\n')); + literal.lineno = literal.column = 1; + if (!this.resolveURL) return literal; + } - if (literal) { - literal = new nodes.Literal(str.replace(/\r\n?/g, '\n')); - literal.lineno = literal.column = 1; - if (!this.resolveURL) return literal; - } - - // parse - var block = new nodes.Block - , parser = new Parser(str, utils.merge({ root: block }, this.options)); + // parse + var block = new nodes.Block + , options = utils.merge({ root: block }, this.options); + options.filename = file; + var parser = new Parser(str, options); - try { - block = parser.parse(); - } catch (err) { - var line = parser.lexer.lineno - , column = parser.lexer.column; + try { + block = parser.parse(); + } catch (err) { + var line = parser.lexer.lineno + , column = parser.lexer.column; - if (literal && this.includeCSS && this.resolveURL) { - this.warn('ParseError: ' + file + ':' + line + ':' + column + '. This file included as-is'); - return literal; - } else { - err.filename = file; - err.lineno = line; - err.column = column; - err.input = str; - throw err; + if (literal && this.includeCSS && this.resolveURL) { + this.warn('ParseError: ' + file + ':' + line + ':' + column + '. This file included as-is'); + return literal; + } else { + err.filename = file; + err.lineno = line; + err.column = column; + err.input = str; + throw err; + } } - } - // Evaluate imported "root" - block = block.clone(this.currentBlock); - block.parent = this.currentBlock; - block.scope = false; - var ret = this.visit(block); - importStack.pop(); - if (!this.resolveURL || this.resolveURL.nocheck) this.paths.pop(); + // Evaluate imported "root" + block = block.clone(this.currentBlock); + block.parent = this.currentBlock; + block.scope = false; + var ret = this.visit(block); + importStack.pop(); + if (!this.resolveURL || this.resolveURL.nocheck) this.paths.pop(); - return ret; + return ret; + } finally{ + nodes.filename = previousFilename; + } } /** @@ -244,7 +250,14 @@ Evaluator.prototype.populateGlobalScope = function(){ Evaluator.prototype.evaluate = function(){ debug('eval %s', this.filename); this.setup(); - return this.visit(this.root); + + var previousFilename = nodes.filename; + nodes.filename = this.filename; + try{ + return this.visit(this.root); + } finally{ + nodes.filename = previousFilename; + } }; /** From 0e57c15dfeb831c28303e759dd7bab44f614074f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Flaventin=20Hauchecorne?= Date: Tue, 14 Jun 2022 19:05:28 +0200 Subject: [PATCH 2/3] Call super-constructor of Root node (fix #2699) --- lib/nodes/root.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/nodes/root.js b/lib/nodes/root.js index 3bfb3c218..a56dce329 100644 --- a/lib/nodes/root.js +++ b/lib/nodes/root.js @@ -18,6 +18,7 @@ var Node = require('./node'); */ var Root = module.exports = function Root(){ + Node.call(this); this.nodes = []; }; From 64c95c0f1e47bc70de5c07d6f446b9cc26d206fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Flaventin=20Hauchecorne?= Date: Tue, 14 Jun 2022 19:15:52 +0200 Subject: [PATCH 3/3] Evaluator, DepsResolver and SourceMapper filename from root ast node if not provided in options --- lib/visitor/deps-resolver.js | 2 +- lib/visitor/evaluator.js | 4 ++-- lib/visitor/sourcemapper.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/visitor/deps-resolver.js b/lib/visitor/deps-resolver.js index 94827db9c..5eed745c2 100644 --- a/lib/visitor/deps-resolver.js +++ b/lib/visitor/deps-resolver.js @@ -21,7 +21,7 @@ var Visitor = require('./') var DepsResolver = module.exports = function DepsResolver(root, options) { this.root = root; - this.filename = options.filename; + this.filename = options.filename || root.filename; this.paths = options.paths || []; this.paths.push(dirname(options.filename || '.')); this.options = options; diff --git a/lib/visitor/evaluator.js b/lib/visitor/evaluator.js index 4230b2eac..6b8bca134 100644 --- a/lib/visitor/evaluator.js +++ b/lib/visitor/evaluator.js @@ -131,12 +131,12 @@ var Evaluator = module.exports = function Evaluator(root, options) { this.globals = options.globals || {}; this.paths = options.paths || []; this.prefix = options.prefix || ''; - this.filename = options.filename; + this.filename = options.filename || root.filename; this.includeCSS = options['include css']; this.resolveURL = functions.url && 'resolver' == functions.url.name && functions.url.options; - this.paths.push(dirname(options.filename || '.')); + this.paths.push(dirname(this.filename || '.')); this.stack.push(this.global = new Frame(root)); this.warnings = options.warn; this.options = options; diff --git a/lib/visitor/sourcemapper.js b/lib/visitor/sourcemapper.js index 0e081104d..aa9a56811 100644 --- a/lib/visitor/sourcemapper.js +++ b/lib/visitor/sourcemapper.js @@ -32,7 +32,7 @@ var SourceMapper = module.exports = function SourceMapper(root, options){ this.column = 1; this.lineno = 1; this.contents = {}; - this.filename = options.filename; + this.filename = options.filename || root.filename; this.dest = options.dest; var sourcemap = options.sourcemap;