From: Mihai Bazon Date: Sun, 19 Aug 2012 19:46:00 +0000 (+0300) Subject: doc (WIP) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=1fe0ff9fff86b5d5fba3f4d1499479d2f23511df;p=UglifyJS.git doc (WIP) --- diff --git a/lib/ast.js b/lib/ast.js index 561cc4b9..c170b629 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -35,6 +35,7 @@ var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_be }, null); var AST_Node = DEFNODE("Node", "start end", { + $documentation: "Base class of all AST nodes", _walk: function(visitor) { return visitor._visit(this); }, @@ -44,14 +45,17 @@ var AST_Node = DEFNODE("Node", "start end", { }, null); var AST_Debugger = DEFNODE("Debugger", null, { + $documentation: "Represents a debugger statement" }); var AST_Directive = DEFNODE("Directive", "value", { + $documentation: "Represents a directive, like \"use strict\";" }); /* -----[ loops ]----- */ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label statement", { + $documentation: "Statement with a label", _walk: function(visitor) { return visitor._visit(this, function(){ this.label._walk(visitor); @@ -61,6 +65,7 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label statement", { }); var AST_Statement = DEFNODE("Statement", "body", { + $documentation: "Base class of all statements", _walk: function(visitor) { return visitor._visit(this, function(){ this.body._walk(visitor); @@ -69,9 +74,11 @@ var AST_Statement = DEFNODE("Statement", "body", { }); var AST_SimpleStatement = DEFNODE("SimpleStatement", null, { + $documentation: "A statement consisting of an expression, i.e. a = 1 + 2." }, AST_Statement); var AST_BlockStatement = DEFNODE("BlockStatement", null, { + $documentation: "A block statement.", _walk: function(visitor) { return visitor._visit(this, function(){ var a = this.body, i = 0, n = a.length; @@ -83,12 +90,14 @@ var AST_BlockStatement = DEFNODE("BlockStatement", null, { }, AST_Statement); var AST_EmptyStatement = DEFNODE("EmptyStatement", null, { + $documentation: "The empty statement (empty block or simply a semicolon).", _walk: function(visitor) { return visitor._visit(this); } }, AST_Statement); var AST_DWLoop = DEFNODE("DWLoop", "condition", { + $documentation: "Base class for do/while statements.", _walk: function(visitor) { return visitor._visit(this, function(){ this.condition._walk(visitor); @@ -98,12 +107,15 @@ var AST_DWLoop = DEFNODE("DWLoop", "condition", { }, AST_Statement); var AST_Do = DEFNODE("Do", null, { + $documentation: "A `do` statement" }, AST_DWLoop); var AST_While = DEFNODE("While", null, { + $documentation: "A `while` statement" }, AST_DWLoop); var AST_For = DEFNODE("For", "init condition step", { + $documentation: "A `for` statement", _walk: function(visitor) { return visitor._visit(this, function(){ if (this.init) this.init._walk(visitor); @@ -114,6 +126,7 @@ var AST_For = DEFNODE("For", "init condition step", { }, AST_Statement); var AST_ForIn = DEFNODE("ForIn", "init name object", { + $documentation: "A `for ... in` statement", _walk: function(visitor) { return visitor._visit(this, function(){ if (this.init) this.init._walk(visitor); @@ -124,6 +137,7 @@ var AST_ForIn = DEFNODE("ForIn", "init name object", { }, AST_Statement); var AST_With = DEFNODE("With", "expression", { + $documentation: "A `with` statement", _walk: function(visitor) { return visitor._visit(this, function(){ this.expression._walk(visitor); @@ -135,6 +149,7 @@ var AST_With = DEFNODE("With", "expression", { /* -----[ scope and functions ]----- */ var AST_Scope = DEFNODE("Scope", null, { + $documentation: "Base class for all statements introducing a lexical scope", initialize: function() { this.labels = {}; this.variables = {}; @@ -146,9 +161,11 @@ var AST_Scope = DEFNODE("Scope", null, { }, AST_BlockStatement); var AST_Toplevel = DEFNODE("Toplevel", null, { + $documentation: "The toplevel scope" }, AST_Scope); var AST_Lambda = DEFNODE("Lambda", "name argnames", { + $documentation: "Base class for functions", initialize: function() { AST_Scope.prototype.initialize.call(this); this.uses_arguments = false; @@ -165,17 +182,21 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames", { }, AST_Scope); var AST_Function = DEFNODE("Function", null, { + $documentation: "A function expression" }, AST_Lambda); var AST_Defun = DEFNODE("Defun", null, { + $documentation: "A function definition" }, AST_Lambda); /* -----[ JUMPS ]----- */ var AST_Jump = DEFNODE("Jump", null, { + $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)" }); var AST_Exit = DEFNODE("Exit", "value", { + $documentation: "Base class for “exits” (`return` and `throw`)", _walk: function(visitor) { return visitor._visit(this, this.value && function(){ this.value._walk(visitor); @@ -184,12 +205,15 @@ var AST_Exit = DEFNODE("Exit", "value", { }, AST_Jump); var AST_Return = DEFNODE("Return", null, { + $documentation: "A `return` statement" }, AST_Exit); var AST_Throw = DEFNODE("Throw", null, { + $documentation: "A `throw` statement" }, AST_Exit); var AST_LoopControl = DEFNODE("LoopControl", "label", { + $documentation: "Base class for loop control statements (`break` and `continue`)", _walk: function(visitor) { return visitor._visit(this, this.label && function(){ this.label._walk(visitor); @@ -198,14 +222,17 @@ var AST_LoopControl = DEFNODE("LoopControl", "label", { }, AST_Jump); var AST_Break = DEFNODE("Break", null, { + $documentation: "A `break` statement" }, AST_LoopControl); var AST_Continue = DEFNODE("Continue", null, { + $documentation: "A `continue` statement" }, AST_LoopControl); /* -----[ IF ]----- */ var AST_If = DEFNODE("If", "condition consequent alternative", { + $documentation: "A `if` statement", _walk: function(visitor) { return visitor._visit(this, function(){ this.condition._walk(visitor); @@ -218,6 +245,7 @@ var AST_If = DEFNODE("If", "condition consequent alternative", { /* -----[ SWITCH ]----- */ var AST_Switch = DEFNODE("Switch", "expression", { + $documentation: "A `switch` statement", _walk: function(visitor) { return visitor._visit(this, function(){ this.expression._walk(visitor); @@ -227,12 +255,15 @@ var AST_Switch = DEFNODE("Switch", "expression", { }, AST_Statement); var AST_SwitchBlock = DEFNODE("SwitchBlock", null, { + $documentation: "The switch block is somewhat special, hence a special node for it" }, AST_BlockStatement); var AST_SwitchBranch = DEFNODE("SwitchBranch", null, { + $documentation: "Base class for `switch` branches" }, AST_BlockStatement); var AST_Default = DEFNODE("Default", null, { + $documentation: "A `default` switch branch", _walk: function(visitor) { return visitor._visit(this, function(){ AST_BlockStatement.prototype._walk.call(this, visitor); @@ -241,6 +272,7 @@ var AST_Default = DEFNODE("Default", null, { }, AST_SwitchBranch); var AST_Case = DEFNODE("Case", "expression", { + $documentation: "A `case` switch branch", _walk: function(visitor) { return visitor._visit(this, function(){ this.expression._walk(visitor); @@ -252,6 +284,7 @@ var AST_Case = DEFNODE("Case", "expression", { /* -----[ EXCEPTIONS ]----- */ var AST_Try = DEFNODE("Try", "btry bcatch bfinally", { + $documentation: "A `try` statement", _walk: function(visitor) { return visitor._visit(this, function(){ this.btry._walk(visitor); @@ -268,6 +301,7 @@ var AST_Try = DEFNODE("Try", "btry bcatch bfinally", { // we ever want to fix this then AST_Catch should inherit from // AST_Scope. var AST_Catch = DEFNODE("Catch", "argname", { + $documentation: "A `catch` node; only makes sense as part of a `try` statement", _walk: function(visitor) { return visitor._visit(this, function(){ this.argname._walk(visitor); @@ -277,11 +311,13 @@ var AST_Catch = DEFNODE("Catch", "argname", { }, AST_BlockStatement); var AST_Finally = DEFNODE("Finally", null, { + $documentation: "A `finally` node; only makes sense as part of a `try` statement" }, AST_BlockStatement); /* -----[ VAR/CONST ]----- */ var AST_Definitions = DEFNODE("Definitions", "definitions", { + $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)", _walk: function(visitor) { return visitor._visit(this, function(){ this.definitions.forEach(function(def){ @@ -292,12 +328,15 @@ var AST_Definitions = DEFNODE("Definitions", "definitions", { }); var AST_Var = DEFNODE("Var", null, { + $documentation: "A `var` statement" }, AST_Definitions); var AST_Const = DEFNODE("Const", null, { + $documentation: "A `const` statement" }, AST_Definitions); var AST_VarDef = DEFNODE("VarDef", "name value", { + $documentation: "A variable declaration; only appears in a AST_Definitions node", _walk: function(visitor) { return visitor._visit(this, function(){ this.name._walk(visitor); @@ -309,6 +348,7 @@ var AST_VarDef = DEFNODE("VarDef", "name value", { /* -----[ OTHER ]----- */ var AST_Call = DEFNODE("Call", "expression args", { + $documentation: "A function call expression", _walk: function(visitor) { return visitor._visit(this, function(){ this.expression._walk(visitor); @@ -320,9 +360,11 @@ var AST_Call = DEFNODE("Call", "expression args", { }); var AST_New = DEFNODE("New", null, { + $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties." }, AST_Call); var AST_Seq = DEFNODE("Seq", "first second", { + $documentation: "A sequence expression (two comma-separated expressions)", _walk: function(visitor) { return visitor._visit(this, function(){ this.first._walk(visitor); diff --git a/lib/scope.js b/lib/scope.js index f8bdb2e8..4c0aa105 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -1,5 +1,12 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(){ - // step 1: handle definitions + // This does what ast_add_scope did in UglifyJS v1. + // + // Part of it could be done at parse time, but it would complicate + // the parser (and it's already kinda complex). It's also worth + // having it separated because we might need to call it multiple + // times on the same tree. + + // pass 1: setup scope chaining and handle definitions var scope = null; var tw = new TreeWalker(function(node, descend){ if (node instanceof AST_Scope) { @@ -41,7 +48,8 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(){ } }); this.walk(tw); - // step 2: find back references and eval/with + + // pass 2: find back references and eval/with var tw = new TreeWalker(function(node){ if (node instanceof AST_LabelRef) { var sym = node.scope.find_label(node); @@ -62,26 +70,31 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(){ }); this.walk(tw); }); + AST_Scope.DEFMETHOD("find_variable", function(name){ if (name instanceof AST_Symbol) name = name.name; return this.variables[name] || (this.name && this.name.name == name && this.name) || (this.parent_scope && this.parent_scope.find_variable(name)); }); + AST_Scope.DEFMETHOD("find_label", function(name){ if (name instanceof AST_Symbol) name = name.name; return this.labels[name]; }); + AST_Scope.DEFMETHOD("def_function", function(symbol){ this.def_variable(symbol); this.functions[symbol.name] = symbol; symbol.scope = this; }); + AST_Scope.DEFMETHOD("def_variable", function(symbol){ this.variables[symbol.name] = symbol; delete this.functions[symbol.name]; symbol.scope = this; }); + AST_Scope.DEFMETHOD("def_label", function(symbol){ this.labels[symbol.name] = symbol; symbol.scope = this; diff --git a/lib/utils.js b/lib/utils.js index c7d6932c..b0020ac8 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -97,3 +97,15 @@ var MAP = (function(){ function Splice(val) { this.v = val }; return MAP; })(); + +var BASE54_DIGITS = "etnrisouaflchpdvmgybwESxTNCkLAOM_DPHBjFIqRUzWXV$JKQGYZ0516372984"; + +function base54(num) { + var ret = "", base = 54; + do { + ret += BASE54_DIGITS.charAt(num % base); + num = Math.floor(num / base); + base = 64; + } while (num > 0); + return ret; +}; diff --git a/lib/test.js b/tmp/browser.js similarity index 100% rename from lib/test.js rename to tmp/browser.js diff --git a/lib/index.html b/tmp/index.html similarity index 100% rename from lib/index.html rename to tmp/index.html