From 3da0ac4897e1b12adbdedbfa1c3a145931f0af56 Mon Sep 17 00:00:00 2001 From: Mihai Bazon Date: Tue, 18 Sep 2012 13:21:09 +0300 Subject: [PATCH] support for directives --- lib/ast.js | 4 ++-- lib/compress.js | 11 +++++++++++ lib/output.js | 1 + lib/parse.js | 4 ++-- lib/scope.js | 11 +++++++++++ 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/ast.js b/lib/ast.js index 39a62b16..5c4b7e6a 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -126,7 +126,7 @@ var AST_Debugger = DEFNODE("Debugger", null, { $documentation: "Represents a debugger statement" }, AST_StatementBase); -var AST_Directive = DEFNODE("Directive", "value", { +var AST_Directive = DEFNODE("Directive", "value scope", { $documentation: "Represents a directive, like \"use strict\";" }, AST_StatementBase); @@ -235,7 +235,7 @@ var AST_With = DEFNODE("With", "expression", { /* -----[ scope and functions ]----- */ -var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent_scope enclosed cname", { +var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { $documentation: "Base class for all statements introducing a lexical scope", }, AST_Block); diff --git a/lib/compress.js b/lib/compress.js index aedd78fd..9d5dac17 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -742,6 +742,13 @@ function Compressor(options, false_by_default) { /* -----[ node squeezers ]----- */ + SQUEEZE(AST_Directive, function(self, compressor){ + if (self.hoisted || self.scope.has_directive(self.value) !== self.scope) { + return new AST_EmptyStatement(self); + } + return self; + }); + SQUEEZE(AST_Debugger, function(self, compressor){ if (compressor.option("drop_debugger")) return new AST_EmptyStatement(self); @@ -796,6 +803,10 @@ function Compressor(options, false_by_default) { var vars = {}, vars_found = 0, vardecl = []; var tw = new TreeWalker(function(node){ if (node !== self) { + if (node instanceof AST_Directive && (hoist_funs || hoist_vars) && !node.hoisted) { + hoisted.unshift(node.clone()); + node.hoisted = true; + } if (node instanceof AST_Defun && hoist_funs && !node.hoisted) { hoisted.push(node.clone()); node.hoisted = true; diff --git a/lib/output.js b/lib/output.js index ee11aebc..149fc05e 100644 --- a/lib/output.js +++ b/lib/output.js @@ -428,6 +428,7 @@ function OutputStream(options) { DEFPRINT(AST_Directive, function(self, output){ output.print_string(self.value); + output.semicolon(); }); DEFPRINT(AST_Debugger, function(self, output){ output.print("debugger"); diff --git a/lib/parse.js b/lib/parse.js index 77c75343..6a5aad26 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -773,8 +773,8 @@ function parse($TEXT, exigent_mode) { case "string": var dir = S.in_directives, stat = simple_statement(); // XXXv2: decide how to fix directives - // if (dir && stat instanceof AST_String && !is("punc", ",")) - // return new AST_Directive({ value: stat.value }); + if (dir && stat.body instanceof AST_String && !is("punc", ",")) + return new AST_Directive({ value: stat.body.value }); return stat; case "num": case "regexp": diff --git a/lib/scope.js b/lib/scope.js index 79d6e91d..dfbff4b8 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -82,6 +82,11 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){ scope = save_scope; return true; // don't descend again in TreeWalker } + if (node instanceof AST_Directive) { + node.scope = scope; + push_uniq(scope.directives, node.value); + return true; + } if (node instanceof AST_With) { for (var s = scope; s; s = s.parent_scope) s.uses_with = true; @@ -193,6 +198,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){ }); AST_Scope.DEFMETHOD("init_scope_vars", function(){ + this.directives = []; // contains the directives defined in this scope, i.e. "use strict" this.variables = {}; // map name to AST_SymbolVar (variables defined in this scope; includes functions) this.functions = {}; // map name to AST_SymbolDefun (functions defined in this scope) this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement @@ -233,6 +239,11 @@ AST_Scope.DEFMETHOD("find_variable", function(name){ : (this.parent_scope && this.parent_scope.find_variable(name)); }); +AST_Scope.DEFMETHOD("has_directive", function(value){ + return this.parent_scope && this.parent_scope.has_directive(value) + || (this.directives.indexOf(value) >= 0 ? this : null); +}); + AST_Scope.DEFMETHOD("def_function", function(symbol){ this.functions[symbol.name] = this.def_variable(symbol); }); -- 2.34.1