diff --git a/lib/parse.js b/lib/parse.js index be103b67..6b4fee4b 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -671,17 +671,19 @@ function parse($TEXT, options) { }); var S = { - input : (typeof $TEXT == "string" - ? tokenizer($TEXT, options.filename, - options.html5_comments, options.shebang) - : $TEXT), - token : null, - prev : null, - peeked : null, - in_function : 0, - in_directives : true, - in_loop : 0, - labels : [] + input : (typeof $TEXT == "string" + ? tokenizer($TEXT, options.filename, + options.html5_comments, options.shebang) + : $TEXT), + token : null, + prev : null, + peeked : null, + in_function : 0, + in_directives : true, + in_loop : 0, + labels : [], + directives : {}, + directive_stack : [] }; S.token = next(); @@ -738,6 +740,26 @@ function parse($TEXT, options) { function expect(punc) { return expect_token("punc", punc); }; + function push_directives_stack() { + S.directive_stack.push([]); + S.in_directives = true; + } + + function pop_directives_stack() { + var directives = S.directive_stack[S.directive_stack.length - 1]; + + for (var i = 0; i < directives.length; i++) { + S.directives[directives[i]]--; + } + + S.directive_stack.pop(); + } + + function has_directive(directive) { + return S.directives[directive] !== undefined && + S.directives[directive] > 0; + } + function can_insert_semicolon() { return !options.strict && ( S.token.nlb || is("eof") || is("punc", "}") @@ -780,8 +802,15 @@ function parse($TEXT, options) { switch (S.token.type) { case "string": var dir = S.in_directives, stat = simple_statement(); - // XXXv2: decide how to fix directives if (dir && stat.body instanceof AST_String && !is("punc", ",")) { + S.directive_stack[S.directive_stack.length - 1].push(stat.body.value); + + if (S.directives[stat.body.value] === undefined) { + S.directives[stat.body.value] = 1; + } else { + S.directives[stat.body.value]++; + } + return new AST_Directive({ start : stat.body.start, end : stat.body.end, @@ -1009,10 +1038,11 @@ function parse($TEXT, options) { })(true, []), body: (function(loop, labels){ ++S.in_function; - S.in_directives = true; + push_directives_stack(); S.in_loop = 0; S.labels = []; var a = block_(); + pop_directives_stack(); --S.in_function; S.in_loop = loop; S.labels = labels; @@ -1512,8 +1542,10 @@ function parse($TEXT, options) { return (function(){ var start = S.token; var body = []; + push_directives_stack(); while (!is("eof")) body.push(statement()); + pop_directives_stack(); var end = prev(); var toplevel = options.toplevel; if (toplevel) {