ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anovi...@apache.org
Subject [12/52] [partial] incubator-ignite git commit: # ignite-843 WIP.
Date Fri, 08 May 2015 11:36:37 GMT
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/0ef79031/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/README.md
----------------------------------------------------------------------
diff --git a/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/README.md b/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/README.md
new file mode 100644
index 0000000..de6abe5
--- /dev/null
+++ b/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/README.md
@@ -0,0 +1,544 @@
+UglifyJS 2
+==========
+
+UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit.
+
+This page documents the command line utility.  For
+[API and internals documentation see my website](http://lisperator.net/uglifyjs/).
+There's also an
+[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,
+Chrome and probably Safari).
+
+Install
+-------
+
+First make sure you have installed the latest version of [node.js](http://nodejs.org/)
+(You may need to restart your computer after this step).
+
+From NPM for use as a command line app:
+
+    npm install uglify-js -g
+
+From NPM for programmatic use:
+
+    npm install uglify-js
+
+From Git:
+
+    git clone git://github.com/mishoo/UglifyJS2.git
+    cd UglifyJS2
+    npm link .
+
+Usage
+-----
+
+    uglifyjs [input files] [options]
+
+UglifyJS2 can take multiple input files.  It's recommended that you pass the
+input files first, then pass the options.  UglifyJS will parse input files
+in sequence and apply any compression options.  The files are parsed in the
+same global scope, that is, a reference from a file to some
+variable/function declared in another file will be matched properly.
+
+If you want to read from STDIN instead, pass a single dash instead of input
+files.
+
+The available options are:
+
+    --source-map       Specify an output file where to generate source map.
+                                                                          [string]
+    --source-map-root  The path to the original source to be included in the
+                       source map.                                        [string]
+    --source-map-url   The path to the source map to be added in //@
+                       sourceMappingURL.  Defaults to the value passed with
+                       --source-map.                                      [string]
+    --in-source-map    Input source map, useful if you're compressing JS that was
+                       generated from some other original code.
+    -p, --prefix       Skip prefix for original filenames that appear in source
+                       maps. For example -p 3 will drop 3 directories from file
+                       names and ensure they are relative paths.
+    -o, --output       Output file (default STDOUT).
+    -b, --beautify     Beautify output/specify output options.            [string]
+    -m, --mangle       Mangle names/pass mangler options.                 [string]
+    -r, --reserved     Reserved names to exclude from mangling.
+    -c, --compress     Enable compressor/pass compressor options. Pass options
+                       like -c hoist_vars=false,if_return=false. Use -c with no
+                       argument to use the default compression options.   [string]
+    -d, --define       Global definitions                                 [string]
+    --comments         Preserve copyright comments in the output. By default this
+                       works like Google Closure, keeping JSDoc-style comments
+                       that contain "@license" or "@preserve". You can optionally
+                       pass one of the following arguments to this flag:
+                       - "all" to keep all comments
+                       - a valid JS regexp (needs to start with a slash) to keep
+                       only comments that match.
+                       Note that currently not *all* comments can be kept when
+                       compression is on, because of dead code removal or
+                       cascading statements into sequences.               [string]
+    --stats            Display operations run time on STDERR.            [boolean]
+    --acorn            Use Acorn for parsing.                            [boolean]
+    --spidermonkey     Assume input fles are SpiderMonkey AST format (as JSON).
+                                                                         [boolean]
+    --self             Build itself (UglifyJS2) as a library (implies
+                       --wrap=UglifyJS --export-all)                     [boolean]
+    --wrap             Embed everything in a big function, making the “exports”
+                       and “global” variables available. You need to pass an
+                       argument to this option to specify the name that your
+                       module will take when included in, say, a browser.
+                                                                          [string]
+    --export-all       Only used when --wrap, this tells UglifyJS to add code to
+                       automatically export all globals.                 [boolean]
+    --lint             Display some scope warnings                       [boolean]
+    -v, --verbose      Verbose                                           [boolean]
+    -V, --version      Print version number and exit.                    [boolean]
+
+Specify `--output` (`-o`) to declare the output file.  Otherwise the output
+goes to STDOUT.
+
+## Source map options
+
+UglifyJS2 can generate a source map file, which is highly useful for
+debugging your compressed JavaScript.  To get a source map, pass
+`--source-map output.js.map` (full path to the file where you want the
+source map dumped).
+
+Additionally you might need `--source-map-root` to pass the URL where the
+original files can be found.  In case you are passing full paths to input
+files to UglifyJS, you can use `--prefix` (`-p`) to specify the number of
+directories to drop from the path prefix when declaring files in the source
+map.
+
+For example:
+
+    uglifyjs /home/doe/work/foo/src/js/file1.js \
+             /home/doe/work/foo/src/js/file2.js \
+             -o foo.min.js \
+             --source-map foo.min.js.map \
+             --source-map-root http://foo.com/src \
+             -p 5 -c -m
+
+The above will compress and mangle `file1.js` and `file2.js`, will drop the
+output in `foo.min.js` and the source map in `foo.min.js.map`.  The source
+mapping will refer to `http://foo.com/src/js/file1.js` and
+`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src`
+as the source map root, and the original files as `js/file1.js` and
+`js/file2.js`).
+
+### Composed source map
+
+When you're compressing JS code that was output by a compiler such as
+CoffeeScript, mapping to the JS code won't be too helpful.  Instead, you'd
+like to map back to the original code (i.e. CoffeeScript).  UglifyJS has an
+option to take an input source map.  Assuming you have a mapping from
+CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →
+compressed JS by mapping every token in the compiled JS to its original
+location.
+
+To use this feature you need to pass `--in-source-map
+/path/to/input/source.map`.  Normally the input source map should also point
+to the file containing the generated JS, so if that's correct you can omit
+input files from the command line.
+
+## Mangler options
+
+To enable the mangler you need to pass `--mangle` (`-m`).  Optionally you
+can pass `-m sort=true` (we'll possibly have other flags in the future) in order
+to assign shorter names to most frequently used variables.  This saves a few
+hundred bytes on jQuery before gzip, but the output is _bigger_ after gzip
+(and seems to happen for other libraries I tried it on) therefore it's not
+enabled by default.
+
+When mangling is enabled but you want to prevent certain names from being
+mangled, you can declare those names with `--reserved` (`-r`) — pass a
+comma-separated list of names.  For example:
+
+    uglifyjs ... -m -r '$,require,exports'
+
+to prevent the `require`, `exports` and `$` names from being changed.
+
+## Compressor options
+
+You need to pass `--compress` (`-c`) to enable the compressor.  Optionally
+you can pass a comma-separated list of options.  Options are in the form
+`foo=bar`, or just `foo` (the latter implies a boolean option that you want
+to set `true`; it's effectively a shortcut for `foo=true`).
+
+The defaults should be tuned for maximum compression on most code.  Here are
+the available options (all are `true` by default, except `hoist_vars`):
+
+- `sequences` -- join consecutive simple statements using the comma operator
+- `properties` -- rewrite property access using the dot notation, for
+  example `foo["bar"] → foo.bar`
+- `dead_code` -- remove unreachable code
+- `drop_debugger` -- remove `debugger;` statements
+- `unsafe` -- apply "unsafe" transformations (discussion below)
+- `conditionals` -- apply optimizations for `if`-s and conditional
+  expressions
+- `comparisons` -- apply certain optimizations to binary nodes, for example:
+  `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes,
+  e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
+- `evaluate` -- attempt to evaluate constant expressions
+- `booleans` -- various optimizations for boolean context, for example `!!a
+  ? b : c → a ? b : c`
+- `loops` -- optimizations for `do`, `while` and `for` loops when we can
+  statically determine the condition
+- `unused` -- drop unreferenced functions and variables
+- `hoist_funs` -- hoist function declarations
+- `hoist_vars` -- hoist `var` declarations (this is `false` by default
+  because it seems to increase the size of the output in general)
+- `if_return` -- optimizations for if/return and if/continue
+- `join_vars` -- join consecutive `var` statements
+- `cascade` -- small optimization for sequences, transform `x, x` into `x`
+  and `x = something(), x` into `x = something()`
+- `warnings` -- display warnings when dropping unreachable code or unused
+  declarations etc.
+
+### Conditional compilation
+
+You can use the `--define` (`-d`) switch in order to declare global
+variables that UglifyJS will assume to be constants (unless defined in
+scope).  For example if you pass `--define DEBUG=false` then, coupled with
+dead code removal UglifyJS will discard the following from the output:
+
+    if (DEBUG) {
+        console.log("debug stuff");
+    }
+
+UglifyJS will warn about the condition being always false and about dropping
+unreachable code; for now there is no option to turn off only this specific
+warning, you can pass `warnings=false` to turn off *all* warnings.
+
+Another way of doing that is to declare your globals as constants in a
+separate file and include it into the build.  For example you can have a
+`build/defines.js` file with the following:
+
+    const DEBUG = false;
+    const PRODUCTION = true;
+    // etc.
+
+and build your code like this:
+
+    uglifyjs build/defines.js js/foo.js js/bar.js... -c
+
+UglifyJS will notice the constants and, since they cannot be altered, it
+will evaluate references to them to the value itself and drop unreachable
+code as usual.  The possible downside of this approach is that the build
+will contain the `const` declarations.
+
+<a name="codegen-options"></a>
+## Beautifier options
+
+The code generator tries to output shortest code possible by default.  In
+case you want beautified output, pass `--beautify` (`-b`).  Optionally you
+can pass additional arguments that control the code output:
+
+- `beautify` (default `true`) -- whether to actually beautify the output.
+  Passing `-b` will set this to true, but you might need to pass `-b` even
+  when you want to generate minified code, in order to specify additional
+  arguments, so you can use `-b beautify=false` to override it.
+- `indent-level` (default 4)
+- `indent-start` (default 0) -- prefix all lines by that many spaces
+- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal
+  objects
+- `space-colon` (default `true`) -- insert a space after the colon signs
+- `ascii-only` (default `false`) -- escape Unicode characters in strings and
+  regexps
+- `inline-script` (default `false`) -- escape the slash in occurrences of
+  `</script` in strings
+- `width` (default 80) -- only takes effect when beautification is on, this
+  specifies an (orientative) line width that the beautifier will try to
+  obey.  It refers to the width of the line text (excluding indentation).
+  It doesn't work very well currently, but it does make the code generated
+  by UglifyJS more readable.
+- `max-line-len` (default 32000) -- maximum line length (for uglified code)
+- `ie-proof` (default `true`) -- generate “IE-proof” code (for now this
+  means add brackets around the do/while in code like this: `if (foo) do
+  something(); while (bar); else ...`.
+- `bracketize` (default `false`) -- always insert brackets in `if`, `for`,
+  `do`, `while` or `with` statements, even if their body is a single
+  statement.
+- `semicolons` (default `true`) -- separate statements with semicolons.  If
+  you pass `false` then whenever possible we will use a newline instead of a
+  semicolon, leading to more readable output of uglified code (size before
+  gzip could be smaller; size after gzip insignificantly larger).
+
+### Keeping copyright notices or other comments
+
+You can pass `--comments` to retain certain comments in the output.  By
+default it will keep JSDoc-style comments that contain "@preserve",
+"@license" or "@cc_on" (conditional compilation for IE).  You can pass
+`--comments all` to keep all the comments, or a valid JavaScript regexp to
+keep only comments that match this regexp.  For example `--comments
+'/foo|bar/'` will keep only comments that contain "foo" or "bar".
+
+Note, however, that there might be situations where comments are lost.  For
+example:
+
+    function f() {
+      /** @preserve Foo Bar */
+      function g() {
+        // this function is never called
+      }
+      return something();
+    }
+
+Even though it has "@preserve", the comment will be lost because the inner
+function `g` (which is the AST node to which the comment is attached to) is
+discarded by the compressor as not referenced.
+
+The safest comments where to place copyright information (or other info that
+needs to be kept in the output) are comments attached to toplevel nodes.
+
+## Support for the SpiderMonkey AST
+
+UglifyJS2 has its own abstract syntax tree format; for
+[practical reasons](http://lisperator.net/blog/uglifyjs-why-not-switching-to-spidermonkey-ast/)
+we can't easily change to using the SpiderMonkey AST internally.  However,
+UglifyJS now has a converter which can import a SpiderMonkey AST.
+
+For example [Acorn][acorn] is a super-fast parser that produces a
+SpiderMonkey AST.  It has a small CLI utility that parses one file and dumps
+the AST in JSON on the standard output.  To use UglifyJS to mangle and
+compress that:
+
+    acorn file.js | uglifyjs --spidermonkey -m -c
+
+The `--spidermonkey` option tells UglifyJS that all input files are not
+JavaScript, but JS code described in SpiderMonkey AST in JSON.  Therefore we
+don't use our own parser in this case, but just transform that AST into our
+internal AST.
+
+### Use Acorn for parsing
+
+More for fun, I added the `--acorn` option which will use Acorn to do all
+the parsing.  If you pass this option, UglifyJS will `require("acorn")`.
+
+Acorn is really fast (e.g. 250ms instead of 380ms on some 650K code), but
+converting the SpiderMonkey tree that Acorn produces takes another 150ms so
+in total it's a bit more than just using UglifyJS's own parser.
+
+API Reference
+-------------
+
+Assuming installation via NPM, you can load UglifyJS in your application
+like this:
+
+    var UglifyJS = require("uglify-js");
+
+It exports a lot of names, but I'll discuss here the basics that are needed
+for parsing, mangling and compressing a piece of code.  The sequence is (1)
+parse, (2) compress, (3) mangle, (4) generate output code.
+
+### The simple way
+
+There's a single toplevel function which combines all the steps.  If you
+don't need additional customization, you might want to go with `minify`.
+Example:
+
+    var result = UglifyJS.minify("/path/to/file.js");
+    console.log(result.code); // minified output
+    // if you need to pass code instead of file name
+    var result = UglifyJS.minify("var b = function () {};", {fromString: true});
+
+You can also compress multiple files:
+
+    var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ]);
+    console.log(result.code);
+
+To generate a source map:
+
+    var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ], {
+        outSourceMap: "out.js.map"
+    });
+    console.log(result.code); // minified output
+    console.log(result.map);
+
+Note that the source map is not saved in a file, it's just returned in
+`result.map`.  The value passed for `outSourceMap` is only used to set the
+`file` attribute in the source map (see [the spec][sm-spec]).
+
+You can also specify sourceRoot property to be included in source map:
+
+    var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ], {
+        outSourceMap: "out.js.map",
+        sourceRoot: "http://example.com/src"
+    });
+
+
+If you're compressing compiled JavaScript and have a source map for it, you
+can use the `inSourceMap` argument:
+
+    var result = UglifyJS.minify("compiled.js", {
+        inSourceMap: "compiled.js.map",
+        outSourceMap: "minified.js.map"
+    });
+    // same as before, it returns `code` and `map`
+
+The `inSourceMap` is only used if you also request `outSourceMap` (it makes
+no sense otherwise).
+
+Other options:
+
+- `warnings` (default `false`) — pass `true` to display compressor warnings.
+
+- `fromString` (default `false`) — if you pass `true` then you can pass
+  JavaScript source code, rather than file names.
+
+- `mangle` — pass `false` to skip mangling names.
+
+- `output` (default `null`) — pass an object if you wish to specify
+  additional [output options][codegen].  The defaults are optimized
+  for best compression.
+
+- `compress` (default `{}`) — pass `false` to skip compressing entirely.
+  Pass an object to specify custom [compressor options][compressor].
+
+We could add more options to `UglifyJS.minify` — if you need additional
+functionality please suggest!
+
+### The hard way
+
+Following there's more detailed API info, in case the `minify` function is
+too simple for your needs.
+
+#### The parser
+
+    var toplevel_ast = UglifyJS.parse(code, options);
+
+`options` is optional and if present it must be an object.  The following
+properties are available:
+
+- `strict` — disable automatic semicolon insertion and support for trailing
+  comma in arrays and objects
+- `filename` — the name of the file where this code is coming from
+- `toplevel` — a `toplevel` node (as returned by a previous invocation of
+  `parse`)
+
+The last two options are useful when you'd like to minify multiple files and
+get a single file as the output and a proper source map.  Our CLI tool does
+something like this:
+
+    var toplevel = null;
+    files.forEach(function(file){
+        var code = fs.readFileSync(file);
+        toplevel = UglifyJS.parse(code, {
+            filename: file,
+            toplevel: toplevel
+        });
+    });
+
+After this, we have in `toplevel` a big AST containing all our files, with
+each token having proper information about where it came from.
+
+#### Scope information
+
+UglifyJS contains a scope analyzer that you need to call manually before
+compressing or mangling.  Basically it augments various nodes in the AST
+with information about where is a name defined, how many times is a name
+referenced, if it is a global or not, if a function is using `eval` or the
+`with` statement etc.  I will discuss this some place else, for now what's
+important to know is that you need to call the following before doing
+anything with the tree:
+
+    toplevel.figure_out_scope()
+
+#### Compression
+
+Like this:
+
+    var compressor = UglifyJS.Compressor(options);
+    var compressed_ast = toplevel.transform(compressor);
+
+The `options` can be missing.  Available options are discussed above in
+“Compressor options”.  Defaults should lead to best compression in most
+scripts.
+
+The compressor is destructive, so don't rely that `toplevel` remains the
+original tree.
+
+#### Mangling
+
+After compression it is a good idea to call again `figure_out_scope` (since
+the compressor might drop unused variables / unreachable code and this might
+change the number of identifiers or their position).  Optionally, you can
+call a trick that helps after Gzip (counting character frequency in
+non-mangleable words).  Example:
+
+    compressed_ast.figure_out_scope();
+    compressed_ast.compute_char_frequency();
+    compressed_ast.mangle_names();
+
+#### Generating output
+
+AST nodes have a `print` method that takes an output stream.  Essentially,
+to generate code you do this:
+
+    var stream = UglifyJS.OutputStream(options);
+    compressed_ast.print(stream);
+    var code = stream.toString(); // this is your minified code
+
+or, for a shortcut you can do:
+
+    var code = compressed_ast.print_to_string(options);
+
+As usual, `options` is optional.  The output stream accepts a lot of otions,
+most of them documented above in section “Beautifier options”.  The two
+which we care about here are `source_map` and `comments`.
+
+#### Keeping comments in the output
+
+In order to keep certain comments in the output you need to pass the
+`comments` option.  Pass a RegExp or a function.  If you pass a RegExp, only
+those comments whose body matches the regexp will be kept.  Note that body
+means without the initial `//` or `/*`.  If you pass a function, it will be
+called for every comment in the tree and will receive two arguments: the
+node that the comment is attached to, and the comment token itself.
+
+The comment token has these properties:
+
+- `type`: "comment1" for single-line comments or "comment2" for multi-line
+  comments
+- `value`: the comment body
+- `pos` and `endpos`: the start/end positions (zero-based indexes) in the
+  original code where this comment appears
+- `line` and `col`: the line and column where this comment appears in the
+  original code
+- `file` — the file name of the original file
+- `nlb` — true if there was a newline before this comment in the original
+  code, or if this comment contains a newline.
+
+Your function should return `true` to keep the comment, or a falsy value
+otherwise.
+
+#### Generating a source mapping
+
+You need to pass the `source_map` argument when calling `print`.  It needs
+to be a `SourceMap` object (which is a thin wrapper on top of the
+[source-map][source-map] library).
+
+Example:
+
+    var source_map = UglifyJS.SourceMap(source_map_options);
+    var stream = UglifyJS.OutputStream({
+        ...
+        source_map: source_map
+    });
+    compressed_ast.print(stream);
+
+    var code = stream.toString();
+    var map = source_map.toString(); // json output for your source map
+
+The `source_map_options` (optional) can contain the following properties:
+
+- `file`: the name of the JavaScript output file that this mapping refers to
+- `root`: the `sourceRoot` property (see the [spec][sm-spec])
+- `orig`: the "original source map", handy when you compress generated JS
+  and want to map the minified output back to the original code where it
+  came from.  It can be simply a string in JSON, or a JSON object containing
+  the original source map.
+
+  [acorn]: https://github.com/marijnh/acorn
+  [source-map]: https://github.com/mozilla/source-map
+  [sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
+  [codegen]: http://lisperator.net/uglifyjs/codegen
+  [compressor]: http://lisperator.net/uglifyjs/compress

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/0ef79031/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/bin/uglifyjs
----------------------------------------------------------------------
diff --git a/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/bin/uglifyjs b/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/bin/uglifyjs
new file mode 100755
index 0000000..dc9a451
--- /dev/null
+++ b/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/bin/uglifyjs
@@ -0,0 +1,370 @@
+#! /usr/bin/env node
+// -*- js -*-
+
+"use strict";
+
+var UglifyJS = require("../tools/node");
+var sys = require("util");
+var optimist = require("optimist");
+var fs = require("fs");
+var acorn;
+var ARGS = optimist
+    .usage("$0 input1.js [input2.js ...] [options]\n\
+Use a single dash to read input from the standard input.\
+\n\n\
+NOTE: by default there is no mangling/compression.\n\
+Without [options] it will simply parse input files and dump the AST\n\
+with whitespace and comments discarded.  To achieve compression and\n\
+mangling you need to use `-c` and `-m`.\
+")
+    .describe("source-map", "Specify an output file where to generate source map.")
+    .describe("source-map-root", "The path to the original source to be included in the source map.")
+    .describe("source-map-url", "The path to the source map to be added in //@ sourceMappingURL.  Defaults to the value passed with --source-map.")
+    .describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
+    .describe("p", "Skip prefix for original filenames that appear in source maps. \
+For example -p 3 will drop 3 directories from file names and ensure they are relative paths.")
+    .describe("o", "Output file (default STDOUT).")
+    .describe("b", "Beautify output/specify output options.")
+    .describe("m", "Mangle names/pass mangler options.")
+    .describe("r", "Reserved names to exclude from mangling.")
+    .describe("c", "Enable compressor/pass compressor options. \
+Pass options like -c hoist_vars=false,if_return=false. \
+Use -c with no argument to use the default compression options.")
+    .describe("d", "Global definitions")
+
+    .describe("comments", "Preserve copyright comments in the output. \
+By default this works like Google Closure, keeping JSDoc-style comments that contain \"@license\" or \"@preserve\". \
+You can optionally pass one of the following arguments to this flag:\n\
+- \"all\" to keep all comments\n\
+- a valid JS regexp (needs to start with a slash) to keep only comments that match.\n\
+\
+Note that currently not *all* comments can be kept when compression is on, \
+because of dead code removal or cascading statements into sequences.")
+
+    .describe("stats", "Display operations run time on STDERR.")
+    .describe("acorn", "Use Acorn for parsing.")
+    .describe("spidermonkey", "Assume input fles are SpiderMonkey AST format (as JSON).")
+    .describe("self", "Build itself (UglifyJS2) as a library (implies --wrap=UglifyJS --export-all)")
+    .describe("wrap", "Embed everything in a big function, making the “exports” and “global” variables available. \
+You need to pass an argument to this option to specify the name that your module will take when included in, say, a browser.")
+    .describe("export-all", "Only used when --wrap, this tells UglifyJS to add code to automatically export all globals.")
+    .describe("lint", "Display some scope warnings")
+    .describe("v", "Verbose")
+    .describe("V", "Print version number and exit.")
+
+    .alias("p", "prefix")
+    .alias("o", "output")
+    .alias("v", "verbose")
+    .alias("b", "beautify")
+    .alias("m", "mangle")
+    .alias("c", "compress")
+    .alias("d", "define")
+    .alias("r", "reserved")
+    .alias("V", "version")
+
+    .string("source-map")
+    .string("source-map-root")
+    .string("source-map-url")
+    .string("b")
+    .string("m")
+    .string("c")
+    .string("d")
+    .string("comments")
+    .string("wrap")
+    .boolean("export-all")
+    .boolean("self")
+    .boolean("v")
+    .boolean("stats")
+    .boolean("acorn")
+    .boolean("spidermonkey")
+    .boolean("lint")
+    .boolean("V")
+
+    .wrap(80)
+
+    .argv
+;
+
+normalize(ARGS);
+
+if (ARGS.version || ARGS.V) {
+    var json = require("../package.json");
+    sys.puts(json.name + ' ' + json.version);
+    process.exit(0);
+}
+
+if (ARGS.ast_help) {
+    var desc = UglifyJS.describe_ast();
+    sys.puts(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
+    process.exit(0);
+}
+
+if (ARGS.h || ARGS.help) {
+    sys.puts(optimist.help());
+    process.exit(0);
+}
+
+if (ARGS.acorn) {
+    acorn = require("acorn");
+}
+
+var COMPRESS = getOptions("c", true);
+var MANGLE = getOptions("m", true);
+var BEAUTIFY = getOptions("b", true);
+
+if (COMPRESS && ARGS.d) {
+    COMPRESS.global_defs = getOptions("d");
+}
+
+if (MANGLE && ARGS.r) {
+    MANGLE.except = ARGS.r.replace(/^\s+|\s+$/g).split(/\s*,+\s*/);
+}
+
+var OUTPUT_OPTIONS = {
+    beautify: BEAUTIFY ? true : false
+};
+
+if (BEAUTIFY)
+    UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY);
+
+if (ARGS.comments) {
+    if (/^\//.test(ARGS.comments)) {
+        OUTPUT_OPTIONS.comments = new Function("return(" + ARGS.comments + ")")();
+    } else if (ARGS.comments == "all") {
+        OUTPUT_OPTIONS.comments = true;
+    } else {
+        OUTPUT_OPTIONS.comments = function(node, comment) {
+            var text = comment.value;
+            var type = comment.type;
+            if (type == "comment2") {
+                // multiline comment
+                return /@preserve|@license|@cc_on/i.test(text);
+            }
+        }
+    }
+}
+
+var files = ARGS._.slice();
+
+if (ARGS.self) {
+    if (files.length > 0) {
+        sys.error("WARN: Ignoring input files since --self was passed");
+    }
+    files = UglifyJS.FILES;
+    if (!ARGS.wrap) ARGS.wrap = "UglifyJS";
+    ARGS.export_all = true;
+}
+
+var ORIG_MAP = ARGS.in_source_map;
+
+if (ORIG_MAP) {
+    ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
+    if (files.length == 0) {
+        sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file);
+        files = [ ORIG_MAP.file ];
+    }
+    if (ARGS.source_map_root == null) {
+        ARGS.source_map_root = ORIG_MAP.sourceRoot;
+    }
+}
+
+if (files.length == 0) {
+    files = [ "-" ];
+}
+
+if (files.indexOf("-") >= 0 && ARGS.source_map) {
+    sys.error("ERROR: Source map doesn't work with input from STDIN");
+    process.exit(1);
+}
+
+if (files.filter(function(el){ return el == "-" }).length > 1) {
+    sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)");
+    process.exit(1);
+}
+
+var STATS = {};
+var OUTPUT_FILE = ARGS.o;
+var TOPLEVEL = null;
+
+var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({
+    file: OUTPUT_FILE,
+    root: ARGS.source_map_root,
+    orig: ORIG_MAP,
+}) : null;
+
+OUTPUT_OPTIONS.source_map = SOURCE_MAP;
+
+try {
+    var output = UglifyJS.OutputStream(OUTPUT_OPTIONS);
+    var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
+} catch(ex) {
+    if (ex instanceof UglifyJS.DefaultsError) {
+        sys.error(ex.msg);
+        sys.error("Supported options:");
+        sys.error(sys.inspect(ex.defs));
+        process.exit(1);
+    }
+}
+
+files.forEach(function(file) {
+    var code = read_whole_file(file);
+    if (ARGS.p != null) {
+        file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/");
+    }
+    time_it("parse", function(){
+        if (ARGS.spidermonkey) {
+            var program = JSON.parse(code);
+            if (!TOPLEVEL) TOPLEVEL = program;
+            else TOPLEVEL.body = TOPLEVEL.body.concat(program.body);
+        }
+        else if (ARGS.acorn) {
+            TOPLEVEL = acorn.parse(code, {
+                locations     : true,
+                trackComments : true,
+                sourceFile    : file,
+                program       : TOPLEVEL
+            });
+        }
+        else {
+            TOPLEVEL = UglifyJS.parse(code, {
+                filename: file,
+                toplevel: TOPLEVEL
+            });
+        };
+    });
+});
+
+if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
+    TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
+});
+
+if (ARGS.wrap) {
+    TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all);
+}
+
+var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint;
+
+if (SCOPE_IS_NEEDED) {
+    time_it("scope", function(){
+        TOPLEVEL.figure_out_scope();
+        if (ARGS.lint) {
+            TOPLEVEL.scope_warnings();
+        }
+    });
+}
+
+if (COMPRESS) {
+    time_it("squeeze", function(){
+        TOPLEVEL = TOPLEVEL.transform(compressor);
+    });
+}
+
+if (SCOPE_IS_NEEDED) {
+    time_it("scope", function(){
+        TOPLEVEL.figure_out_scope();
+        if (MANGLE) {
+            TOPLEVEL.compute_char_frequency(MANGLE);
+        }
+    });
+}
+
+if (MANGLE) time_it("mangle", function(){
+    TOPLEVEL.mangle_names(MANGLE);
+});
+time_it("generate", function(){
+    TOPLEVEL.print(output);
+});
+
+output = output.get();
+
+if (SOURCE_MAP) {
+    fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
+    output += "\n/*\n//@ sourceMappingURL=" + (ARGS.source_map_url || ARGS.source_map) + "\n*/";
+}
+
+if (OUTPUT_FILE) {
+    fs.writeFileSync(OUTPUT_FILE, output, "utf8");
+} else {
+    sys.print(output);
+    sys.error("\n");
+}
+
+if (ARGS.stats) {
+    sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", {
+        count: files.length
+    }));
+    for (var i in STATS) if (STATS.hasOwnProperty(i)) {
+        sys.error(UglifyJS.string_template("- {name}: {time}s", {
+            name: i,
+            time: (STATS[i] / 1000).toFixed(3)
+        }));
+    }
+}
+
+/* -----[ functions ]----- */
+
+function normalize(o) {
+    for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) {
+        o[i.replace(/-/g, "_")] = o[i];
+        delete o[i];
+    }
+}
+
+function getOptions(x, constants) {
+    x = ARGS[x];
+    if (!x) return null;
+    var ret = {};
+    if (x !== true) {
+        var ast;
+        try {
+            ast = UglifyJS.parse(x);
+        } catch(ex) {
+            if (ex instanceof UglifyJS.JS_Parse_Error) {
+                sys.error("Error parsing arguments in: " + x);
+                process.exit(1);
+            }
+        }
+        ast.walk(new UglifyJS.TreeWalker(function(node){
+            if (node instanceof UglifyJS.AST_Toplevel) return; // descend
+            if (node instanceof UglifyJS.AST_SimpleStatement) return; // descend
+            if (node instanceof UglifyJS.AST_Seq) return; // descend
+            if (node instanceof UglifyJS.AST_Assign) {
+                var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_");
+                var value = node.right;
+                if (constants)
+                    value = new Function("return (" + value.print_to_string() + ")")();
+                ret[name] = value;
+                return true;    // no descend
+            }
+            sys.error(node.TYPE)
+            sys.error("Error parsing arguments in: " + x);
+            process.exit(1);
+        }));
+    }
+    return ret;
+}
+
+function read_whole_file(filename) {
+    if (filename == "-") {
+        // XXX: this sucks.  How does one read the whole STDIN
+        // synchronously?
+        filename = "/dev/stdin";
+    }
+    try {
+        return fs.readFileSync(filename, "utf8");
+    } catch(ex) {
+        sys.error("ERROR: can't read file: " + filename);
+        process.exit(1);
+    }
+}
+
+function time_it(name, cont) {
+    var t1 = new Date().getTime();
+    var ret = cont();
+    if (ARGS.stats) {
+        var spent = new Date().getTime() - t1;
+        if (STATS[name]) STATS[name] += spent;
+        else STATS[name] = spent;
+    }
+    return ret;
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/0ef79031/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/ast.js
----------------------------------------------------------------------
diff --git a/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/ast.js b/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/ast.js
new file mode 100644
index 0000000..62bdd8d
--- /dev/null
+++ b/modules/webconfig/nodejs/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/ast.js
@@ -0,0 +1,964 @@
+/***********************************************************************
+
+  A JavaScript tokenizer / parser / beautifier / compressor.
+  https://github.com/mishoo/UglifyJS2
+
+  -------------------------------- (C) ---------------------------------
+
+                           Author: Mihai Bazon
+                         <mihai.bazon@gmail.com>
+                       http://mihai.bazon.net/blog
+
+  Distributed under the BSD license:
+
+    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+        * Redistributions of source code must retain the above
+          copyright notice, this list of conditions and the following
+          disclaimer.
+
+        * Redistributions in binary form must reproduce the above
+          copyright notice, this list of conditions and the following
+          disclaimer in the documentation and/or other materials
+          provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+
+ ***********************************************************************/
+
+"use strict";
+
+function DEFNODE(type, props, methods, base) {
+    if (arguments.length < 4) base = AST_Node;
+    if (!props) props = [];
+    else props = props.split(/\s+/);
+    var self_props = props;
+    if (base && base.PROPS)
+        props = props.concat(base.PROPS);
+    var code = "return function AST_" + type + "(props){ if (props) { ";
+    for (var i = props.length; --i >= 0;) {
+        code += "this." + props[i] + " = props." + props[i] + ";";
+    }
+    var proto = base && new base;
+    if (proto && proto.initialize || (methods && methods.initialize))
+        code += "this.initialize();";
+    code += "}}";
+    var ctor = new Function(code)();
+    if (proto) {
+        ctor.prototype = proto;
+        ctor.BASE = base;
+    }
+    if (base) base.SUBCLASSES.push(ctor);
+    ctor.prototype.CTOR = ctor;
+    ctor.PROPS = props || null;
+    ctor.SELF_PROPS = self_props;
+    ctor.SUBCLASSES = [];
+    if (type) {
+        ctor.prototype.TYPE = ctor.TYPE = type;
+    }
+    if (methods) for (i in methods) if (methods.hasOwnProperty(i)) {
+        if (/^\$/.test(i)) {
+            ctor[i.substr(1)] = methods[i];
+        } else {
+            ctor.prototype[i] = methods[i];
+        }
+    }
+    ctor.DEFMETHOD = function(name, method) {
+        this.prototype[name] = method;
+    };
+    return ctor;
+};
+
+var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", {
+}, null);
+
+var AST_Node = DEFNODE("Node", "start end", {
+    clone: function() {
+        return new this.CTOR(this);
+    },
+    $documentation: "Base class of all AST nodes",
+    $propdoc: {
+        start: "[AST_Token] The first token of this node",
+        end: "[AST_Token] The last token of this node"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this);
+    },
+    walk: function(visitor) {
+        return this._walk(visitor); // not sure the indirection will be any help
+    }
+}, null);
+
+AST_Node.warn_function = null;
+AST_Node.warn = function(txt, props) {
+    if (AST_Node.warn_function)
+        AST_Node.warn_function(string_template(txt, props));
+};
+
+/* -----[ statements ]----- */
+
+var AST_Statement = DEFNODE("Statement", null, {
+    $documentation: "Base class of all statements",
+});
+
+var AST_Debugger = DEFNODE("Debugger", null, {
+    $documentation: "Represents a debugger statement",
+}, AST_Statement);
+
+var AST_Directive = DEFNODE("Directive", "value scope", {
+    $documentation: "Represents a directive, like \"use strict\";",
+    $propdoc: {
+        value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
+        scope: "[AST_Scope/S] The scope that this directive affects"
+    },
+}, AST_Statement);
+
+var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
+    $documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
+    $propdoc: {
+        body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.body._walk(visitor);
+        });
+    }
+}, AST_Statement);
+
+function walk_body(node, visitor) {
+    if (node.body instanceof AST_Statement) {
+        node.body._walk(visitor);
+    }
+    else node.body.forEach(function(stat){
+        stat._walk(visitor);
+    });
+};
+
+var AST_Block = DEFNODE("Block", "body", {
+    $documentation: "A body of statements (usually bracketed)",
+    $propdoc: {
+        body: "[AST_Statement*] an array of statements"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            walk_body(this, visitor);
+        });
+    }
+}, AST_Statement);
+
+var AST_BlockStatement = DEFNODE("BlockStatement", null, {
+    $documentation: "A block statement",
+}, AST_Block);
+
+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_StatementWithBody = DEFNODE("StatementWithBody", "body", {
+    $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
+    $propdoc: {
+        body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.body._walk(visitor);
+        });
+    }
+}, AST_Statement);
+
+var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
+    $documentation: "Statement with a label",
+    $propdoc: {
+        label: "[AST_Label] a label definition"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.label._walk(visitor);
+            this.body._walk(visitor);
+        });
+    }
+}, AST_StatementWithBody);
+
+var AST_DWLoop = DEFNODE("DWLoop", "condition", {
+    $documentation: "Base class for do/while statements",
+    $propdoc: {
+        condition: "[AST_Node] the loop condition.  Should not be instanceof AST_Statement"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.condition._walk(visitor);
+            this.body._walk(visitor);
+        });
+    }
+}, AST_StatementWithBody);
+
+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",
+    $propdoc: {
+        init: "[AST_Node?] the `for` initialization code, or null if empty",
+        condition: "[AST_Node?] the `for` termination clause, or null if empty",
+        step: "[AST_Node?] the `for` update clause, or null if empty"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            if (this.init) this.init._walk(visitor);
+            if (this.condition) this.condition._walk(visitor);
+            if (this.step) this.step._walk(visitor);
+            this.body._walk(visitor);
+        });
+    }
+}, AST_StatementWithBody);
+
+var AST_ForIn = DEFNODE("ForIn", "init name object", {
+    $documentation: "A `for ... in` statement",
+    $propdoc: {
+        init: "[AST_Node] the `for/in` initialization code",
+        name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
+        object: "[AST_Node] the object that we're looping through"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.init._walk(visitor);
+            this.object._walk(visitor);
+            this.body._walk(visitor);
+        });
+    }
+}, AST_StatementWithBody);
+
+var AST_With = DEFNODE("With", "expression", {
+    $documentation: "A `with` statement",
+    $propdoc: {
+        expression: "[AST_Node] the `with` expression"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.expression._walk(visitor);
+            this.body._walk(visitor);
+        });
+    }
+}, AST_StatementWithBody);
+
+/* -----[ scope and functions ]----- */
+
+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",
+    $propdoc: {
+        directives: "[string*/S] an array of directives declared in this scope",
+        variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
+        functions: "[Object/S] like `variables`, but only lists function declarations",
+        uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
+        uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
+        parent_scope: "[AST_Scope?/S] link to the parent scope",
+        enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
+        cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
+    },
+}, AST_Block);
+
+var AST_Toplevel = DEFNODE("Toplevel", "globals", {
+    $documentation: "The toplevel scope",
+    $propdoc: {
+        globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
+    },
+    wrap_commonjs: function(name, export_all) {
+        var self = this;
+        var to_export = [];
+        if (export_all) {
+            self.figure_out_scope();
+            self.walk(new TreeWalker(function(node){
+                if (node instanceof AST_SymbolDeclaration && node.definition().global) {
+                    if (!find_if(function(n){ return n.name == node.name }, to_export))
+                        to_export.push(node);
+                }
+            }));
+        }
+        var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))";
+        wrapped_tl = parse(wrapped_tl);
+        wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
+            if (node instanceof AST_SimpleStatement) {
+                node = node.body;
+                if (node instanceof AST_String) switch (node.getValue()) {
+                  case "$ORIG":
+                    return MAP.splice(self.body);
+                  case "$EXPORTS":
+                    var body = [];
+                    to_export.forEach(function(sym){
+                        body.push(new AST_SimpleStatement({
+                            body: new AST_Assign({
+                                left: new AST_Sub({
+                                    expression: new AST_SymbolRef({ name: "exports" }),
+                                    property: new AST_String({ value: sym.name }),
+                                }),
+                                operator: "=",
+                                right: new AST_SymbolRef(sym),
+                            }),
+                        }));
+                    });
+                    return MAP.splice(body);
+                }
+            }
+        }));
+        return wrapped_tl;
+    }
+}, AST_Scope);
+
+var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
+    $documentation: "Base class for functions",
+    $propdoc: {
+        name: "[AST_SymbolDeclaration?] the name of this function",
+        argnames: "[AST_SymbolFunarg*] array of function arguments",
+        uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            if (this.name) this.name._walk(visitor);
+            this.argnames.forEach(function(arg){
+                arg._walk(visitor);
+            });
+            walk_body(this, visitor);
+        });
+    }
+}, AST_Scope);
+
+var AST_Accessor = DEFNODE("Accessor", null, {
+    $documentation: "A setter/getter function"
+}, AST_Lambda);
+
+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`)"
+}, AST_Statement);
+
+var AST_Exit = DEFNODE("Exit", "value", {
+    $documentation: "Base class for “exits” (`return` and `throw`)",
+    $propdoc: {
+        value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, this.value && function(){
+            this.value._walk(visitor);
+        });
+    }
+}, 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`)",
+    $propdoc: {
+        label: "[AST_LabelRef?] the label, or null if none",
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, this.label && function(){
+            this.label._walk(visitor);
+        });
+    }
+}, 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 alternative", {
+    $documentation: "A `if` statement",
+    $propdoc: {
+        condition: "[AST_Node] the `if` condition",
+        alternative: "[AST_Statement?] the `else` part, or null if not present"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.condition._walk(visitor);
+            this.body._walk(visitor);
+            if (this.alternative) this.alternative._walk(visitor);
+        });
+    }
+}, AST_StatementWithBody);
+
+/* -----[ SWITCH ]----- */
+
+var AST_Switch = DEFNODE("Switch", "expression", {
+    $documentation: "A `switch` statement",
+    $propdoc: {
+        expression: "[AST_Node] the `switch` “discriminant”"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.expression._walk(visitor);
+            walk_body(this, visitor);
+        });
+    }
+}, AST_Block);
+
+var AST_SwitchBranch = DEFNODE("SwitchBranch", null, {
+    $documentation: "Base class for `switch` branches",
+}, AST_Block);
+
+var AST_Default = DEFNODE("Default", null, {
+    $documentation: "A `default` switch branch",
+}, AST_SwitchBranch);
+
+var AST_Case = DEFNODE("Case", "expression", {
+    $documentation: "A `case` switch branch",
+    $propdoc: {
+        expression: "[AST_Node] the `case` expression"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.expression._walk(visitor);
+            walk_body(this, visitor);
+        });
+    }
+}, AST_SwitchBranch);
+
+/* -----[ EXCEPTIONS ]----- */
+
+var AST_Try = DEFNODE("Try", "bcatch bfinally", {
+    $documentation: "A `try` statement",
+    $propdoc: {
+        bcatch: "[AST_Catch?] the catch block, or null if not present",
+        bfinally: "[AST_Finally?] the finally block, or null if not present"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            walk_body(this, visitor);
+            if (this.bcatch) this.bcatch._walk(visitor);
+            if (this.bfinally) this.bfinally._walk(visitor);
+        });
+    }
+}, AST_Block);
+
+// XXX: this is wrong according to ECMA-262 (12.4).  the catch block
+// should introduce another scope, as the argname should be visible
+// only inside the catch block.  However, doing it this way because of
+// IE which simply introduces the name in the surrounding scope.  If
+// 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",
+    $propdoc: {
+        argname: "[AST_SymbolCatch] symbol for the exception"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.argname._walk(visitor);
+            walk_body(this, visitor);
+        });
+    }
+}, AST_Block);
+
+var AST_Finally = DEFNODE("Finally", null, {
+    $documentation: "A `finally` node; only makes sense as part of a `try` statement"
+}, AST_Block);
+
+/* -----[ VAR/CONST ]----- */
+
+var AST_Definitions = DEFNODE("Definitions", "definitions", {
+    $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
+    $propdoc: {
+        definitions: "[AST_VarDef*] array of variable definitions"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.definitions.forEach(function(def){
+                def._walk(visitor);
+            });
+        });
+    }
+}, AST_Statement);
+
+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",
+    $propdoc: {
+        name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
+        value: "[AST_Node?] initializer, or null of there's no initializer"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.name._walk(visitor);
+            if (this.value) this.value._walk(visitor);
+        });
+    }
+});
+
+/* -----[ OTHER ]----- */
+
+var AST_Call = DEFNODE("Call", "expression args", {
+    $documentation: "A function call expression",
+    $propdoc: {
+        expression: "[AST_Node] expression to invoke as function",
+        args: "[AST_Node*] array of arguments"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.expression._walk(visitor);
+            this.args.forEach(function(arg){
+                arg._walk(visitor);
+            });
+        });
+    }
+});
+
+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", "car cdr", {
+    $documentation: "A sequence expression (two comma-separated expressions)",
+    $propdoc: {
+        car: "[AST_Node] first element in sequence",
+        cdr: "[AST_Node] second element in sequence"
+    },
+    $cons: function(x, y) {
+        var seq = new AST_Seq(x);
+        seq.car = x;
+        seq.cdr = y;
+        return seq;
+    },
+    $from_array: function(array) {
+        if (array.length == 0) return null;
+        if (array.length == 1) return array[0].clone();
+        var list = null;
+        for (var i = array.length; --i >= 0;) {
+            list = AST_Seq.cons(array[i], list);
+        }
+        var p = list;
+        while (p) {
+            if (p.cdr && !p.cdr.cdr) {
+                p.cdr = p.cdr.car;
+                break;
+            }
+            p = p.cdr;
+        }
+        return list;
+    },
+    to_array: function() {
+        var p = this, a = [];
+        while (p) {
+            a.push(p.car);
+            if (p.cdr && !(p.cdr instanceof AST_Seq)) {
+                a.push(p.cdr);
+                break;
+            }
+            p = p.cdr;
+        }
+        return a;
+    },
+    add: function(node) {
+        var p = this;
+        while (p) {
+            if (!(p.cdr instanceof AST_Seq)) {
+                var cell = AST_Seq.cons(p.cdr, node);
+                return p.cdr = cell;
+            }
+            p = p.cdr;
+        }
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.car._walk(visitor);
+            if (this.cdr) this.cdr._walk(visitor);
+        });
+    }
+});
+
+var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
+    $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`",
+    $propdoc: {
+        expression: "[AST_Node] the “container” expression",
+        property: "[AST_Node|string] the property to access.  For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"
+    }
+});
+
+var AST_Dot = DEFNODE("Dot", null, {
+    $documentation: "A dotted property access expression",
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.expression._walk(visitor);
+        });
+    }
+}, AST_PropAccess);
+
+var AST_Sub = DEFNODE("Sub", null, {
+    $documentation: "Index-style property access, i.e. `a[\"foo\"]`",
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.expression._walk(visitor);
+            this.property._walk(visitor);
+        });
+    }
+}, AST_PropAccess);
+
+var AST_Unary = DEFNODE("Unary", "operator expression", {
+    $documentation: "Base class for unary expressions",
+    $propdoc: {
+        operator: "[string] the operator",
+        expression: "[AST_Node] expression that this unary operator applies to"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.expression._walk(visitor);
+        });
+    }
+});
+
+var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {
+    $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
+}, AST_Unary);
+
+var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
+    $documentation: "Unary postfix expression, i.e. `i++`"
+}, AST_Unary);
+
+var AST_Binary = DEFNODE("Binary", "left operator right", {
+    $documentation: "Binary expression, i.e. `a + b`",
+    $propdoc: {
+        left: "[AST_Node] left-hand side expression",
+        operator: "[string] the operator",
+        right: "[AST_Node] right-hand side expression"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.left._walk(visitor);
+            this.right._walk(visitor);
+        });
+    }
+});
+
+var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {
+    $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
+    $propdoc: {
+        condition: "[AST_Node]",
+        consequent: "[AST_Node]",
+        alternative: "[AST_Node]"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.condition._walk(visitor);
+            this.consequent._walk(visitor);
+            this.alternative._walk(visitor);
+        });
+    }
+});
+
+var AST_Assign = DEFNODE("Assign", null, {
+    $documentation: "An assignment expression — `a = b + 5`",
+}, AST_Binary);
+
+/* -----[ LITERALS ]----- */
+
+var AST_Array = DEFNODE("Array", "elements", {
+    $documentation: "An array literal",
+    $propdoc: {
+        elements: "[AST_Node*] array of elements"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.elements.forEach(function(el){
+                el._walk(visitor);
+            });
+        });
+    }
+});
+
+var AST_Object = DEFNODE("Object", "properties", {
+    $documentation: "An object literal",
+    $propdoc: {
+        properties: "[AST_ObjectProperty*] array of properties"
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.properties.forEach(function(prop){
+                prop._walk(visitor);
+            });
+        });
+    }
+});
+
+var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
+    $documentation: "Base class for literal object properties",
+    $propdoc: {
+        key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code",
+        value: "[AST_Node] property value.  For setters and getters this is an AST_Function."
+    },
+    _walk: function(visitor) {
+        return visitor._visit(this, function(){
+            this.value._walk(visitor);
+        });
+    }
+});
+
+var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, {
+    $documentation: "A key: value object property",
+}, AST_ObjectProperty);
+
+var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
+    $documentation: "An object setter property",
+}, AST_ObjectProperty);
+
+var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
+    $documentation: "An object getter property",
+}, AST_ObjectProperty);
+
+var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
+    $propdoc: {
+        name: "[string] name of this symbol",
+        scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
+        thedef: "[SymbolDef/S] the definition of this symbol"
+    },
+    $documentation: "Base class for all symbols",
+});
+
+var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
+    $documentation: "The name of a property accessor (setter/getter function)"
+}, AST_Symbol);
+
+var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
+    $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
+    $propdoc: {
+        init: "[AST_Node*/S] array of initializers for this declaration."
+    }
+}, AST_Symbol);
+
+var AST_SymbolVar = DEFNODE("SymbolVar", null, {
+    $documentation: "Symbol defining a variable",
+}, AST_SymbolDeclaration);
+
+var AST_SymbolConst = DEFNODE("SymbolConst", null, {
+    $documentation: "A constant declaration"
+}, AST_SymbolDeclaration);
+
+var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
+    $documentation: "Symbol naming a function argument",
+}, AST_SymbolVar);
+
+var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
+    $documentation: "Symbol defining a function",
+}, AST_SymbolDeclaration);
+
+var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
+    $documentation: "Symbol naming a function expression",
+}, AST_SymbolDeclaration);
+
+var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
+    $documentation: "Symbol naming the exception in catch",
+}, AST_SymbolDeclaration);
+
+var AST_Label = DEFNODE("Label", "references", {
+    $documentation: "Symbol naming a label (declaration)",
+    $propdoc: {
+        references: "[AST_LabelRef*] a list of nodes referring to this label"
+    }
+}, AST_Symbol);
+
+var AST_SymbolRef = DEFNODE("SymbolRef", null, {
+    $documentation: "Reference to some symbol (not definition/declaration)",
+}, AST_Symbol);
+
+var AST_LabelRef = DEFNODE("LabelRef", null, {
+    $documentation: "Reference to a label symbol",
+}, AST_Symbol);
+
+var AST_This = DEFNODE("This", null, {
+    $documentation: "The `this` symbol",
+}, AST_Symbol);
+
+var AST_Constant = DEFNODE("Constant", null, {
+    $documentation: "Base class for all constants",
+    getValue: function() {
+        return this.value;
+    }
+});
+
+var AST_String = DEFNODE("String", "value", {
+    $documentation: "A string literal",
+    $propdoc: {
+        value: "[string] the contents of this string"
+    }
+}, AST_Constant);
+
+var AST_Number = DEFNODE("Number", "value", {
+    $documentation: "A number literal",
+    $propdoc: {
+        value: "[number] the numeric value"
+    }
+}, AST_Constant);
+
+var AST_RegExp = DEFNODE("RegExp", "value", {
+    $documentation: "A regexp literal",
+    $propdoc: {
+        value: "[RegExp] the actual regexp"
+    }
+}, AST_Constant);
+
+var AST_Atom = DEFNODE("Atom", null, {
+    $documentation: "Base class for atoms",
+}, AST_Constant);
+
+var AST_Null = DEFNODE("Null", null, {
+    $documentation: "The `null` atom",
+    value: null
+}, AST_Atom);
+
+var AST_NaN = DEFNODE("NaN", null, {
+    $documentation: "The impossible value",
+    value: 0/0
+}, AST_Atom);
+
+var AST_Undefined = DEFNODE("Undefined", null, {
+    $documentation: "The `undefined` value",
+    value: (function(){}())
+}, AST_Atom);
+
+var AST_Hole = DEFNODE("Hole", null, {
+    $documentation: "A hole in an array",
+    value: (function(){}())
+}, AST_Atom);
+
+var AST_Infinity = DEFNODE("Infinity", null, {
+    $documentation: "The `Infinity` value",
+    value: 1/0
+}, AST_Atom);
+
+var AST_Boolean = DEFNODE("Boolean", null, {
+    $documentation: "Base class for booleans",
+}, AST_Atom);
+
+var AST_False = DEFNODE("False", null, {
+    $documentation: "The `false` atom",
+    value: false
+}, AST_Boolean);
+
+var AST_True = DEFNODE("True", null, {
+    $documentation: "The `true` atom",
+    value: true
+}, AST_Boolean);
+
+/* -----[ TreeWalker ]----- */
+
+function TreeWalker(callback) {
+    this.visit = callback;
+    this.stack = [];
+};
+TreeWalker.prototype = {
+    _visit: function(node, descend) {
+        this.stack.push(node);
+        var ret = this.visit(node, descend ? function(){
+            descend.call(node);
+        } : noop);
+        if (!ret && descend) {
+            descend.call(node);
+        }
+        this.stack.pop();
+        return ret;
+    },
+    parent: function(n) {
+        return this.stack[this.stack.length - 2 - (n || 0)];
+    },
+    push: function (node) {
+        this.stack.push(node);
+    },
+    pop: function() {
+        return this.stack.pop();
+    },
+    self: function() {
+        return this.stack[this.stack.length - 1];
+    },
+    find_parent: function(type) {
+        var stack = this.stack;
+        for (var i = stack.length; --i >= 0;) {
+            var x = stack[i];
+            if (x instanceof type) return x;
+        }
+    },
+    in_boolean_context: function() {
+        var stack = this.stack;
+        var i = stack.length, self = stack[--i];
+        while (i > 0) {
+            var p = stack[--i];
+            if ((p instanceof AST_If           && p.condition === self) ||
+                (p instanceof AST_Conditional  && p.condition === self) ||
+                (p instanceof AST_DWLoop       && p.condition === self) ||
+                (p instanceof AST_For          && p.condition === self) ||
+                (p instanceof AST_UnaryPrefix  && p.operator == "!" && p.expression === self))
+            {
+                return true;
+            }
+            if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))
+                return false;
+            self = p;
+        }
+    },
+    loopcontrol_target: function(label) {
+        var stack = this.stack;
+        if (label) {
+            for (var i = stack.length; --i >= 0;) {
+                var x = stack[i];
+                if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
+                    return x.body;
+                }
+            }
+        } else {
+            for (var i = stack.length; --i >= 0;) {
+                var x = stack[i];
+                if (x instanceof AST_Switch
+                    || x instanceof AST_For
+                    || x instanceof AST_ForIn
+                    || x instanceof AST_DWLoop) return x;
+            }
+        }
+    }
+};


Mime
View raw message