Tizen 2.0 Release
[platform/framework/web/web-ui-fw.git] / libs / js / jquery-mobile-1.2.0 / node_modules / grunt / node_modules / nodeunit / node_modules / tap / node_modules / runforcover / node_modules / bunker / node_modules / burrito / example / web / bs.js
1 var require = function (file, cwd) {
2     var resolved = require.resolve(file, cwd || '/');
3     var mod = require.modules[resolved];
4     if (!mod) throw new Error(
5         'Failed to resolve module ' + file + ', tried ' + resolved
6     );
7     var res = mod._cached ? mod._cached : mod();
8     return res;
9 }
10 var __require = require;
11
12 require.paths = [];
13 require.modules = {};
14 require.extensions = [".js",".coffee"];
15
16 require.resolve = (function () {
17     var core = {
18         'assert': true,
19         'events': true,
20         'fs': true,
21         'path': true,
22         'vm': true
23     };
24     
25     return function (x, cwd) {
26         if (!cwd) cwd = '/';
27         
28         if (core[x]) return x;
29         var path = require.modules.path();
30         var y = cwd || '.';
31         
32         if (x.match(/^(?:\.\.?\/|\/)/)) {
33             var m = loadAsFileSync(path.resolve(y, x))
34                 || loadAsDirectorySync(path.resolve(y, x));
35             if (m) return m;
36         }
37         
38         var n = loadNodeModulesSync(x, y);
39         if (n) return n;
40         
41         throw new Error("Cannot find module '" + x + "'");
42         
43         function loadAsFileSync (x) {
44             if (require.modules[x]) {
45                 return x;
46             }
47             
48             for (var i = 0; i < require.extensions.length; i++) {
49                 var ext = require.extensions[i];
50                 if (require.modules[x + ext]) return x + ext;
51             }
52         }
53         
54         function loadAsDirectorySync (x) {
55             x = x.replace(/\/+$/, '');
56             var pkgfile = x + '/package.json';
57             if (require.modules[pkgfile]) {
58                 var pkg = require.modules[pkgfile]();
59                 var b = pkg.browserify;
60                 if (typeof b === 'object' && b.main) {
61                     var m = loadAsFileSync(path.resolve(x, b.main));
62                     if (m) return m;
63                 }
64                 else if (typeof b === 'string') {
65                     var m = loadAsFileSync(path.resolve(x, b));
66                     if (m) return m;
67                 }
68                 else if (pkg.main) {
69                     var m = loadAsFileSync(path.resolve(x, pkg.main));
70                     if (m) return m;
71                 }
72             }
73             
74             return loadAsFileSync(x + '/index');
75         }
76         
77         function loadNodeModulesSync (x, start) {
78             var dirs = nodeModulesPathsSync(start);
79             for (var i = 0; i < dirs.length; i++) {
80                 var dir = dirs[i];
81                 var m = loadAsFileSync(dir + '/' + x);
82                 if (m) return m;
83                 var n = loadAsDirectorySync(dir + '/' + x);
84                 if (n) return n;
85             }
86             
87             var m = loadAsFileSync(x);
88             if (m) return m;
89         }
90         
91         function nodeModulesPathsSync (start) {
92             var parts;
93             if (start === '/') parts = [ '' ];
94             else parts = path.normalize(start).split('/');
95             
96             var dirs = [];
97             for (var i = parts.length - 1; i >= 0; i--) {
98                 if (parts[i] === 'node_modules') continue;
99                 var dir = parts.slice(0, i + 1).join('/') + '/node_modules';
100                 dirs.push(dir);
101             }
102             
103             return dirs;
104         }
105     };
106 })();
107
108 require.alias = function (from, to) {
109     var path = require.modules.path();
110     var res = null;
111     try {
112         res = require.resolve(from + '/package.json', '/');
113     }
114     catch (err) {
115         res = require.resolve(from, '/');
116     }
117     var basedir = path.dirname(res);
118     
119     var keys = Object_keys(require.modules);
120     
121     for (var i = 0; i < keys.length; i++) {
122         var key = keys[i];
123         if (key.slice(0, basedir.length + 1) === basedir + '/') {
124             var f = key.slice(basedir.length);
125             require.modules[to + f] = require.modules[basedir + f];
126         }
127         else if (key === basedir) {
128             require.modules[to] = require.modules[basedir];
129         }
130     }
131 };
132
133 var Object_keys = Object.keys || function (obj) {
134     var res = [];
135     for (var key in obj) res.push(key)
136     return res;
137 };
138
139 if (typeof process === 'undefined') process = {};
140
141 if (!process.nextTick) process.nextTick = function (fn) {
142     setTimeout(fn, 0);
143 };
144
145 if (!process.title) process.title = 'browser';
146
147 if (!process.binding) process.binding = function (name) {
148     if (name === 'evals') return require('vm')
149     else throw new Error('No such module')
150 };
151
152 if (!process.cwd) process.cwd = function () { return '.' };
153
154 require.modules["path"] = function () {
155     var module = { exports : {} };
156     var exports = module.exports;
157     var __dirname = ".";
158     var __filename = "path";
159     
160     var require = function (file) {
161         return __require(file, ".");
162     };
163     
164     require.resolve = function (file) {
165         return __require.resolve(name, ".");
166     };
167     
168     require.modules = __require.modules;
169     __require.modules["path"]._cached = module.exports;
170     
171     (function () {
172         function filter (xs, fn) {
173     var res = [];
174     for (var i = 0; i < xs.length; i++) {
175         if (fn(xs[i], i, xs)) res.push(xs[i]);
176     }
177     return res;
178 }
179
180 // resolves . and .. elements in a path array with directory names there
181 // must be no slashes, empty elements, or device names (c:\) in the array
182 // (so also no leading and trailing slashes - it does not distinguish
183 // relative and absolute paths)
184 function normalizeArray(parts, allowAboveRoot) {
185   // if the path tries to go above the root, `up` ends up > 0
186   var up = 0;
187   for (var i = parts.length; i >= 0; i--) {
188     var last = parts[i];
189     if (last == '.') {
190       parts.splice(i, 1);
191     } else if (last === '..') {
192       parts.splice(i, 1);
193       up++;
194     } else if (up) {
195       parts.splice(i, 1);
196       up--;
197     }
198   }
199
200   // if the path is allowed to go above the root, restore leading ..s
201   if (allowAboveRoot) {
202     for (; up--; up) {
203       parts.unshift('..');
204     }
205   }
206
207   return parts;
208 }
209
210 // Regex to split a filename into [*, dir, basename, ext]
211 // posix version
212 var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
213
214 // path.resolve([from ...], to)
215 // posix version
216 exports.resolve = function() {
217 var resolvedPath = '',
218     resolvedAbsolute = false;
219
220 for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
221   var path = (i >= 0)
222       ? arguments[i]
223       : process.cwd();
224
225   // Skip empty and invalid entries
226   if (typeof path !== 'string' || !path) {
227     continue;
228   }
229
230   resolvedPath = path + '/' + resolvedPath;
231   resolvedAbsolute = path.charAt(0) === '/';
232 }
233
234 // At this point the path should be resolved to a full absolute path, but
235 // handle relative paths to be safe (might happen when process.cwd() fails)
236
237 // Normalize the path
238 resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
239     return !!p;
240   }), !resolvedAbsolute).join('/');
241
242   return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
243 };
244
245 // path.normalize(path)
246 // posix version
247 exports.normalize = function(path) {
248 var isAbsolute = path.charAt(0) === '/',
249     trailingSlash = path.slice(-1) === '/';
250
251 // Normalize the path
252 path = normalizeArray(filter(path.split('/'), function(p) {
253     return !!p;
254   }), !isAbsolute).join('/');
255
256   if (!path && !isAbsolute) {
257     path = '.';
258   }
259   if (path && trailingSlash) {
260     path += '/';
261   }
262   
263   return (isAbsolute ? '/' : '') + path;
264 };
265
266
267 // posix version
268 exports.join = function() {
269   var paths = Array.prototype.slice.call(arguments, 0);
270   return exports.normalize(filter(paths, function(p, index) {
271     return p && typeof p === 'string';
272   }).join('/'));
273 };
274
275
276 exports.dirname = function(path) {
277   var dir = splitPathRe.exec(path)[1] || '';
278   var isWindows = false;
279   if (!dir) {
280     // No dirname
281     return '.';
282   } else if (dir.length === 1 ||
283       (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
284     // It is just a slash or a drive letter with a slash
285     return dir;
286   } else {
287     // It is a full dirname, strip trailing slash
288     return dir.substring(0, dir.length - 1);
289   }
290 };
291
292
293 exports.basename = function(path, ext) {
294   var f = splitPathRe.exec(path)[2] || '';
295   // TODO: make this comparison case-insensitive on windows?
296   if (ext && f.substr(-1 * ext.length) === ext) {
297     f = f.substr(0, f.length - ext.length);
298   }
299   return f;
300 };
301
302
303 exports.extname = function(path) {
304   return splitPathRe.exec(path)[3] || '';
305 };
306 ;
307     }).call(module.exports);
308     
309     __require.modules["path"]._cached = module.exports;
310     return module.exports;
311 };
312
313 require.modules["/node_modules/burrito/package.json"] = function () {
314     var module = { exports : {} };
315     var exports = module.exports;
316     var __dirname = "/node_modules/burrito";
317     var __filename = "/node_modules/burrito/package.json";
318     
319     var require = function (file) {
320         return __require(file, "/node_modules/burrito");
321     };
322     
323     require.resolve = function (file) {
324         return __require.resolve(name, "/node_modules/burrito");
325     };
326     
327     require.modules = __require.modules;
328     __require.modules["/node_modules/burrito/package.json"]._cached = module.exports;
329     
330     (function () {
331         module.exports = {"name":"burrito","description":"Wrap up expressions with a trace function while walking the AST with rice and beans on the side","version":"0.2.8","repository":{"type":"git","url":"git://github.com/substack/node-burrito.git"},"main":"./index.js","keywords":["trace","ast","walk","syntax","source","tree","uglify"],"directories":{"lib":".","example":"example","test":"test"},"scripts":{"test":"expresso"},"dependencies":{"traverse":">=0.5.1 <0.6","uglify-js":"1.0.4"},"devDependencies":{"expresso":"=0.7.x"},"engines":{"node":">=0.4.0"},"license":"BSD","author":{"name":"James Halliday","email":"mail@substack.net","url":"http://substack.net"}};
332     }).call(module.exports);
333     
334     __require.modules["/node_modules/burrito/package.json"]._cached = module.exports;
335     return module.exports;
336 };
337
338 require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"] = function () {
339     var module = { exports : {} };
340     var exports = module.exports;
341     var __dirname = "/node_modules/burrito/node_modules/uglify-js";
342     var __filename = "/node_modules/burrito/node_modules/uglify-js/package.json";
343     
344     var require = function (file) {
345         return __require(file, "/node_modules/burrito/node_modules/uglify-js");
346     };
347     
348     require.resolve = function (file) {
349         return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js");
350     };
351     
352     require.modules = __require.modules;
353     __require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"]._cached = module.exports;
354     
355     (function () {
356         module.exports = {"name":"uglify-js","author":{"name":"Mihai Bazon","email":"mihai.bazon@gmail.com","url":"http://mihai.bazon.net/blog"},"version":"1.0.4","main":"./uglify-js.js","bin":{"uglifyjs":"./bin/uglifyjs"},"repository":{"type":"git","url":"git@github.com:mishoo/UglifyJS.git"}};
357     }).call(module.exports);
358     
359     __require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"]._cached = module.exports;
360     return module.exports;
361 };
362
363 require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"] = function () {
364     var module = { exports : {} };
365     var exports = module.exports;
366     var __dirname = "/node_modules/burrito/node_modules/uglify-js";
367     var __filename = "/node_modules/burrito/node_modules/uglify-js/uglify-js.js";
368     
369     var require = function (file) {
370         return __require(file, "/node_modules/burrito/node_modules/uglify-js");
371     };
372     
373     require.resolve = function (file) {
374         return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js");
375     };
376     
377     require.modules = __require.modules;
378     __require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"]._cached = module.exports;
379     
380     (function () {
381         //convienence function(src, [options]);
382 function uglify(orig_code, options){
383   options || (options = {});
384   var jsp = uglify.parser;
385   var pro = uglify.uglify;
386
387   var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST
388   ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names
389   ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations
390   var final_code = pro.gen_code(ast, options.gen_options); // compressed code here
391   return final_code;
392 };
393
394 uglify.parser = require("./lib/parse-js");
395 uglify.uglify = require("./lib/process");
396
397 module.exports = uglify;
398     }).call(module.exports);
399     
400     __require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"]._cached = module.exports;
401     return module.exports;
402 };
403
404 require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"] = function () {
405     var module = { exports : {} };
406     var exports = module.exports;
407     var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib";
408     var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js";
409     
410     var require = function (file) {
411         return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib");
412     };
413     
414     require.resolve = function (file) {
415         return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib");
416     };
417     
418     require.modules = __require.modules;
419     __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"]._cached = module.exports;
420     
421     (function () {
422         /***********************************************************************
423
424   A JavaScript tokenizer / parser / beautifier / compressor.
425
426   This version is suitable for Node.js.  With minimal changes (the
427   exports stuff) it should work on any JS platform.
428
429   This file contains the tokenizer/parser.  It is a port to JavaScript
430   of parse-js [1], a JavaScript parser library written in Common Lisp
431   by Marijn Haverbeke.  Thank you Marijn!
432
433   [1] http://marijn.haverbeke.nl/parse-js/
434
435   Exported functions:
436
437     - tokenizer(code) -- returns a function.  Call the returned
438       function to fetch the next token.
439
440     - parse(code) -- returns an AST of the given JavaScript code.
441
442   -------------------------------- (C) ---------------------------------
443
444                            Author: Mihai Bazon
445                          <mihai.bazon@gmail.com>
446                        http://mihai.bazon.net/blog
447
448   Distributed under the BSD license:
449
450     Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
451     Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
452
453     Redistribution and use in source and binary forms, with or without
454     modification, are permitted provided that the following conditions
455     are met:
456
457         * Redistributions of source code must retain the above
458           copyright notice, this list of conditions and the following
459           disclaimer.
460
461         * Redistributions in binary form must reproduce the above
462           copyright notice, this list of conditions and the following
463           disclaimer in the documentation and/or other materials
464           provided with the distribution.
465
466     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
467     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
468     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
469     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
470     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
471     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
472     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
473     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
474     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
475     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
476     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
477     SUCH DAMAGE.
478
479  ***********************************************************************/
480
481 /* -----[ Tokenizer (constants) ]----- */
482
483 var KEYWORDS = array_to_hash([
484         "break",
485         "case",
486         "catch",
487         "const",
488         "continue",
489         "default",
490         "delete",
491         "do",
492         "else",
493         "finally",
494         "for",
495         "function",
496         "if",
497         "in",
498         "instanceof",
499         "new",
500         "return",
501         "switch",
502         "throw",
503         "try",
504         "typeof",
505         "var",
506         "void",
507         "while",
508         "with"
509 ]);
510
511 var RESERVED_WORDS = array_to_hash([
512         "abstract",
513         "boolean",
514         "byte",
515         "char",
516         "class",
517         "debugger",
518         "double",
519         "enum",
520         "export",
521         "extends",
522         "final",
523         "float",
524         "goto",
525         "implements",
526         "import",
527         "int",
528         "interface",
529         "long",
530         "native",
531         "package",
532         "private",
533         "protected",
534         "public",
535         "short",
536         "static",
537         "super",
538         "synchronized",
539         "throws",
540         "transient",
541         "volatile"
542 ]);
543
544 var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([
545         "return",
546         "new",
547         "delete",
548         "throw",
549         "else",
550         "case"
551 ]);
552
553 var KEYWORDS_ATOM = array_to_hash([
554         "false",
555         "null",
556         "true",
557         "undefined"
558 ]);
559
560 var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^"));
561
562 var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
563 var RE_OCT_NUMBER = /^0[0-7]+$/;
564 var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
565
566 var OPERATORS = array_to_hash([
567         "in",
568         "instanceof",
569         "typeof",
570         "new",
571         "void",
572         "delete",
573         "++",
574         "--",
575         "+",
576         "-",
577         "!",
578         "~",
579         "&",
580         "|",
581         "^",
582         "*",
583         "/",
584         "%",
585         ">>",
586         "<<",
587         ">>>",
588         "<",
589         ">",
590         "<=",
591         ">=",
592         "==",
593         "===",
594         "!=",
595         "!==",
596         "?",
597         "=",
598         "+=",
599         "-=",
600         "/=",
601         "*=",
602         "%=",
603         ">>=",
604         "<<=",
605         ">>>=",
606         "|=",
607         "^=",
608         "&=",
609         "&&",
610         "||"
611 ]);
612
613 var WHITESPACE_CHARS = array_to_hash(characters(" \u00a0\n\r\t\f\v\u200b"));
614
615 var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{}(,.;:"));
616
617 var PUNC_CHARS = array_to_hash(characters("[]{}(),;:"));
618
619 var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy"));
620
621 /* -----[ Tokenizer ]----- */
622
623 // regexps adapted from http://xregexp.com/plugins/#unicode
624 var UNICODE = {
625         letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),
626         non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"),
627         space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"),
628         connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
629 };
630
631 function is_letter(ch) {
632         return UNICODE.letter.test(ch);
633 };
634
635 function is_digit(ch) {
636         ch = ch.charCodeAt(0);
637         return ch >= 48 && ch <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9
638 };
639
640 function is_alphanumeric_char(ch) {
641         return is_digit(ch) || is_letter(ch);
642 };
643
644 function is_unicode_combining_mark(ch) {
645         return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
646 };
647
648 function is_unicode_connector_punctuation(ch) {
649         return UNICODE.connector_punctuation.test(ch);
650 };
651
652 function is_identifier_start(ch) {
653         return ch == "$" || ch == "_" || is_letter(ch);
654 };
655
656 function is_identifier_char(ch) {
657         return is_identifier_start(ch)
658                 || is_unicode_combining_mark(ch)
659                 || is_digit(ch)
660                 || is_unicode_connector_punctuation(ch)
661                 || ch == "\u200c" // zero-width non-joiner <ZWNJ>
662                 || ch == "\u200d" // zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
663         ;
664 };
665
666 function parse_js_number(num) {
667         if (RE_HEX_NUMBER.test(num)) {
668                 return parseInt(num.substr(2), 16);
669         } else if (RE_OCT_NUMBER.test(num)) {
670                 return parseInt(num.substr(1), 8);
671         } else if (RE_DEC_NUMBER.test(num)) {
672                 return parseFloat(num);
673         }
674 };
675
676 function JS_Parse_Error(message, line, col, pos) {
677         this.message = message;
678         this.line = line;
679         this.col = col;
680         this.pos = pos;
681         try {
682                 ({})();
683         } catch(ex) {
684                 this.stack = ex.stack;
685         };
686 };
687
688 JS_Parse_Error.prototype.toString = function() {
689         return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
690 };
691
692 function js_error(message, line, col, pos) {
693         throw new JS_Parse_Error(message, line, col, pos);
694 };
695
696 function is_token(token, type, val) {
697         return token.type == type && (val == null || token.value == val);
698 };
699
700 var EX_EOF = {};
701
702 function tokenizer($TEXT) {
703
704         var S = {
705                 text            : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''),
706                 pos             : 0,
707                 tokpos          : 0,
708                 line            : 0,
709                 tokline         : 0,
710                 col             : 0,
711                 tokcol          : 0,
712                 newline_before  : false,
713                 regex_allowed   : false,
714                 comments_before : []
715         };
716
717         function peek() { return S.text.charAt(S.pos); };
718
719         function next(signal_eof) {
720                 var ch = S.text.charAt(S.pos++);
721                 if (signal_eof && !ch)
722                         throw EX_EOF;
723                 if (ch == "\n") {
724                         S.newline_before = true;
725                         ++S.line;
726                         S.col = 0;
727                 } else {
728                         ++S.col;
729                 }
730                 return ch;
731         };
732
733         function eof() {
734                 return !S.peek();
735         };
736
737         function find(what, signal_eof) {
738                 var pos = S.text.indexOf(what, S.pos);
739                 if (signal_eof && pos == -1) throw EX_EOF;
740                 return pos;
741         };
742
743         function start_token() {
744                 S.tokline = S.line;
745                 S.tokcol = S.col;
746                 S.tokpos = S.pos;
747         };
748
749         function token(type, value, is_comment) {
750                 S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) ||
751                                    (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) ||
752                                    (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value)));
753                 var ret = {
754                         type  : type,
755                         value : value,
756                         line  : S.tokline,
757                         col   : S.tokcol,
758                         pos   : S.tokpos,
759                         nlb   : S.newline_before
760                 };
761                 if (!is_comment) {
762                         ret.comments_before = S.comments_before;
763                         S.comments_before = [];
764                 }
765                 S.newline_before = false;
766                 return ret;
767         };
768
769         function skip_whitespace() {
770                 while (HOP(WHITESPACE_CHARS, peek()))
771                         next();
772         };
773
774         function read_while(pred) {
775                 var ret = "", ch = peek(), i = 0;
776                 while (ch && pred(ch, i++)) {
777                         ret += next();
778                         ch = peek();
779                 }
780                 return ret;
781         };
782
783         function parse_error(err) {
784                 js_error(err, S.tokline, S.tokcol, S.tokpos);
785         };
786
787         function read_num(prefix) {
788                 var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
789                 var num = read_while(function(ch, i){
790                         if (ch == "x" || ch == "X") {
791                                 if (has_x) return false;
792                                 return has_x = true;
793                         }
794                         if (!has_x && (ch == "E" || ch == "e")) {
795                                 if (has_e) return false;
796                                 return has_e = after_e = true;
797                         }
798                         if (ch == "-") {
799                                 if (after_e || (i == 0 && !prefix)) return true;
800                                 return false;
801                         }
802                         if (ch == "+") return after_e;
803                         after_e = false;
804                         if (ch == ".") {
805                                 if (!has_dot && !has_x)
806                                         return has_dot = true;
807                                 return false;
808                         }
809                         return is_alphanumeric_char(ch);
810                 });
811                 if (prefix)
812                         num = prefix + num;
813                 var valid = parse_js_number(num);
814                 if (!isNaN(valid)) {
815                         return token("num", valid);
816                 } else {
817                         parse_error("Invalid syntax: " + num);
818                 }
819         };
820
821         function read_escaped_char() {
822                 var ch = next(true);
823                 switch (ch) {
824                     case "n" : return "\n";
825                     case "r" : return "\r";
826                     case "t" : return "\t";
827                     case "b" : return "\b";
828                     case "v" : return "\v";
829                     case "f" : return "\f";
830                     case "0" : return "\0";
831                     case "x" : return String.fromCharCode(hex_bytes(2));
832                     case "u" : return String.fromCharCode(hex_bytes(4));
833                     default  : return ch;
834                 }
835         };
836
837         function hex_bytes(n) {
838                 var num = 0;
839                 for (; n > 0; --n) {
840                         var digit = parseInt(next(true), 16);
841                         if (isNaN(digit))
842                                 parse_error("Invalid hex-character pattern in string");
843                         num = (num << 4) | digit;
844                 }
845                 return num;
846         };
847
848         function read_string() {
849                 return with_eof_error("Unterminated string constant", function(){
850                         var quote = next(), ret = "";
851                         for (;;) {
852                                 var ch = next(true);
853                                 if (ch == "\\") ch = read_escaped_char();
854                                 else if (ch == quote) break;
855                                 ret += ch;
856                         }
857                         return token("string", ret);
858                 });
859         };
860
861         function read_line_comment() {
862                 next();
863                 var i = find("\n"), ret;
864                 if (i == -1) {
865                         ret = S.text.substr(S.pos);
866                         S.pos = S.text.length;
867                 } else {
868                         ret = S.text.substring(S.pos, i);
869                         S.pos = i;
870                 }
871                 return token("comment1", ret, true);
872         };
873
874         function read_multiline_comment() {
875                 next();
876                 return with_eof_error("Unterminated multiline comment", function(){
877                         var i = find("*/", true),
878                             text = S.text.substring(S.pos, i),
879                             tok = token("comment2", text, true);
880                         S.pos = i + 2;
881                         S.line += text.split("\n").length - 1;
882                         S.newline_before = text.indexOf("\n") >= 0;
883
884                         // https://github.com/mishoo/UglifyJS/issues/#issue/100
885                         if (/^@cc_on/i.test(text)) {
886                                 warn("WARNING: at line " + S.line);
887                                 warn("*** Found \"conditional comment\": " + text);
888                                 warn("*** UglifyJS DISCARDS ALL COMMENTS.  This means your code might no longer work properly in Internet Explorer.");
889                         }
890
891                         return tok;
892                 });
893         };
894
895         function read_name() {
896                 var backslash = false, name = "", ch;
897                 while ((ch = peek()) != null) {
898                         if (!backslash) {
899                                 if (ch == "\\") backslash = true, next();
900                                 else if (is_identifier_char(ch)) name += next();
901                                 else break;
902                         }
903                         else {
904                                 if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
905                                 ch = read_escaped_char();
906                                 if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
907                                 name += ch;
908                                 backslash = false;
909                         }
910                 }
911                 return name;
912         };
913
914         function read_regexp() {
915                 return with_eof_error("Unterminated regular expression", function(){
916                         var prev_backslash = false, regexp = "", ch, in_class = false;
917                         while ((ch = next(true))) if (prev_backslash) {
918                                 regexp += "\\" + ch;
919                                 prev_backslash = false;
920                         } else if (ch == "[") {
921                                 in_class = true;
922                                 regexp += ch;
923                         } else if (ch == "]" && in_class) {
924                                 in_class = false;
925                                 regexp += ch;
926                         } else if (ch == "/" && !in_class) {
927                                 break;
928                         } else if (ch == "\\") {
929                                 prev_backslash = true;
930                         } else {
931                                 regexp += ch;
932                         }
933                         var mods = read_name();
934                         return token("regexp", [ regexp, mods ]);
935                 });
936         };
937
938         function read_operator(prefix) {
939                 function grow(op) {
940                         if (!peek()) return op;
941                         var bigger = op + peek();
942                         if (HOP(OPERATORS, bigger)) {
943                                 next();
944                                 return grow(bigger);
945                         } else {
946                                 return op;
947                         }
948                 };
949                 return token("operator", grow(prefix || next()));
950         };
951
952         function handle_slash() {
953                 next();
954                 var regex_allowed = S.regex_allowed;
955                 switch (peek()) {
956                     case "/":
957                         S.comments_before.push(read_line_comment());
958                         S.regex_allowed = regex_allowed;
959                         return next_token();
960                     case "*":
961                         S.comments_before.push(read_multiline_comment());
962                         S.regex_allowed = regex_allowed;
963                         return next_token();
964                 }
965                 return S.regex_allowed ? read_regexp() : read_operator("/");
966         };
967
968         function handle_dot() {
969                 next();
970                 return is_digit(peek())
971                         ? read_num(".")
972                         : token("punc", ".");
973         };
974
975         function read_word() {
976                 var word = read_name();
977                 return !HOP(KEYWORDS, word)
978                         ? token("name", word)
979                         : HOP(OPERATORS, word)
980                         ? token("operator", word)
981                         : HOP(KEYWORDS_ATOM, word)
982                         ? token("atom", word)
983                         : token("keyword", word);
984         };
985
986         function with_eof_error(eof_error, cont) {
987                 try {
988                         return cont();
989                 } catch(ex) {
990                         if (ex === EX_EOF) parse_error(eof_error);
991                         else throw ex;
992                 }
993         };
994
995         function next_token(force_regexp) {
996                 if (force_regexp)
997                         return read_regexp();
998                 skip_whitespace();
999                 start_token();
1000                 var ch = peek();
1001                 if (!ch) return token("eof");
1002                 if (is_digit(ch)) return read_num();
1003                 if (ch == '"' || ch == "'") return read_string();
1004                 if (HOP(PUNC_CHARS, ch)) return token("punc", next());
1005                 if (ch == ".") return handle_dot();
1006                 if (ch == "/") return handle_slash();
1007                 if (HOP(OPERATOR_CHARS, ch)) return read_operator();
1008                 if (ch == "\\" || is_identifier_start(ch)) return read_word();
1009                 parse_error("Unexpected character '" + ch + "'");
1010         };
1011
1012         next_token.context = function(nc) {
1013                 if (nc) S = nc;
1014                 return S;
1015         };
1016
1017         return next_token;
1018
1019 };
1020
1021 /* -----[ Parser (constants) ]----- */
1022
1023 var UNARY_PREFIX = array_to_hash([
1024         "typeof",
1025         "void",
1026         "delete",
1027         "--",
1028         "++",
1029         "!",
1030         "~",
1031         "-",
1032         "+"
1033 ]);
1034
1035 var UNARY_POSTFIX = array_to_hash([ "--", "++" ]);
1036
1037 var ASSIGNMENT = (function(a, ret, i){
1038         while (i < a.length) {
1039                 ret[a[i]] = a[i].substr(0, a[i].length - 1);
1040                 i++;
1041         }
1042         return ret;
1043 })(
1044         ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="],
1045         { "=": true },
1046         0
1047 );
1048
1049 var PRECEDENCE = (function(a, ret){
1050         for (var i = 0, n = 1; i < a.length; ++i, ++n) {
1051                 var b = a[i];
1052                 for (var j = 0; j < b.length; ++j) {
1053                         ret[b[j]] = n;
1054                 }
1055         }
1056         return ret;
1057 })(
1058         [
1059                 ["||"],
1060                 ["&&"],
1061                 ["|"],
1062                 ["^"],
1063                 ["&"],
1064                 ["==", "===", "!=", "!=="],
1065                 ["<", ">", "<=", ">=", "in", "instanceof"],
1066                 [">>", "<<", ">>>"],
1067                 ["+", "-"],
1068                 ["*", "/", "%"]
1069         ],
1070         {}
1071 );
1072
1073 var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
1074
1075 var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
1076
1077 /* -----[ Parser ]----- */
1078
1079 function NodeWithToken(str, start, end) {
1080         this.name = str;
1081         this.start = start;
1082         this.end = end;
1083 };
1084
1085 NodeWithToken.prototype.toString = function() { return this.name; };
1086
1087 function parse($TEXT, exigent_mode, embed_tokens) {
1088
1089         var S = {
1090                 input       : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT,
1091                 token       : null,
1092                 prev        : null,
1093                 peeked      : null,
1094                 in_function : 0,
1095                 in_loop     : 0,
1096                 labels      : []
1097         };
1098
1099         S.token = next();
1100
1101         function is(type, value) {
1102                 return is_token(S.token, type, value);
1103         };
1104
1105         function peek() { return S.peeked || (S.peeked = S.input()); };
1106
1107         function next() {
1108                 S.prev = S.token;
1109                 if (S.peeked) {
1110                         S.token = S.peeked;
1111                         S.peeked = null;
1112                 } else {
1113                         S.token = S.input();
1114                 }
1115                 return S.token;
1116         };
1117
1118         function prev() {
1119                 return S.prev;
1120         };
1121
1122         function croak(msg, line, col, pos) {
1123                 var ctx = S.input.context();
1124                 js_error(msg,
1125                          line != null ? line : ctx.tokline,
1126                          col != null ? col : ctx.tokcol,
1127                          pos != null ? pos : ctx.tokpos);
1128         };
1129
1130         function token_error(token, msg) {
1131                 croak(msg, token.line, token.col);
1132         };
1133
1134         function unexpected(token) {
1135                 if (token == null)
1136                         token = S.token;
1137                 token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
1138         };
1139
1140         function expect_token(type, val) {
1141                 if (is(type, val)) {
1142                         return next();
1143                 }
1144                 token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type);
1145         };
1146
1147         function expect(punc) { return expect_token("punc", punc); };
1148
1149         function can_insert_semicolon() {
1150                 return !exigent_mode && (
1151                         S.token.nlb || is("eof") || is("punc", "}")
1152                 );
1153         };
1154
1155         function semicolon() {
1156                 if (is("punc", ";")) next();
1157                 else if (!can_insert_semicolon()) unexpected();
1158         };
1159
1160         function as() {
1161                 return slice(arguments);
1162         };
1163
1164         function parenthesised() {
1165                 expect("(");
1166                 var ex = expression();
1167                 expect(")");
1168                 return ex;
1169         };
1170
1171         function add_tokens(str, start, end) {
1172                 return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);
1173         };
1174
1175         function maybe_embed_tokens(parser) {
1176                 if (embed_tokens) return function() {
1177                         var start = S.token;
1178                         var ast = parser.apply(this, arguments);
1179                         ast[0] = add_tokens(ast[0], start, prev());
1180                         return ast;
1181                 };
1182                 else return parser;
1183         };
1184
1185         var statement = maybe_embed_tokens(function() {
1186                 if (is("operator", "/")) {
1187                         S.peeked = null;
1188                         S.token = S.input(true); // force regexp
1189                 }
1190                 switch (S.token.type) {
1191                     case "num":
1192                     case "string":
1193                     case "regexp":
1194                     case "operator":
1195                     case "atom":
1196                         return simple_statement();
1197
1198                     case "name":
1199                         return is_token(peek(), "punc", ":")
1200                                 ? labeled_statement(prog1(S.token.value, next, next))
1201                                 : simple_statement();
1202
1203                     case "punc":
1204                         switch (S.token.value) {
1205                             case "{":
1206                                 return as("block", block_());
1207                             case "[":
1208                             case "(":
1209                                 return simple_statement();
1210                             case ";":
1211                                 next();
1212                                 return as("block");
1213                             default:
1214                                 unexpected();
1215                         }
1216
1217                     case "keyword":
1218                         switch (prog1(S.token.value, next)) {
1219                             case "break":
1220                                 return break_cont("break");
1221
1222                             case "continue":
1223                                 return break_cont("continue");
1224
1225                             case "debugger":
1226                                 semicolon();
1227                                 return as("debugger");
1228
1229                             case "do":
1230                                 return (function(body){
1231                                         expect_token("keyword", "while");
1232                                         return as("do", prog1(parenthesised, semicolon), body);
1233                                 })(in_loop(statement));
1234
1235                             case "for":
1236                                 return for_();
1237
1238                             case "function":
1239                                 return function_(true);
1240
1241                             case "if":
1242                                 return if_();
1243
1244                             case "return":
1245                                 if (S.in_function == 0)
1246                                         croak("'return' outside of function");
1247                                 return as("return",
1248                                           is("punc", ";")
1249                                           ? (next(), null)
1250                                           : can_insert_semicolon()
1251                                           ? null
1252                                           : prog1(expression, semicolon));
1253
1254                             case "switch":
1255                                 return as("switch", parenthesised(), switch_block_());
1256
1257                             case "throw":
1258                                 return as("throw", prog1(expression, semicolon));
1259
1260                             case "try":
1261                                 return try_();
1262
1263                             case "var":
1264                                 return prog1(var_, semicolon);
1265
1266                             case "const":
1267                                 return prog1(const_, semicolon);
1268
1269                             case "while":
1270                                 return as("while", parenthesised(), in_loop(statement));
1271
1272                             case "with":
1273                                 return as("with", parenthesised(), statement());
1274
1275                             default:
1276                                 unexpected();
1277                         }
1278                 }
1279         });
1280
1281         function labeled_statement(label) {
1282                 S.labels.push(label);
1283                 var start = S.token, stat = statement();
1284                 if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))
1285                         unexpected(start);
1286                 S.labels.pop();
1287                 return as("label", label, stat);
1288         };
1289
1290         function simple_statement() {
1291                 return as("stat", prog1(expression, semicolon));
1292         };
1293
1294         function break_cont(type) {
1295                 var name;
1296                 if (!can_insert_semicolon()) {
1297                         name = is("name") ? S.token.value : null;
1298                 }
1299                 if (name != null) {
1300                         next();
1301                         if (!member(name, S.labels))
1302                                 croak("Label " + name + " without matching loop or statement");
1303                 }
1304                 else if (S.in_loop == 0)
1305                         croak(type + " not inside a loop or switch");
1306                 semicolon();
1307                 return as(type, name);
1308         };
1309
1310         function for_() {
1311                 expect("(");
1312                 var init = null;
1313                 if (!is("punc", ";")) {
1314                         init = is("keyword", "var")
1315                                 ? (next(), var_(true))
1316                                 : expression(true, true);
1317                         if (is("operator", "in"))
1318                                 return for_in(init);
1319                 }
1320                 return regular_for(init);
1321         };
1322
1323         function regular_for(init) {
1324                 expect(";");
1325                 var test = is("punc", ";") ? null : expression();
1326                 expect(";");
1327                 var step = is("punc", ")") ? null : expression();
1328                 expect(")");
1329                 return as("for", init, test, step, in_loop(statement));
1330         };
1331
1332         function for_in(init) {
1333                 var lhs = init[0] == "var" ? as("name", init[1][0]) : init;
1334                 next();
1335                 var obj = expression();
1336                 expect(")");
1337                 return as("for-in", init, lhs, obj, in_loop(statement));
1338         };
1339
1340         var function_ = maybe_embed_tokens(function(in_statement) {
1341                 var name = is("name") ? prog1(S.token.value, next) : null;
1342                 if (in_statement && !name)
1343                         unexpected();
1344                 expect("(");
1345                 return as(in_statement ? "defun" : "function",
1346                           name,
1347                           // arguments
1348                           (function(first, a){
1349                                   while (!is("punc", ")")) {
1350                                           if (first) first = false; else expect(",");
1351                                           if (!is("name")) unexpected();
1352                                           a.push(S.token.value);
1353                                           next();
1354                                   }
1355                                   next();
1356                                   return a;
1357                           })(true, []),
1358                           // body
1359                           (function(){
1360                                   ++S.in_function;
1361                                   var loop = S.in_loop;
1362                                   S.in_loop = 0;
1363                                   var a = block_();
1364                                   --S.in_function;
1365                                   S.in_loop = loop;
1366                                   return a;
1367                           })());
1368         });
1369
1370         function if_() {
1371                 var cond = parenthesised(), body = statement(), belse;
1372                 if (is("keyword", "else")) {
1373                         next();
1374                         belse = statement();
1375                 }
1376                 return as("if", cond, body, belse);
1377         };
1378
1379         function block_() {
1380                 expect("{");
1381                 var a = [];
1382                 while (!is("punc", "}")) {
1383                         if (is("eof")) unexpected();
1384                         a.push(statement());
1385                 }
1386                 next();
1387                 return a;
1388         };
1389
1390         var switch_block_ = curry(in_loop, function(){
1391                 expect("{");
1392                 var a = [], cur = null;
1393                 while (!is("punc", "}")) {
1394                         if (is("eof")) unexpected();
1395                         if (is("keyword", "case")) {
1396                                 next();
1397                                 cur = [];
1398                                 a.push([ expression(), cur ]);
1399                                 expect(":");
1400                         }
1401                         else if (is("keyword", "default")) {
1402                                 next();
1403                                 expect(":");
1404                                 cur = [];
1405                                 a.push([ null, cur ]);
1406                         }
1407                         else {
1408                                 if (!cur) unexpected();
1409                                 cur.push(statement());
1410                         }
1411                 }
1412                 next();
1413                 return a;
1414         });
1415
1416         function try_() {
1417                 var body = block_(), bcatch, bfinally;
1418                 if (is("keyword", "catch")) {
1419                         next();
1420                         expect("(");
1421                         if (!is("name"))
1422                                 croak("Name expected");
1423                         var name = S.token.value;
1424                         next();
1425                         expect(")");
1426                         bcatch = [ name, block_() ];
1427                 }
1428                 if (is("keyword", "finally")) {
1429                         next();
1430                         bfinally = block_();
1431                 }
1432                 if (!bcatch && !bfinally)
1433                         croak("Missing catch/finally blocks");
1434                 return as("try", body, bcatch, bfinally);
1435         };
1436
1437         function vardefs(no_in) {
1438                 var a = [];
1439                 for (;;) {
1440                         if (!is("name"))
1441                                 unexpected();
1442                         var name = S.token.value;
1443                         next();
1444                         if (is("operator", "=")) {
1445                                 next();
1446                                 a.push([ name, expression(false, no_in) ]);
1447                         } else {
1448                                 a.push([ name ]);
1449                         }
1450                         if (!is("punc", ","))
1451                                 break;
1452                         next();
1453                 }
1454                 return a;
1455         };
1456
1457         function var_(no_in) {
1458                 return as("var", vardefs(no_in));
1459         };
1460
1461         function const_() {
1462                 return as("const", vardefs());
1463         };
1464
1465         function new_() {
1466                 var newexp = expr_atom(false), args;
1467                 if (is("punc", "(")) {
1468                         next();
1469                         args = expr_list(")");
1470                 } else {
1471                         args = [];
1472                 }
1473                 return subscripts(as("new", newexp, args), true);
1474         };
1475
1476         var expr_atom = maybe_embed_tokens(function(allow_calls) {
1477                 if (is("operator", "new")) {
1478                         next();
1479                         return new_();
1480                 }
1481                 if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) {
1482                         return make_unary("unary-prefix",
1483                                           prog1(S.token.value, next),
1484                                           expr_atom(allow_calls));
1485                 }
1486                 if (is("punc")) {
1487                         switch (S.token.value) {
1488                             case "(":
1489                                 next();
1490                                 return subscripts(prog1(expression, curry(expect, ")")), allow_calls);
1491                             case "[":
1492                                 next();
1493                                 return subscripts(array_(), allow_calls);
1494                             case "{":
1495                                 next();
1496                                 return subscripts(object_(), allow_calls);
1497                         }
1498                         unexpected();
1499                 }
1500                 if (is("keyword", "function")) {
1501                         next();
1502                         return subscripts(function_(false), allow_calls);
1503                 }
1504                 if (HOP(ATOMIC_START_TOKEN, S.token.type)) {
1505                         var atom = S.token.type == "regexp"
1506                                 ? as("regexp", S.token.value[0], S.token.value[1])
1507                                 : as(S.token.type, S.token.value);
1508                         return subscripts(prog1(atom, next), allow_calls);
1509                 }
1510                 unexpected();
1511         });
1512
1513         function expr_list(closing, allow_trailing_comma, allow_empty) {
1514                 var first = true, a = [];
1515                 while (!is("punc", closing)) {
1516                         if (first) first = false; else expect(",");
1517                         if (allow_trailing_comma && is("punc", closing)) break;
1518                         if (is("punc", ",") && allow_empty) {
1519                                 a.push([ "atom", "undefined" ]);
1520                         } else {
1521                                 a.push(expression(false));
1522                         }
1523                 }
1524                 next();
1525                 return a;
1526         };
1527
1528         function array_() {
1529                 return as("array", expr_list("]", !exigent_mode, true));
1530         };
1531
1532         function object_() {
1533                 var first = true, a = [];
1534                 while (!is("punc", "}")) {
1535                         if (first) first = false; else expect(",");
1536                         if (!exigent_mode && is("punc", "}"))
1537                                 // allow trailing comma
1538                                 break;
1539                         var type = S.token.type;
1540                         var name = as_property_name();
1541                         if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) {
1542                                 a.push([ as_name(), function_(false), name ]);
1543                         } else {
1544                                 expect(":");
1545                                 a.push([ name, expression(false) ]);
1546                         }
1547                 }
1548                 next();
1549                 return as("object", a);
1550         };
1551
1552         function as_property_name() {
1553                 switch (S.token.type) {
1554                     case "num":
1555                     case "string":
1556                         return prog1(S.token.value, next);
1557                 }
1558                 return as_name();
1559         };
1560
1561         function as_name() {
1562                 switch (S.token.type) {
1563                     case "name":
1564                     case "operator":
1565                     case "keyword":
1566                     case "atom":
1567                         return prog1(S.token.value, next);
1568                     default:
1569                         unexpected();
1570                 }
1571         };
1572
1573         function subscripts(expr, allow_calls) {
1574                 if (is("punc", ".")) {
1575                         next();
1576                         return subscripts(as("dot", expr, as_name()), allow_calls);
1577                 }
1578                 if (is("punc", "[")) {
1579                         next();
1580                         return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls);
1581                 }
1582                 if (allow_calls && is("punc", "(")) {
1583                         next();
1584                         return subscripts(as("call", expr, expr_list(")")), true);
1585                 }
1586                 if (allow_calls && is("operator") && HOP(UNARY_POSTFIX, S.token.value)) {
1587                         return prog1(curry(make_unary, "unary-postfix", S.token.value, expr),
1588                                      next);
1589                 }
1590                 return expr;
1591         };
1592
1593         function make_unary(tag, op, expr) {
1594                 if ((op == "++" || op == "--") && !is_assignable(expr))
1595                         croak("Invalid use of " + op + " operator");
1596                 return as(tag, op, expr);
1597         };
1598
1599         function expr_op(left, min_prec, no_in) {
1600                 var op = is("operator") ? S.token.value : null;
1601                 if (op && op == "in" && no_in) op = null;
1602                 var prec = op != null ? PRECEDENCE[op] : null;
1603                 if (prec != null && prec > min_prec) {
1604                         next();
1605                         var right = expr_op(expr_atom(true), prec, no_in);
1606                         return expr_op(as("binary", op, left, right), min_prec, no_in);
1607                 }
1608                 return left;
1609         };
1610
1611         function expr_ops(no_in) {
1612                 return expr_op(expr_atom(true), 0, no_in);
1613         };
1614
1615         function maybe_conditional(no_in) {
1616                 var expr = expr_ops(no_in);
1617                 if (is("operator", "?")) {
1618                         next();
1619                         var yes = expression(false);
1620                         expect(":");
1621                         return as("conditional", expr, yes, expression(false, no_in));
1622                 }
1623                 return expr;
1624         };
1625
1626         function is_assignable(expr) {
1627                 if (!exigent_mode) return true;
1628                 switch (expr[0]) {
1629                     case "dot":
1630                     case "sub":
1631                     case "new":
1632                     case "call":
1633                         return true;
1634                     case "name":
1635                         return expr[1] != "this";
1636                 }
1637         };
1638
1639         function maybe_assign(no_in) {
1640                 var left = maybe_conditional(no_in), val = S.token.value;
1641                 if (is("operator") && HOP(ASSIGNMENT, val)) {
1642                         if (is_assignable(left)) {
1643                                 next();
1644                                 return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in));
1645                         }
1646                         croak("Invalid assignment");
1647                 }
1648                 return left;
1649         };
1650
1651         var expression = maybe_embed_tokens(function(commas, no_in) {
1652                 if (arguments.length == 0)
1653                         commas = true;
1654                 var expr = maybe_assign(no_in);
1655                 if (commas && is("punc", ",")) {
1656                         next();
1657                         return as("seq", expr, expression(true, no_in));
1658                 }
1659                 return expr;
1660         });
1661
1662         function in_loop(cont) {
1663                 try {
1664                         ++S.in_loop;
1665                         return cont();
1666                 } finally {
1667                         --S.in_loop;
1668                 }
1669         };
1670
1671         return as("toplevel", (function(a){
1672                 while (!is("eof"))
1673                         a.push(statement());
1674                 return a;
1675         })([]));
1676
1677 };
1678
1679 /* -----[ Utilities ]----- */
1680
1681 function curry(f) {
1682         var args = slice(arguments, 1);
1683         return function() { return f.apply(this, args.concat(slice(arguments))); };
1684 };
1685
1686 function prog1(ret) {
1687         if (ret instanceof Function)
1688                 ret = ret();
1689         for (var i = 1, n = arguments.length; --n > 0; ++i)
1690                 arguments[i]();
1691         return ret;
1692 };
1693
1694 function array_to_hash(a) {
1695         var ret = {};
1696         for (var i = 0; i < a.length; ++i)
1697                 ret[a[i]] = true;
1698         return ret;
1699 };
1700
1701 function slice(a, start) {
1702         return Array.prototype.slice.call(a, start == null ? 0 : start);
1703 };
1704
1705 function characters(str) {
1706         return str.split("");
1707 };
1708
1709 function member(name, array) {
1710         for (var i = array.length; --i >= 0;)
1711                 if (array[i] === name)
1712                         return true;
1713         return false;
1714 };
1715
1716 function HOP(obj, prop) {
1717         return Object.prototype.hasOwnProperty.call(obj, prop);
1718 };
1719
1720 var warn = function() {};
1721
1722 /* -----[ Exports ]----- */
1723
1724 exports.tokenizer = tokenizer;
1725 exports.parse = parse;
1726 exports.slice = slice;
1727 exports.curry = curry;
1728 exports.member = member;
1729 exports.array_to_hash = array_to_hash;
1730 exports.PRECEDENCE = PRECEDENCE;
1731 exports.KEYWORDS_ATOM = KEYWORDS_ATOM;
1732 exports.RESERVED_WORDS = RESERVED_WORDS;
1733 exports.KEYWORDS = KEYWORDS;
1734 exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN;
1735 exports.OPERATORS = OPERATORS;
1736 exports.is_alphanumeric_char = is_alphanumeric_char;
1737 exports.set_logger = function(logger) {
1738         warn = logger;
1739 };
1740 ;
1741     }).call(module.exports);
1742     
1743     __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"]._cached = module.exports;
1744     return module.exports;
1745 };
1746
1747 require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"] = function () {
1748     var module = { exports : {} };
1749     var exports = module.exports;
1750     var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib";
1751     var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/process.js";
1752     
1753     var require = function (file) {
1754         return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib");
1755     };
1756     
1757     require.resolve = function (file) {
1758         return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib");
1759     };
1760     
1761     require.modules = __require.modules;
1762     __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"]._cached = module.exports;
1763     
1764     (function () {
1765         /***********************************************************************
1766
1767   A JavaScript tokenizer / parser / beautifier / compressor.
1768
1769   This version is suitable for Node.js.  With minimal changes (the
1770   exports stuff) it should work on any JS platform.
1771
1772   This file implements some AST processors.  They work on data built
1773   by parse-js.
1774
1775   Exported functions:
1776
1777     - ast_mangle(ast, options) -- mangles the variable/function names
1778       in the AST.  Returns an AST.
1779
1780     - ast_squeeze(ast) -- employs various optimizations to make the
1781       final generated code even smaller.  Returns an AST.
1782
1783     - gen_code(ast, options) -- generates JS code from the AST.  Pass
1784       true (or an object, see the code for some options) as second
1785       argument to get "pretty" (indented) code.
1786
1787   -------------------------------- (C) ---------------------------------
1788
1789                            Author: Mihai Bazon
1790                          <mihai.bazon@gmail.com>
1791                        http://mihai.bazon.net/blog
1792
1793   Distributed under the BSD license:
1794
1795     Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
1796
1797     Redistribution and use in source and binary forms, with or without
1798     modification, are permitted provided that the following conditions
1799     are met:
1800
1801         * Redistributions of source code must retain the above
1802           copyright notice, this list of conditions and the following
1803           disclaimer.
1804
1805         * Redistributions in binary form must reproduce the above
1806           copyright notice, this list of conditions and the following
1807           disclaimer in the documentation and/or other materials
1808           provided with the distribution.
1809
1810     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
1811     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1812     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1813     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
1814     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
1815     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1816     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1817     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1818     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
1819     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
1820     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1821     SUCH DAMAGE.
1822
1823  ***********************************************************************/
1824
1825 var jsp = require("./parse-js"),
1826     slice = jsp.slice,
1827     member = jsp.member,
1828     PRECEDENCE = jsp.PRECEDENCE,
1829     OPERATORS = jsp.OPERATORS;
1830
1831 /* -----[ helper for AST traversal ]----- */
1832
1833 function ast_walker(ast) {
1834         function _vardefs(defs) {
1835                 return [ this[0], MAP(defs, function(def){
1836                         var a = [ def[0] ];
1837                         if (def.length > 1)
1838                                 a[1] = walk(def[1]);
1839                         return a;
1840                 }) ];
1841         };
1842         function _block(statements) {
1843                 var out = [ this[0] ];
1844                 if (statements != null)
1845                         out.push(MAP(statements, walk));
1846                 return out;
1847         };
1848         var walkers = {
1849                 "string": function(str) {
1850                         return [ this[0], str ];
1851                 },
1852                 "num": function(num) {
1853                         return [ this[0], num ];
1854                 },
1855                 "name": function(name) {
1856                         return [ this[0], name ];
1857                 },
1858                 "toplevel": function(statements) {
1859                         return [ this[0], MAP(statements, walk) ];
1860                 },
1861                 "block": _block,
1862                 "splice": _block,
1863                 "var": _vardefs,
1864                 "const": _vardefs,
1865                 "try": function(t, c, f) {
1866                         return [
1867                                 this[0],
1868                                 MAP(t, walk),
1869                                 c != null ? [ c[0], MAP(c[1], walk) ] : null,
1870                                 f != null ? MAP(f, walk) : null
1871                         ];
1872                 },
1873                 "throw": function(expr) {
1874                         return [ this[0], walk(expr) ];
1875                 },
1876                 "new": function(ctor, args) {
1877                         return [ this[0], walk(ctor), MAP(args, walk) ];
1878                 },
1879                 "switch": function(expr, body) {
1880                         return [ this[0], walk(expr), MAP(body, function(branch){
1881                                 return [ branch[0] ? walk(branch[0]) : null,
1882                                          MAP(branch[1], walk) ];
1883                         }) ];
1884                 },
1885                 "break": function(label) {
1886                         return [ this[0], label ];
1887                 },
1888                 "continue": function(label) {
1889                         return [ this[0], label ];
1890                 },
1891                 "conditional": function(cond, t, e) {
1892                         return [ this[0], walk(cond), walk(t), walk(e) ];
1893                 },
1894                 "assign": function(op, lvalue, rvalue) {
1895                         return [ this[0], op, walk(lvalue), walk(rvalue) ];
1896                 },
1897                 "dot": function(expr) {
1898                         return [ this[0], walk(expr) ].concat(slice(arguments, 1));
1899                 },
1900                 "call": function(expr, args) {
1901                         return [ this[0], walk(expr), MAP(args, walk) ];
1902                 },
1903                 "function": function(name, args, body) {
1904                         return [ this[0], name, args.slice(), MAP(body, walk) ];
1905                 },
1906                 "defun": function(name, args, body) {
1907                         return [ this[0], name, args.slice(), MAP(body, walk) ];
1908                 },
1909                 "if": function(conditional, t, e) {
1910                         return [ this[0], walk(conditional), walk(t), walk(e) ];
1911                 },
1912                 "for": function(init, cond, step, block) {
1913                         return [ this[0], walk(init), walk(cond), walk(step), walk(block) ];
1914                 },
1915                 "for-in": function(vvar, key, hash, block) {
1916                         return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ];
1917                 },
1918                 "while": function(cond, block) {
1919                         return [ this[0], walk(cond), walk(block) ];
1920                 },
1921                 "do": function(cond, block) {
1922                         return [ this[0], walk(cond), walk(block) ];
1923                 },
1924                 "return": function(expr) {
1925                         return [ this[0], walk(expr) ];
1926                 },
1927                 "binary": function(op, left, right) {
1928                         return [ this[0], op, walk(left), walk(right) ];
1929                 },
1930                 "unary-prefix": function(op, expr) {
1931                         return [ this[0], op, walk(expr) ];
1932                 },
1933                 "unary-postfix": function(op, expr) {
1934                         return [ this[0], op, walk(expr) ];
1935                 },
1936                 "sub": function(expr, subscript) {
1937                         return [ this[0], walk(expr), walk(subscript) ];
1938                 },
1939                 "object": function(props) {
1940                         return [ this[0], MAP(props, function(p){
1941                                 return p.length == 2
1942                                         ? [ p[0], walk(p[1]) ]
1943                                         : [ p[0], walk(p[1]), p[2] ]; // get/set-ter
1944                         }) ];
1945                 },
1946                 "regexp": function(rx, mods) {
1947                         return [ this[0], rx, mods ];
1948                 },
1949                 "array": function(elements) {
1950                         return [ this[0], MAP(elements, walk) ];
1951                 },
1952                 "stat": function(stat) {
1953                         return [ this[0], walk(stat) ];
1954                 },
1955                 "seq": function() {
1956                         return [ this[0] ].concat(MAP(slice(arguments), walk));
1957                 },
1958                 "label": function(name, block) {
1959                         return [ this[0], name, walk(block) ];
1960                 },
1961                 "with": function(expr, block) {
1962                         return [ this[0], walk(expr), walk(block) ];
1963                 },
1964                 "atom": function(name) {
1965                         return [ this[0], name ];
1966                 }
1967         };
1968
1969         var user = {};
1970         var stack = [];
1971         function walk(ast) {
1972                 if (ast == null)
1973                         return null;
1974                 try {
1975                         stack.push(ast);
1976                         var type = ast[0];
1977                         var gen = user[type];
1978                         if (gen) {
1979                                 var ret = gen.apply(ast, ast.slice(1));
1980                                 if (ret != null)
1981                                         return ret;
1982                         }
1983                         gen = walkers[type];
1984                         return gen.apply(ast, ast.slice(1));
1985                 } finally {
1986                         stack.pop();
1987                 }
1988         };
1989
1990         function with_walkers(walkers, cont){
1991                 var save = {}, i;
1992                 for (i in walkers) if (HOP(walkers, i)) {
1993                         save[i] = user[i];
1994                         user[i] = walkers[i];
1995                 }
1996                 var ret = cont();
1997                 for (i in save) if (HOP(save, i)) {
1998                         if (!save[i]) delete user[i];
1999                         else user[i] = save[i];
2000                 }
2001                 return ret;
2002         };
2003
2004         return {
2005                 walk: walk,
2006                 with_walkers: with_walkers,
2007                 parent: function() {
2008                         return stack[stack.length - 2]; // last one is current node
2009                 },
2010                 stack: function() {
2011                         return stack;
2012                 }
2013         };
2014 };
2015
2016 /* -----[ Scope and mangling ]----- */
2017
2018 function Scope(parent) {
2019         this.names = {};        // names defined in this scope
2020         this.mangled = {};      // mangled names (orig.name => mangled)
2021         this.rev_mangled = {};  // reverse lookup (mangled => orig.name)
2022         this.cname = -1;        // current mangled name
2023         this.refs = {};         // names referenced from this scope
2024         this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes
2025         this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes
2026         this.parent = parent;   // parent scope
2027         this.children = [];     // sub-scopes
2028         if (parent) {
2029                 this.level = parent.level + 1;
2030                 parent.children.push(this);
2031         } else {
2032                 this.level = 0;
2033         }
2034 };
2035
2036 var base54 = (function(){
2037         var DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
2038         return function(num) {
2039                 var ret = "";
2040                 do {
2041                         ret = DIGITS.charAt(num % 54) + ret;
2042                         num = Math.floor(num / 54);
2043                 } while (num > 0);
2044                 return ret;
2045         };
2046 })();
2047
2048 Scope.prototype = {
2049         has: function(name) {
2050                 for (var s = this; s; s = s.parent)
2051                         if (HOP(s.names, name))
2052                                 return s;
2053         },
2054         has_mangled: function(mname) {
2055                 for (var s = this; s; s = s.parent)
2056                         if (HOP(s.rev_mangled, mname))
2057                                 return s;
2058         },
2059         toJSON: function() {
2060                 return {
2061                         names: this.names,
2062                         uses_eval: this.uses_eval,
2063                         uses_with: this.uses_with
2064                 };
2065         },
2066
2067         next_mangled: function() {
2068                 // we must be careful that the new mangled name:
2069                 //
2070                 // 1. doesn't shadow a mangled name from a parent
2071                 //    scope, unless we don't reference the original
2072                 //    name from this scope OR from any sub-scopes!
2073                 //    This will get slow.
2074                 //
2075                 // 2. doesn't shadow an original name from a parent
2076                 //    scope, in the event that the name is not mangled
2077                 //    in the parent scope and we reference that name
2078                 //    here OR IN ANY SUBSCOPES!
2079                 //
2080                 // 3. doesn't shadow a name that is referenced but not
2081                 //    defined (possibly global defined elsewhere).
2082                 for (;;) {
2083                         var m = base54(++this.cname), prior;
2084
2085                         // case 1.
2086                         prior = this.has_mangled(m);
2087                         if (prior && this.refs[prior.rev_mangled[m]] === prior)
2088                                 continue;
2089
2090                         // case 2.
2091                         prior = this.has(m);
2092                         if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m))
2093                                 continue;
2094
2095                         // case 3.
2096                         if (HOP(this.refs, m) && this.refs[m] == null)
2097                                 continue;
2098
2099                         // I got "do" once. :-/
2100                         if (!is_identifier(m))
2101                                 continue;
2102
2103                         return m;
2104                 }
2105         },
2106         set_mangle: function(name, m) {
2107                 this.rev_mangled[m] = name;
2108                 return this.mangled[name] = m;
2109         },
2110         get_mangled: function(name, newMangle) {
2111                 if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use
2112                 var s = this.has(name);
2113                 if (!s) return name; // not in visible scope, no mangle
2114                 if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope
2115                 if (!newMangle) return name;                      // not found and no mangling requested
2116                 return s.set_mangle(name, s.next_mangled());
2117         },
2118         define: function(name) {
2119                 if (name != null)
2120                         return this.names[name] = name;
2121         }
2122 };
2123
2124 function ast_add_scope(ast) {
2125
2126         var current_scope = null;
2127         var w = ast_walker(), walk = w.walk;
2128         var having_eval = [];
2129
2130         function with_new_scope(cont) {
2131                 current_scope = new Scope(current_scope);
2132                 var ret = current_scope.body = cont();
2133                 ret.scope = current_scope;
2134                 current_scope = current_scope.parent;
2135                 return ret;
2136         };
2137
2138         function define(name) {
2139                 return current_scope.define(name);
2140         };
2141
2142         function reference(name) {
2143                 current_scope.refs[name] = true;
2144         };
2145
2146         function _lambda(name, args, body) {
2147                 var is_defun = this[0] == "defun";
2148                 return [ this[0], is_defun ? define(name) : name, args, with_new_scope(function(){
2149                         if (!is_defun) define(name);
2150                         MAP(args, define);
2151                         return MAP(body, walk);
2152                 })];
2153         };
2154
2155         return with_new_scope(function(){
2156                 // process AST
2157                 var ret = w.with_walkers({
2158                         "function": _lambda,
2159                         "defun": _lambda,
2160                         "with": function(expr, block) {
2161                                 for (var s = current_scope; s; s = s.parent)
2162                                         s.uses_with = true;
2163                         },
2164                         "var": function(defs) {
2165                                 MAP(defs, function(d){ define(d[0]) });
2166                         },
2167                         "const": function(defs) {
2168                                 MAP(defs, function(d){ define(d[0]) });
2169                         },
2170                         "try": function(t, c, f) {
2171                                 if (c != null) return [
2172                                         this[0],
2173                                         MAP(t, walk),
2174                                         [ define(c[0]), MAP(c[1], walk) ],
2175                                         f != null ? MAP(f, walk) : null
2176                                 ];
2177                         },
2178                         "name": function(name) {
2179                                 if (name == "eval")
2180                                         having_eval.push(current_scope);
2181                                 reference(name);
2182                         }
2183                 }, function(){
2184                         return walk(ast);
2185                 });
2186
2187                 // the reason why we need an additional pass here is
2188                 // that names can be used prior to their definition.
2189
2190                 // scopes where eval was detected and their parents
2191                 // are marked with uses_eval, unless they define the
2192                 // "eval" name.
2193                 MAP(having_eval, function(scope){
2194                         if (!scope.has("eval")) while (scope) {
2195                                 scope.uses_eval = true;
2196                                 scope = scope.parent;
2197                         }
2198                 });
2199
2200                 // for referenced names it might be useful to know
2201                 // their origin scope.  current_scope here is the
2202                 // toplevel one.
2203                 function fixrefs(scope, i) {
2204                         // do children first; order shouldn't matter
2205                         for (i = scope.children.length; --i >= 0;)
2206                                 fixrefs(scope.children[i]);
2207                         for (i in scope.refs) if (HOP(scope.refs, i)) {
2208                                 // find origin scope and propagate the reference to origin
2209                                 for (var origin = scope.has(i), s = scope; s; s = s.parent) {
2210                                         s.refs[i] = origin;
2211                                         if (s === origin) break;
2212                                 }
2213                         }
2214                 };
2215                 fixrefs(current_scope);
2216
2217                 return ret;
2218         });
2219
2220 };
2221
2222 /* -----[ mangle names ]----- */
2223
2224 function ast_mangle(ast, options) {
2225         var w = ast_walker(), walk = w.walk, scope;
2226         options = options || {};
2227
2228         function get_mangled(name, newMangle) {
2229                 if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel
2230                 if (options.except && member(name, options.except))
2231                         return name;
2232                 return scope.get_mangled(name, newMangle);
2233         };
2234
2235         function get_define(name) {
2236                 if (options.defines) {
2237                         // we always lookup a defined symbol for the current scope FIRST, so declared
2238                         // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value
2239                         if (!scope.has(name)) {
2240                                 if (HOP(options.defines, name)) {
2241                                         return options.defines[name];
2242                                 }
2243                         }
2244                         return null;
2245                 }
2246         };
2247
2248         function _lambda(name, args, body) {
2249                 var is_defun = this[0] == "defun", extra;
2250                 if (name) {
2251                         if (is_defun) name = get_mangled(name);
2252                         else {
2253                                 extra = {};
2254                                 name = extra[name] = scope.next_mangled();
2255                         }
2256                 }
2257                 body = with_scope(body.scope, function(){
2258                         args = MAP(args, function(name){ return get_mangled(name) });
2259                         return MAP(body, walk);
2260                 }, extra);
2261                 return [ this[0], name, args, body ];
2262         };
2263
2264         function with_scope(s, cont, extra) {
2265                 var _scope = scope;
2266                 scope = s;
2267                 if (extra) for (var i in extra) if (HOP(extra, i)) {
2268                         s.set_mangle(i, extra[i]);
2269                 }
2270                 for (var i in s.names) if (HOP(s.names, i)) {
2271                         get_mangled(i, true);
2272                 }
2273                 var ret = cont();
2274                 ret.scope = s;
2275                 scope = _scope;
2276                 return ret;
2277         };
2278
2279         function _vardefs(defs) {
2280                 return [ this[0], MAP(defs, function(d){
2281                         return [ get_mangled(d[0]), walk(d[1]) ];
2282                 }) ];
2283         };
2284
2285         return w.with_walkers({
2286                 "function": _lambda,
2287                 "defun": function() {
2288                         // move function declarations to the top when
2289                         // they are not in some block.
2290                         var ast = _lambda.apply(this, arguments);
2291                         switch (w.parent()[0]) {
2292                             case "toplevel":
2293                             case "function":
2294                             case "defun":
2295                                 return MAP.at_top(ast);
2296                         }
2297                         return ast;
2298                 },
2299                 "var": _vardefs,
2300                 "const": _vardefs,
2301                 "name": function(name) {
2302                         return get_define(name) || [ this[0], get_mangled(name) ];
2303                 },
2304                 "try": function(t, c, f) {
2305                         return [ this[0],
2306                                  MAP(t, walk),
2307                                  c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null,
2308                                  f != null ? MAP(f, walk) : null ];
2309                 },
2310                 "toplevel": function(body) {
2311                         var self = this;
2312                         return with_scope(self.scope, function(){
2313                                 return [ self[0], MAP(body, walk) ];
2314                         });
2315                 }
2316         }, function() {
2317                 return walk(ast_add_scope(ast));
2318         });
2319 };
2320
2321 /* -----[
2322    - compress foo["bar"] into foo.bar,
2323    - remove block brackets {} where possible
2324    - join consecutive var declarations
2325    - various optimizations for IFs:
2326      - if (cond) foo(); else bar();  ==>  cond?foo():bar();
2327      - if (cond) foo();  ==>  cond&&foo();
2328      - if (foo) return bar(); else return baz();  ==> return foo?bar():baz(); // also for throw
2329      - if (foo) return bar(); else something();  ==> {if(foo)return bar();something()}
2330    ]----- */
2331
2332 var warn = function(){};
2333
2334 function best_of(ast1, ast2) {
2335         return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1;
2336 };
2337
2338 function last_stat(b) {
2339         if (b[0] == "block" && b[1] && b[1].length > 0)
2340                 return b[1][b[1].length - 1];
2341         return b;
2342 }
2343
2344 function aborts(t) {
2345         if (t) {
2346                 t = last_stat(t);
2347                 if (t[0] == "return" || t[0] == "break" || t[0] == "continue" || t[0] == "throw")
2348                         return true;
2349         }
2350 };
2351
2352 function boolean_expr(expr) {
2353         return ( (expr[0] == "unary-prefix"
2354                   && member(expr[1], [ "!", "delete" ])) ||
2355
2356                  (expr[0] == "binary"
2357                   && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) ||
2358
2359                  (expr[0] == "binary"
2360                   && member(expr[1], [ "&&", "||" ])
2361                   && boolean_expr(expr[2])
2362                   && boolean_expr(expr[3])) ||
2363
2364                  (expr[0] == "conditional"
2365                   && boolean_expr(expr[2])
2366                   && boolean_expr(expr[3])) ||
2367
2368                  (expr[0] == "assign"
2369                   && expr[1] === true
2370                   && boolean_expr(expr[3])) ||
2371
2372                  (expr[0] == "seq"
2373                   && boolean_expr(expr[expr.length - 1]))
2374                );
2375 };
2376
2377 function make_conditional(c, t, e) {
2378     var make_real_conditional = function() {
2379         if (c[0] == "unary-prefix" && c[1] == "!") {
2380             return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ];
2381         } else {
2382             return e ? [ "conditional", c, t, e ] : [ "binary", "&&", c, t ];
2383         }
2384     };
2385     // shortcut the conditional if the expression has a constant value
2386     return when_constant(c, function(ast, val){
2387         warn_unreachable(val ? e : t);
2388         return          (val ? t : e);
2389     }, make_real_conditional);
2390 };
2391
2392 function empty(b) {
2393         return !b || (b[0] == "block" && (!b[1] || b[1].length == 0));
2394 };
2395
2396 function is_string(node) {
2397         return (node[0] == "string" ||
2398                 node[0] == "unary-prefix" && node[1] == "typeof" ||
2399                 node[0] == "binary" && node[1] == "+" &&
2400                 (is_string(node[2]) || is_string(node[3])));
2401 };
2402
2403 var when_constant = (function(){
2404
2405         var $NOT_CONSTANT = {};
2406
2407         // this can only evaluate constant expressions.  If it finds anything
2408         // not constant, it throws $NOT_CONSTANT.
2409         function evaluate(expr) {
2410                 switch (expr[0]) {
2411                     case "string":
2412                     case "num":
2413                         return expr[1];
2414                     case "name":
2415                     case "atom":
2416                         switch (expr[1]) {
2417                             case "true": return true;
2418                             case "false": return false;
2419                         }
2420                         break;
2421                     case "unary-prefix":
2422                         switch (expr[1]) {
2423                             case "!": return !evaluate(expr[2]);
2424                             case "typeof": return typeof evaluate(expr[2]);
2425                             case "~": return ~evaluate(expr[2]);
2426                             case "-": return -evaluate(expr[2]);
2427                             case "+": return +evaluate(expr[2]);
2428                         }
2429                         break;
2430                     case "binary":
2431                         var left = expr[2], right = expr[3];
2432                         switch (expr[1]) {
2433                             case "&&"         : return evaluate(left) &&         evaluate(right);
2434                             case "||"         : return evaluate(left) ||         evaluate(right);
2435                             case "|"          : return evaluate(left) |          evaluate(right);
2436                             case "&"          : return evaluate(left) &          evaluate(right);
2437                             case "^"          : return evaluate(left) ^          evaluate(right);
2438                             case "+"          : return evaluate(left) +          evaluate(right);
2439                             case "*"          : return evaluate(left) *          evaluate(right);
2440                             case "/"          : return evaluate(left) /          evaluate(right);
2441                             case "-"          : return evaluate(left) -          evaluate(right);
2442                             case "<<"         : return evaluate(left) <<         evaluate(right);
2443                             case ">>"         : return evaluate(left) >>         evaluate(right);
2444                             case ">>>"        : return evaluate(left) >>>        evaluate(right);
2445                             case "=="         : return evaluate(left) ==         evaluate(right);
2446                             case "==="        : return evaluate(left) ===        evaluate(right);
2447                             case "!="         : return evaluate(left) !=         evaluate(right);
2448                             case "!=="        : return evaluate(left) !==        evaluate(right);
2449                             case "<"          : return evaluate(left) <          evaluate(right);
2450                             case "<="         : return evaluate(left) <=         evaluate(right);
2451                             case ">"          : return evaluate(left) >          evaluate(right);
2452                             case ">="         : return evaluate(left) >=         evaluate(right);
2453                             case "in"         : return evaluate(left) in         evaluate(right);
2454                             case "instanceof" : return evaluate(left) instanceof evaluate(right);
2455                         }
2456                 }
2457                 throw $NOT_CONSTANT;
2458         };
2459
2460         return function(expr, yes, no) {
2461                 try {
2462                         var val = evaluate(expr), ast;
2463                         switch (typeof val) {
2464                             case "string": ast =  [ "string", val ]; break;
2465                             case "number": ast =  [ "num", val ]; break;
2466                             case "boolean": ast =  [ "name", String(val) ]; break;
2467                             default: throw new Error("Can't handle constant of type: " + (typeof val));
2468                         }
2469                         return yes.call(expr, ast, val);
2470                 } catch(ex) {
2471                         if (ex === $NOT_CONSTANT) {
2472                                 if (expr[0] == "binary"
2473                                     && (expr[1] == "===" || expr[1] == "!==")
2474                                     && ((is_string(expr[2]) && is_string(expr[3]))
2475                                         || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) {
2476                                         expr[1] = expr[1].substr(0, 2);
2477                                 }
2478                                 else if (no && expr[0] == "binary"
2479                                          && (expr[1] == "||" || expr[1] == "&&")) {
2480                                     // the whole expression is not constant but the lval may be...
2481                                     try {
2482                                         var lval = evaluate(expr[2]);
2483                                         expr = ((expr[1] == "&&" && (lval ? expr[3] : lval))    ||
2484                                                 (expr[1] == "||" && (lval ? lval    : expr[3])) ||
2485                                                 expr);
2486                                     } catch(ex2) {
2487                                         // IGNORE... lval is not constant
2488                                     }
2489                                 }
2490                                 return no ? no.call(expr, expr) : null;
2491                         }
2492                         else throw ex;
2493                 }
2494         };
2495
2496 })();
2497
2498 function warn_unreachable(ast) {
2499         if (!empty(ast))
2500                 warn("Dropping unreachable code: " + gen_code(ast, true));
2501 };
2502
2503 function prepare_ifs(ast) {
2504         var w = ast_walker(), walk = w.walk;
2505         // In this first pass, we rewrite ifs which abort with no else with an
2506         // if-else.  For example:
2507         //
2508         // if (x) {
2509         //     blah();
2510         //     return y;
2511         // }
2512         // foobar();
2513         //
2514         // is rewritten into:
2515         //
2516         // if (x) {
2517         //     blah();
2518         //     return y;
2519         // } else {
2520         //     foobar();
2521         // }
2522         function redo_if(statements) {
2523                 statements = MAP(statements, walk);
2524
2525                 for (var i = 0; i < statements.length; ++i) {
2526                         var fi = statements[i];
2527                         if (fi[0] != "if") continue;
2528
2529                         if (fi[3] && walk(fi[3])) continue;
2530
2531                         var t = walk(fi[2]);
2532                         if (!aborts(t)) continue;
2533
2534                         var conditional = walk(fi[1]);
2535
2536                         var e_body = statements.slice(i + 1);
2537                         var e;
2538                         if (e_body.length == 1) e = e_body[0];
2539                         else e = [ "block", e_body ];
2540
2541                         var ret = statements.slice(0, i).concat([ [
2542                                 fi[0],          // "if"
2543                                 conditional,    // conditional
2544                                 t,              // then
2545                                 e               // else
2546                         ] ]);
2547
2548                         return redo_if(ret);
2549                 }
2550
2551                 return statements;
2552         };
2553
2554         function redo_if_lambda(name, args, body) {
2555                 body = redo_if(body);
2556                 return [ this[0], name, args.slice(), body ];
2557         };
2558
2559         function redo_if_block(statements) {
2560                 var out = [ this[0] ];
2561                 if (statements != null)
2562                         out.push(redo_if(statements));
2563                 return out;
2564         };
2565
2566         return w.with_walkers({
2567                 "defun": redo_if_lambda,
2568                 "function": redo_if_lambda,
2569                 "block": redo_if_block,
2570                 "splice": redo_if_block,
2571                 "toplevel": function(statements) {
2572                         return [ this[0], redo_if(statements) ];
2573                 },
2574                 "try": function(t, c, f) {
2575                         return [
2576                                 this[0],
2577                                 redo_if(t),
2578                                 c != null ? [ c[0], redo_if(c[1]) ] : null,
2579                                 f != null ? redo_if(f) : null
2580                         ];
2581                 },
2582                 "with": function(expr, block) {
2583                         return [ this[0], walk(expr), redo_if(block) ];
2584                 }
2585         }, function() {
2586                 return walk(ast);
2587         });
2588 };
2589
2590 function ast_squeeze(ast, options) {
2591         options = defaults(options, {
2592                 make_seqs   : true,
2593                 dead_code   : true,
2594                 keep_comps  : true,
2595                 no_warnings : false
2596         });
2597
2598         var w = ast_walker(), walk = w.walk, scope;
2599
2600         function negate(c) {
2601                 var not_c = [ "unary-prefix", "!", c ];
2602                 switch (c[0]) {
2603                     case "unary-prefix":
2604                         return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c;
2605                     case "seq":
2606                         c = slice(c);
2607                         c[c.length - 1] = negate(c[c.length - 1]);
2608                         return c;
2609                     case "conditional":
2610                         return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]);
2611                     case "binary":
2612                         var op = c[1], left = c[2], right = c[3];
2613                         if (!options.keep_comps) switch (op) {
2614                             case "<="  : return [ "binary", ">", left, right ];
2615                             case "<"   : return [ "binary", ">=", left, right ];
2616                             case ">="  : return [ "binary", "<", left, right ];
2617                             case ">"   : return [ "binary", "<=", left, right ];
2618                         }
2619                         switch (op) {
2620                             case "=="  : return [ "binary", "!=", left, right ];
2621                             case "!="  : return [ "binary", "==", left, right ];
2622                             case "===" : return [ "binary", "!==", left, right ];
2623                             case "!==" : return [ "binary", "===", left, right ];
2624                             case "&&"  : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]);
2625                             case "||"  : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]);
2626                         }
2627                         break;
2628                 }
2629                 return not_c;
2630         };
2631
2632         function with_scope(s, cont) {
2633                 var _scope = scope;
2634                 scope = s;
2635                 var ret = cont();
2636                 ret.scope = s;
2637                 scope = _scope;
2638                 return ret;
2639         };
2640
2641         function rmblock(block) {
2642                 if (block != null && block[0] == "block" && block[1]) {
2643                         if (block[1].length == 1)
2644                                 block = block[1][0];
2645                         else if (block[1].length == 0)
2646                                 block = [ "block" ];
2647                 }
2648                 return block;
2649         };
2650
2651         function _lambda(name, args, body) {
2652                 var is_defun = this[0] == "defun";
2653                 body = with_scope(body.scope, function(){
2654                         var ret = tighten(MAP(body, walk), "lambda");
2655                         if (!is_defun && name && !HOP(scope.refs, name))
2656                                 name = null;
2657                         return ret;
2658                 });
2659                 return [ this[0], name, args, body ];
2660         };
2661
2662         // we get here for blocks that have been already transformed.
2663         // this function does a few things:
2664         // 1. discard useless blocks
2665         // 2. join consecutive var declarations
2666         // 3. remove obviously dead code
2667         // 4. transform consecutive statements using the comma operator
2668         // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... }
2669         function tighten(statements, block_type) {
2670                 statements = statements.reduce(function(a, stat){
2671                         if (stat[0] == "block") {
2672                                 if (stat[1]) {
2673                                         a.push.apply(a, stat[1]);
2674                                 }
2675                         } else {
2676                                 a.push(stat);
2677                         }
2678                         return a;
2679                 }, []);
2680
2681                 statements = (function(a, prev){
2682                         statements.forEach(function(cur){
2683                                 if (prev && ((cur[0] == "var" && prev[0] == "var") ||
2684                                              (cur[0] == "const" && prev[0] == "const"))) {
2685                                         prev[1] = prev[1].concat(cur[1]);
2686                                 } else {
2687                                         a.push(cur);
2688                                         prev = cur;
2689                                 }
2690                         });
2691                         return a;
2692                 })([]);
2693
2694                 if (options.dead_code) statements = (function(a, has_quit){
2695                         statements.forEach(function(st){
2696                                 if (has_quit) {
2697                                         if (member(st[0], [ "function", "defun" , "var", "const" ])) {
2698                                                 a.push(st);
2699                                         }
2700                                         else if (!options.no_warnings)
2701                                                 warn_unreachable(st);
2702                                 }
2703                                 else {
2704                                         a.push(st);
2705                                         if (member(st[0], [ "return", "throw", "break", "continue" ]))
2706                                                 has_quit = true;
2707                                 }
2708                         });
2709                         return a;
2710                 })([]);
2711
2712                 if (options.make_seqs) statements = (function(a, prev) {
2713                         statements.forEach(function(cur){
2714                                 if (prev && prev[0] == "stat" && cur[0] == "stat") {
2715                                         prev[1] = [ "seq", prev[1], cur[1] ];
2716                                 } else {
2717                                         a.push(cur);
2718                                         prev = cur;
2719                                 }
2720                         });
2721                         return a;
2722                 })([]);
2723
2724                 if (block_type == "lambda") statements = (function(i, a, stat){
2725                         while (i < statements.length) {
2726                                 stat = statements[i++];
2727                                 if (stat[0] == "if" && !stat[3]) {
2728                                         if (stat[2][0] == "return" && stat[2][1] == null) {
2729                                                 a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ]));
2730                                                 break;
2731                                         }
2732                                         var last = last_stat(stat[2]);
2733                                         if (last[0] == "return" && last[1] == null) {
2734                                                 a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ]));
2735                                                 break;
2736                                         }
2737                                 }
2738                                 a.push(stat);
2739                         }
2740                         return a;
2741                 })(0, []);
2742
2743                 return statements;
2744         };
2745
2746         function make_if(c, t, e) {
2747                 return when_constant(c, function(ast, val){
2748                         if (val) {
2749                                 warn_unreachable(e);
2750                                 return t;
2751                         } else {
2752                                 warn_unreachable(t);
2753                                 return e;
2754                         }
2755                 }, function() {
2756                         return make_real_if(c, t, e);
2757                 });
2758         };
2759
2760         function make_real_if(c, t, e) {
2761                 c = walk(c);
2762                 t = walk(t);
2763                 e = walk(e);
2764
2765                 if (empty(t)) {
2766                         c = negate(c);
2767                         t = e;
2768                         e = null;
2769                 } else if (empty(e)) {
2770                         e = null;
2771                 } else {
2772                         // if we have both else and then, maybe it makes sense to switch them?
2773                         (function(){
2774                                 var a = gen_code(c);
2775                                 var n = negate(c);
2776                                 var b = gen_code(n);
2777                                 if (b.length < a.length) {
2778                                         var tmp = t;
2779                                         t = e;
2780                                         e = tmp;
2781                                         c = n;
2782                                 }
2783                         })();
2784                 }
2785                 if (empty(e) && empty(t))
2786                         return [ "stat", c ];
2787                 var ret = [ "if", c, t, e ];
2788                 if (t[0] == "if" && empty(t[3]) && empty(e)) {
2789                         ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ]));
2790                 }
2791                 else if (t[0] == "stat") {
2792                         if (e) {
2793                                 if (e[0] == "stat") {
2794                                         ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]);
2795                                 }
2796                         }
2797                         else {
2798                                 ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]);
2799                         }
2800                 }
2801                 else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw") && t[1] && e[1]) {
2802                         ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]);
2803                 }
2804                 else if (e && aborts(t)) {
2805                         ret = [ [ "if", c, t ] ];
2806                         if (e[0] == "block") {
2807                                 if (e[1]) ret = ret.concat(e[1]);
2808                         }
2809                         else {
2810                                 ret.push(e);
2811                         }
2812                         ret = walk([ "block", ret ]);
2813                 }
2814                 else if (t && aborts(e)) {
2815                         ret = [ [ "if", negate(c), e ] ];
2816                         if (t[0] == "block") {
2817                                 if (t[1]) ret = ret.concat(t[1]);
2818                         } else {
2819                                 ret.push(t);
2820                         }
2821                         ret = walk([ "block", ret ]);
2822                 }
2823                 return ret;
2824         };
2825
2826         function _do_while(cond, body) {
2827                 return when_constant(cond, function(cond, val){
2828                         if (!val) {
2829                                 warn_unreachable(body);
2830                                 return [ "block" ];
2831                         } else {
2832                                 return [ "for", null, null, null, walk(body) ];
2833                         }
2834                 });
2835         };
2836
2837         ast = prepare_ifs(ast);
2838         ast = ast_add_scope(ast);
2839
2840         return w.with_walkers({
2841                 "sub": function(expr, subscript) {
2842                         if (subscript[0] == "string") {
2843                                 var name = subscript[1];
2844                                 if (is_identifier(name))
2845                                         return [ "dot", walk(expr), name ];
2846                                 else if (/^[1-9][0-9]*$/.test(name) || name === "0")
2847                                         return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ];
2848                         }
2849                 },
2850                 "if": make_if,
2851                 "toplevel": function(body) {
2852                         return [ "toplevel", with_scope(this.scope, function(){
2853                                 return tighten(MAP(body, walk));
2854                         }) ];
2855                 },
2856                 "switch": function(expr, body) {
2857                         var last = body.length - 1;
2858                         return [ "switch", walk(expr), MAP(body, function(branch, i){
2859                                 var block = tighten(MAP(branch[1], walk));
2860                                 if (i == last && block.length > 0) {
2861                                         var node = block[block.length - 1];
2862                                         if (node[0] == "break" && !node[1])
2863                                                 block.pop();
2864                                 }
2865                                 return [ branch[0] ? walk(branch[0]) : null, block ];
2866                         }) ];
2867                 },
2868                 "function": _lambda,
2869                 "defun": _lambda,
2870                 "block": function(body) {
2871                         if (body) return rmblock([ "block", tighten(MAP(body, walk)) ]);
2872                 },
2873                 "binary": function(op, left, right) {
2874                         return when_constant([ "binary", op, walk(left), walk(right) ], function yes(c){
2875                                 return best_of(walk(c), this);
2876                         }, function no() {
2877                                 return this;
2878                         });
2879                 },
2880                 "conditional": function(c, t, e) {
2881                         return make_conditional(walk(c), walk(t), walk(e));
2882                 },
2883                 "try": function(t, c, f) {
2884                         return [
2885                                 "try",
2886                                 tighten(MAP(t, walk)),
2887                                 c != null ? [ c[0], tighten(MAP(c[1], walk)) ] : null,
2888                                 f != null ? tighten(MAP(f, walk)) : null
2889                         ];
2890                 },
2891                 "unary-prefix": function(op, expr) {
2892                         expr = walk(expr);
2893                         var ret = [ "unary-prefix", op, expr ];
2894                         if (op == "!")
2895                                 ret = best_of(ret, negate(expr));
2896                         return when_constant(ret, function(ast, val){
2897                                 return walk(ast); // it's either true or false, so minifies to !0 or !1
2898                         }, function() { return ret });
2899                 },
2900                 "name": function(name) {
2901                         switch (name) {
2902                             case "true": return [ "unary-prefix", "!", [ "num", 0 ]];
2903                             case "false": return [ "unary-prefix", "!", [ "num", 1 ]];
2904                         }
2905                 },
2906                 "new": function(ctor, args) {
2907                         if (ctor[0] == "name" && ctor[1] == "Array" && !scope.has("Array")) {
2908                                 if (args.length != 1) {
2909                                         return [ "array", args ];
2910                                 } else {
2911                                         return [ "call", [ "name", "Array" ], args ];
2912                                 }
2913                         }
2914                 },
2915                 "call": function(expr, args) {
2916                         if (expr[0] == "name" && expr[1] == "Array" && args.length != 1 && !scope.has("Array")) {
2917                                 return [ "array", args ];
2918                         }
2919                 },
2920                 "while": _do_while
2921         }, function() {
2922                 return walk(ast);
2923         });
2924 };
2925
2926 /* -----[ re-generate code from the AST ]----- */
2927
2928 var DOT_CALL_NO_PARENS = jsp.array_to_hash([
2929         "name",
2930         "array",
2931         "object",
2932         "string",
2933         "dot",
2934         "sub",
2935         "call",
2936         "regexp"
2937 ]);
2938
2939 function make_string(str, ascii_only) {
2940         var dq = 0, sq = 0;
2941         str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029]/g, function(s){
2942                 switch (s) {
2943                     case "\\": return "\\\\";
2944                     case "\b": return "\\b";
2945                     case "\f": return "\\f";
2946                     case "\n": return "\\n";
2947                     case "\r": return "\\r";
2948                     case "\t": return "\\t";
2949                     case "\u2028": return "\\u2028";
2950                     case "\u2029": return "\\u2029";
2951                     case '"': ++dq; return '"';
2952                     case "'": ++sq; return "'";
2953                 }
2954                 return s;
2955         });
2956         if (ascii_only) str = to_ascii(str);
2957         if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'";
2958         else return '"' + str.replace(/\x22/g, '\\"') + '"';
2959 };
2960
2961 function to_ascii(str) {
2962         return str.replace(/[\u0080-\uffff]/g, function(ch) {
2963                 var code = ch.charCodeAt(0).toString(16);
2964                 while (code.length < 4) code = "0" + code;
2965                 return "\\u" + code;
2966         });
2967 };
2968
2969 var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]);
2970
2971 function gen_code(ast, options) {
2972         options = defaults(options, {
2973                 indent_start : 0,
2974                 indent_level : 4,
2975                 quote_keys   : false,
2976                 space_colon  : false,
2977                 beautify     : false,
2978                 ascii_only   : false
2979         });
2980         var beautify = !!options.beautify;
2981         var indentation = 0,
2982             newline = beautify ? "\n" : "",
2983             space = beautify ? " " : "";
2984
2985         function encode_string(str) {
2986                 return make_string(str, options.ascii_only);
2987         };
2988
2989         function make_name(name) {
2990                 name = name.toString();
2991                 if (options.ascii_only)
2992                         name = to_ascii(name);
2993                 return name;
2994         };
2995
2996         function indent(line) {
2997                 if (line == null)
2998                         line = "";
2999                 if (beautify)
3000                         line = repeat_string(" ", options.indent_start + indentation * options.indent_level) + line;
3001                 return line;
3002         };
3003
3004         function with_indent(cont, incr) {
3005                 if (incr == null) incr = 1;
3006                 indentation += incr;
3007                 try { return cont.apply(null, slice(arguments, 1)); }
3008                 finally { indentation -= incr; }
3009         };
3010
3011         function add_spaces(a) {
3012                 if (beautify)
3013                         return a.join(" ");
3014                 var b = [];
3015                 for (var i = 0; i < a.length; ++i) {
3016                         var next = a[i + 1];
3017                         b.push(a[i]);
3018                         if (next &&
3019                             ((/[a-z0-9_\x24]$/i.test(a[i].toString()) && /^[a-z0-9_\x24]/i.test(next.toString())) ||
3020                              (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString())))) {
3021                                 b.push(" ");
3022                         }
3023                 }
3024                 return b.join("");
3025         };
3026
3027         function add_commas(a) {
3028                 return a.join("," + space);
3029         };
3030
3031         function parenthesize(expr) {
3032                 var gen = make(expr);
3033                 for (var i = 1; i < arguments.length; ++i) {
3034                         var el = arguments[i];
3035                         if ((el instanceof Function && el(expr)) || expr[0] == el)
3036                                 return "(" + gen + ")";
3037                 }
3038                 return gen;
3039         };
3040
3041         function best_of(a) {
3042                 if (a.length == 1) {
3043                         return a[0];
3044                 }
3045                 if (a.length == 2) {
3046                         var b = a[1];
3047                         a = a[0];
3048                         return a.length <= b.length ? a : b;
3049                 }
3050                 return best_of([ a[0], best_of(a.slice(1)) ]);
3051         };
3052
3053         function needs_parens(expr) {
3054                 if (expr[0] == "function" || expr[0] == "object") {
3055                         // dot/call on a literal function requires the
3056                         // function literal itself to be parenthesized
3057                         // only if it's the first "thing" in a
3058                         // statement.  This means that the parent is
3059                         // "stat", but it could also be a "seq" and
3060                         // we're the first in this "seq" and the
3061                         // parent is "stat", and so on.  Messy stuff,
3062                         // but it worths the trouble.
3063                         var a = slice($stack), self = a.pop(), p = a.pop();
3064                         while (p) {
3065                                 if (p[0] == "stat") return true;
3066                                 if (((p[0] == "seq" || p[0] == "call" || p[0] == "dot" || p[0] == "sub" || p[0] == "conditional") && p[1] === self) ||
3067                                     ((p[0] == "binary" || p[0] == "assign" || p[0] == "unary-postfix") && p[2] === self)) {
3068                                         self = p;
3069                                         p = a.pop();
3070                                 } else {
3071                                         return false;
3072                                 }
3073                         }
3074                 }
3075                 return !HOP(DOT_CALL_NO_PARENS, expr[0]);
3076         };
3077
3078         function make_num(num) {
3079                 var str = num.toString(10), a = [ str.replace(/^0\./, ".") ], m;
3080                 if (Math.floor(num) === num) {
3081                         a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
3082                                "0" + num.toString(8)); // same.
3083                         if ((m = /^(.*?)(0+)$/.exec(num))) {
3084                                 a.push(m[1] + "e" + m[2].length);
3085                         }
3086                 } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
3087                         a.push(m[2] + "e-" + (m[1].length + m[2].length),
3088                                str.substr(str.indexOf(".")));
3089                 }
3090                 return best_of(a);
3091         };
3092
3093         var generators = {
3094                 "string": encode_string,
3095                 "num": make_num,
3096                 "name": make_name,
3097                 "toplevel": function(statements) {
3098                         return make_block_statements(statements)
3099                                 .join(newline + newline);
3100                 },
3101                 "splice": function(statements) {
3102                         var parent = $stack[$stack.length - 2][0];
3103                         if (HOP(SPLICE_NEEDS_BRACKETS, parent)) {
3104                                 // we need block brackets in this case
3105                                 return make_block.apply(this, arguments);
3106                         } else {
3107                                 return MAP(make_block_statements(statements, true),
3108                                            function(line, i) {
3109                                                    // the first line is already indented
3110                                                    return i > 0 ? indent(line) : line;
3111                                            }).join(newline);
3112                         }
3113                 },
3114                 "block": make_block,
3115                 "var": function(defs) {
3116                         return "var " + add_commas(MAP(defs, make_1vardef)) + ";";
3117                 },
3118                 "const": function(defs) {
3119                         return "const " + add_commas(MAP(defs, make_1vardef)) + ";";
3120                 },
3121                 "try": function(tr, ca, fi) {
3122                         var out = [ "try", make_block(tr) ];
3123                         if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1]));
3124                         if (fi) out.push("finally", make_block(fi));
3125                         return add_spaces(out);
3126                 },
3127                 "throw": function(expr) {
3128                         return add_spaces([ "throw", make(expr) ]) + ";";
3129                 },
3130                 "new": function(ctor, args) {
3131                         args = args.length > 0 ? "(" + add_commas(MAP(args, make)) + ")" : "";
3132                         return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){
3133                                 var w = ast_walker(), has_call = {};
3134                                 try {
3135                                         w.with_walkers({
3136                                                 "call": function() { throw has_call },
3137                                                 "function": function() { return this }
3138                                         }, function(){
3139                                                 w.walk(expr);
3140                                         });
3141                                 } catch(ex) {
3142                                         if (ex === has_call)
3143                                                 return true;
3144                                         throw ex;
3145                                 }
3146                         }) + args ]);
3147                 },
3148                 "switch": function(expr, body) {
3149                         return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]);
3150                 },
3151                 "break": function(label) {
3152                         var out = "break";
3153                         if (label != null)
3154                                 out += " " + make_name(label);
3155                         return out + ";";
3156                 },
3157                 "continue": function(label) {
3158                         var out = "continue";
3159                         if (label != null)
3160                                 out += " " + make_name(label);
3161                         return out + ";";
3162                 },
3163                 "conditional": function(co, th, el) {
3164                         return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?",
3165                                             parenthesize(th, "seq"), ":",
3166                                             parenthesize(el, "seq") ]);
3167                 },
3168                 "assign": function(op, lvalue, rvalue) {
3169                         if (op && op !== true) op += "=";
3170                         else op = "=";
3171                         return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]);
3172                 },
3173                 "dot": function(expr) {
3174                         var out = make(expr), i = 1;
3175                         if (expr[0] == "num") {
3176                                 if (!/\./.test(expr[1]))
3177                                         out += ".";
3178                         } else if (needs_parens(expr))
3179                                 out = "(" + out + ")";
3180                         while (i < arguments.length)
3181                                 out += "." + make_name(arguments[i++]);
3182                         return out;
3183                 },
3184                 "call": function(func, args) {
3185                         var f = make(func);
3186                         if (needs_parens(func))
3187                                 f = "(" + f + ")";
3188                         return f + "(" + add_commas(MAP(args, function(expr){
3189                                 return parenthesize(expr, "seq");
3190                         })) + ")";
3191                 },
3192                 "function": make_function,
3193                 "defun": make_function,
3194                 "if": function(co, th, el) {
3195                         var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ];
3196                         if (el) {
3197                                 out.push("else", make(el));
3198                         }
3199                         return add_spaces(out);
3200                 },
3201                 "for": function(init, cond, step, block) {
3202                         var out = [ "for" ];
3203                         init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space);
3204                         cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space);
3205                         step = (step != null ? make(step) : "").replace(/;*\s*$/, "");
3206                         var args = init + cond + step;
3207                         if (args == "; ; ") args = ";;";
3208                         out.push("(" + args + ")", make(block));
3209                         return add_spaces(out);
3210                 },
3211                 "for-in": function(vvar, key, hash, block) {
3212                         return add_spaces([ "for", "(" +
3213                                             (vvar ? make(vvar).replace(/;+$/, "") : make(key)),
3214                                             "in",
3215                                             make(hash) + ")", make(block) ]);
3216                 },
3217                 "while": function(condition, block) {
3218                         return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]);
3219                 },
3220                 "do": function(condition, block) {
3221                         return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";";
3222                 },
3223                 "return": function(expr) {
3224                         var out = [ "return" ];
3225                         if (expr != null) out.push(make(expr));
3226                         return add_spaces(out) + ";";
3227                 },
3228                 "binary": function(operator, lvalue, rvalue) {
3229                         var left = make(lvalue), right = make(rvalue);
3230                         // XXX: I'm pretty sure other cases will bite here.
3231                         //      we need to be smarter.
3232                         //      adding parens all the time is the safest bet.
3233                         if (member(lvalue[0], [ "assign", "conditional", "seq" ]) ||
3234                             lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]]) {
3235                                 left = "(" + left + ")";
3236                         }
3237                         if (member(rvalue[0], [ "assign", "conditional", "seq" ]) ||
3238                             rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] &&
3239                             !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) {
3240                                 right = "(" + right + ")";
3241                         }
3242                         return add_spaces([ left, operator, right ]);
3243                 },
3244                 "unary-prefix": function(operator, expr) {
3245                         var val = make(expr);
3246                         if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))
3247                                 val = "(" + val + ")";
3248                         return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val;
3249                 },
3250                 "unary-postfix": function(operator, expr) {
3251                         var val = make(expr);
3252                         if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))
3253                                 val = "(" + val + ")";
3254                         return val + operator;
3255                 },
3256                 "sub": function(expr, subscript) {
3257                         var hash = make(expr);
3258                         if (needs_parens(expr))
3259                                 hash = "(" + hash + ")";
3260                         return hash + "[" + make(subscript) + "]";
3261                 },
3262                 "object": function(props) {
3263                         if (props.length == 0)
3264                                 return "{}";
3265                         return "{" + newline + with_indent(function(){
3266                                 return MAP(props, function(p){
3267                                         if (p.length == 3) {
3268                                                 // getter/setter.  The name is in p[0], the arg.list in p[1][2], the
3269                                                 // body in p[1][3] and type ("get" / "set") in p[2].
3270                                                 return indent(make_function(p[0], p[1][2], p[1][3], p[2]));
3271                                         }
3272                                         var key = p[0], val = make(p[1]);
3273                                         if (options.quote_keys) {
3274                                                 key = encode_string(key);
3275                                         } else if ((typeof key == "number" || !beautify && +key + "" == key)
3276                                                    && parseFloat(key) >= 0) {
3277                                                 key = make_num(+key);
3278                                         } else if (!is_identifier(key)) {
3279                                                 key = encode_string(key);
3280                                         }
3281                                         return indent(add_spaces(beautify && options.space_colon
3282                                                                  ? [ key, ":", val ]
3283                                                                  : [ key + ":", val ]));
3284                                 }).join("," + newline);
3285                         }) + newline + indent("}");
3286                 },
3287                 "regexp": function(rx, mods) {
3288                         return "/" + rx + "/" + mods;
3289                 },
3290                 "array": function(elements) {
3291                         if (elements.length == 0) return "[]";
3292                         return add_spaces([ "[", add_commas(MAP(elements, function(el){
3293                                 if (!beautify && el[0] == "atom" && el[1] == "undefined") return "";
3294                                 return parenthesize(el, "seq");
3295                         })), "]" ]);
3296                 },
3297                 "stat": function(stmt) {
3298                         return make(stmt).replace(/;*\s*$/, ";");
3299                 },
3300                 "seq": function() {
3301                         return add_commas(MAP(slice(arguments), make));
3302                 },
3303                 "label": function(name, block) {
3304                         return add_spaces([ make_name(name), ":", make(block) ]);
3305                 },
3306                 "with": function(expr, block) {
3307                         return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]);
3308                 },
3309                 "atom": function(name) {
3310                         return make_name(name);
3311                 }
3312         };
3313
3314         // The squeezer replaces "block"-s that contain only a single
3315         // statement with the statement itself; technically, the AST
3316         // is correct, but this can create problems when we output an
3317         // IF having an ELSE clause where the THEN clause ends in an
3318         // IF *without* an ELSE block (then the outer ELSE would refer
3319         // to the inner IF).  This function checks for this case and
3320         // adds the block brackets if needed.
3321         function make_then(th) {
3322                 if (th[0] == "do") {
3323                         // https://github.com/mishoo/UglifyJS/issues/#issue/57
3324                         // IE croaks with "syntax error" on code like this:
3325                         //     if (foo) do ... while(cond); else ...
3326                         // we need block brackets around do/while
3327                         return make([ "block", [ th ]]);
3328                 }
3329                 var b = th;
3330                 while (true) {
3331                         var type = b[0];
3332                         if (type == "if") {
3333                                 if (!b[3])
3334                                         // no else, we must add the block
3335                                         return make([ "block", [ th ]]);
3336                                 b = b[3];
3337                         }
3338                         else if (type == "while" || type == "do") b = b[2];
3339                         else if (type == "for" || type == "for-in") b = b[4];
3340                         else break;
3341                 }
3342                 return make(th);
3343         };
3344
3345         function make_function(name, args, body, keyword) {
3346                 var out = keyword || "function";
3347                 if (name) {
3348                         out += " " + make_name(name);
3349                 }
3350                 out += "(" + add_commas(MAP(args, make_name)) + ")";
3351                 return add_spaces([ out, make_block(body) ]);
3352         };
3353
3354         function make_block_statements(statements, noindent) {
3355                 for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) {
3356                         var stat = statements[i];
3357                         var code = make(stat);
3358                         if (code != ";") {
3359                                 if (!beautify && i == last) {
3360                                         if ((stat[0] == "while" && empty(stat[2])) ||
3361                                             (member(stat[0], [ "for", "for-in"] ) && empty(stat[4])) ||
3362                                             (stat[0] == "if" && empty(stat[2]) && !stat[3]) ||
3363                                             (stat[0] == "if" && stat[3] && empty(stat[3]))) {
3364                                                 code = code.replace(/;*\s*$/, ";");
3365                                         } else {
3366                                                 code = code.replace(/;+\s*$/, "");
3367                                         }
3368                                 }
3369                                 a.push(code);
3370                         }
3371                 }
3372                 return noindent ? a : MAP(a, indent);
3373         };
3374
3375         function make_switch_block(body) {
3376                 var n = body.length;
3377                 if (n == 0) return "{}";
3378                 return "{" + newline + MAP(body, function(branch, i){
3379                         var has_body = branch[1].length > 0, code = with_indent(function(){
3380                                 return indent(branch[0]
3381                                               ? add_spaces([ "case", make(branch[0]) + ":" ])
3382                                               : "default:");
3383                         }, 0.5) + (has_body ? newline + with_indent(function(){
3384                                 return make_block_statements(branch[1]).join(newline);
3385                         }) : "");
3386                         if (!beautify && has_body && i < n - 1)
3387                                 code += ";";
3388                         return code;
3389                 }).join(newline) + newline + indent("}");
3390         };
3391
3392         function make_block(statements) {
3393                 if (!statements) return ";";
3394                 if (statements.length == 0) return "{}";
3395                 return "{" + newline + with_indent(function(){
3396                         return make_block_statements(statements).join(newline);
3397                 }) + newline + indent("}");
3398         };
3399
3400         function make_1vardef(def) {
3401                 var name = def[0], val = def[1];
3402                 if (val != null)
3403                         name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]);
3404                 return name;
3405         };
3406
3407         var $stack = [];
3408
3409         function make(node) {
3410                 var type = node[0];
3411                 var gen = generators[type];
3412                 if (!gen)
3413                         throw new Error("Can't find generator for \"" + type + "\"");
3414                 $stack.push(node);
3415                 var ret = gen.apply(type, node.slice(1));
3416                 $stack.pop();
3417                 return ret;
3418         };
3419
3420         return make(ast);
3421 };
3422
3423 function split_lines(code, max_line_length) {
3424         var splits = [ 0 ];
3425         jsp.parse(function(){
3426                 var next_token = jsp.tokenizer(code);
3427                 var last_split = 0;
3428                 var prev_token;
3429                 function current_length(tok) {
3430                         return tok.pos - last_split;
3431                 };
3432                 function split_here(tok) {
3433                         last_split = tok.pos;
3434                         splits.push(last_split);
3435                 };
3436                 function custom(){
3437                         var tok = next_token.apply(this, arguments);
3438                         out: {
3439                                 if (prev_token) {
3440                                         if (prev_token.type == "keyword") break out;
3441                                 }
3442                                 if (current_length(tok) > max_line_length) {
3443                                         switch (tok.type) {
3444                                             case "keyword":
3445                                             case "atom":
3446                                             case "name":
3447                                             case "punc":
3448                                                 split_here(tok);
3449                                                 break out;
3450                                         }
3451                                 }
3452                         }
3453                         prev_token = tok;
3454                         return tok;
3455                 };
3456                 custom.context = function() {
3457                         return next_token.context.apply(this, arguments);
3458                 };
3459                 return custom;
3460         }());
3461         return splits.map(function(pos, i){
3462                 return code.substring(pos, splits[i + 1] || code.length);
3463         }).join("\n");
3464 };
3465
3466 /* -----[ Utilities ]----- */
3467
3468 function repeat_string(str, i) {
3469         if (i <= 0) return "";
3470         if (i == 1) return str;
3471         var d = repeat_string(str, i >> 1);
3472         d += d;
3473         if (i & 1) d += str;
3474         return d;
3475 };
3476
3477 function defaults(args, defs) {
3478         var ret = {};
3479         if (args === true)
3480                 args = {};
3481         for (var i in defs) if (HOP(defs, i)) {
3482                 ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
3483         }
3484         return ret;
3485 };
3486
3487 function is_identifier(name) {
3488         return /^[a-z_$][a-z0-9_$]*$/i.test(name)
3489                 && name != "this"
3490                 && !HOP(jsp.KEYWORDS_ATOM, name)
3491                 && !HOP(jsp.RESERVED_WORDS, name)
3492                 && !HOP(jsp.KEYWORDS, name);
3493 };
3494
3495 function HOP(obj, prop) {
3496         return Object.prototype.hasOwnProperty.call(obj, prop);
3497 };
3498
3499 // some utilities
3500
3501 var MAP;
3502
3503 (function(){
3504         MAP = function(a, f, o) {
3505                 var ret = [];
3506                 for (var i = 0; i < a.length; ++i) {
3507                         var val = f.call(o, a[i], i);
3508                         if (val instanceof AtTop) ret.unshift(val.v);
3509                         else ret.push(val);
3510                 }
3511                 return ret;
3512         };
3513         MAP.at_top = function(val) { return new AtTop(val) };
3514         function AtTop(val) { this.v = val };
3515 })();
3516
3517 /* -----[ Exports ]----- */
3518
3519 exports.ast_walker = ast_walker;
3520 exports.ast_mangle = ast_mangle;
3521 exports.ast_squeeze = ast_squeeze;
3522 exports.gen_code = gen_code;
3523 exports.ast_add_scope = ast_add_scope;
3524 exports.set_logger = function(logger) { warn = logger };
3525 exports.make_string = make_string;
3526 exports.split_lines = split_lines;
3527 exports.MAP = MAP;
3528
3529 // keep this last!
3530 exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more;
3531 ;
3532     }).call(module.exports);
3533     
3534     __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"]._cached = module.exports;
3535     return module.exports;
3536 };
3537
3538 require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"] = function () {
3539     var module = { exports : {} };
3540     var exports = module.exports;
3541     var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib";
3542     var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js";
3543     
3544     var require = function (file) {
3545         return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib");
3546     };
3547     
3548     require.resolve = function (file) {
3549         return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib");
3550     };
3551     
3552     require.modules = __require.modules;
3553     __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"]._cached = module.exports;
3554     
3555     (function () {
3556         var jsp = require("./parse-js"),
3557     pro = require("./process"),
3558     slice = jsp.slice,
3559     member = jsp.member,
3560     PRECEDENCE = jsp.PRECEDENCE,
3561     OPERATORS = jsp.OPERATORS;
3562
3563 function ast_squeeze_more(ast) {
3564         var w = pro.ast_walker(), walk = w.walk;
3565         return w.with_walkers({
3566                 "call": function(expr, args) {
3567                         if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) {
3568                                 // foo.toString()  ==>  foo+""
3569                                 return [ "binary", "+", expr[1], [ "string", "" ]];
3570                         }
3571                 }
3572         }, function() {
3573                 return walk(ast);
3574         });
3575 };
3576
3577 exports.ast_squeeze_more = ast_squeeze_more;
3578 ;
3579     }).call(module.exports);
3580     
3581     __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"]._cached = module.exports;
3582     return module.exports;
3583 };
3584
3585 require.modules["/node_modules/burrito/node_modules/traverse/package.json"] = function () {
3586     var module = { exports : {} };
3587     var exports = module.exports;
3588     var __dirname = "/node_modules/burrito/node_modules/traverse";
3589     var __filename = "/node_modules/burrito/node_modules/traverse/package.json";
3590     
3591     var require = function (file) {
3592         return __require(file, "/node_modules/burrito/node_modules/traverse");
3593     };
3594     
3595     require.resolve = function (file) {
3596         return __require.resolve(name, "/node_modules/burrito/node_modules/traverse");
3597     };
3598     
3599     require.modules = __require.modules;
3600     __require.modules["/node_modules/burrito/node_modules/traverse/package.json"]._cached = module.exports;
3601     
3602     (function () {
3603         module.exports = {"name":"traverse","version":"0.5.0","description":"Traverse and transform objects by visiting every node on a recursive walk","author":"James Halliday","license":"MIT/X11","main":"./index","repository":{"type":"git","url":"http://github.com/substack/js-traverse.git"},"devDependencies":{"expresso":"0.7.x"},"scripts":{"test":"expresso"}};
3604     }).call(module.exports);
3605     
3606     __require.modules["/node_modules/burrito/node_modules/traverse/package.json"]._cached = module.exports;
3607     return module.exports;
3608 };
3609
3610 require.modules["/node_modules/burrito/node_modules/traverse/index.js"] = function () {
3611     var module = { exports : {} };
3612     var exports = module.exports;
3613     var __dirname = "/node_modules/burrito/node_modules/traverse";
3614     var __filename = "/node_modules/burrito/node_modules/traverse/index.js";
3615     
3616     var require = function (file) {
3617         return __require(file, "/node_modules/burrito/node_modules/traverse");
3618     };
3619     
3620     require.resolve = function (file) {
3621         return __require.resolve(name, "/node_modules/burrito/node_modules/traverse");
3622     };
3623     
3624     require.modules = __require.modules;
3625     __require.modules["/node_modules/burrito/node_modules/traverse/index.js"]._cached = module.exports;
3626     
3627     (function () {
3628         module.exports = Traverse;
3629 function Traverse (obj) {
3630     if (!(this instanceof Traverse)) return new Traverse(obj);
3631     this.value = obj;
3632 }
3633
3634 Traverse.prototype.get = function (ps) {
3635     var node = this.value;
3636     for (var i = 0; i < ps.length; i ++) {
3637         var key = ps[i];
3638         if (!Object.hasOwnProperty.call(node, key)) {
3639             node = undefined;
3640             break;
3641         }
3642         node = node[key];
3643     }
3644     return node;
3645 };
3646
3647 Traverse.prototype.set = function (ps, value) {
3648     var node = this.value;
3649     for (var i = 0; i < ps.length - 1; i ++) {
3650         var key = ps[i];
3651         if (!Object.hasOwnProperty.call(node, key)) node[key] = {};
3652         node = node[key];
3653     }
3654     node[ps[i]] = value;
3655     return value;
3656 };
3657
3658 Traverse.prototype.map = function (cb) {
3659     return walk(this.value, cb, true);
3660 };
3661
3662 Traverse.prototype.forEach = function (cb) {
3663     this.value = walk(this.value, cb, false);
3664     return this.value;
3665 };
3666
3667 Traverse.prototype.reduce = function (cb, init) {
3668     var skip = arguments.length === 1;
3669     var acc = skip ? this.value : init;
3670     this.forEach(function (x) {
3671         if (!this.isRoot || !skip) {
3672             acc = cb.call(this, acc, x);
3673         }
3674     });
3675     return acc;
3676 };
3677
3678 Traverse.prototype.paths = function () {
3679     var acc = [];
3680     this.forEach(function (x) {
3681         acc.push(this.path); 
3682     });
3683     return acc;
3684 };
3685
3686 Traverse.prototype.nodes = function () {
3687     var acc = [];
3688     this.forEach(function (x) {
3689         acc.push(this.node);
3690     });
3691     return acc;
3692 };
3693
3694 Traverse.prototype.clone = function () {
3695     var parents = [], nodes = [];
3696     
3697     return (function clone (src) {
3698         for (var i = 0; i < parents.length; i++) {
3699             if (parents[i] === src) {
3700                 return nodes[i];
3701             }
3702         }
3703         
3704         if (typeof src === 'object' && src !== null) {
3705             var dst = copy(src);
3706             
3707             parents.push(src);
3708             nodes.push(dst);
3709             
3710             forEach(Object_keys(src), function (key) {
3711                 dst[key] = clone(src[key]);
3712             });
3713             
3714             parents.pop();
3715             nodes.pop();
3716             return dst;
3717         }
3718         else {
3719             return src;
3720         }
3721     })(this.value);
3722 };
3723
3724 function walk (root, cb, immutable) {
3725     var path = [];
3726     var parents = [];
3727     var alive = true;
3728     
3729     return (function walker (node_) {
3730         var node = immutable ? copy(node_) : node_;
3731         var modifiers = {};
3732         
3733         var keepGoing = true;
3734         
3735         var state = {
3736             node : node,
3737             node_ : node_,
3738             path : [].concat(path),
3739             parent : parents[parents.length - 1],
3740             parents : parents,
3741             key : path.slice(-1)[0],
3742             isRoot : path.length === 0,
3743             level : path.length,
3744             circular : null,
3745             update : function (x, stopHere) {
3746                 if (!state.isRoot) {
3747                     state.parent.node[state.key] = x;
3748                 }
3749                 state.node = x;
3750                 if (stopHere) keepGoing = false;
3751             },
3752             'delete' : function () {
3753                 delete state.parent.node[state.key];
3754             },
3755             remove : function () {
3756                 if (Array_isArray(state.parent.node)) {
3757                     state.parent.node.splice(state.key, 1);
3758                 }
3759                 else {
3760                     delete state.parent.node[state.key];
3761                 }
3762             },
3763             keys : null,
3764             before : function (f) { modifiers.before = f },
3765             after : function (f) { modifiers.after = f },
3766             pre : function (f) { modifiers.pre = f },
3767             post : function (f) { modifiers.post = f },
3768             stop : function () { alive = false },
3769             block : function () { keepGoing = false }
3770         };
3771         
3772         if (!alive) return state;
3773         
3774         if (typeof node === 'object' && node !== null) {
3775             state.keys = Object_keys(node);
3776             
3777             state.isLeaf = state.keys.length == 0;
3778             
3779             for (var i = 0; i < parents.length; i++) {
3780                 if (parents[i].node_ === node_) {
3781                     state.circular = parents[i];
3782                     break;
3783                 }
3784             }
3785         }
3786         else {
3787             state.isLeaf = true;
3788         }
3789         
3790         state.notLeaf = !state.isLeaf;
3791         state.notRoot = !state.isRoot;
3792         
3793         // use return values to update if defined
3794         var ret = cb.call(state, state.node);
3795         if (ret !== undefined && state.update) state.update(ret);
3796         
3797         if (modifiers.before) modifiers.before.call(state, state.node);
3798         
3799         if (!keepGoing) return state;
3800         
3801         if (typeof state.node == 'object'
3802         && state.node !== null && !state.circular) {
3803             parents.push(state);
3804             
3805             forEach(state.keys, function (key, i) {
3806                 path.push(key);
3807                 
3808                 if (modifiers.pre) modifiers.pre.call(state, state.node[key], key);
3809                 
3810                 var child = walker(state.node[key]);
3811                 if (immutable && Object.hasOwnProperty.call(state.node, key)) {
3812                     state.node[key] = child.node;
3813                 }
3814                 
3815                 child.isLast = i == state.keys.length - 1;
3816                 child.isFirst = i == 0;
3817                 
3818                 if (modifiers.post) modifiers.post.call(state, child);
3819                 
3820                 path.pop();
3821             });
3822             parents.pop();
3823         }
3824         
3825         if (modifiers.after) modifiers.after.call(state, state.node);
3826         
3827         return state;
3828     })(root).node;
3829 }
3830
3831 function copy (src) {
3832     if (typeof src === 'object' && src !== null) {
3833         var dst;
3834         
3835         if (Array_isArray(src)) {
3836             dst = [];
3837         }
3838         else if (src instanceof Date) {
3839             dst = new Date(src);
3840         }
3841         else if (src instanceof Boolean) {
3842             dst = new Boolean(src);
3843         }
3844         else if (src instanceof Number) {
3845             dst = new Number(src);
3846         }
3847         else if (src instanceof String) {
3848             dst = new String(src);
3849         }
3850         else if (Object.create && Object.getPrototypeOf) {
3851             dst = Object.create(Object.getPrototypeOf(src));
3852         }
3853         else if (src.__proto__ || src.constructor.prototype) {
3854             var proto = src.__proto__ || src.constructor.prototype || {};
3855             var T = function () {};
3856             T.prototype = proto;
3857             dst = new T;
3858             if (!dst.__proto__) dst.__proto__ = proto;
3859         }
3860         
3861         forEach(Object_keys(src), function (key) {
3862             dst[key] = src[key];
3863         });
3864         return dst;
3865     }
3866     else return src;
3867 }
3868
3869 var Object_keys = Object.keys || function keys (obj) {
3870     var res = [];
3871     for (var key in obj) res.push(key)
3872     return res;
3873 };
3874
3875 var Array_isArray = Array.isArray || function isArray (xs) {
3876     return Object.prototype.toString.call(xs) === '[object Array]';
3877 };
3878
3879 var forEach = function (xs, fn) {
3880     if (xs.forEach) return xs.forEach(fn)
3881     else for (var i = 0; i < xs.length; i++) {
3882         fn(xs[i], i, xs);
3883     }
3884 };
3885
3886 forEach(Object_keys(Traverse.prototype), function (key) {
3887     Traverse[key] = function (obj) {
3888         var args = [].slice.call(arguments, 1);
3889         var t = Traverse(obj);
3890         return t[key].apply(t, args);
3891     };
3892 });
3893 ;
3894     }).call(module.exports);
3895     
3896     __require.modules["/node_modules/burrito/node_modules/traverse/index.js"]._cached = module.exports;
3897     return module.exports;
3898 };
3899
3900 require.modules["vm"] = function () {
3901     var module = { exports : {} };
3902     var exports = module.exports;
3903     var __dirname = ".";
3904     var __filename = "vm";
3905     
3906     var require = function (file) {
3907         return __require(file, ".");
3908     };
3909     
3910     require.resolve = function (file) {
3911         return __require.resolve(name, ".");
3912     };
3913     
3914     require.modules = __require.modules;
3915     __require.modules["vm"]._cached = module.exports;
3916     
3917     (function () {
3918         var Object_keys = function (obj) {
3919     if (Object.keys) return Object.keys(obj)
3920     else {
3921         var res = [];
3922         for (var key in obj) res.push(key)
3923         return res;
3924     }
3925 };
3926
3927 var forEach = function (xs, fn) {
3928     if (xs.forEach) return xs.forEach(fn)
3929     else for (var i = 0; i < xs.length; i++) {
3930         fn(xs[i], i, xs);
3931     }
3932 };
3933
3934 var Script = exports.Script = function NodeScript (code) {
3935     if (!(this instanceof Script)) return new Script(code);
3936     this.code = code;
3937 };
3938
3939 var iframe = document.createElement('iframe');
3940 if (!iframe.style) iframe.style = {};
3941 iframe.style.display = 'none';
3942
3943 var iframeCapable = true; // until proven otherwise
3944 if (navigator.appName === 'Microsoft Internet Explorer') {
3945     var m = navigator.appVersion.match(/\bMSIE (\d+\.\d+);/);
3946     if (m && parseFloat(m[1]) <= 9.0) {
3947         iframeCapable = false;
3948     }
3949 }
3950
3951 Script.prototype.runInNewContext = function (context) {
3952     if (!context) context = {};
3953     
3954     if (!iframeCapable) {
3955         var keys = Object_keys(context);
3956         var args = [];
3957         for (var i = 0; i < keys.length; i++) {
3958             args.push(context[keys[i]]);
3959         }
3960         
3961         var fn = Function(keys, this.code);
3962         return fn.apply(null, args);
3963     }
3964     
3965     document.body.appendChild(iframe);
3966     
3967     var win = iframe.contentWindow
3968         || (window.frames && window.frames[window.frames.length - 1])
3969         || window[window.length - 1]
3970     ;
3971     
3972     forEach(Object_keys(context), function (key) {
3973         win[key] = context[key];
3974         iframe[key] = context[key];
3975     });
3976      
3977     if (win.eval) {
3978         // chrome and ff can just .eval()
3979         var res = win.eval(this.code);
3980     }
3981     else {
3982         // this works in IE9 but not anything newer
3983         iframe.setAttribute('src',
3984             'javascript:__browserifyVmResult=(' + this.code + ')'
3985         );
3986         if ('__browserifyVmResult' in win) {
3987             var res = win.__browserifyVmResult;
3988         }
3989         else {
3990             iframeCapable = false;
3991             res = this.runInThisContext(context);
3992         }
3993     }
3994     
3995     forEach(Object_keys(win), function (key) {
3996         context[key] = win[key];
3997     });
3998     
3999     document.body.removeChild(iframe);
4000     
4001     return res;
4002 };
4003
4004 Script.prototype.runInThisContext = function () {
4005     return eval(this.code); // maybe...
4006 };
4007
4008 Script.prototype.runInContext = function (context) {
4009     // seems to be just runInNewContext on magical context objects which are
4010     // otherwise indistinguishable from objects except plain old objects
4011     // for the parameter segfaults node
4012     return this.runInNewContext(context);
4013 };
4014
4015 forEach(Object_keys(Script.prototype), function (name) {
4016     exports[name] = Script[name] = function (code) {
4017         var s = Script(code);
4018         return s[name].apply(s, [].slice.call(arguments, 1));
4019     };
4020 });
4021
4022 exports.createScript = function (code) {
4023     return exports.Script(code);
4024 };
4025
4026 exports.createContext = Script.createContext = function (context) {
4027     // not really sure what this one does
4028     // seems to just make a shallow copy
4029     var copy = {};
4030     forEach(Object_keys(context), function (key) {
4031         copy[key] = context[key];
4032     });
4033     return copy;
4034 };
4035 ;
4036     }).call(module.exports);
4037     
4038     __require.modules["vm"]._cached = module.exports;
4039     return module.exports;
4040 };
4041
4042 require.modules["/node_modules/jsonify/package.json"] = function () {
4043     var module = { exports : {} };
4044     var exports = module.exports;
4045     var __dirname = "/node_modules/jsonify";
4046     var __filename = "/node_modules/jsonify/package.json";
4047     
4048     var require = function (file) {
4049         return __require(file, "/node_modules/jsonify");
4050     };
4051     
4052     require.resolve = function (file) {
4053         return __require.resolve(name, "/node_modules/jsonify");
4054     };
4055     
4056     require.modules = __require.modules;
4057     __require.modules["/node_modules/jsonify/package.json"]._cached = module.exports;
4058     
4059     (function () {
4060         module.exports = {"name":"jsonify","version":"0.0.0","description":"JSON without touching any globals","main":"index.js","directories":{"lib":".","test":"test"},"devDependencies":{"tap":"0.0.x","garbage":"0.0.x"},"scripts":{"test":"tap test"},"repository":{"type":"git","url":"http://github.com/substack/jsonify.git"},"keywords":["json","browser"],"author":{"name":"Douglas Crockford","url":"http://crockford.com/"},"license":"Public Domain"};
4061     }).call(module.exports);
4062     
4063     __require.modules["/node_modules/jsonify/package.json"]._cached = module.exports;
4064     return module.exports;
4065 };
4066
4067 require.modules["/node_modules/jsonify/index.js"] = function () {
4068     var module = { exports : {} };
4069     var exports = module.exports;
4070     var __dirname = "/node_modules/jsonify";
4071     var __filename = "/node_modules/jsonify/index.js";
4072     
4073     var require = function (file) {
4074         return __require(file, "/node_modules/jsonify");
4075     };
4076     
4077     require.resolve = function (file) {
4078         return __require.resolve(name, "/node_modules/jsonify");
4079     };
4080     
4081     require.modules = __require.modules;
4082     __require.modules["/node_modules/jsonify/index.js"]._cached = module.exports;
4083     
4084     (function () {
4085         exports.parse = require('./lib/parse');
4086 exports.stringify = require('./lib/stringify');
4087 ;
4088     }).call(module.exports);
4089     
4090     __require.modules["/node_modules/jsonify/index.js"]._cached = module.exports;
4091     return module.exports;
4092 };
4093
4094 require.modules["/node_modules/jsonify/lib/parse.js"] = function () {
4095     var module = { exports : {} };
4096     var exports = module.exports;
4097     var __dirname = "/node_modules/jsonify/lib";
4098     var __filename = "/node_modules/jsonify/lib/parse.js";
4099     
4100     var require = function (file) {
4101         return __require(file, "/node_modules/jsonify/lib");
4102     };
4103     
4104     require.resolve = function (file) {
4105         return __require.resolve(name, "/node_modules/jsonify/lib");
4106     };
4107     
4108     require.modules = __require.modules;
4109     __require.modules["/node_modules/jsonify/lib/parse.js"]._cached = module.exports;
4110     
4111     (function () {
4112         var at, // The index of the current character
4113     ch, // The current character
4114     escapee = {
4115         '"':  '"',
4116         '\\': '\\',
4117         '/':  '/',
4118         b:    '\b',
4119         f:    '\f',
4120         n:    '\n',
4121         r:    '\r',
4122         t:    '\t'
4123     },
4124     text,
4125
4126     error = function (m) {
4127         // Call error when something is wrong.
4128         throw {
4129             name:    'SyntaxError',
4130             message: m,
4131             at:      at,
4132             text:    text
4133         };
4134     },
4135     
4136     next = function (c) {
4137         // If a c parameter is provided, verify that it matches the current character.
4138         if (c && c !== ch) {
4139             error("Expected '" + c + "' instead of '" + ch + "'");
4140         }
4141         
4142         // Get the next character. When there are no more characters,
4143         // return the empty string.
4144         
4145         ch = text.charAt(at);
4146         at += 1;
4147         return ch;
4148     },
4149     
4150     number = function () {
4151         // Parse a number value.
4152         var number,
4153             string = '';
4154         
4155         if (ch === '-') {
4156             string = '-';
4157             next('-');
4158         }
4159         while (ch >= '0' && ch <= '9') {
4160             string += ch;
4161             next();
4162         }
4163         if (ch === '.') {
4164             string += '.';
4165             while (next() && ch >= '0' && ch <= '9') {
4166                 string += ch;
4167             }
4168         }
4169         if (ch === 'e' || ch === 'E') {
4170             string += ch;
4171             next();
4172             if (ch === '-' || ch === '+') {
4173                 string += ch;
4174                 next();
4175             }
4176             while (ch >= '0' && ch <= '9') {
4177                 string += ch;
4178                 next();
4179             }
4180         }
4181         number = +string;
4182         if (!isFinite(number)) {
4183             error("Bad number");
4184         } else {
4185             return number;
4186         }
4187     },
4188     
4189     string = function () {
4190         // Parse a string value.
4191         var hex,
4192             i,
4193             string = '',
4194             uffff;
4195         
4196         // When parsing for string values, we must look for " and \ characters.
4197         if (ch === '"') {
4198             while (next()) {
4199                 if (ch === '"') {
4200                     next();
4201                     return string;
4202                 } else if (ch === '\\') {
4203                     next();
4204                     if (ch === 'u') {
4205                         uffff = 0;
4206                         for (i = 0; i < 4; i += 1) {
4207                             hex = parseInt(next(), 16);
4208                             if (!isFinite(hex)) {
4209                                 break;
4210                             }
4211                             uffff = uffff * 16 + hex;
4212                         }
4213                         string += String.fromCharCode(uffff);
4214                     } else if (typeof escapee[ch] === 'string') {
4215                         string += escapee[ch];
4216                     } else {
4217                         break;
4218                     }
4219                 } else {
4220                     string += ch;
4221                 }
4222             }
4223         }
4224         error("Bad string");
4225     },
4226
4227     white = function () {
4228
4229 // Skip whitespace.
4230
4231         while (ch && ch <= ' ') {
4232             next();
4233         }
4234     },
4235
4236     word = function () {
4237
4238 // true, false, or null.
4239
4240         switch (ch) {
4241         case 't':
4242             next('t');
4243             next('r');
4244             next('u');
4245             next('e');
4246             return true;
4247         case 'f':
4248             next('f');
4249             next('a');
4250             next('l');
4251             next('s');
4252             next('e');
4253             return false;
4254         case 'n':
4255             next('n');
4256             next('u');
4257             next('l');
4258             next('l');
4259             return null;
4260         }
4261         error("Unexpected '" + ch + "'");
4262     },
4263
4264     value,  // Place holder for the value function.
4265
4266     array = function () {
4267
4268 // Parse an array value.
4269
4270         var array = [];
4271
4272         if (ch === '[') {
4273             next('[');
4274             white();
4275             if (ch === ']') {
4276                 next(']');
4277                 return array;   // empty array
4278             }
4279             while (ch) {
4280                 array.push(value());
4281                 white();
4282                 if (ch === ']') {
4283                     next(']');
4284                     return array;
4285                 }
4286                 next(',');
4287                 white();
4288             }
4289         }
4290         error("Bad array");
4291     },
4292
4293     object = function () {
4294
4295 // Parse an object value.
4296
4297         var key,
4298             object = {};
4299
4300         if (ch === '{') {
4301             next('{');
4302             white();
4303             if (ch === '}') {
4304                 next('}');
4305                 return object;   // empty object
4306             }
4307             while (ch) {
4308                 key = string();
4309                 white();
4310                 next(':');
4311                 if (Object.hasOwnProperty.call(object, key)) {
4312                     error('Duplicate key "' + key + '"');
4313                 }
4314                 object[key] = value();
4315                 white();
4316                 if (ch === '}') {
4317                     next('}');
4318                     return object;
4319                 }
4320                 next(',');
4321                 white();
4322             }
4323         }
4324         error("Bad object");
4325     };
4326
4327 value = function () {
4328
4329 // Parse a JSON value. It could be an object, an array, a string, a number,
4330 // or a word.
4331
4332     white();
4333     switch (ch) {
4334     case '{':
4335         return object();
4336     case '[':
4337         return array();
4338     case '"':
4339         return string();
4340     case '-':
4341         return number();
4342     default:
4343         return ch >= '0' && ch <= '9' ? number() : word();
4344     }
4345 };
4346
4347 // Return the json_parse function. It will have access to all of the above
4348 // functions and variables.
4349
4350 module.exports = function (source, reviver) {
4351     var result;
4352     
4353     text = source;
4354     at = 0;
4355     ch = ' ';
4356     result = value();
4357     white();
4358     if (ch) {
4359         error("Syntax error");
4360     }
4361
4362     // If there is a reviver function, we recursively walk the new structure,
4363     // passing each name/value pair to the reviver function for possible
4364     // transformation, starting with a temporary root object that holds the result
4365     // in an empty key. If there is not a reviver function, we simply return the
4366     // result.
4367
4368     return typeof reviver === 'function' ? (function walk(holder, key) {
4369         var k, v, value = holder[key];
4370         if (value && typeof value === 'object') {
4371             for (k in value) {
4372                 if (Object.prototype.hasOwnProperty.call(value, k)) {
4373                     v = walk(value, k);
4374                     if (v !== undefined) {
4375                         value[k] = v;
4376                     } else {
4377                         delete value[k];
4378                     }
4379                 }
4380             }
4381         }
4382         return reviver.call(holder, key, value);
4383     }({'': result}, '')) : result;
4384 };
4385 ;
4386     }).call(module.exports);
4387     
4388     __require.modules["/node_modules/jsonify/lib/parse.js"]._cached = module.exports;
4389     return module.exports;
4390 };
4391
4392 require.modules["/node_modules/jsonify/lib/stringify.js"] = function () {
4393     var module = { exports : {} };
4394     var exports = module.exports;
4395     var __dirname = "/node_modules/jsonify/lib";
4396     var __filename = "/node_modules/jsonify/lib/stringify.js";
4397     
4398     var require = function (file) {
4399         return __require(file, "/node_modules/jsonify/lib");
4400     };
4401     
4402     require.resolve = function (file) {
4403         return __require.resolve(name, "/node_modules/jsonify/lib");
4404     };
4405     
4406     require.modules = __require.modules;
4407     __require.modules["/node_modules/jsonify/lib/stringify.js"]._cached = module.exports;
4408     
4409     (function () {
4410         var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
4411     escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
4412     gap,
4413     indent,
4414     meta = {    // table of character substitutions
4415         '\b': '\\b',
4416         '\t': '\\t',
4417         '\n': '\\n',
4418         '\f': '\\f',
4419         '\r': '\\r',
4420         '"' : '\\"',
4421         '\\': '\\\\'
4422     },
4423     rep;
4424
4425 function quote(string) {
4426     // If the string contains no control characters, no quote characters, and no
4427     // backslash characters, then we can safely slap some quotes around it.
4428     // Otherwise we must also replace the offending characters with safe escape
4429     // sequences.
4430     
4431     escapable.lastIndex = 0;
4432     return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
4433         var c = meta[a];
4434         return typeof c === 'string' ? c :
4435             '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
4436     }) + '"' : '"' + string + '"';
4437 }
4438
4439 function str(key, holder) {
4440     // Produce a string from holder[key].
4441     var i,          // The loop counter.
4442         k,          // The member key.
4443         v,          // The member value.
4444         length,
4445         mind = gap,
4446         partial,
4447         value = holder[key];
4448     
4449     // If the value has a toJSON method, call it to obtain a replacement value.
4450     if (value && typeof value === 'object' &&
4451             typeof value.toJSON === 'function') {
4452         value = value.toJSON(key);
4453     }
4454     
4455     // If we were called with a replacer function, then call the replacer to
4456     // obtain a replacement value.
4457     if (typeof rep === 'function') {
4458         value = rep.call(holder, key, value);
4459     }
4460     
4461     // What happens next depends on the value's type.
4462     switch (typeof value) {
4463         case 'string':
4464             return quote(value);
4465         
4466         case 'number':
4467             // JSON numbers must be finite. Encode non-finite numbers as null.
4468             return isFinite(value) ? String(value) : 'null';
4469         
4470         case 'boolean':
4471         case 'null':
4472             // If the value is a boolean or null, convert it to a string. Note:
4473             // typeof null does not produce 'null'. The case is included here in
4474             // the remote chance that this gets fixed someday.
4475             return String(value);
4476             
4477         case 'object':
4478             if (!value) return 'null';
4479             gap += indent;
4480             partial = [];
4481             
4482             // Array.isArray
4483             if (Object.prototype.toString.apply(value) === '[object Array]') {
4484                 length = value.length;
4485                 for (i = 0; i < length; i += 1) {
4486                     partial[i] = str(i, value) || 'null';
4487                 }
4488                 
4489                 // Join all of the elements together, separated with commas, and
4490                 // wrap them in brackets.
4491                 v = partial.length === 0 ? '[]' : gap ?
4492                     '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
4493                     '[' + partial.join(',') + ']';
4494                 gap = mind;
4495                 return v;
4496             }
4497             
4498             // If the replacer is an array, use it to select the members to be
4499             // stringified.
4500             if (rep && typeof rep === 'object') {
4501                 length = rep.length;
4502                 for (i = 0; i < length; i += 1) {
4503                     k = rep[i];
4504                     if (typeof k === 'string') {
4505                         v = str(k, value);
4506                         if (v) {
4507                             partial.push(quote(k) + (gap ? ': ' : ':') + v);
4508                         }
4509                     }
4510                 }
4511             }
4512             else {
4513                 // Otherwise, iterate through all of the keys in the object.
4514                 for (k in value) {
4515                     if (Object.prototype.hasOwnProperty.call(value, k)) {
4516                         v = str(k, value);
4517                         if (v) {
4518                             partial.push(quote(k) + (gap ? ': ' : ':') + v);
4519                         }
4520                     }
4521                 }
4522             }
4523             
4524         // Join all of the member texts together, separated with commas,
4525         // and wrap them in braces.
4526
4527         v = partial.length === 0 ? '{}' : gap ?
4528             '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
4529             '{' + partial.join(',') + '}';
4530         gap = mind;
4531         return v;
4532     }
4533 }
4534
4535 module.exports = function (value, replacer, space) {
4536     var i;
4537     gap = '';
4538     indent = '';
4539     
4540     // If the space parameter is a number, make an indent string containing that
4541     // many spaces.
4542     if (typeof space === 'number') {
4543         for (i = 0; i < space; i += 1) {
4544             indent += ' ';
4545         }
4546     }
4547     // If the space parameter is a string, it will be used as the indent string.
4548     else if (typeof space === 'string') {
4549         indent = space;
4550     }
4551
4552     // If there is a replacer, it must be a function or an array.
4553     // Otherwise, throw an error.
4554     rep = replacer;
4555     if (replacer && typeof replacer !== 'function'
4556     && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) {
4557         throw new Error('JSON.stringify');
4558     }
4559     
4560     // Make a fake root object containing our value under the key of ''.
4561     // Return the result of stringifying the value.
4562     return str('', {'': value});
4563 };
4564 ;
4565     }).call(module.exports);
4566     
4567     __require.modules["/node_modules/jsonify/lib/stringify.js"]._cached = module.exports;
4568     return module.exports;
4569 };
4570
4571 require.modules["/node_modules/burrito/index.js"] = function () {
4572     var module = { exports : {} };
4573     var exports = module.exports;
4574     var __dirname = "/node_modules/burrito";
4575     var __filename = "/node_modules/burrito/index.js";
4576     
4577     var require = function (file) {
4578         return __require(file, "/node_modules/burrito");
4579     };
4580     
4581     require.resolve = function (file) {
4582         return __require.resolve(name, "/node_modules/burrito");
4583     };
4584     
4585     require.modules = __require.modules;
4586     __require.modules["/node_modules/burrito/index.js"]._cached = module.exports;
4587     
4588     (function () {
4589         var uglify = require('uglify-js');
4590 var parser = uglify.parser;
4591 var parse = function (expr) {
4592     if (typeof expr !== 'string') throw 'expression should be a string';
4593     
4594     //try {
4595         var args = [].slice.call(arguments);
4596         var ast = parser.parse.apply(null, args);
4597     /* }
4598     catch (err) {
4599         if (err.message === undefined
4600         || err.line === undefined
4601         || err.col === undefined
4602         || err.pos === undefined
4603         ) { throw err }
4604         
4605         var e = new SyntaxError(
4606             err.message
4607             + '\n  at line ' + err.line + ':' + err.col + ' in expression:\n\n'
4608             + '  ' + expr.split(/\r?\n/)[err.line]
4609         );
4610         
4611         e.original = err;
4612         e.line = err.line;
4613         e.col = err.col;
4614         e.pos = err.pos;
4615         throw e;
4616     }
4617     */
4618     return ast;
4619 };
4620
4621 var deparse = function (ast, b) {
4622     return uglify.uglify.gen_code(ast, { beautify : b });
4623 };
4624
4625 var traverse = require('traverse');
4626 var vm = require('vm');
4627
4628 var burrito = module.exports = function (code, cb) {
4629     var ast = Array_isArray(code)
4630         ? code // already an ast
4631         : parse(code.toString(), false, true)
4632     ;
4633     
4634     var ast_ = traverse(ast).map(function mapper () {
4635         wrapNode(this, cb);
4636     });
4637     
4638     return deparse(parse(deparse(ast_)), true);
4639 };
4640
4641 var wrapNode = burrito.wrapNode = function (state, cb) {
4642     var node = state.node;
4643     
4644     var ann = Array_isArray(node) && node[0]
4645     && typeof node[0] === 'object' && node[0].name
4646         ? node[0]
4647         : null
4648     ;
4649     
4650     if (!ann) return undefined;
4651     
4652     var self = {
4653         name : ann.name,
4654         node : node,
4655         start : node[0].start,
4656         end : node[0].end,
4657         value : node.slice(1),
4658         state : state
4659     };
4660     
4661     self.wrap = function (s) {
4662         var subsrc = deparse(
4663             traverse(node).map(function (x) {
4664                 if (!this.isRoot) wrapNode(this, cb)
4665             })
4666         );
4667         
4668         if (self.name === 'binary') {
4669             var a = deparse(traverse(node[2]).map(function (x) {
4670                 if (!this.isRoot) wrapNode(this, cb)
4671             }));
4672             var b = deparse(traverse(node[3]).map(function (x) {
4673                 if (!this.isRoot) wrapNode(this, cb)
4674             }));
4675         }
4676         
4677         var src = '';
4678         
4679         if (typeof s === 'function') {
4680             if (self.name === 'binary') {
4681                 src = s(subsrc, a, b);
4682             }
4683             else {
4684                 src = s(subsrc);
4685             }
4686         }
4687         else {
4688             src = s.toString()
4689                 .replace(/%s/g, function () {
4690                     return subsrc
4691                 })
4692             ;
4693             
4694             if (self.name === 'binary') {
4695                 src = src
4696                     .replace(/%a/g, function () { return a })
4697                     .replace(/%b/g, function () { return b })
4698                 ;
4699             }
4700         }
4701         
4702         var expr = parse(src);
4703         state.update(expr, true);
4704     };
4705     
4706     var cache = {};
4707     
4708     self.parent = state.isRoot ? null : function () {
4709         if (!cache.parent) {
4710             var s = state;
4711             var x;
4712             do {
4713                 s = s.parent;
4714                 if (s) x = wrapNode(s);
4715             } while (s && !x);
4716             
4717             cache.parent = x;
4718         }
4719         
4720         return cache.parent;
4721     };
4722     
4723     self.source = function () {
4724         if (!cache.source) cache.source = deparse(node);
4725         return cache.source;
4726     };
4727     
4728     self.label = function () {
4729         return burrito.label(self);
4730     };
4731     
4732     if (cb) cb.call(state, self);
4733     
4734     if (self.node[0].name === 'conditional') {
4735         self.wrap('[%s][0]');
4736     }
4737     
4738     return self;
4739 }
4740
4741 burrito.microwave = function (code, context, cb) {
4742     if (!cb) { cb = context; context = {} };
4743     if (!context) context = {};
4744     
4745     var src = burrito(code, cb);
4746     return vm.runInNewContext(src, context);
4747 };
4748
4749 burrito.generateName = function (len) {
4750     var name = '';
4751     var lower = '$'.charCodeAt(0);
4752     var upper = 'z'.charCodeAt(0);
4753     
4754     while (name.length < len) {
4755         var c = String.fromCharCode(Math.floor(
4756             Math.random() * (upper - lower + 1) + lower
4757         ));
4758         if ((name + c).match(/^[A-Za-z_$][A-Za-z0-9_$]*$/)) name += c;
4759     }
4760     
4761     return name;
4762 };
4763
4764 burrito.parse = parse;
4765 burrito.deparse = deparse;
4766
4767 burrito.label = function (node) {
4768     if (node.name === 'call') {
4769         if (typeof node.value[0] === 'string') {
4770             return node.value[0];
4771         }
4772         else if (node.value[0] && typeof node.value[0][1] === 'string') {
4773             return node.value[0][1];
4774         }
4775         else {
4776             return null;
4777         }
4778     }
4779     else if (node.name === 'var') {
4780         return node.value[0].map(function (x) { return x[0] });
4781     }
4782     else if (node.name === 'defun') {
4783         return node.value[0];
4784     }
4785     else if (node.name === 'function') {
4786         return node.value[0];
4787     }
4788     else {
4789         return null;
4790     }
4791 };
4792
4793 var Array_isArray = Array.isArray || function isArray (xs) {
4794     return Object.prototype.toString.call(xs) === '[object Array]';
4795 };
4796 ;
4797     }).call(module.exports);
4798     
4799     __require.modules["/node_modules/burrito/index.js"]._cached = module.exports;
4800     return module.exports;
4801 };
4802
4803 process.nextTick(function () {
4804     var module = { exports : {} };
4805     var exports = module.exports;
4806     var __dirname = "/";
4807     var __filename = "//home/substack/projects/node-burrito/example/web";
4808     
4809     var require = function (file) {
4810         return __require(file, "/");
4811     };
4812     require.modules = __require.modules;
4813     
4814     var burrito = require('burrito');
4815 var json = require('jsonify');
4816
4817 var src = [
4818     'function f () { g() }',
4819     'function g () { h() }',
4820     'function h () { throw "moo" + Array(x).join("!") }',
4821     'var x = 4',
4822     'f()'
4823 ].join('\r\n');
4824
4825 window.onload = function () {
4826     burrito(src, function (node) {
4827         document.body.innerHTML += node.name + '<br>\n';
4828     });
4829 };
4830 if (document.readyState === 'complete') window.onload();
4831 ;
4832 });