Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix 2699 : filename set at parsing stage + nodes.filename scope + filename in the Root AST node #2700

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/nodes/root.js
Expand Up @@ -18,6 +18,7 @@ var Node = require('./node');
*/

var Root = module.exports = function Root(){
Node.call(this);
this.nodes = [];
};

Expand Down
46 changes: 30 additions & 16 deletions lib/parser.js
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
},

/**
Expand Down
2 changes: 0 additions & 2 deletions lib/renderer.js
Expand Up @@ -75,7 +75,6 @@ Renderer.prototype.render = function(fn){
}

try {
nodes.filename = this.options.filename;
// parse
var ast = parser.parse();

Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion lib/visitor/deps-resolver.js
Expand Up @@ -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;
Expand Down
83 changes: 48 additions & 35 deletions lib/visitor/evaluator.js
Expand Up @@ -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;
}
}

/**
Expand All @@ -125,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;
Expand Down Expand Up @@ -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;
}
};

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/visitor/sourcemapper.js
Expand Up @@ -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;
Expand Down