AMD-ify jQuery sourcegit s! Woo! Fixes #14113, #14163.
[jquery.git] / build / r.js
blob2708f51ddf7c48f4e30f565332909da2e1e1253b
1 /**
2  * @license r.js 2.1.8+ Tue, 13 Aug 2013 02:54:07 GMT Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
3  * Available via the MIT or new BSD license.
4  * see: http://github.com/jrburke/requirejs for details
5  */
7 /*
8  * This is a bootstrap script to allow running RequireJS in the command line
9  * in either a Java/Rhino or Node environment. It is modified by the top-level
10  * dist.js file to inject other files to completely enable this file. It is
11  * the shell of the r.js file.
12  */
14 /*jslint evil: true, nomen: true, sloppy: true */
15 /*global readFile: true, process: false, Packages: false, print: false,
16 console: false, java: false, module: false, requirejsVars, navigator,
17 document, importScripts, self, location, Components, FileUtils */
19 var requirejs, require, define, xpcUtil;
20 (function (console, args, readFileFunc) {
21     var fileName, env, fs, vm, path, exec, rhinoContext, dir, nodeRequire,
22         nodeDefine, exists, reqMain, loadedOptimizedLib, existsForNode, Cc, Ci,
23         version = '2.1.8+ Tue, 13 Aug 2013 02:54:07 GMT',
24         jsSuffixRegExp = /\.js$/,
25         commandOption = '',
26         useLibLoaded = {},
27         //Used by jslib/rhino/args.js
28         rhinoArgs = args,
29         //Used by jslib/xpconnect/args.js
30         xpconnectArgs = args,
31         readFile = typeof readFileFunc !== 'undefined' ? readFileFunc : null;
33     function showHelp() {
34         console.log('See https://github.com/jrburke/r.js for usage.');
35     }
37     if ((typeof navigator !== 'undefined' && typeof document !== 'undefined') ||
38             (typeof importScripts !== 'undefined' && typeof self !== 'undefined')) {
39         env = 'browser';
41         readFile = function (path) {
42             return fs.readFileSync(path, 'utf8');
43         };
45         exec = function (string) {
46             return eval(string);
47         };
49         exists = function () {
50             console.log('x.js exists not applicable in browser env');
51             return false;
52         };
54     } else if (typeof Packages !== 'undefined') {
55         env = 'rhino';
57         fileName = args[0];
59         if (fileName && fileName.indexOf('-') === 0) {
60             commandOption = fileName.substring(1);
61             fileName = args[1];
62         }
64         //Set up execution context.
65         rhinoContext = Packages.org.mozilla.javascript.ContextFactory.getGlobal().enterContext();
67         exec = function (string, name) {
68             return rhinoContext.evaluateString(this, string, name, 0, null);
69         };
71         exists = function (fileName) {
72             return (new java.io.File(fileName)).exists();
73         };
75         //Define a console.log for easier logging. Don't
76         //get fancy though.
77         if (typeof console === 'undefined') {
78             console = {
79                 log: function () {
80                     print.apply(undefined, arguments);
81                 }
82             };
83         }
84     } else if (typeof process !== 'undefined' && process.versions && !!process.versions.node) {
85         env = 'node';
87         //Get the fs module via Node's require before it
88         //gets replaced. Used in require/node.js
89         fs = require('fs');
90         vm = require('vm');
91         path = require('path');
92         //In Node 0.7+ existsSync is on fs.
93         existsForNode = fs.existsSync || path.existsSync;
95         nodeRequire = require;
96         nodeDefine = define;
97         reqMain = require.main;
99         //Temporarily hide require and define to allow require.js to define
100         //them.
101         require = undefined;
102         define = undefined;
104         readFile = function (path) {
105             return fs.readFileSync(path, 'utf8');
106         };
108         exec = function (string, name) {
109             return vm.runInThisContext(this.requirejsVars.require.makeNodeWrapper(string),
110                                        name ? fs.realpathSync(name) : '');
111         };
113         exists = function (fileName) {
114             return existsForNode(fileName);
115         };
118         fileName = process.argv[2];
120         if (fileName && fileName.indexOf('-') === 0) {
121             commandOption = fileName.substring(1);
122             fileName = process.argv[3];
123         }
124     } else if (typeof Components !== 'undefined' && Components.classes && Components.interfaces) {
125         env = 'xpconnect';
127         Components.utils['import']('resource://gre/modules/FileUtils.jsm');
128         Cc = Components.classes;
129         Ci = Components.interfaces;
131         fileName = args[0];
133         if (fileName && fileName.indexOf('-') === 0) {
134             commandOption = fileName.substring(1);
135             fileName = args[1];
136         }
138         xpcUtil = {
139             isWindows: ('@mozilla.org/windows-registry-key;1' in Cc),
140             cwd: function () {
141                 return FileUtils.getFile("CurWorkD", []).path;
142             },
144             //Remove . and .. from paths, normalize on front slashes
145             normalize: function (path) {
146                 //There has to be an easier way to do this.
147                 var i, part, ary,
148                     firstChar = path.charAt(0);
150                 if (firstChar !== '/' &&
151                         firstChar !== '\\' &&
152                         path.indexOf(':') === -1) {
153                     //A relative path. Use the current working directory.
154                     path = xpcUtil.cwd() + '/' + path;
155                 }
157                 ary = path.replace(/\\/g, '/').split('/');
159                 for (i = 0; i < ary.length; i += 1) {
160                     part = ary[i];
161                     if (part === '.') {
162                         ary.splice(i, 1);
163                         i -= 1;
164                     } else if (part === '..') {
165                         ary.splice(i - 1, 2);
166                         i -= 2;
167                     }
168                 }
169                 return ary.join('/');
170             },
172             xpfile: function (path) {
173                 var fullPath;
174                 try {
175                     fullPath = xpcUtil.normalize(path);
176                     if (xpcUtil.isWindows) {
177                         fullPath = fullPath.replace(/\//g, '\\');
178                     }
179                     return new FileUtils.File(fullPath);
180                 } catch (e) {
181                     throw new Error((fullPath || path) + ' failed: ' + e);
182                 }
183             },
185             readFile: function (/*String*/path, /*String?*/encoding) {
186                 //A file read function that can deal with BOMs
187                 encoding = encoding || "utf-8";
189                 var inStream, convertStream,
190                     readData = {},
191                     fileObj = xpcUtil.xpfile(path);
193                 //XPCOM, you so crazy
194                 try {
195                     inStream = Cc['@mozilla.org/network/file-input-stream;1']
196                                .createInstance(Ci.nsIFileInputStream);
197                     inStream.init(fileObj, 1, 0, false);
199                     convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']
200                                     .createInstance(Ci.nsIConverterInputStream);
201                     convertStream.init(inStream, encoding, inStream.available(),
202                     Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
204                     convertStream.readString(inStream.available(), readData);
205                     return readData.value;
206                 } catch (e) {
207                     throw new Error((fileObj && fileObj.path || '') + ': ' + e);
208                 } finally {
209                     if (convertStream) {
210                         convertStream.close();
211                     }
212                     if (inStream) {
213                         inStream.close();
214                     }
215                 }
216             }
217         };
219         readFile = xpcUtil.readFile;
221         exec = function (string) {
222             return eval(string);
223         };
225         exists = function (fileName) {
226             return xpcUtil.xpfile(fileName).exists();
227         };
229         //Define a console.log for easier logging. Don't
230         //get fancy though.
231         if (typeof console === 'undefined') {
232             console = {
233                 log: function () {
234                     print.apply(undefined, arguments);
235                 }
236             };
237         }
238     }
240     /** vim: et:ts=4:sw=4:sts=4
241  * @license RequireJS 2.1.8 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
242  * Available via the MIT or new BSD license.
243  * see: http://github.com/jrburke/requirejs for details
244  */
245 //Not using strict: uneven strict support in browsers, #392, and causes
246 //problems with requirejs.exec()/transpiler plugins that may not be strict.
247 /*jslint regexp: true, nomen: true, sloppy: true */
248 /*global window, navigator, document, importScripts, setTimeout, opera */
251 (function (global) {
252     var req, s, head, baseElement, dataMain, src,
253         interactiveScript, currentlyAddingScript, mainScript, subPath,
254         version = '2.1.8',
255         commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
256         cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
257         jsSuffixRegExp = /\.js$/,
258         currDirRegExp = /^\.\//,
259         op = Object.prototype,
260         ostring = op.toString,
261         hasOwn = op.hasOwnProperty,
262         ap = Array.prototype,
263         apsp = ap.splice,
264         isBrowser = !!(typeof window !== 'undefined' && navigator && window.document),
265         isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
266         //PS3 indicates loaded and complete, but need to wait for complete
267         //specifically. Sequence is 'loading', 'loaded', execution,
268         // then 'complete'. The UA check is unfortunate, but not sure how
269         //to feature test w/o causing perf issues.
270         readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
271                       /^complete$/ : /^(complete|loaded)$/,
272         defContextName = '_',
273         //Oh the tragedy, detecting opera. See the usage of isOpera for reason.
274         isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]',
275         contexts = {},
276         cfg = {},
277         globalDefQueue = [],
278         useInteractive = false;
280     function isFunction(it) {
281         return ostring.call(it) === '[object Function]';
282     }
284     function isArray(it) {
285         return ostring.call(it) === '[object Array]';
286     }
288     /**
289      * Helper function for iterating over an array. If the func returns
290      * a true value, it will break out of the loop.
291      */
292     function each(ary, func) {
293         if (ary) {
294             var i;
295             for (i = 0; i < ary.length; i += 1) {
296                 if (ary[i] && func(ary[i], i, ary)) {
297                     break;
298                 }
299             }
300         }
301     }
303     /**
304      * Helper function for iterating over an array backwards. If the func
305      * returns a true value, it will break out of the loop.
306      */
307     function eachReverse(ary, func) {
308         if (ary) {
309             var i;
310             for (i = ary.length - 1; i > -1; i -= 1) {
311                 if (ary[i] && func(ary[i], i, ary)) {
312                     break;
313                 }
314             }
315         }
316     }
318     function hasProp(obj, prop) {
319         return hasOwn.call(obj, prop);
320     }
322     function getOwn(obj, prop) {
323         return hasProp(obj, prop) && obj[prop];
324     }
326     /**
327      * Cycles over properties in an object and calls a function for each
328      * property value. If the function returns a truthy value, then the
329      * iteration is stopped.
330      */
331     function eachProp(obj, func) {
332         var prop;
333         for (prop in obj) {
334             if (hasProp(obj, prop)) {
335                 if (func(obj[prop], prop)) {
336                     break;
337                 }
338             }
339         }
340     }
342     /**
343      * Simple function to mix in properties from source into target,
344      * but only if target does not already have a property of the same name.
345      */
346     function mixin(target, source, force, deepStringMixin) {
347         if (source) {
348             eachProp(source, function (value, prop) {
349                 if (force || !hasProp(target, prop)) {
350                     if (deepStringMixin && typeof value !== 'string') {
351                         if (!target[prop]) {
352                             target[prop] = {};
353                         }
354                         mixin(target[prop], value, force, deepStringMixin);
355                     } else {
356                         target[prop] = value;
357                     }
358                 }
359             });
360         }
361         return target;
362     }
364     //Similar to Function.prototype.bind, but the 'this' object is specified
365     //first, since it is easier to read/figure out what 'this' will be.
366     function bind(obj, fn) {
367         return function () {
368             return fn.apply(obj, arguments);
369         };
370     }
372     function scripts() {
373         return document.getElementsByTagName('script');
374     }
376     function defaultOnError(err) {
377         throw err;
378     }
380     //Allow getting a global that expressed in
381     //dot notation, like 'a.b.c'.
382     function getGlobal(value) {
383         if (!value) {
384             return value;
385         }
386         var g = global;
387         each(value.split('.'), function (part) {
388             g = g[part];
389         });
390         return g;
391     }
393     /**
394      * Constructs an error with a pointer to an URL with more information.
395      * @param {String} id the error ID that maps to an ID on a web page.
396      * @param {String} message human readable error.
397      * @param {Error} [err] the original error, if there is one.
398      *
399      * @returns {Error}
400      */
401     function makeError(id, msg, err, requireModules) {
402         var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
403         e.requireType = id;
404         e.requireModules = requireModules;
405         if (err) {
406             e.originalError = err;
407         }
408         return e;
409     }
411     if (typeof define !== 'undefined') {
412         //If a define is already in play via another AMD loader,
413         //do not overwrite.
414         return;
415     }
417     if (typeof requirejs !== 'undefined') {
418         if (isFunction(requirejs)) {
419             //Do not overwrite and existing requirejs instance.
420             return;
421         }
422         cfg = requirejs;
423         requirejs = undefined;
424     }
426     //Allow for a require config object
427     if (typeof require !== 'undefined' && !isFunction(require)) {
428         //assume it is a config object.
429         cfg = require;
430         require = undefined;
431     }
433     function newContext(contextName) {
434         var inCheckLoaded, Module, context, handlers,
435             checkLoadedTimeoutId,
436             config = {
437                 //Defaults. Do not set a default for map
438                 //config to speed up normalize(), which
439                 //will run faster if there is no default.
440                 waitSeconds: 7,
441                 baseUrl: './',
442                 paths: {},
443                 pkgs: {},
444                 shim: {},
445                 config: {}
446             },
447             registry = {},
448             //registry of just enabled modules, to speed
449             //cycle breaking code when lots of modules
450             //are registered, but not activated.
451             enabledRegistry = {},
452             undefEvents = {},
453             defQueue = [],
454             defined = {},
455             urlFetched = {},
456             requireCounter = 1,
457             unnormalizedCounter = 1;
459         /**
460          * Trims the . and .. from an array of path segments.
461          * It will keep a leading path segment if a .. will become
462          * the first path segment, to help with module name lookups,
463          * which act like paths, but can be remapped. But the end result,
464          * all paths that use this function should look normalized.
465          * NOTE: this method MODIFIES the input array.
466          * @param {Array} ary the array of path segments.
467          */
468         function trimDots(ary) {
469             var i, part;
470             for (i = 0; ary[i]; i += 1) {
471                 part = ary[i];
472                 if (part === '.') {
473                     ary.splice(i, 1);
474                     i -= 1;
475                 } else if (part === '..') {
476                     if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
477                         //End of the line. Keep at least one non-dot
478                         //path segment at the front so it can be mapped
479                         //correctly to disk. Otherwise, there is likely
480                         //no path mapping for a path starting with '..'.
481                         //This can still fail, but catches the most reasonable
482                         //uses of ..
483                         break;
484                     } else if (i > 0) {
485                         ary.splice(i - 1, 2);
486                         i -= 2;
487                     }
488                 }
489             }
490         }
492         /**
493          * Given a relative module name, like ./something, normalize it to
494          * a real name that can be mapped to a path.
495          * @param {String} name the relative name
496          * @param {String} baseName a real name that the name arg is relative
497          * to.
498          * @param {Boolean} applyMap apply the map config to the value. Should
499          * only be done if this normalization is for a dependency ID.
500          * @returns {String} normalized name
501          */
502         function normalize(name, baseName, applyMap) {
503             var pkgName, pkgConfig, mapValue, nameParts, i, j, nameSegment,
504                 foundMap, foundI, foundStarMap, starI,
505                 baseParts = baseName && baseName.split('/'),
506                 normalizedBaseParts = baseParts,
507                 map = config.map,
508                 starMap = map && map['*'];
510             //Adjust any relative paths.
511             if (name && name.charAt(0) === '.') {
512                 //If have a base name, try to normalize against it,
513                 //otherwise, assume it is a top-level require that will
514                 //be relative to baseUrl in the end.
515                 if (baseName) {
516                     if (getOwn(config.pkgs, baseName)) {
517                         //If the baseName is a package name, then just treat it as one
518                         //name to concat the name with.
519                         normalizedBaseParts = baseParts = [baseName];
520                     } else {
521                         //Convert baseName to array, and lop off the last part,
522                         //so that . matches that 'directory' and not name of the baseName's
523                         //module. For instance, baseName of 'one/two/three', maps to
524                         //'one/two/three.js', but we want the directory, 'one/two' for
525                         //this normalization.
526                         normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
527                     }
529                     name = normalizedBaseParts.concat(name.split('/'));
530                     trimDots(name);
532                     //Some use of packages may use a . path to reference the
533                     //'main' module name, so normalize for that.
534                     pkgConfig = getOwn(config.pkgs, (pkgName = name[0]));
535                     name = name.join('/');
536                     if (pkgConfig && name === pkgName + '/' + pkgConfig.main) {
537                         name = pkgName;
538                     }
539                 } else if (name.indexOf('./') === 0) {
540                     // No baseName, so this is ID is resolved relative
541                     // to baseUrl, pull off the leading dot.
542                     name = name.substring(2);
543                 }
544             }
546             //Apply map config if available.
547             if (applyMap && map && (baseParts || starMap)) {
548                 nameParts = name.split('/');
550                 for (i = nameParts.length; i > 0; i -= 1) {
551                     nameSegment = nameParts.slice(0, i).join('/');
553                     if (baseParts) {
554                         //Find the longest baseName segment match in the config.
555                         //So, do joins on the biggest to smallest lengths of baseParts.
556                         for (j = baseParts.length; j > 0; j -= 1) {
557                             mapValue = getOwn(map, baseParts.slice(0, j).join('/'));
559                             //baseName segment has config, find if it has one for
560                             //this name.
561                             if (mapValue) {
562                                 mapValue = getOwn(mapValue, nameSegment);
563                                 if (mapValue) {
564                                     //Match, update name to the new value.
565                                     foundMap = mapValue;
566                                     foundI = i;
567                                     break;
568                                 }
569                             }
570                         }
571                     }
573                     if (foundMap) {
574                         break;
575                     }
577                     //Check for a star map match, but just hold on to it,
578                     //if there is a shorter segment match later in a matching
579                     //config, then favor over this star map.
580                     if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) {
581                         foundStarMap = getOwn(starMap, nameSegment);
582                         starI = i;
583                     }
584                 }
586                 if (!foundMap && foundStarMap) {
587                     foundMap = foundStarMap;
588                     foundI = starI;
589                 }
591                 if (foundMap) {
592                     nameParts.splice(0, foundI, foundMap);
593                     name = nameParts.join('/');
594                 }
595             }
597             return name;
598         }
600         function removeScript(name) {
601             if (isBrowser) {
602                 each(scripts(), function (scriptNode) {
603                     if (scriptNode.getAttribute('data-requiremodule') === name &&
604                             scriptNode.getAttribute('data-requirecontext') === context.contextName) {
605                         scriptNode.parentNode.removeChild(scriptNode);
606                         return true;
607                     }
608                 });
609             }
610         }
612         function hasPathFallback(id) {
613             var pathConfig = getOwn(config.paths, id);
614             if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {
615                 removeScript(id);
616                 //Pop off the first array value, since it failed, and
617                 //retry
618                 pathConfig.shift();
619                 context.require.undef(id);
620                 context.require([id]);
621                 return true;
622             }
623         }
625         //Turns a plugin!resource to [plugin, resource]
626         //with the plugin being undefined if the name
627         //did not have a plugin prefix.
628         function splitPrefix(name) {
629             var prefix,
630                 index = name ? name.indexOf('!') : -1;
631             if (index > -1) {
632                 prefix = name.substring(0, index);
633                 name = name.substring(index + 1, name.length);
634             }
635             return [prefix, name];
636         }
638         /**
639          * Creates a module mapping that includes plugin prefix, module
640          * name, and path. If parentModuleMap is provided it will
641          * also normalize the name via require.normalize()
642          *
643          * @param {String} name the module name
644          * @param {String} [parentModuleMap] parent module map
645          * for the module name, used to resolve relative names.
646          * @param {Boolean} isNormalized: is the ID already normalized.
647          * This is true if this call is done for a define() module ID.
648          * @param {Boolean} applyMap: apply the map config to the ID.
649          * Should only be true if this map is for a dependency.
650          *
651          * @returns {Object}
652          */
653         function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
654             var url, pluginModule, suffix, nameParts,
655                 prefix = null,
656                 parentName = parentModuleMap ? parentModuleMap.name : null,
657                 originalName = name,
658                 isDefine = true,
659                 normalizedName = '';
661             //If no name, then it means it is a require call, generate an
662             //internal name.
663             if (!name) {
664                 isDefine = false;
665                 name = '_@r' + (requireCounter += 1);
666             }
668             nameParts = splitPrefix(name);
669             prefix = nameParts[0];
670             name = nameParts[1];
672             if (prefix) {
673                 prefix = normalize(prefix, parentName, applyMap);
674                 pluginModule = getOwn(defined, prefix);
675             }
677             //Account for relative paths if there is a base name.
678             if (name) {
679                 if (prefix) {
680                     if (pluginModule && pluginModule.normalize) {
681                         //Plugin is loaded, use its normalize method.
682                         normalizedName = pluginModule.normalize(name, function (name) {
683                             return normalize(name, parentName, applyMap);
684                         });
685                     } else {
686                         normalizedName = normalize(name, parentName, applyMap);
687                     }
688                 } else {
689                     //A regular module.
690                     normalizedName = normalize(name, parentName, applyMap);
692                     //Normalized name may be a plugin ID due to map config
693                     //application in normalize. The map config values must
694                     //already be normalized, so do not need to redo that part.
695                     nameParts = splitPrefix(normalizedName);
696                     prefix = nameParts[0];
697                     normalizedName = nameParts[1];
698                     isNormalized = true;
700                     url = context.nameToUrl(normalizedName);
701                 }
702             }
704             //If the id is a plugin id that cannot be determined if it needs
705             //normalization, stamp it with a unique ID so two matching relative
706             //ids that may conflict can be separate.
707             suffix = prefix && !pluginModule && !isNormalized ?
708                      '_unnormalized' + (unnormalizedCounter += 1) :
709                      '';
711             return {
712                 prefix: prefix,
713                 name: normalizedName,
714                 parentMap: parentModuleMap,
715                 unnormalized: !!suffix,
716                 url: url,
717                 originalName: originalName,
718                 isDefine: isDefine,
719                 id: (prefix ?
720                         prefix + '!' + normalizedName :
721                         normalizedName) + suffix
722             };
723         }
725         function getModule(depMap) {
726             var id = depMap.id,
727                 mod = getOwn(registry, id);
729             if (!mod) {
730                 mod = registry[id] = new context.Module(depMap);
731             }
733             return mod;
734         }
736         function on(depMap, name, fn) {
737             var id = depMap.id,
738                 mod = getOwn(registry, id);
740             if (hasProp(defined, id) &&
741                     (!mod || mod.defineEmitComplete)) {
742                 if (name === 'defined') {
743                     fn(defined[id]);
744                 }
745             } else {
746                 mod = getModule(depMap);
747                 if (mod.error && name === 'error') {
748                     fn(mod.error);
749                 } else {
750                     mod.on(name, fn);
751                 }
752             }
753         }
755         function onError(err, errback) {
756             var ids = err.requireModules,
757                 notified = false;
759             if (errback) {
760                 errback(err);
761             } else {
762                 each(ids, function (id) {
763                     var mod = getOwn(registry, id);
764                     if (mod) {
765                         //Set error on module, so it skips timeout checks.
766                         mod.error = err;
767                         if (mod.events.error) {
768                             notified = true;
769                             mod.emit('error', err);
770                         }
771                     }
772                 });
774                 if (!notified) {
775                     req.onError(err);
776                 }
777             }
778         }
780         /**
781          * Internal method to transfer globalQueue items to this context's
782          * defQueue.
783          */
784         function takeGlobalQueue() {
785             //Push all the globalDefQueue items into the context's defQueue
786             if (globalDefQueue.length) {
787                 //Array splice in the values since the context code has a
788                 //local var ref to defQueue, so cannot just reassign the one
789                 //on context.
790                 apsp.apply(defQueue,
791                            [defQueue.length - 1, 0].concat(globalDefQueue));
792                 globalDefQueue = [];
793             }
794         }
796         handlers = {
797             'require': function (mod) {
798                 if (mod.require) {
799                     return mod.require;
800                 } else {
801                     return (mod.require = context.makeRequire(mod.map));
802                 }
803             },
804             'exports': function (mod) {
805                 mod.usingExports = true;
806                 if (mod.map.isDefine) {
807                     if (mod.exports) {
808                         return mod.exports;
809                     } else {
810                         return (mod.exports = defined[mod.map.id] = {});
811                     }
812                 }
813             },
814             'module': function (mod) {
815                 if (mod.module) {
816                     return mod.module;
817                 } else {
818                     return (mod.module = {
819                         id: mod.map.id,
820                         uri: mod.map.url,
821                         config: function () {
822                             var c,
823                                 pkg = getOwn(config.pkgs, mod.map.id);
824                             // For packages, only support config targeted
825                             // at the main module.
826                             c = pkg ? getOwn(config.config, mod.map.id + '/' + pkg.main) :
827                                       getOwn(config.config, mod.map.id);
828                             return  c || {};
829                         },
830                         exports: defined[mod.map.id]
831                     });
832                 }
833             }
834         };
836         function cleanRegistry(id) {
837             //Clean up machinery used for waiting modules.
838             delete registry[id];
839             delete enabledRegistry[id];
840         }
842         function breakCycle(mod, traced, processed) {
843             var id = mod.map.id;
845             if (mod.error) {
846                 mod.emit('error', mod.error);
847             } else {
848                 traced[id] = true;
849                 each(mod.depMaps, function (depMap, i) {
850                     var depId = depMap.id,
851                         dep = getOwn(registry, depId);
853                     //Only force things that have not completed
854                     //being defined, so still in the registry,
855                     //and only if it has not been matched up
856                     //in the module already.
857                     if (dep && !mod.depMatched[i] && !processed[depId]) {
858                         if (getOwn(traced, depId)) {
859                             mod.defineDep(i, defined[depId]);
860                             mod.check(); //pass false?
861                         } else {
862                             breakCycle(dep, traced, processed);
863                         }
864                     }
865                 });
866                 processed[id] = true;
867             }
868         }
870         function checkLoaded() {
871             var map, modId, err, usingPathFallback,
872                 waitInterval = config.waitSeconds * 1000,
873                 //It is possible to disable the wait interval by using waitSeconds of 0.
874                 expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
875                 noLoads = [],
876                 reqCalls = [],
877                 stillLoading = false,
878                 needCycleCheck = true;
880             //Do not bother if this call was a result of a cycle break.
881             if (inCheckLoaded) {
882                 return;
883             }
885             inCheckLoaded = true;
887             //Figure out the state of all the modules.
888             eachProp(enabledRegistry, function (mod) {
889                 map = mod.map;
890                 modId = map.id;
892                 //Skip things that are not enabled or in error state.
893                 if (!mod.enabled) {
894                     return;
895                 }
897                 if (!map.isDefine) {
898                     reqCalls.push(mod);
899                 }
901                 if (!mod.error) {
902                     //If the module should be executed, and it has not
903                     //been inited and time is up, remember it.
904                     if (!mod.inited && expired) {
905                         if (hasPathFallback(modId)) {
906                             usingPathFallback = true;
907                             stillLoading = true;
908                         } else {
909                             noLoads.push(modId);
910                             removeScript(modId);
911                         }
912                     } else if (!mod.inited && mod.fetched && map.isDefine) {
913                         stillLoading = true;
914                         if (!map.prefix) {
915                             //No reason to keep looking for unfinished
916                             //loading. If the only stillLoading is a
917                             //plugin resource though, keep going,
918                             //because it may be that a plugin resource
919                             //is waiting on a non-plugin cycle.
920                             return (needCycleCheck = false);
921                         }
922                     }
923                 }
924             });
926             if (expired && noLoads.length) {
927                 //If wait time expired, throw error of unloaded modules.
928                 err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads);
929                 err.contextName = context.contextName;
930                 return onError(err);
931             }
933             //Not expired, check for a cycle.
934             if (needCycleCheck) {
935                 each(reqCalls, function (mod) {
936                     breakCycle(mod, {}, {});
937                 });
938             }
940             //If still waiting on loads, and the waiting load is something
941             //other than a plugin resource, or there are still outstanding
942             //scripts, then just try back later.
943             if ((!expired || usingPathFallback) && stillLoading) {
944                 //Something is still waiting to load. Wait for it, but only
945                 //if a timeout is not already in effect.
946                 if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
947                     checkLoadedTimeoutId = setTimeout(function () {
948                         checkLoadedTimeoutId = 0;
949                         checkLoaded();
950                     }, 50);
951                 }
952             }
954             inCheckLoaded = false;
955         }
957         Module = function (map) {
958             this.events = getOwn(undefEvents, map.id) || {};
959             this.map = map;
960             this.shim = getOwn(config.shim, map.id);
961             this.depExports = [];
962             this.depMaps = [];
963             this.depMatched = [];
964             this.pluginMaps = {};
965             this.depCount = 0;
967             /* this.exports this.factory
968                this.depMaps = [],
969                this.enabled, this.fetched
970             */
971         };
973         Module.prototype = {
974             init: function (depMaps, factory, errback, options) {
975                 options = options || {};
977                 //Do not do more inits if already done. Can happen if there
978                 //are multiple define calls for the same module. That is not
979                 //a normal, common case, but it is also not unexpected.
980                 if (this.inited) {
981                     return;
982                 }
984                 this.factory = factory;
986                 if (errback) {
987                     //Register for errors on this module.
988                     this.on('error', errback);
989                 } else if (this.events.error) {
990                     //If no errback already, but there are error listeners
991                     //on this module, set up an errback to pass to the deps.
992                     errback = bind(this, function (err) {
993                         this.emit('error', err);
994                     });
995                 }
997                 //Do a copy of the dependency array, so that
998                 //source inputs are not modified. For example
999                 //"shim" deps are passed in here directly, and
1000                 //doing a direct modification of the depMaps array
1001                 //would affect that config.
1002                 this.depMaps = depMaps && depMaps.slice(0);
1004                 this.errback = errback;
1006                 //Indicate this module has be initialized
1007                 this.inited = true;
1009                 this.ignore = options.ignore;
1011                 //Could have option to init this module in enabled mode,
1012                 //or could have been previously marked as enabled. However,
1013                 //the dependencies are not known until init is called. So
1014                 //if enabled previously, now trigger dependencies as enabled.
1015                 if (options.enabled || this.enabled) {
1016                     //Enable this module and dependencies.
1017                     //Will call this.check()
1018                     this.enable();
1019                 } else {
1020                     this.check();
1021                 }
1022             },
1024             defineDep: function (i, depExports) {
1025                 //Because of cycles, defined callback for a given
1026                 //export can be called more than once.
1027                 if (!this.depMatched[i]) {
1028                     this.depMatched[i] = true;
1029                     this.depCount -= 1;
1030                     this.depExports[i] = depExports;
1031                 }
1032             },
1034             fetch: function () {
1035                 if (this.fetched) {
1036                     return;
1037                 }
1038                 this.fetched = true;
1040                 context.startTime = (new Date()).getTime();
1042                 var map = this.map;
1044                 //If the manager is for a plugin managed resource,
1045                 //ask the plugin to load it now.
1046                 if (this.shim) {
1047                     context.makeRequire(this.map, {
1048                         enableBuildCallback: true
1049                     })(this.shim.deps || [], bind(this, function () {
1050                         return map.prefix ? this.callPlugin() : this.load();
1051                     }));
1052                 } else {
1053                     //Regular dependency.
1054                     return map.prefix ? this.callPlugin() : this.load();
1055                 }
1056             },
1058             load: function () {
1059                 var url = this.map.url;
1061                 //Regular dependency.
1062                 if (!urlFetched[url]) {
1063                     urlFetched[url] = true;
1064                     context.load(this.map.id, url);
1065                 }
1066             },
1068             /**
1069              * Checks if the module is ready to define itself, and if so,
1070              * define it.
1071              */
1072             check: function () {
1073                 if (!this.enabled || this.enabling) {
1074                     return;
1075                 }
1077                 var err, cjsModule,
1078                     id = this.map.id,
1079                     depExports = this.depExports,
1080                     exports = this.exports,
1081                     factory = this.factory;
1083                 if (!this.inited) {
1084                     this.fetch();
1085                 } else if (this.error) {
1086                     this.emit('error', this.error);
1087                 } else if (!this.defining) {
1088                     //The factory could trigger another require call
1089                     //that would result in checking this module to
1090                     //define itself again. If already in the process
1091                     //of doing that, skip this work.
1092                     this.defining = true;
1094                     if (this.depCount < 1 && !this.defined) {
1095                         if (isFunction(factory)) {
1096                             //If there is an error listener, favor passing
1097                             //to that instead of throwing an error. However,
1098                             //only do it for define()'d  modules. require
1099                             //errbacks should not be called for failures in
1100                             //their callbacks (#699). However if a global
1101                             //onError is set, use that.
1102                             if ((this.events.error && this.map.isDefine) ||
1103                                 req.onError !== defaultOnError) {
1104                                 try {
1105                                     exports = context.execCb(id, factory, depExports, exports);
1106                                 } catch (e) {
1107                                     err = e;
1108                                 }
1109                             } else {
1110                                 exports = context.execCb(id, factory, depExports, exports);
1111                             }
1113                             if (this.map.isDefine) {
1114                                 //If setting exports via 'module' is in play,
1115                                 //favor that over return value and exports. After that,
1116                                 //favor a non-undefined return value over exports use.
1117                                 cjsModule = this.module;
1118                                 if (cjsModule &&
1119                                         cjsModule.exports !== undefined &&
1120                                         //Make sure it is not already the exports value
1121                                         cjsModule.exports !== this.exports) {
1122                                     exports = cjsModule.exports;
1123                                 } else if (exports === undefined && this.usingExports) {
1124                                     //exports already set the defined value.
1125                                     exports = this.exports;
1126                                 }
1127                             }
1129                             if (err) {
1130                                 err.requireMap = this.map;
1131                                 err.requireModules = this.map.isDefine ? [this.map.id] : null;
1132                                 err.requireType = this.map.isDefine ? 'define' : 'require';
1133                                 return onError((this.error = err));
1134                             }
1136                         } else {
1137                             //Just a literal value
1138                             exports = factory;
1139                         }
1141                         this.exports = exports;
1143                         if (this.map.isDefine && !this.ignore) {
1144                             defined[id] = exports;
1146                             if (req.onResourceLoad) {
1147                                 req.onResourceLoad(context, this.map, this.depMaps);
1148                             }
1149                         }
1151                         //Clean up
1152                         cleanRegistry(id);
1154                         this.defined = true;
1155                     }
1157                     //Finished the define stage. Allow calling check again
1158                     //to allow define notifications below in the case of a
1159                     //cycle.
1160                     this.defining = false;
1162                     if (this.defined && !this.defineEmitted) {
1163                         this.defineEmitted = true;
1164                         this.emit('defined', this.exports);
1165                         this.defineEmitComplete = true;
1166                     }
1168                 }
1169             },
1171             callPlugin: function () {
1172                 var map = this.map,
1173                     id = map.id,
1174                     //Map already normalized the prefix.
1175                     pluginMap = makeModuleMap(map.prefix);
1177                 //Mark this as a dependency for this plugin, so it
1178                 //can be traced for cycles.
1179                 this.depMaps.push(pluginMap);
1181                 on(pluginMap, 'defined', bind(this, function (plugin) {
1182                     var load, normalizedMap, normalizedMod,
1183                         name = this.map.name,
1184                         parentName = this.map.parentMap ? this.map.parentMap.name : null,
1185                         localRequire = context.makeRequire(map.parentMap, {
1186                             enableBuildCallback: true
1187                         });
1189                     //If current map is not normalized, wait for that
1190                     //normalized name to load instead of continuing.
1191                     if (this.map.unnormalized) {
1192                         //Normalize the ID if the plugin allows it.
1193                         if (plugin.normalize) {
1194                             name = plugin.normalize(name, function (name) {
1195                                 return normalize(name, parentName, true);
1196                             }) || '';
1197                         }
1199                         //prefix and name should already be normalized, no need
1200                         //for applying map config again either.
1201                         normalizedMap = makeModuleMap(map.prefix + '!' + name,
1202                                                       this.map.parentMap);
1203                         on(normalizedMap,
1204                             'defined', bind(this, function (value) {
1205                                 this.init([], function () { return value; }, null, {
1206                                     enabled: true,
1207                                     ignore: true
1208                                 });
1209                             }));
1211                         normalizedMod = getOwn(registry, normalizedMap.id);
1212                         if (normalizedMod) {
1213                             //Mark this as a dependency for this plugin, so it
1214                             //can be traced for cycles.
1215                             this.depMaps.push(normalizedMap);
1217                             if (this.events.error) {
1218                                 normalizedMod.on('error', bind(this, function (err) {
1219                                     this.emit('error', err);
1220                                 }));
1221                             }
1222                             normalizedMod.enable();
1223                         }
1225                         return;
1226                     }
1228                     load = bind(this, function (value) {
1229                         this.init([], function () { return value; }, null, {
1230                             enabled: true
1231                         });
1232                     });
1234                     load.error = bind(this, function (err) {
1235                         this.inited = true;
1236                         this.error = err;
1237                         err.requireModules = [id];
1239                         //Remove temp unnormalized modules for this module,
1240                         //since they will never be resolved otherwise now.
1241                         eachProp(registry, function (mod) {
1242                             if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
1243                                 cleanRegistry(mod.map.id);
1244                             }
1245                         });
1247                         onError(err);
1248                     });
1250                     //Allow plugins to load other code without having to know the
1251                     //context or how to 'complete' the load.
1252                     load.fromText = bind(this, function (text, textAlt) {
1253                         /*jslint evil: true */
1254                         var moduleName = map.name,
1255                             moduleMap = makeModuleMap(moduleName),
1256                             hasInteractive = useInteractive;
1258                         //As of 2.1.0, support just passing the text, to reinforce
1259                         //fromText only being called once per resource. Still
1260                         //support old style of passing moduleName but discard
1261                         //that moduleName in favor of the internal ref.
1262                         if (textAlt) {
1263                             text = textAlt;
1264                         }
1266                         //Turn off interactive script matching for IE for any define
1267                         //calls in the text, then turn it back on at the end.
1268                         if (hasInteractive) {
1269                             useInteractive = false;
1270                         }
1272                         //Prime the system by creating a module instance for
1273                         //it.
1274                         getModule(moduleMap);
1276                         //Transfer any config to this other module.
1277                         if (hasProp(config.config, id)) {
1278                             config.config[moduleName] = config.config[id];
1279                         }
1281                         try {
1282                             req.exec(text);
1283                         } catch (e) {
1284                             return onError(makeError('fromtexteval',
1285                                              'fromText eval for ' + id +
1286                                             ' failed: ' + e,
1287                                              e,
1288                                              [id]));
1289                         }
1291                         if (hasInteractive) {
1292                             useInteractive = true;
1293                         }
1295                         //Mark this as a dependency for the plugin
1296                         //resource
1297                         this.depMaps.push(moduleMap);
1299                         //Support anonymous modules.
1300                         context.completeLoad(moduleName);
1302                         //Bind the value of that module to the value for this
1303                         //resource ID.
1304                         localRequire([moduleName], load);
1305                     });
1307                     //Use parentName here since the plugin's name is not reliable,
1308                     //could be some weird string with no path that actually wants to
1309                     //reference the parentName's path.
1310                     plugin.load(map.name, localRequire, load, config);
1311                 }));
1313                 context.enable(pluginMap, this);
1314                 this.pluginMaps[pluginMap.id] = pluginMap;
1315             },
1317             enable: function () {
1318                 enabledRegistry[this.map.id] = this;
1319                 this.enabled = true;
1321                 //Set flag mentioning that the module is enabling,
1322                 //so that immediate calls to the defined callbacks
1323                 //for dependencies do not trigger inadvertent load
1324                 //with the depCount still being zero.
1325                 this.enabling = true;
1327                 //Enable each dependency
1328                 each(this.depMaps, bind(this, function (depMap, i) {
1329                     var id, mod, handler;
1331                     if (typeof depMap === 'string') {
1332                         //Dependency needs to be converted to a depMap
1333                         //and wired up to this module.
1334                         depMap = makeModuleMap(depMap,
1335                                                (this.map.isDefine ? this.map : this.map.parentMap),
1336                                                false,
1337                                                !this.skipMap);
1338                         this.depMaps[i] = depMap;
1340                         handler = getOwn(handlers, depMap.id);
1342                         if (handler) {
1343                             this.depExports[i] = handler(this);
1344                             return;
1345                         }
1347                         this.depCount += 1;
1349                         on(depMap, 'defined', bind(this, function (depExports) {
1350                             this.defineDep(i, depExports);
1351                             this.check();
1352                         }));
1354                         if (this.errback) {
1355                             on(depMap, 'error', bind(this, this.errback));
1356                         }
1357                     }
1359                     id = depMap.id;
1360                     mod = registry[id];
1362                     //Skip special modules like 'require', 'exports', 'module'
1363                     //Also, don't call enable if it is already enabled,
1364                     //important in circular dependency cases.
1365                     if (!hasProp(handlers, id) && mod && !mod.enabled) {
1366                         context.enable(depMap, this);
1367                     }
1368                 }));
1370                 //Enable each plugin that is used in
1371                 //a dependency
1372                 eachProp(this.pluginMaps, bind(this, function (pluginMap) {
1373                     var mod = getOwn(registry, pluginMap.id);
1374                     if (mod && !mod.enabled) {
1375                         context.enable(pluginMap, this);
1376                     }
1377                 }));
1379                 this.enabling = false;
1381                 this.check();
1382             },
1384             on: function (name, cb) {
1385                 var cbs = this.events[name];
1386                 if (!cbs) {
1387                     cbs = this.events[name] = [];
1388                 }
1389                 cbs.push(cb);
1390             },
1392             emit: function (name, evt) {
1393                 each(this.events[name], function (cb) {
1394                     cb(evt);
1395                 });
1396                 if (name === 'error') {
1397                     //Now that the error handler was triggered, remove
1398                     //the listeners, since this broken Module instance
1399                     //can stay around for a while in the registry.
1400                     delete this.events[name];
1401                 }
1402             }
1403         };
1405         function callGetModule(args) {
1406             //Skip modules already defined.
1407             if (!hasProp(defined, args[0])) {
1408                 getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
1409             }
1410         }
1412         function removeListener(node, func, name, ieName) {
1413             //Favor detachEvent because of IE9
1414             //issue, see attachEvent/addEventListener comment elsewhere
1415             //in this file.
1416             if (node.detachEvent && !isOpera) {
1417                 //Probably IE. If not it will throw an error, which will be
1418                 //useful to know.
1419                 if (ieName) {
1420                     node.detachEvent(ieName, func);
1421                 }
1422             } else {
1423                 node.removeEventListener(name, func, false);
1424             }
1425         }
1427         /**
1428          * Given an event from a script node, get the requirejs info from it,
1429          * and then removes the event listeners on the node.
1430          * @param {Event} evt
1431          * @returns {Object}
1432          */
1433         function getScriptData(evt) {
1434             //Using currentTarget instead of target for Firefox 2.0's sake. Not
1435             //all old browsers will be supported, but this one was easy enough
1436             //to support and still makes sense.
1437             var node = evt.currentTarget || evt.srcElement;
1439             //Remove the listeners once here.
1440             removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange');
1441             removeListener(node, context.onScriptError, 'error');
1443             return {
1444                 node: node,
1445                 id: node && node.getAttribute('data-requiremodule')
1446             };
1447         }
1449         function intakeDefines() {
1450             var args;
1452             //Any defined modules in the global queue, intake them now.
1453             takeGlobalQueue();
1455             //Make sure any remaining defQueue items get properly processed.
1456             while (defQueue.length) {
1457                 args = defQueue.shift();
1458                 if (args[0] === null) {
1459                     return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
1460                 } else {
1461                     //args are id, deps, factory. Should be normalized by the
1462                     //define() function.
1463                     callGetModule(args);
1464                 }
1465             }
1466         }
1468         context = {
1469             config: config,
1470             contextName: contextName,
1471             registry: registry,
1472             defined: defined,
1473             urlFetched: urlFetched,
1474             defQueue: defQueue,
1475             Module: Module,
1476             makeModuleMap: makeModuleMap,
1477             nextTick: req.nextTick,
1478             onError: onError,
1480             /**
1481              * Set a configuration for the context.
1482              * @param {Object} cfg config object to integrate.
1483              */
1484             configure: function (cfg) {
1485                 //Make sure the baseUrl ends in a slash.
1486                 if (cfg.baseUrl) {
1487                     if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {
1488                         cfg.baseUrl += '/';
1489                     }
1490                 }
1492                 //Save off the paths and packages since they require special processing,
1493                 //they are additive.
1494                 var pkgs = config.pkgs,
1495                     shim = config.shim,
1496                     objs = {
1497                         paths: true,
1498                         config: true,
1499                         map: true
1500                     };
1502                 eachProp(cfg, function (value, prop) {
1503                     if (objs[prop]) {
1504                         if (prop === 'map') {
1505                             if (!config.map) {
1506                                 config.map = {};
1507                             }
1508                             mixin(config[prop], value, true, true);
1509                         } else {
1510                             mixin(config[prop], value, true);
1511                         }
1512                     } else {
1513                         config[prop] = value;
1514                     }
1515                 });
1517                 //Merge shim
1518                 if (cfg.shim) {
1519                     eachProp(cfg.shim, function (value, id) {
1520                         //Normalize the structure
1521                         if (isArray(value)) {
1522                             value = {
1523                                 deps: value
1524                             };
1525                         }
1526                         if ((value.exports || value.init) && !value.exportsFn) {
1527                             value.exportsFn = context.makeShimExports(value);
1528                         }
1529                         shim[id] = value;
1530                     });
1531                     config.shim = shim;
1532                 }
1534                 //Adjust packages if necessary.
1535                 if (cfg.packages) {
1536                     each(cfg.packages, function (pkgObj) {
1537                         var location;
1539                         pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj;
1540                         location = pkgObj.location;
1542                         //Create a brand new object on pkgs, since currentPackages can
1543                         //be passed in again, and config.pkgs is the internal transformed
1544                         //state for all package configs.
1545                         pkgs[pkgObj.name] = {
1546                             name: pkgObj.name,
1547                             location: location || pkgObj.name,
1548                             //Remove leading dot in main, so main paths are normalized,
1549                             //and remove any trailing .js, since different package
1550                             //envs have different conventions: some use a module name,
1551                             //some use a file name.
1552                             main: (pkgObj.main || 'main')
1553                                   .replace(currDirRegExp, '')
1554                                   .replace(jsSuffixRegExp, '')
1555                         };
1556                     });
1558                     //Done with modifications, assing packages back to context config
1559                     config.pkgs = pkgs;
1560                 }
1562                 //If there are any "waiting to execute" modules in the registry,
1563                 //update the maps for them, since their info, like URLs to load,
1564                 //may have changed.
1565                 eachProp(registry, function (mod, id) {
1566                     //If module already has init called, since it is too
1567                     //late to modify them, and ignore unnormalized ones
1568                     //since they are transient.
1569                     if (!mod.inited && !mod.map.unnormalized) {
1570                         mod.map = makeModuleMap(id);
1571                     }
1572                 });
1574                 //If a deps array or a config callback is specified, then call
1575                 //require with those args. This is useful when require is defined as a
1576                 //config object before require.js is loaded.
1577                 if (cfg.deps || cfg.callback) {
1578                     context.require(cfg.deps || [], cfg.callback);
1579                 }
1580             },
1582             makeShimExports: function (value) {
1583                 function fn() {
1584                     var ret;
1585                     if (value.init) {
1586                         ret = value.init.apply(global, arguments);
1587                     }
1588                     return ret || (value.exports && getGlobal(value.exports));
1589                 }
1590                 return fn;
1591             },
1593             makeRequire: function (relMap, options) {
1594                 options = options || {};
1596                 function localRequire(deps, callback, errback) {
1597                     var id, map, requireMod;
1599                     if (options.enableBuildCallback && callback && isFunction(callback)) {
1600                         callback.__requireJsBuild = true;
1601                     }
1603                     if (typeof deps === 'string') {
1604                         if (isFunction(callback)) {
1605                             //Invalid call
1606                             return onError(makeError('requireargs', 'Invalid require call'), errback);
1607                         }
1609                         //If require|exports|module are requested, get the
1610                         //value for them from the special handlers. Caveat:
1611                         //this only works while module is being defined.
1612                         if (relMap && hasProp(handlers, deps)) {
1613                             return handlers[deps](registry[relMap.id]);
1614                         }
1616                         //Synchronous access to one module. If require.get is
1617                         //available (as in the Node adapter), prefer that.
1618                         if (req.get) {
1619                             return req.get(context, deps, relMap, localRequire);
1620                         }
1622                         //Normalize module name, if it contains . or ..
1623                         map = makeModuleMap(deps, relMap, false, true);
1624                         id = map.id;
1626                         if (!hasProp(defined, id)) {
1627                             return onError(makeError('notloaded', 'Module name "' +
1628                                         id +
1629                                         '" has not been loaded yet for context: ' +
1630                                         contextName +
1631                                         (relMap ? '' : '. Use require([])')));
1632                         }
1633                         return defined[id];
1634                     }
1636                     //Grab defines waiting in the global queue.
1637                     intakeDefines();
1639                     //Mark all the dependencies as needing to be loaded.
1640                     context.nextTick(function () {
1641                         //Some defines could have been added since the
1642                         //require call, collect them.
1643                         intakeDefines();
1645                         requireMod = getModule(makeModuleMap(null, relMap));
1647                         //Store if map config should be applied to this require
1648                         //call for dependencies.
1649                         requireMod.skipMap = options.skipMap;
1651                         requireMod.init(deps, callback, errback, {
1652                             enabled: true
1653                         });
1655                         checkLoaded();
1656                     });
1658                     return localRequire;
1659                 }
1661                 mixin(localRequire, {
1662                     isBrowser: isBrowser,
1664                     /**
1665                      * Converts a module name + .extension into an URL path.
1666                      * *Requires* the use of a module name. It does not support using
1667                      * plain URLs like nameToUrl.
1668                      */
1669                     toUrl: function (moduleNamePlusExt) {
1670                         var ext,
1671                             index = moduleNamePlusExt.lastIndexOf('.'),
1672                             segment = moduleNamePlusExt.split('/')[0],
1673                             isRelative = segment === '.' || segment === '..';
1675                         //Have a file extension alias, and it is not the
1676                         //dots from a relative path.
1677                         if (index !== -1 && (!isRelative || index > 1)) {
1678                             ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
1679                             moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
1680                         }
1682                         return context.nameToUrl(normalize(moduleNamePlusExt,
1683                                                 relMap && relMap.id, true), ext,  true);
1684                     },
1686                     defined: function (id) {
1687                         return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
1688                     },
1690                     specified: function (id) {
1691                         id = makeModuleMap(id, relMap, false, true).id;
1692                         return hasProp(defined, id) || hasProp(registry, id);
1693                     }
1694                 });
1696                 //Only allow undef on top level require calls
1697                 if (!relMap) {
1698                     localRequire.undef = function (id) {
1699                         //Bind any waiting define() calls to this context,
1700                         //fix for #408
1701                         takeGlobalQueue();
1703                         var map = makeModuleMap(id, relMap, true),
1704                             mod = getOwn(registry, id);
1706                         delete defined[id];
1707                         delete urlFetched[map.url];
1708                         delete undefEvents[id];
1710                         if (mod) {
1711                             //Hold on to listeners in case the
1712                             //module will be attempted to be reloaded
1713                             //using a different config.
1714                             if (mod.events.defined) {
1715                                 undefEvents[id] = mod.events;
1716                             }
1718                             cleanRegistry(id);
1719                         }
1720                     };
1721                 }
1723                 return localRequire;
1724             },
1726             /**
1727              * Called to enable a module if it is still in the registry
1728              * awaiting enablement. A second arg, parent, the parent module,
1729              * is passed in for context, when this method is overriden by
1730              * the optimizer. Not shown here to keep code compact.
1731              */
1732             enable: function (depMap) {
1733                 var mod = getOwn(registry, depMap.id);
1734                 if (mod) {
1735                     getModule(depMap).enable();
1736                 }
1737             },
1739             /**
1740              * Internal method used by environment adapters to complete a load event.
1741              * A load event could be a script load or just a load pass from a synchronous
1742              * load call.
1743              * @param {String} moduleName the name of the module to potentially complete.
1744              */
1745             completeLoad: function (moduleName) {
1746                 var found, args, mod,
1747                     shim = getOwn(config.shim, moduleName) || {},
1748                     shExports = shim.exports;
1750                 takeGlobalQueue();
1752                 while (defQueue.length) {
1753                     args = defQueue.shift();
1754                     if (args[0] === null) {
1755                         args[0] = moduleName;
1756                         //If already found an anonymous module and bound it
1757                         //to this name, then this is some other anon module
1758                         //waiting for its completeLoad to fire.
1759                         if (found) {
1760                             break;
1761                         }
1762                         found = true;
1763                     } else if (args[0] === moduleName) {
1764                         //Found matching define call for this script!
1765                         found = true;
1766                     }
1768                     callGetModule(args);
1769                 }
1771                 //Do this after the cycle of callGetModule in case the result
1772                 //of those calls/init calls changes the registry.
1773                 mod = getOwn(registry, moduleName);
1775                 if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
1776                     if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
1777                         if (hasPathFallback(moduleName)) {
1778                             return;
1779                         } else {
1780                             return onError(makeError('nodefine',
1781                                              'No define call for ' + moduleName,
1782                                              null,
1783                                              [moduleName]));
1784                         }
1785                     } else {
1786                         //A script that does not call define(), so just simulate
1787                         //the call for it.
1788                         callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
1789                     }
1790                 }
1792                 checkLoaded();
1793             },
1795             /**
1796              * Converts a module name to a file path. Supports cases where
1797              * moduleName may actually be just an URL.
1798              * Note that it **does not** call normalize on the moduleName,
1799              * it is assumed to have already been normalized. This is an
1800              * internal API, not a public one. Use toUrl for the public API.
1801              */
1802             nameToUrl: function (moduleName, ext, skipExt) {
1803                 var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,
1804                     parentPath;
1806                 //If a colon is in the URL, it indicates a protocol is used and it is just
1807                 //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
1808                 //or ends with .js, then assume the user meant to use an url and not a module id.
1809                 //The slash is important for protocol-less URLs as well as full paths.
1810                 if (req.jsExtRegExp.test(moduleName)) {
1811                     //Just a plain path, not module name lookup, so just return it.
1812                     //Add extension if it is included. This is a bit wonky, only non-.js things pass
1813                     //an extension, this method probably needs to be reworked.
1814                     url = moduleName + (ext || '');
1815                 } else {
1816                     //A module that needs to be converted to a path.
1817                     paths = config.paths;
1818                     pkgs = config.pkgs;
1820                     syms = moduleName.split('/');
1821                     //For each module name segment, see if there is a path
1822                     //registered for it. Start with most specific name
1823                     //and work up from it.
1824                     for (i = syms.length; i > 0; i -= 1) {
1825                         parentModule = syms.slice(0, i).join('/');
1826                         pkg = getOwn(pkgs, parentModule);
1827                         parentPath = getOwn(paths, parentModule);
1828                         if (parentPath) {
1829                             //If an array, it means there are a few choices,
1830                             //Choose the one that is desired
1831                             if (isArray(parentPath)) {
1832                                 parentPath = parentPath[0];
1833                             }
1834                             syms.splice(0, i, parentPath);
1835                             break;
1836                         } else if (pkg) {
1837                             //If module name is just the package name, then looking
1838                             //for the main module.
1839                             if (moduleName === pkg.name) {
1840                                 pkgPath = pkg.location + '/' + pkg.main;
1841                             } else {
1842                                 pkgPath = pkg.location;
1843                             }
1844                             syms.splice(0, i, pkgPath);
1845                             break;
1846                         }
1847                     }
1849                     //Join the path parts together, then figure out if baseUrl is needed.
1850                     url = syms.join('/');
1851                     url += (ext || (/\?/.test(url) || skipExt ? '' : '.js'));
1852                     url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
1853                 }
1855                 return config.urlArgs ? url +
1856                                         ((url.indexOf('?') === -1 ? '?' : '&') +
1857                                          config.urlArgs) : url;
1858             },
1860             //Delegates to req.load. Broken out as a separate function to
1861             //allow overriding in the optimizer.
1862             load: function (id, url) {
1863                 req.load(context, id, url);
1864             },
1866             /**
1867              * Executes a module callback function. Broken out as a separate function
1868              * solely to allow the build system to sequence the files in the built
1869              * layer in the right sequence.
1870              *
1871              * @private
1872              */
1873             execCb: function (name, callback, args, exports) {
1874                 return callback.apply(exports, args);
1875             },
1877             /**
1878              * callback for script loads, used to check status of loading.
1879              *
1880              * @param {Event} evt the event from the browser for the script
1881              * that was loaded.
1882              */
1883             onScriptLoad: function (evt) {
1884                 //Using currentTarget instead of target for Firefox 2.0's sake. Not
1885                 //all old browsers will be supported, but this one was easy enough
1886                 //to support and still makes sense.
1887                 if (evt.type === 'load' ||
1888                         (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
1889                     //Reset interactive script so a script node is not held onto for
1890                     //to long.
1891                     interactiveScript = null;
1893                     //Pull out the name of the module and the context.
1894                     var data = getScriptData(evt);
1895                     context.completeLoad(data.id);
1896                 }
1897             },
1899             /**
1900              * Callback for script errors.
1901              */
1902             onScriptError: function (evt) {
1903                 var data = getScriptData(evt);
1904                 if (!hasPathFallback(data.id)) {
1905                     return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id]));
1906                 }
1907             }
1908         };
1910         context.require = context.makeRequire();
1911         return context;
1912     }
1914     /**
1915      * Main entry point.
1916      *
1917      * If the only argument to require is a string, then the module that
1918      * is represented by that string is fetched for the appropriate context.
1919      *
1920      * If the first argument is an array, then it will be treated as an array
1921      * of dependency string names to fetch. An optional function callback can
1922      * be specified to execute when all of those dependencies are available.
1923      *
1924      * Make a local req variable to help Caja compliance (it assumes things
1925      * on a require that are not standardized), and to give a short
1926      * name for minification/local scope use.
1927      */
1928     req = requirejs = function (deps, callback, errback, optional) {
1930         //Find the right context, use default
1931         var context, config,
1932             contextName = defContextName;
1934         // Determine if have config object in the call.
1935         if (!isArray(deps) && typeof deps !== 'string') {
1936             // deps is a config object
1937             config = deps;
1938             if (isArray(callback)) {
1939                 // Adjust args if there are dependencies
1940                 deps = callback;
1941                 callback = errback;
1942                 errback = optional;
1943             } else {
1944                 deps = [];
1945             }
1946         }
1948         if (config && config.context) {
1949             contextName = config.context;
1950         }
1952         context = getOwn(contexts, contextName);
1953         if (!context) {
1954             context = contexts[contextName] = req.s.newContext(contextName);
1955         }
1957         if (config) {
1958             context.configure(config);
1959         }
1961         return context.require(deps, callback, errback);
1962     };
1964     /**
1965      * Support require.config() to make it easier to cooperate with other
1966      * AMD loaders on globally agreed names.
1967      */
1968     req.config = function (config) {
1969         return req(config);
1970     };
1972     /**
1973      * Execute something after the current tick
1974      * of the event loop. Override for other envs
1975      * that have a better solution than setTimeout.
1976      * @param  {Function} fn function to execute later.
1977      */
1978     req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) {
1979         setTimeout(fn, 4);
1980     } : function (fn) { fn(); };
1982     /**
1983      * Export require as a global, but only if it does not already exist.
1984      */
1985     if (!require) {
1986         require = req;
1987     }
1989     req.version = version;
1991     //Used to filter out dependencies that are already paths.
1992     req.jsExtRegExp = /^\/|:|\?|\.js$/;
1993     req.isBrowser = isBrowser;
1994     s = req.s = {
1995         contexts: contexts,
1996         newContext: newContext
1997     };
1999     //Create default context.
2000     req({});
2002     //Exports some context-sensitive methods on global require.
2003     each([
2004         'toUrl',
2005         'undef',
2006         'defined',
2007         'specified'
2008     ], function (prop) {
2009         //Reference from contexts instead of early binding to default context,
2010         //so that during builds, the latest instance of the default context
2011         //with its config gets used.
2012         req[prop] = function () {
2013             var ctx = contexts[defContextName];
2014             return ctx.require[prop].apply(ctx, arguments);
2015         };
2016     });
2018     if (isBrowser) {
2019         head = s.head = document.getElementsByTagName('head')[0];
2020         //If BASE tag is in play, using appendChild is a problem for IE6.
2021         //When that browser dies, this can be removed. Details in this jQuery bug:
2022         //http://dev.jquery.com/ticket/2709
2023         baseElement = document.getElementsByTagName('base')[0];
2024         if (baseElement) {
2025             head = s.head = baseElement.parentNode;
2026         }
2027     }
2029     /**
2030      * Any errors that require explicitly generates will be passed to this
2031      * function. Intercept/override it if you want custom error handling.
2032      * @param {Error} err the error object.
2033      */
2034     req.onError = defaultOnError;
2036     /**
2037      * Creates the node for the load command. Only used in browser envs.
2038      */
2039     req.createNode = function (config, moduleName, url) {
2040         var node = config.xhtml ?
2041                 document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
2042                 document.createElement('script');
2043         node.type = config.scriptType || 'text/javascript';
2044         node.charset = 'utf-8';
2045         node.async = true;
2046         return node;
2047     };
2049     /**
2050      * Does the request to load a module for the browser case.
2051      * Make this a separate function to allow other environments
2052      * to override it.
2053      *
2054      * @param {Object} context the require context to find state.
2055      * @param {String} moduleName the name of the module.
2056      * @param {Object} url the URL to the module.
2057      */
2058     req.load = function (context, moduleName, url) {
2059         var config = (context && context.config) || {},
2060             node;
2061         if (isBrowser) {
2062             //In the browser so use a script tag
2063             node = req.createNode(config, moduleName, url);
2065             node.setAttribute('data-requirecontext', context.contextName);
2066             node.setAttribute('data-requiremodule', moduleName);
2068             //Set up load listener. Test attachEvent first because IE9 has
2069             //a subtle issue in its addEventListener and script onload firings
2070             //that do not match the behavior of all other browsers with
2071             //addEventListener support, which fire the onload event for a
2072             //script right after the script execution. See:
2073             //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
2074             //UNFORTUNATELY Opera implements attachEvent but does not follow the script
2075             //script execution mode.
2076             if (node.attachEvent &&
2077                     //Check if node.attachEvent is artificially added by custom script or
2078                     //natively supported by browser
2079                     //read https://github.com/jrburke/requirejs/issues/187
2080                     //if we can NOT find [native code] then it must NOT natively supported.
2081                     //in IE8, node.attachEvent does not have toString()
2082                     //Note the test for "[native code" with no closing brace, see:
2083                     //https://github.com/jrburke/requirejs/issues/273
2084                     !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
2085                     !isOpera) {
2086                 //Probably IE. IE (at least 6-8) do not fire
2087                 //script onload right after executing the script, so
2088                 //we cannot tie the anonymous define call to a name.
2089                 //However, IE reports the script as being in 'interactive'
2090                 //readyState at the time of the define call.
2091                 useInteractive = true;
2093                 node.attachEvent('onreadystatechange', context.onScriptLoad);
2094                 //It would be great to add an error handler here to catch
2095                 //404s in IE9+. However, onreadystatechange will fire before
2096                 //the error handler, so that does not help. If addEventListener
2097                 //is used, then IE will fire error before load, but we cannot
2098                 //use that pathway given the connect.microsoft.com issue
2099                 //mentioned above about not doing the 'script execute,
2100                 //then fire the script load event listener before execute
2101                 //next script' that other browsers do.
2102                 //Best hope: IE10 fixes the issues,
2103                 //and then destroys all installs of IE 6-9.
2104                 //node.attachEvent('onerror', context.onScriptError);
2105             } else {
2106                 node.addEventListener('load', context.onScriptLoad, false);
2107                 node.addEventListener('error', context.onScriptError, false);
2108             }
2109             node.src = url;
2111             //For some cache cases in IE 6-8, the script executes before the end
2112             //of the appendChild execution, so to tie an anonymous define
2113             //call to the module name (which is stored on the node), hold on
2114             //to a reference to this node, but clear after the DOM insertion.
2115             currentlyAddingScript = node;
2116             if (baseElement) {
2117                 head.insertBefore(node, baseElement);
2118             } else {
2119                 head.appendChild(node);
2120             }
2121             currentlyAddingScript = null;
2123             return node;
2124         } else if (isWebWorker) {
2125             try {
2126                 //In a web worker, use importScripts. This is not a very
2127                 //efficient use of importScripts, importScripts will block until
2128                 //its script is downloaded and evaluated. However, if web workers
2129                 //are in play, the expectation that a build has been done so that
2130                 //only one script needs to be loaded anyway. This may need to be
2131                 //reevaluated if other use cases become common.
2132                 importScripts(url);
2134                 //Account for anonymous modules
2135                 context.completeLoad(moduleName);
2136             } catch (e) {
2137                 context.onError(makeError('importscripts',
2138                                 'importScripts failed for ' +
2139                                     moduleName + ' at ' + url,
2140                                 e,
2141                                 [moduleName]));
2142             }
2143         }
2144     };
2146     function getInteractiveScript() {
2147         if (interactiveScript && interactiveScript.readyState === 'interactive') {
2148             return interactiveScript;
2149         }
2151         eachReverse(scripts(), function (script) {
2152             if (script.readyState === 'interactive') {
2153                 return (interactiveScript = script);
2154             }
2155         });
2156         return interactiveScript;
2157     }
2159     //Look for a data-main script attribute, which could also adjust the baseUrl.
2160     if (isBrowser) {
2161         //Figure out baseUrl. Get it from the script tag with require.js in it.
2162         eachReverse(scripts(), function (script) {
2163             //Set the 'head' where we can append children by
2164             //using the script's parent.
2165             if (!head) {
2166                 head = script.parentNode;
2167             }
2169             //Look for a data-main attribute to set main script for the page
2170             //to load. If it is there, the path to data main becomes the
2171             //baseUrl, if it is not already set.
2172             dataMain = script.getAttribute('data-main');
2173             if (dataMain) {
2174                 //Preserve dataMain in case it is a path (i.e. contains '?')
2175                 mainScript = dataMain;
2177                 //Set final baseUrl if there is not already an explicit one.
2178                 if (!cfg.baseUrl) {
2179                     //Pull off the directory of data-main for use as the
2180                     //baseUrl.
2181                     src = mainScript.split('/');
2182                     mainScript = src.pop();
2183                     subPath = src.length ? src.join('/')  + '/' : './';
2185                     cfg.baseUrl = subPath;
2186                 }
2188                 //Strip off any trailing .js since mainScript is now
2189                 //like a module name.
2190                 mainScript = mainScript.replace(jsSuffixRegExp, '');
2192                  //If mainScript is still a path, fall back to dataMain
2193                 if (req.jsExtRegExp.test(mainScript)) {
2194                     mainScript = dataMain;
2195                 }
2197                 //Put the data-main script in the files to load.
2198                 cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];
2200                 return true;
2201             }
2202         });
2203     }
2205     /**
2206      * The function that handles definitions of modules. Differs from
2207      * require() in that a string for the module should be the first argument,
2208      * and the function to execute after dependencies are loaded should
2209      * return a value to define the module corresponding to the first argument's
2210      * name.
2211      */
2212     define = function (name, deps, callback) {
2213         var node, context;
2215         //Allow for anonymous modules
2216         if (typeof name !== 'string') {
2217             //Adjust args appropriately
2218             callback = deps;
2219             deps = name;
2220             name = null;
2221         }
2223         //This module may not have dependencies
2224         if (!isArray(deps)) {
2225             callback = deps;
2226             deps = null;
2227         }
2229         //If no name, and callback is a function, then figure out if it a
2230         //CommonJS thing with dependencies.
2231         if (!deps && isFunction(callback)) {
2232             deps = [];
2233             //Remove comments from the callback string,
2234             //look for require calls, and pull them into the dependencies,
2235             //but only if there are function args.
2236             if (callback.length) {
2237                 callback
2238                     .toString()
2239                     .replace(commentRegExp, '')
2240                     .replace(cjsRequireRegExp, function (match, dep) {
2241                         deps.push(dep);
2242                     });
2244                 //May be a CommonJS thing even without require calls, but still
2245                 //could use exports, and module. Avoid doing exports and module
2246                 //work though if it just needs require.
2247                 //REQUIRES the function to expect the CommonJS variables in the
2248                 //order listed below.
2249                 deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
2250             }
2251         }
2253         //If in IE 6-8 and hit an anonymous define() call, do the interactive
2254         //work.
2255         if (useInteractive) {
2256             node = currentlyAddingScript || getInteractiveScript();
2257             if (node) {
2258                 if (!name) {
2259                     name = node.getAttribute('data-requiremodule');
2260                 }
2261                 context = contexts[node.getAttribute('data-requirecontext')];
2262             }
2263         }
2265         //Always save off evaluating the def call until the script onload handler.
2266         //This allows multiple modules to be in a file without prematurely
2267         //tracing dependencies, and allows for anonymous module support,
2268         //where the module name is not known until the script onload event
2269         //occurs. If no context, use the global queue, and get it processed
2270         //in the onscript load callback.
2271         (context ? context.defQueue : globalDefQueue).push([name, deps, callback]);
2272     };
2274     define.amd = {
2275         jQuery: true
2276     };
2279     /**
2280      * Executes the text. Normally just uses eval, but can be modified
2281      * to use a better, environment-specific call. Only used for transpiling
2282      * loader plugins, not for plain JS modules.
2283      * @param {String} text the text to execute/evaluate.
2284      */
2285     req.exec = function (text) {
2286         /*jslint evil: true */
2287         return eval(text);
2288     };
2290     //Set up with config info.
2291     req(cfg);
2292 }(this));
2296     this.requirejsVars = {
2297         require: require,
2298         requirejs: require,
2299         define: define
2300     };
2302     if (env === 'browser') {
2303         /**
2304  * @license RequireJS rhino Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
2305  * Available via the MIT or new BSD license.
2306  * see: http://github.com/jrburke/requirejs for details
2307  */
2309 //sloppy since eval enclosed with use strict causes problems if the source
2310 //text is not strict-compliant.
2311 /*jslint sloppy: true, evil: true */
2312 /*global require, XMLHttpRequest */
2314 (function () {
2315     require.load = function (context, moduleName, url) {
2316         var xhr = new XMLHttpRequest();
2318         xhr.open('GET', url, true);
2319         xhr.send();
2321         xhr.onreadystatechange = function () {
2322             if (xhr.readyState === 4) {
2323                 eval(xhr.responseText);
2325                 //Support anonymous modules.
2326                 context.completeLoad(moduleName);
2327             }
2328         };
2329     };
2330 }());
2331     } else if (env === 'rhino') {
2332         /**
2333  * @license RequireJS rhino Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2334  * Available via the MIT or new BSD license.
2335  * see: http://github.com/jrburke/requirejs for details
2336  */
2338 /*jslint */
2339 /*global require: false, java: false, load: false */
2341 (function () {
2342     'use strict';
2343     require.load = function (context, moduleName, url) {
2345         load(url);
2347         //Support anonymous modules.
2348         context.completeLoad(moduleName);
2349     };
2351 }());
2352     } else if (env === 'node') {
2353         this.requirejsVars.nodeRequire = nodeRequire;
2354         require.nodeRequire = nodeRequire;
2356         /**
2357  * @license RequireJS node Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2358  * Available via the MIT or new BSD license.
2359  * see: http://github.com/jrburke/requirejs for details
2360  */
2362 /*jslint regexp: false */
2363 /*global require: false, define: false, requirejsVars: false, process: false */
2366  * This adapter assumes that x.js has loaded it and set up
2367  * some variables. This adapter just allows limited RequireJS
2368  * usage from within the requirejs directory. The general
2369  * node adapater is r.js.
2370  */
2372 (function () {
2373     'use strict';
2375     var nodeReq = requirejsVars.nodeRequire,
2376         req = requirejsVars.require,
2377         def = requirejsVars.define,
2378         fs = nodeReq('fs'),
2379         path = nodeReq('path'),
2380         vm = nodeReq('vm'),
2381         //In Node 0.7+ existsSync is on fs.
2382         exists = fs.existsSync || path.existsSync,
2383         hasOwn = Object.prototype.hasOwnProperty;
2385     function hasProp(obj, prop) {
2386         return hasOwn.call(obj, prop);
2387     }
2389     function syncTick(fn) {
2390         fn();
2391     }
2393     //Supply an implementation that allows synchronous get of a module.
2394     req.get = function (context, moduleName, relModuleMap, localRequire) {
2395         if (moduleName === "require" || moduleName === "exports" || moduleName === "module") {
2396             req.onError(new Error("Explicit require of " + moduleName + " is not allowed."));
2397         }
2399         var ret, oldTick,
2400             moduleMap = context.makeModuleMap(moduleName, relModuleMap, false, true);
2402         //Normalize module name, if it contains . or ..
2403         moduleName = moduleMap.id;
2405         if (hasProp(context.defined, moduleName)) {
2406             ret = context.defined[moduleName];
2407         } else {
2408             if (ret === undefined) {
2409                 //Make sure nextTick for this type of call is sync-based.
2410                 oldTick = context.nextTick;
2411                 context.nextTick = syncTick;
2412                 try {
2413                     if (moduleMap.prefix) {
2414                         //A plugin, call requirejs to handle it. Now that
2415                         //nextTick is syncTick, the require will complete
2416                         //synchronously.
2417                         localRequire([moduleMap.originalName]);
2419                         //Now that plugin is loaded, can regenerate the moduleMap
2420                         //to get the final, normalized ID.
2421                         moduleMap = context.makeModuleMap(moduleMap.originalName, relModuleMap, false, true);
2422                         moduleName = moduleMap.id;
2423                     } else {
2424                         //Try to dynamically fetch it.
2425                         req.load(context, moduleName, moduleMap.url);
2427                         //Enable the module
2428                         context.enable(moduleMap, relModuleMap);
2429                     }
2431                     //Break any cycles by requiring it normally, but this will
2432                     //finish synchronously
2433                     require([moduleName]);
2435                     //The above calls are sync, so can do the next thing safely.
2436                     ret = context.defined[moduleName];
2437                 } finally {
2438                     context.nextTick = oldTick;
2439                 }
2440             }
2441         }
2443         return ret;
2444     };
2446     req.nextTick = function (fn) {
2447         process.nextTick(fn);
2448     };
2450     //Add wrapper around the code so that it gets the requirejs
2451     //API instead of the Node API, and it is done lexically so
2452     //that it survives later execution.
2453     req.makeNodeWrapper = function (contents) {
2454         return '(function (require, requirejs, define) { ' +
2455                 contents +
2456                 '\n}(requirejsVars.require, requirejsVars.requirejs, requirejsVars.define));';
2457     };
2459     req.load = function (context, moduleName, url) {
2460         var contents, err,
2461             config = context.config;
2463         if (config.shim[moduleName] && (!config.suppress || !config.suppress.nodeShim)) {
2464             console.warn('Shim config not supported in Node, may or may not work. Detected ' +
2465                             'for module: ' + moduleName);
2466         }
2468         if (exists(url)) {
2469             contents = fs.readFileSync(url, 'utf8');
2471             contents = req.makeNodeWrapper(contents);
2472             try {
2473                 vm.runInThisContext(contents, fs.realpathSync(url));
2474             } catch (e) {
2475                 err = new Error('Evaluating ' + url + ' as module "' +
2476                                 moduleName + '" failed with error: ' + e);
2477                 err.originalError = e;
2478                 err.moduleName = moduleName;
2479                 err.fileName = url;
2480                 return req.onError(err);
2481             }
2482         } else {
2483             def(moduleName, function () {
2484                 //Get the original name, since relative requires may be
2485                 //resolved differently in node (issue #202). Also, if relative,
2486                 //make it relative to the URL of the item requesting it
2487                 //(issue #393)
2488                 var dirName,
2489                     map = hasProp(context.registry, moduleName) &&
2490                             context.registry[moduleName].map,
2491                     parentMap = map && map.parentMap,
2492                     originalName = map && map.originalName;
2494                 if (originalName.charAt(0) === '.' && parentMap) {
2495                     dirName = parentMap.url.split('/');
2496                     dirName.pop();
2497                     originalName = dirName.join('/') + '/' + originalName;
2498                 }
2500                 try {
2501                     return (context.config.nodeRequire || req.nodeRequire)(originalName);
2502                 } catch (e) {
2503                     err = new Error('Tried loading "' + moduleName + '" at ' +
2504                                      url + ' then tried node\'s require("' +
2505                                         originalName + '") and it failed ' +
2506                                      'with error: ' + e);
2507                     err.originalError = e;
2508                     err.moduleName = originalName;
2509                     return req.onError(err);
2510                 }
2511             });
2512         }
2514         //Support anonymous modules.
2515         context.completeLoad(moduleName);
2516     };
2518     //Override to provide the function wrapper for define/require.
2519     req.exec = function (text) {
2520         /*jslint evil: true */
2521         text = req.makeNodeWrapper(text);
2522         return eval(text);
2523     };
2524 }());
2526     } else if (env === 'xpconnect') {
2527         /**
2528  * @license RequireJS xpconnect Copyright (c) 2013, The Dojo Foundation All Rights Reserved.
2529  * Available via the MIT or new BSD license.
2530  * see: http://github.com/jrburke/requirejs for details
2531  */
2533 /*jslint */
2534 /*global require, load */
2536 (function () {
2537     'use strict';
2538     require.load = function (context, moduleName, url) {
2540         load(url);
2542         //Support anonymous modules.
2543         context.completeLoad(moduleName);
2544     };
2546 }());
2548     }
2550     //Support a default file name to execute. Useful for hosted envs
2551     //like Joyent where it defaults to a server.js as the only executed
2552     //script. But only do it if this is not an optimization run.
2553     if (commandOption !== 'o' && (!fileName || !jsSuffixRegExp.test(fileName))) {
2554         fileName = 'main.js';
2555     }
2557     /**
2558      * Loads the library files that can be used for the optimizer, or for other
2559      * tasks.
2560      */
2561     function loadLib() {
2562         /**
2563  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2564  * Available via the MIT or new BSD license.
2565  * see: http://github.com/jrburke/requirejs for details
2566  */
2568 /*jslint strict: false */
2569 /*global Packages: false, process: false, window: false, navigator: false,
2570   document: false, define: false */
2573  * A plugin that modifies any /env/ path to be the right path based on
2574  * the host environment. Right now only works for Node, Rhino and browser.
2575  */
2576 (function () {
2577     var pathRegExp = /(\/|^)env\/|\{env\}/,
2578         env = 'unknown';
2580     if (typeof Packages !== 'undefined') {
2581         env = 'rhino';
2582     } else if (typeof process !== 'undefined' && process.versions && !!process.versions.node) {
2583         env = 'node';
2584     } else if ((typeof navigator !== 'undefined' && typeof document !== 'undefined') ||
2585             (typeof importScripts !== 'undefined' && typeof self !== 'undefined')) {
2586         env = 'browser';
2587     } else if (typeof Components !== 'undefined' && Components.classes && Components.interfaces) {
2588         env = 'xpconnect';
2589     }
2591     define('env', {
2592         get: function () {
2593             return env;
2594         },
2596         load: function (name, req, load, config) {
2597             //Allow override in the config.
2598             if (config.env) {
2599                 env = config.env;
2600             }
2602             name = name.replace(pathRegExp, function (match, prefix) {
2603                 if (match.indexOf('{') === -1) {
2604                     return prefix + env + '/';
2605                 } else {
2606                     return env;
2607                 }
2608             });
2610             req([name], function (mod) {
2611                 load(mod);
2612             });
2613         }
2614     });
2615 }());/**
2616  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
2617  * Available via the MIT or new BSD license.
2618  * see: http://github.com/jrburke/requirejs for details
2619  */
2621 /*jslint plusplus: true */
2622 /*global define */
2624 define('lang', function () {
2625     'use strict';
2627     var lang,
2628         hasOwn = Object.prototype.hasOwnProperty;
2630     function hasProp(obj, prop) {
2631         return hasOwn.call(obj, prop);
2632     }
2634     lang = {
2635         backSlashRegExp: /\\/g,
2636         ostring: Object.prototype.toString,
2638         isArray: Array.isArray || function (it) {
2639             return lang.ostring.call(it) === "[object Array]";
2640         },
2642         isFunction: function(it) {
2643             return lang.ostring.call(it) === "[object Function]";
2644         },
2646         isRegExp: function(it) {
2647             return it && it instanceof RegExp;
2648         },
2650         hasProp: hasProp,
2652         //returns true if the object does not have an own property prop,
2653         //or if it does, it is a falsy value.
2654         falseProp: function (obj, prop) {
2655             return !hasProp(obj, prop) || !obj[prop];
2656         },
2658         //gets own property value for given prop on object
2659         getOwn: function (obj, prop) {
2660             return hasProp(obj, prop) && obj[prop];
2661         },
2663         _mixin: function(dest, source, override){
2664             var name;
2665             for (name in source) {
2666                 if(source.hasOwnProperty(name)
2667                     && (override || !dest.hasOwnProperty(name))) {
2668                     dest[name] = source[name];
2669                 }
2670             }
2672             return dest; // Object
2673         },
2675         /**
2676          * mixin({}, obj1, obj2) is allowed. If the last argument is a boolean,
2677          * then the source objects properties are force copied over to dest.
2678          */
2679         mixin: function(dest){
2680             var parameters = Array.prototype.slice.call(arguments),
2681                 override, i, l;
2683             if (!dest) { dest = {}; }
2685             if (parameters.length > 2 && typeof arguments[parameters.length-1] === 'boolean') {
2686                 override = parameters.pop();
2687             }
2689             for (i = 1, l = parameters.length; i < l; i++) {
2690                 lang._mixin(dest, parameters[i], override);
2691             }
2692             return dest; // Object
2693         },
2695         delegate: (function () {
2696             // boodman/crockford delegation w/ cornford optimization
2697             function TMP() {}
2698             return function (obj, props) {
2699                 TMP.prototype = obj;
2700                 var tmp = new TMP();
2701                 TMP.prototype = null;
2702                 if (props) {
2703                     lang.mixin(tmp, props);
2704                 }
2705                 return tmp; // Object
2706             };
2707         }()),
2709         /**
2710          * Helper function for iterating over an array. If the func returns
2711          * a true value, it will break out of the loop.
2712          */
2713         each: function each(ary, func) {
2714             if (ary) {
2715                 var i;
2716                 for (i = 0; i < ary.length; i += 1) {
2717                     if (func(ary[i], i, ary)) {
2718                         break;
2719                     }
2720                 }
2721             }
2722         },
2724         /**
2725          * Cycles over properties in an object and calls a function for each
2726          * property value. If the function returns a truthy value, then the
2727          * iteration is stopped.
2728          */
2729         eachProp: function eachProp(obj, func) {
2730             var prop;
2731             for (prop in obj) {
2732                 if (hasProp(obj, prop)) {
2733                     if (func(obj[prop], prop)) {
2734                         break;
2735                     }
2736                 }
2737             }
2738         },
2740         //Similar to Function.prototype.bind, but the "this" object is specified
2741         //first, since it is easier to read/figure out what "this" will be.
2742         bind: function bind(obj, fn) {
2743             return function () {
2744                 return fn.apply(obj, arguments);
2745             };
2746         },
2748         //Escapes a content string to be be a string that has characters escaped
2749         //for inclusion as part of a JS string.
2750         jsEscape: function (content) {
2751             return content.replace(/(["'\\])/g, '\\$1')
2752                 .replace(/[\f]/g, "\\f")
2753                 .replace(/[\b]/g, "\\b")
2754                 .replace(/[\n]/g, "\\n")
2755                 .replace(/[\t]/g, "\\t")
2756                 .replace(/[\r]/g, "\\r");
2757         }
2758     };
2759     return lang;
2762  * prim 0.0.1 Copyright (c) 2012-2013, The Dojo Foundation All Rights Reserved.
2763  * Available via the MIT or new BSD license.
2764  * see: http://github.com/requirejs/prim for details
2765  */
2767 /*global setImmediate, process, setTimeout, define, module */
2769 //Set prime.hideResolutionConflict = true to allow "resolution-races"
2770 //in promise-tests to pass.
2771 //Since the goal of prim is to be a small impl for trusted code, it is
2772 //more important to normally throw in this case so that we can find
2773 //logic errors quicker.
2775 var prim;
2776 (function () {
2777     'use strict';
2778     var op = Object.prototype,
2779         hasOwn = op.hasOwnProperty;
2781     function hasProp(obj, prop) {
2782         return hasOwn.call(obj, prop);
2783     }
2785     /**
2786      * Helper function for iterating over an array. If the func returns
2787      * a true value, it will break out of the loop.
2788      */
2789     function each(ary, func) {
2790         if (ary) {
2791             var i;
2792             for (i = 0; i < ary.length; i += 1) {
2793                 if (ary[i]) {
2794                     func(ary[i], i, ary);
2795                 }
2796             }
2797         }
2798     }
2800     function check(p) {
2801         if (hasProp(p, 'e') || hasProp(p, 'v')) {
2802             if (!prim.hideResolutionConflict) {
2803                 throw new Error('nope');
2804             }
2805             return false;
2806         }
2807         return true;
2808     }
2810     function notify(ary, value) {
2811         prim.nextTick(function () {
2812             each(ary, function (item) {
2813                 item(value);
2814             });
2815         });
2816     }
2818     prim = function prim() {
2819         var p,
2820             ok = [],
2821             fail = [];
2823         return (p = {
2824             callback: function (yes, no) {
2825                 if (no) {
2826                     p.errback(no);
2827                 }
2829                 if (hasProp(p, 'v')) {
2830                     prim.nextTick(function () {
2831                         yes(p.v);
2832                     });
2833                 } else {
2834                     ok.push(yes);
2835                 }
2836             },
2838             errback: function (no) {
2839                 if (hasProp(p, 'e')) {
2840                     prim.nextTick(function () {
2841                         no(p.e);
2842                     });
2843                 } else {
2844                     fail.push(no);
2845                 }
2846             },
2848             finished: function () {
2849                 return hasProp(p, 'e') || hasProp(p, 'v');
2850             },
2852             rejected: function () {
2853                 return hasProp(p, 'e');
2854             },
2856             resolve: function (v) {
2857                 if (check(p)) {
2858                     p.v = v;
2859                     notify(ok, v);
2860                 }
2861                 return p;
2862             },
2863             reject: function (e) {
2864                 if (check(p)) {
2865                     p.e = e;
2866                     notify(fail, e);
2867                 }
2868                 return p;
2869             },
2871             start: function (fn) {
2872                 p.resolve();
2873                 return p.promise.then(fn);
2874             },
2876             promise: {
2877                 then: function (yes, no) {
2878                     var next = prim();
2880                     p.callback(function (v) {
2881                         try {
2882                             if (yes && typeof yes === 'function') {
2883                                 v = yes(v);
2884                             }
2886                             if (v && v.then) {
2887                                 v.then(next.resolve, next.reject);
2888                             } else {
2889                                 next.resolve(v);
2890                             }
2891                         } catch (e) {
2892                             next.reject(e);
2893                         }
2894                     }, function (e) {
2895                         var err;
2897                         try {
2898                             if (!no || typeof no !== 'function') {
2899                                 next.reject(e);
2900                             } else {
2901                                 err = no(e);
2903                                 if (err && err.then) {
2904                                     err.then(next.resolve, next.reject);
2905                                 } else {
2906                                     next.resolve(err);
2907                                 }
2908                             }
2909                         } catch (e2) {
2910                             next.reject(e2);
2911                         }
2912                     });
2914                     return next.promise;
2915                 },
2917                 fail: function (no) {
2918                     return p.promise.then(null, no);
2919                 },
2921                 end: function () {
2922                     p.errback(function (e) {
2923                         throw e;
2924                     });
2925                 }
2926             }
2927         });
2928     };
2930     prim.serial = function (ary) {
2931         var result = prim().resolve().promise;
2932         each(ary, function (item) {
2933             result = result.then(function () {
2934                 return item();
2935             });
2936         });
2937         return result;
2938     };
2940     prim.nextTick = typeof setImmediate === 'function' ? setImmediate :
2941         (typeof process !== 'undefined' && process.nextTick ?
2942             process.nextTick : (typeof setTimeout !== 'undefined' ?
2943                 function (fn) {
2944                 setTimeout(fn, 0);
2945             } : function (fn) {
2946         fn();
2947     }));
2949     if (typeof define === 'function' && define.amd) {
2950         define('prim', function () { return prim; });
2951     } else if (typeof module !== 'undefined' && module.exports) {
2952         module.exports = prim;
2953     }
2954 }());
2955 if(env === 'browser') {
2957  * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
2958  * Available via the MIT or new BSD license.
2959  * see: http://github.com/jrburke/requirejs for details
2960  */
2962 /*jslint strict: false */
2963 /*global define: false, load: false */
2965 //Just a stub for use with uglify's consolidator.js
2966 define('browser/assert', function () {
2967     return {};
2972 if(env === 'node') {
2974  * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
2975  * Available via the MIT or new BSD license.
2976  * see: http://github.com/jrburke/requirejs for details
2977  */
2979 /*jslint strict: false */
2980 /*global define: false, load: false */
2982 //Needed so that rhino/assert can return a stub for uglify's consolidator.js
2983 define('node/assert', ['assert'], function (assert) {
2984     return assert;
2989 if(env === 'rhino') {
2991  * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
2992  * Available via the MIT or new BSD license.
2993  * see: http://github.com/jrburke/requirejs for details
2994  */
2996 /*jslint strict: false */
2997 /*global define: false, load: false */
2999 //Just a stub for use with uglify's consolidator.js
3000 define('rhino/assert', function () {
3001     return {};
3006 if(env === 'xpconnect') {
3008  * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved.
3009  * Available via the MIT or new BSD license.
3010  * see: http://github.com/jrburke/requirejs for details
3011  */
3013 /*jslint strict: false */
3014 /*global define: false, load: false */
3016 //Just a stub for use with uglify's consolidator.js
3017 define('xpconnect/assert', function () {
3018     return {};
3023 if(env === 'browser') {
3025  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3026  * Available via the MIT or new BSD license.
3027  * see: http://github.com/jrburke/requirejs for details
3028  */
3030 /*jslint strict: false */
3031 /*global define: false, process: false */
3033 define('browser/args', function () {
3034     //Always expect config via an API call
3035     return [];
3040 if(env === 'node') {
3042  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3043  * Available via the MIT or new BSD license.
3044  * see: http://github.com/jrburke/requirejs for details
3045  */
3047 /*jslint strict: false */
3048 /*global define: false, process: false */
3050 define('node/args', function () {
3051     //Do not return the "node" or "r.js" arguments
3052     var args = process.argv.slice(2);
3054     //Ignore any command option used for main x.js branching
3055     if (args[0] && args[0].indexOf('-') === 0) {
3056         args = args.slice(1);
3057     }
3059     return args;
3064 if(env === 'rhino') {
3066  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3067  * Available via the MIT or new BSD license.
3068  * see: http://github.com/jrburke/requirejs for details
3069  */
3071 /*jslint strict: false */
3072 /*global define: false, process: false */
3074 var jsLibRhinoArgs = (typeof rhinoArgs !== 'undefined' && rhinoArgs) || [].concat(Array.prototype.slice.call(arguments, 0));
3076 define('rhino/args', function () {
3077     var args = jsLibRhinoArgs;
3079     //Ignore any command option used for main x.js branching
3080     if (args[0] && args[0].indexOf('-') === 0) {
3081         args = args.slice(1);
3082     }
3084     return args;
3089 if(env === 'xpconnect') {
3091  * @license Copyright (c) 2013, The Dojo Foundation All Rights Reserved.
3092  * Available via the MIT or new BSD license.
3093  * see: http://github.com/jrburke/requirejs for details
3094  */
3096 /*jslint strict: false */
3097 /*global define, xpconnectArgs */
3099 var jsLibXpConnectArgs = (typeof xpconnectArgs !== 'undefined' && xpconnectArgs) || [].concat(Array.prototype.slice.call(arguments, 0));
3101 define('xpconnect/args', function () {
3102     var args = jsLibXpConnectArgs;
3104     //Ignore any command option used for main x.js branching
3105     if (args[0] && args[0].indexOf('-') === 0) {
3106         args = args.slice(1);
3107     }
3109     return args;
3114 if(env === 'browser') {
3116  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3117  * Available via the MIT or new BSD license.
3118  * see: http://github.com/jrburke/requirejs for details
3119  */
3121 /*jslint strict: false */
3122 /*global define: false, console: false */
3124 define('browser/load', ['./file'], function (file) {
3125     function load(fileName) {
3126         eval(file.readFile(fileName));
3127     }
3129     return load;
3134 if(env === 'node') {
3136  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3137  * Available via the MIT or new BSD license.
3138  * see: http://github.com/jrburke/requirejs for details
3139  */
3141 /*jslint strict: false */
3142 /*global define: false, console: false */
3144 define('node/load', ['fs'], function (fs) {
3145     function load(fileName) {
3146         var contents = fs.readFileSync(fileName, 'utf8');
3147         process.compile(contents, fileName);
3148     }
3150     return load;
3155 if(env === 'rhino') {
3157  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3158  * Available via the MIT or new BSD license.
3159  * see: http://github.com/jrburke/requirejs for details
3160  */
3162 /*jslint strict: false */
3163 /*global define: false, load: false */
3165 define('rhino/load', function () {
3166     return load;
3171 if(env === 'xpconnect') {
3173  * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved.
3174  * Available via the MIT or new BSD license.
3175  * see: http://github.com/jrburke/requirejs for details
3176  */
3178 /*jslint strict: false */
3179 /*global define: false, load: false */
3181 define('xpconnect/load', function () {
3182     return load;
3187 if(env === 'browser') {
3189  * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
3190  * Available via the MIT or new BSD license.
3191  * see: http://github.com/jrburke/requirejs for details
3192  */
3194 /*jslint sloppy: true, nomen: true */
3195 /*global require, define, console, XMLHttpRequest, requirejs, location */
3197 define('browser/file', ['prim'], function (prim) {
3199     var file,
3200         currDirRegExp = /^\.(\/|$)/;
3202     function frontSlash(path) {
3203         return path.replace(/\\/g, '/');
3204     }
3206     function exists(path) {
3207         var status, xhr = new XMLHttpRequest();
3209         //Oh yeah, that is right SYNC IO. Behold its glory
3210         //and horrible blocking behavior.
3211         xhr.open('HEAD', path, false);
3212         xhr.send();
3213         status = xhr.status;
3215         return status === 200 || status === 304;
3216     }
3218     function mkDir(dir) {
3219         console.log('mkDir is no-op in browser');
3220     }
3222     function mkFullDir(dir) {
3223         console.log('mkFullDir is no-op in browser');
3224     }
3226     file = {
3227         backSlashRegExp: /\\/g,
3228         exclusionRegExp: /^\./,
3229         getLineSeparator: function () {
3230             return '/';
3231         },
3233         exists: function (fileName) {
3234             return exists(fileName);
3235         },
3237         parent: function (fileName) {
3238             var parts = fileName.split('/');
3239             parts.pop();
3240             return parts.join('/');
3241         },
3243         /**
3244          * Gets the absolute file path as a string, normalized
3245          * to using front slashes for path separators.
3246          * @param {String} fileName
3247          */
3248         absPath: function (fileName) {
3249             var dir;
3250             if (currDirRegExp.test(fileName)) {
3251                 dir = frontSlash(location.href);
3252                 if (dir.indexOf('/') !== -1) {
3253                     dir = dir.split('/');
3255                     //Pull off protocol and host, just want
3256                     //to allow paths (other build parts, like
3257                     //require._isSupportedBuildUrl do not support
3258                     //full URLs), but a full path from
3259                     //the root.
3260                     dir.splice(0, 3);
3262                     dir.pop();
3263                     dir = '/' + dir.join('/');
3264                 }
3266                 fileName = dir + fileName.substring(1);
3267             }
3269             return fileName;
3270         },
3272         normalize: function (fileName) {
3273             return fileName;
3274         },
3276         isFile: function (path) {
3277             return true;
3278         },
3280         isDirectory: function (path) {
3281             return false;
3282         },
3284         getFilteredFileList: function (startDir, regExpFilters, makeUnixPaths) {
3285             console.log('file.getFilteredFileList is no-op in browser');
3286         },
3288         copyDir: function (srcDir, destDir, regExpFilter, onlyCopyNew) {
3289             console.log('file.copyDir is no-op in browser');
3291         },
3293         copyFile: function (srcFileName, destFileName, onlyCopyNew) {
3294             console.log('file.copyFile is no-op in browser');
3295         },
3297         /**
3298          * Renames a file. May fail if "to" already exists or is on another drive.
3299          */
3300         renameFile: function (from, to) {
3301             console.log('file.renameFile is no-op in browser');
3302         },
3304         /**
3305          * Reads a *text* file.
3306          */
3307         readFile: function (path, encoding) {
3308             var xhr = new XMLHttpRequest();
3310             //Oh yeah, that is right SYNC IO. Behold its glory
3311             //and horrible blocking behavior.
3312             xhr.open('GET', path, false);
3313             xhr.send();
3315             return xhr.responseText;
3316         },
3318         readFileAsync: function (path, encoding) {
3319             var xhr = new XMLHttpRequest(),
3320                 d = prim();
3322             xhr.open('GET', path, true);
3323             xhr.send();
3325             xhr.onreadystatechange = function () {
3326                 if (xhr.readyState === 4) {
3327                     if (xhr.status > 400) {
3328                         d.reject(new Error('Status: ' + xhr.status + ': ' + xhr.statusText));
3329                     } else {
3330                         d.resolve(xhr.responseText);
3331                     }
3332                 }
3333             };
3335             return d.promise;
3336         },
3338         saveUtf8File: function (fileName, fileContents) {
3339             //summary: saves a *text* file using UTF-8 encoding.
3340             file.saveFile(fileName, fileContents, "utf8");
3341         },
3343         saveFile: function (fileName, fileContents, encoding) {
3344             requirejs.browser.saveFile(fileName, fileContents, encoding);
3345         },
3347         deleteFile: function (fileName) {
3348             console.log('file.deleteFile is no-op in browser');
3349         },
3351         /**
3352          * Deletes any empty directories under the given directory.
3353          */
3354         deleteEmptyDirs: function (startDir) {
3355             console.log('file.deleteEmptyDirs is no-op in browser');
3356         }
3357     };
3359     return file;
3365 if(env === 'node') {
3367  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3368  * Available via the MIT or new BSD license.
3369  * see: http://github.com/jrburke/requirejs for details
3370  */
3372 /*jslint plusplus: false, octal:false, strict: false */
3373 /*global define: false, process: false */
3375 define('node/file', ['fs', 'path', 'prim'], function (fs, path, prim) {
3377     var isWindows = process.platform === 'win32',
3378         windowsDriveRegExp = /^[a-zA-Z]\:\/$/,
3379         file;
3381     function frontSlash(path) {
3382         return path.replace(/\\/g, '/');
3383     }
3385     function exists(path) {
3386         if (isWindows && path.charAt(path.length - 1) === '/' &&
3387             path.charAt(path.length - 2) !== ':') {
3388             path = path.substring(0, path.length - 1);
3389         }
3391         try {
3392             fs.statSync(path);
3393             return true;
3394         } catch (e) {
3395             return false;
3396         }
3397     }
3399     function mkDir(dir) {
3400         if (!exists(dir) && (!isWindows || !windowsDriveRegExp.test(dir))) {
3401             fs.mkdirSync(dir, 511);
3402         }
3403     }
3405     function mkFullDir(dir) {
3406         var parts = dir.split('/'),
3407             currDir = '',
3408             first = true;
3410         parts.forEach(function (part) {
3411             //First part may be empty string if path starts with a slash.
3412             currDir += part + '/';
3413             first = false;
3415             if (part) {
3416                 mkDir(currDir);
3417             }
3418         });
3419     }
3421     file = {
3422         backSlashRegExp: /\\/g,
3423         exclusionRegExp: /^\./,
3424         getLineSeparator: function () {
3425             return '/';
3426         },
3428         exists: function (fileName) {
3429             return exists(fileName);
3430         },
3432         parent: function (fileName) {
3433             var parts = fileName.split('/');
3434             parts.pop();
3435             return parts.join('/');
3436         },
3438         /**
3439          * Gets the absolute file path as a string, normalized
3440          * to using front slashes for path separators.
3441          * @param {String} fileName
3442          */
3443         absPath: function (fileName) {
3444             return frontSlash(path.normalize(frontSlash(fs.realpathSync(fileName))));
3445         },
3447         normalize: function (fileName) {
3448             return frontSlash(path.normalize(fileName));
3449         },
3451         isFile: function (path) {
3452             return fs.statSync(path).isFile();
3453         },
3455         isDirectory: function (path) {
3456             return fs.statSync(path).isDirectory();
3457         },
3459         getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths) {
3460             //summary: Recurses startDir and finds matches to the files that match regExpFilters.include
3461             //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
3462             //and it will be treated as the "include" case.
3463             //Ignores files/directories that start with a period (.) unless exclusionRegExp
3464             //is set to another value.
3465             var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
3466                 i, stat, filePath, ok, dirFiles, fileName;
3468             topDir = startDir;
3470             regExpInclude = regExpFilters.include || regExpFilters;
3471             regExpExclude = regExpFilters.exclude || null;
3473             if (file.exists(topDir)) {
3474                 dirFileArray = fs.readdirSync(topDir);
3475                 for (i = 0; i < dirFileArray.length; i++) {
3476                     fileName = dirFileArray[i];
3477                     filePath = path.join(topDir, fileName);
3478                     stat = fs.statSync(filePath);
3479                     if (stat.isFile()) {
3480                         if (makeUnixPaths) {
3481                             //Make sure we have a JS string.
3482                             if (filePath.indexOf("/") === -1) {
3483                                 filePath = frontSlash(filePath);
3484                             }
3485                         }
3487                         ok = true;
3488                         if (regExpInclude) {
3489                             ok = filePath.match(regExpInclude);
3490                         }
3491                         if (ok && regExpExclude) {
3492                             ok = !filePath.match(regExpExclude);
3493                         }
3495                         if (ok && (!file.exclusionRegExp ||
3496                             !file.exclusionRegExp.test(fileName))) {
3497                             files.push(filePath);
3498                         }
3499                     } else if (stat.isDirectory() &&
3500                               (!file.exclusionRegExp || !file.exclusionRegExp.test(fileName))) {
3501                         dirFiles = this.getFilteredFileList(filePath, regExpFilters, makeUnixPaths);
3502                         files.push.apply(files, dirFiles);
3503                     }
3504                 }
3505             }
3507             return files; //Array
3508         },
3510         copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
3511             //summary: copies files from srcDir to destDir using the regExpFilter to determine if the
3512             //file should be copied. Returns a list file name strings of the destinations that were copied.
3513             regExpFilter = regExpFilter || /\w/;
3515             //Normalize th directory names, but keep front slashes.
3516             //path module on windows now returns backslashed paths.
3517             srcDir = frontSlash(path.normalize(srcDir));
3518             destDir = frontSlash(path.normalize(destDir));
3520             var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true),
3521             copiedFiles = [], i, srcFileName, destFileName;
3523             for (i = 0; i < fileNames.length; i++) {
3524                 srcFileName = fileNames[i];
3525                 destFileName = srcFileName.replace(srcDir, destDir);
3527                 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) {
3528                     copiedFiles.push(destFileName);
3529                 }
3530             }
3532             return copiedFiles.length ? copiedFiles : null; //Array or null
3533         },
3535         copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
3536             //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
3537             //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
3538             var parentDir;
3540             //logger.trace("Src filename: " + srcFileName);
3541             //logger.trace("Dest filename: " + destFileName);
3543             //If onlyCopyNew is true, then compare dates and only copy if the src is newer
3544             //than dest.
3545             if (onlyCopyNew) {
3546                 if (file.exists(destFileName) && fs.statSync(destFileName).mtime.getTime() >= fs.statSync(srcFileName).mtime.getTime()) {
3547                     return false; //Boolean
3548                 }
3549             }
3551             //Make sure destination dir exists.
3552             parentDir = path.dirname(destFileName);
3553             if (!file.exists(parentDir)) {
3554                 mkFullDir(parentDir);
3555             }
3557             fs.writeFileSync(destFileName, fs.readFileSync(srcFileName, 'binary'), 'binary');
3559             return true; //Boolean
3560         },
3562         /**
3563          * Renames a file. May fail if "to" already exists or is on another drive.
3564          */
3565         renameFile: function (from, to) {
3566             return fs.renameSync(from, to);
3567         },
3569         /**
3570          * Reads a *text* file.
3571          */
3572         readFile: function (/*String*/path, /*String?*/encoding) {
3573             if (encoding === 'utf-8') {
3574                 encoding = 'utf8';
3575             }
3576             if (!encoding) {
3577                 encoding = 'utf8';
3578             }
3580             var text = fs.readFileSync(path, encoding);
3582             //Hmm, would not expect to get A BOM, but it seems to happen,
3583             //remove it just in case.
3584             if (text.indexOf('\uFEFF') === 0) {
3585                 text = text.substring(1, text.length);
3586             }
3588             return text;
3589         },
3591         readFileAsync: function (path, encoding) {
3592             var d = prim();
3593             try {
3594                 d.resolve(file.readFile(path, encoding));
3595             } catch (e) {
3596                 d.reject(e);
3597             }
3598             return d.promise;
3599         },
3601         saveUtf8File: function (/*String*/fileName, /*String*/fileContents) {
3602             //summary: saves a *text* file using UTF-8 encoding.
3603             file.saveFile(fileName, fileContents, "utf8");
3604         },
3606         saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
3607             //summary: saves a *text* file.
3608             var parentDir;
3610             if (encoding === 'utf-8') {
3611                 encoding = 'utf8';
3612             }
3613             if (!encoding) {
3614                 encoding = 'utf8';
3615             }
3617             //Make sure destination directories exist.
3618             parentDir = path.dirname(fileName);
3619             if (!file.exists(parentDir)) {
3620                 mkFullDir(parentDir);
3621             }
3623             fs.writeFileSync(fileName, fileContents, encoding);
3624         },
3626         deleteFile: function (/*String*/fileName) {
3627             //summary: deletes a file or directory if it exists.
3628             var files, i, stat;
3629             if (file.exists(fileName)) {
3630                 stat = fs.statSync(fileName);
3631                 if (stat.isDirectory()) {
3632                     files = fs.readdirSync(fileName);
3633                     for (i = 0; i < files.length; i++) {
3634                         this.deleteFile(path.join(fileName, files[i]));
3635                     }
3636                     fs.rmdirSync(fileName);
3637                 } else {
3638                     fs.unlinkSync(fileName);
3639                 }
3640             }
3641         },
3644         /**
3645          * Deletes any empty directories under the given directory.
3646          */
3647         deleteEmptyDirs: function (startDir) {
3648             var dirFileArray, i, fileName, filePath, stat;
3650             if (file.exists(startDir)) {
3651                 dirFileArray = fs.readdirSync(startDir);
3652                 for (i = 0; i < dirFileArray.length; i++) {
3653                     fileName = dirFileArray[i];
3654                     filePath = path.join(startDir, fileName);
3655                     stat = fs.statSync(filePath);
3656                     if (stat.isDirectory()) {
3657                         file.deleteEmptyDirs(filePath);
3658                     }
3659                 }
3661                 //If directory is now empty, remove it.
3662                 if (fs.readdirSync(startDir).length ===  0) {
3663                     file.deleteFile(startDir);
3664                 }
3665             }
3666         }
3667     };
3669     return file;
3675 if(env === 'rhino') {
3677  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3678  * Available via the MIT or new BSD license.
3679  * see: http://github.com/jrburke/requirejs for details
3680  */
3681 //Helper functions to deal with file I/O.
3683 /*jslint plusplus: false */
3684 /*global java: false, define: false */
3686 define('rhino/file', ['prim'], function (prim) {
3687     var file = {
3688         backSlashRegExp: /\\/g,
3690         exclusionRegExp: /^\./,
3692         getLineSeparator: function () {
3693             return file.lineSeparator;
3694         },
3696         lineSeparator: java.lang.System.getProperty("line.separator"), //Java String
3698         exists: function (fileName) {
3699             return (new java.io.File(fileName)).exists();
3700         },
3702         parent: function (fileName) {
3703             return file.absPath((new java.io.File(fileName)).getParentFile());
3704         },
3706         normalize: function (fileName) {
3707             return file.absPath(fileName);
3708         },
3710         isFile: function (path) {
3711             return (new java.io.File(path)).isFile();
3712         },
3714         isDirectory: function (path) {
3715             return (new java.io.File(path)).isDirectory();
3716         },
3718         /**
3719          * Gets the absolute file path as a string, normalized
3720          * to using front slashes for path separators.
3721          * @param {java.io.File||String} file
3722          */
3723         absPath: function (fileObj) {
3724             if (typeof fileObj === "string") {
3725                 fileObj = new java.io.File(fileObj);
3726             }
3727             return (fileObj.getCanonicalPath() + "").replace(file.backSlashRegExp, "/");
3728         },
3730         getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsJavaObject) {
3731             //summary: Recurses startDir and finds matches to the files that match regExpFilters.include
3732             //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
3733             //and it will be treated as the "include" case.
3734             //Ignores files/directories that start with a period (.) unless exclusionRegExp
3735             //is set to another value.
3736             var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
3737                 i, fileObj, filePath, ok, dirFiles;
3739             topDir = startDir;
3740             if (!startDirIsJavaObject) {
3741                 topDir = new java.io.File(startDir);
3742             }
3744             regExpInclude = regExpFilters.include || regExpFilters;
3745             regExpExclude = regExpFilters.exclude || null;
3747             if (topDir.exists()) {
3748                 dirFileArray = topDir.listFiles();
3749                 for (i = 0; i < dirFileArray.length; i++) {
3750                     fileObj = dirFileArray[i];
3751                     if (fileObj.isFile()) {
3752                         filePath = fileObj.getPath();
3753                         if (makeUnixPaths) {
3754                             //Make sure we have a JS string.
3755                             filePath = String(filePath);
3756                             if (filePath.indexOf("/") === -1) {
3757                                 filePath = filePath.replace(/\\/g, "/");
3758                             }
3759                         }
3761                         ok = true;
3762                         if (regExpInclude) {
3763                             ok = filePath.match(regExpInclude);
3764                         }
3765                         if (ok && regExpExclude) {
3766                             ok = !filePath.match(regExpExclude);
3767                         }
3769                         if (ok && (!file.exclusionRegExp ||
3770                             !file.exclusionRegExp.test(fileObj.getName()))) {
3771                             files.push(filePath);
3772                         }
3773                     } else if (fileObj.isDirectory() &&
3774                               (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.getName()))) {
3775                         dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true);
3776                         files.push.apply(files, dirFiles);
3777                     }
3778                 }
3779             }
3781             return files; //Array
3782         },
3784         copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
3785             //summary: copies files from srcDir to destDir using the regExpFilter to determine if the
3786             //file should be copied. Returns a list file name strings of the destinations that were copied.
3787             regExpFilter = regExpFilter || /\w/;
3789             var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true),
3790             copiedFiles = [], i, srcFileName, destFileName;
3792             for (i = 0; i < fileNames.length; i++) {
3793                 srcFileName = fileNames[i];
3794                 destFileName = srcFileName.replace(srcDir, destDir);
3796                 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) {
3797                     copiedFiles.push(destFileName);
3798                 }
3799             }
3801             return copiedFiles.length ? copiedFiles : null; //Array or null
3802         },
3804         copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
3805             //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
3806             //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
3807             var destFile = new java.io.File(destFileName), srcFile, parentDir,
3808             srcChannel, destChannel;
3810             //logger.trace("Src filename: " + srcFileName);
3811             //logger.trace("Dest filename: " + destFileName);
3813             //If onlyCopyNew is true, then compare dates and only copy if the src is newer
3814             //than dest.
3815             if (onlyCopyNew) {
3816                 srcFile = new java.io.File(srcFileName);
3817                 if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) {
3818                     return false; //Boolean
3819                 }
3820             }
3822             //Make sure destination dir exists.
3823             parentDir = destFile.getParentFile();
3824             if (!parentDir.exists()) {
3825                 if (!parentDir.mkdirs()) {
3826                     throw "Could not create directory: " + parentDir.getCanonicalPath();
3827                 }
3828             }
3830             //Java's version of copy file.
3831             srcChannel = new java.io.FileInputStream(srcFileName).getChannel();
3832             destChannel = new java.io.FileOutputStream(destFileName).getChannel();
3833             destChannel.transferFrom(srcChannel, 0, srcChannel.size());
3834             srcChannel.close();
3835             destChannel.close();
3837             return true; //Boolean
3838         },
3840         /**
3841          * Renames a file. May fail if "to" already exists or is on another drive.
3842          */
3843         renameFile: function (from, to) {
3844             return (new java.io.File(from)).renameTo((new java.io.File(to)));
3845         },
3847         readFile: function (/*String*/path, /*String?*/encoding) {
3848             //A file read function that can deal with BOMs
3849             encoding = encoding || "utf-8";
3850             var fileObj = new java.io.File(path),
3851                     input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(fileObj), encoding)),
3852                     stringBuffer, line;
3853             try {
3854                 stringBuffer = new java.lang.StringBuffer();
3855                 line = input.readLine();
3857                 // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
3858                 // http://www.unicode.org/faq/utf_bom.html
3860                 // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
3861                 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
3862                 if (line && line.length() && line.charAt(0) === 0xfeff) {
3863                     // Eat the BOM, since we've already found the encoding on this file,
3864                     // and we plan to concatenating this buffer with others; the BOM should
3865                     // only appear at the top of a file.
3866                     line = line.substring(1);
3867                 }
3868                 while (line !== null) {
3869                     stringBuffer.append(line);
3870                     stringBuffer.append(file.lineSeparator);
3871                     line = input.readLine();
3872                 }
3873                 //Make sure we return a JavaScript string and not a Java string.
3874                 return String(stringBuffer.toString()); //String
3875             } finally {
3876                 input.close();
3877             }
3878         },
3880         readFileAsync: function (path, encoding) {
3881             var d = prim();
3882             try {
3883                 d.resolve(file.readFile(path, encoding));
3884             } catch (e) {
3885                 d.reject(e);
3886             }
3887             return d.promise;
3888         },
3890         saveUtf8File: function (/*String*/fileName, /*String*/fileContents) {
3891             //summary: saves a file using UTF-8 encoding.
3892             file.saveFile(fileName, fileContents, "utf-8");
3893         },
3895         saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
3896             //summary: saves a file.
3897             var outFile = new java.io.File(fileName), outWriter, parentDir, os;
3899             parentDir = outFile.getAbsoluteFile().getParentFile();
3900             if (!parentDir.exists()) {
3901                 if (!parentDir.mkdirs()) {
3902                     throw "Could not create directory: " + parentDir.getAbsolutePath();
3903                 }
3904             }
3906             if (encoding) {
3907                 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding);
3908             } else {
3909                 outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
3910             }
3912             os = new java.io.BufferedWriter(outWriter);
3913             try {
3914                 os.write(fileContents);
3915             } finally {
3916                 os.close();
3917             }
3918         },
3920         deleteFile: function (/*String*/fileName) {
3921             //summary: deletes a file or directory if it exists.
3922             var fileObj = new java.io.File(fileName), files, i;
3923             if (fileObj.exists()) {
3924                 if (fileObj.isDirectory()) {
3925                     files = fileObj.listFiles();
3926                     for (i = 0; i < files.length; i++) {
3927                         this.deleteFile(files[i]);
3928                     }
3929                 }
3930                 fileObj["delete"]();
3931             }
3932         },
3934         /**
3935          * Deletes any empty directories under the given directory.
3936          * The startDirIsJavaObject is private to this implementation's
3937          * recursion needs.
3938          */
3939         deleteEmptyDirs: function (startDir, startDirIsJavaObject) {
3940             var topDir = startDir,
3941                 dirFileArray, i, fileObj;
3943             if (!startDirIsJavaObject) {
3944                 topDir = new java.io.File(startDir);
3945             }
3947             if (topDir.exists()) {
3948                 dirFileArray = topDir.listFiles();
3949                 for (i = 0; i < dirFileArray.length; i++) {
3950                     fileObj = dirFileArray[i];
3951                     if (fileObj.isDirectory()) {
3952                         file.deleteEmptyDirs(fileObj, true);
3953                     }
3954                 }
3956                 //If the directory is empty now, delete it.
3957                 if (topDir.listFiles().length === 0) {
3958                     file.deleteFile(String(topDir.getPath()));
3959                 }
3960             }
3961         }
3962     };
3964     return file;
3969 if(env === 'xpconnect') {
3971  * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved.
3972  * Available via the MIT or new BSD license.
3973  * see: http://github.com/jrburke/requirejs for details
3974  */
3975 //Helper functions to deal with file I/O.
3977 /*jslint plusplus: false */
3978 /*global define, Components, xpcUtil */
3980 define('xpconnect/file', ['prim'], function (prim) {
3981     var file,
3982         Cc = Components.classes,
3983         Ci = Components.interfaces,
3984         //Depends on xpcUtil which is set up in x.js
3985         xpfile = xpcUtil.xpfile;
3987     function mkFullDir(dirObj) {
3988         //1 is DIRECTORY_TYPE, 511 is 0777 permissions
3989         if (!dirObj.exists()) {
3990             dirObj.create(1, 511);
3991         }
3992     }
3994     file = {
3995         backSlashRegExp: /\\/g,
3997         exclusionRegExp: /^\./,
3999         getLineSeparator: function () {
4000             return file.lineSeparator;
4001         },
4003         lineSeparator: ('@mozilla.org/windows-registry-key;1' in Cc) ?
4004                         '\r\n' : '\n',
4006         exists: function (fileName) {
4007             return xpfile(fileName).exists();
4008         },
4010         parent: function (fileName) {
4011             return xpfile(fileName).parent;
4012         },
4014         normalize: function (fileName) {
4015             return file.absPath(fileName);
4016         },
4018         isFile: function (path) {
4019             return xpfile(path).isFile();
4020         },
4022         isDirectory: function (path) {
4023             return xpfile(path).isDirectory();
4024         },
4026         /**
4027          * Gets the absolute file path as a string, normalized
4028          * to using front slashes for path separators.
4029          * @param {java.io.File||String} file
4030          */
4031         absPath: function (fileObj) {
4032             if (typeof fileObj === "string") {
4033                 fileObj = xpfile(fileObj);
4034             }
4035             return fileObj.path;
4036         },
4038         getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsObject) {
4039             //summary: Recurses startDir and finds matches to the files that match regExpFilters.include
4040             //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
4041             //and it will be treated as the "include" case.
4042             //Ignores files/directories that start with a period (.) unless exclusionRegExp
4043             //is set to another value.
4044             var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
4045                 fileObj, filePath, ok, dirFiles;
4047             topDir = startDir;
4048             if (!startDirIsObject) {
4049                 topDir = xpfile(startDir);
4050             }
4052             regExpInclude = regExpFilters.include || regExpFilters;
4053             regExpExclude = regExpFilters.exclude || null;
4055             if (topDir.exists()) {
4056                 dirFileArray = topDir.directoryEntries;
4057                 while (dirFileArray.hasMoreElements()) {
4058                     fileObj = dirFileArray.getNext().QueryInterface(Ci.nsILocalFile);
4059                     if (fileObj.isFile()) {
4060                         filePath = fileObj.path;
4061                         if (makeUnixPaths) {
4062                             if (filePath.indexOf("/") === -1) {
4063                                 filePath = filePath.replace(/\\/g, "/");
4064                             }
4065                         }
4067                         ok = true;
4068                         if (regExpInclude) {
4069                             ok = filePath.match(regExpInclude);
4070                         }
4071                         if (ok && regExpExclude) {
4072                             ok = !filePath.match(regExpExclude);
4073                         }
4075                         if (ok && (!file.exclusionRegExp ||
4076                             !file.exclusionRegExp.test(fileObj.leafName))) {
4077                             files.push(filePath);
4078                         }
4079                     } else if (fileObj.isDirectory() &&
4080                               (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.leafName))) {
4081                         dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true);
4082                         files.push.apply(files, dirFiles);
4083                     }
4084                 }
4085             }
4087             return files; //Array
4088         },
4090         copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
4091             //summary: copies files from srcDir to destDir using the regExpFilter to determine if the
4092             //file should be copied. Returns a list file name strings of the destinations that were copied.
4093             regExpFilter = regExpFilter || /\w/;
4095             var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true),
4096             copiedFiles = [], i, srcFileName, destFileName;
4098             for (i = 0; i < fileNames.length; i += 1) {
4099                 srcFileName = fileNames[i];
4100                 destFileName = srcFileName.replace(srcDir, destDir);
4102                 if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) {
4103                     copiedFiles.push(destFileName);
4104                 }
4105             }
4107             return copiedFiles.length ? copiedFiles : null; //Array or null
4108         },
4110         copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
4111             //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
4112             //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
4113             var destFile = xpfile(destFileName),
4114             srcFile = xpfile(srcFileName);
4116             //logger.trace("Src filename: " + srcFileName);
4117             //logger.trace("Dest filename: " + destFileName);
4119             //If onlyCopyNew is true, then compare dates and only copy if the src is newer
4120             //than dest.
4121             if (onlyCopyNew) {
4122                 if (destFile.exists() && destFile.lastModifiedTime >= srcFile.lastModifiedTime) {
4123                     return false; //Boolean
4124                 }
4125             }
4127             srcFile.copyTo(destFile.parent, destFile.leafName);
4129             return true; //Boolean
4130         },
4132         /**
4133          * Renames a file. May fail if "to" already exists or is on another drive.
4134          */
4135         renameFile: function (from, to) {
4136             var toFile = xpfile(to);
4137             return xpfile(from).moveTo(toFile.parent, toFile.leafName);
4138         },
4140         readFile: xpcUtil.readFile,
4142         readFileAsync: function (path, encoding) {
4143             var d = prim();
4144             try {
4145                 d.resolve(file.readFile(path, encoding));
4146             } catch (e) {
4147                 d.reject(e);
4148             }
4149             return d.promise;
4150         },
4152         saveUtf8File: function (/*String*/fileName, /*String*/fileContents) {
4153             //summary: saves a file using UTF-8 encoding.
4154             file.saveFile(fileName, fileContents, "utf-8");
4155         },
4157         saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
4158             var outStream, convertStream,
4159                 fileObj = xpfile(fileName);
4161             mkFullDir(fileObj.parent);
4163             try {
4164                 outStream = Cc['@mozilla.org/network/file-output-stream;1']
4165                              .createInstance(Ci.nsIFileOutputStream);
4166                 //438 is decimal for 0777
4167                 outStream.init(fileObj, 0x02 | 0x08 | 0x20, 511, 0);
4169                 convertStream = Cc['@mozilla.org/intl/converter-output-stream;1']
4170                                   .createInstance(Ci.nsIConverterOutputStream);
4172                 convertStream.init(outStream, encoding, 0, 0);
4173                 convertStream.writeString(fileContents);
4174             } catch (e) {
4175                 throw new Error((fileObj && fileObj.path || '') + ': ' + e);
4176             } finally {
4177                 if (convertStream) {
4178                     convertStream.close();
4179                 }
4180                 if (outStream) {
4181                     outStream.close();
4182                 }
4183             }
4184         },
4186         deleteFile: function (/*String*/fileName) {
4187             //summary: deletes a file or directory if it exists.
4188             var fileObj = xpfile(fileName);
4189             if (fileObj.exists()) {
4190                 fileObj.remove(true);
4191             }
4192         },
4194         /**
4195          * Deletes any empty directories under the given directory.
4196          * The startDirIsJavaObject is private to this implementation's
4197          * recursion needs.
4198          */
4199         deleteEmptyDirs: function (startDir, startDirIsObject) {
4200             var topDir = startDir,
4201                 dirFileArray, fileObj;
4203             if (!startDirIsObject) {
4204                 topDir = xpfile(startDir);
4205             }
4207             if (topDir.exists()) {
4208                 dirFileArray = topDir.directoryEntries;
4209                 while (dirFileArray.hasMoreElements()) {
4210                     fileObj = dirFileArray.getNext().QueryInterface(Ci.nsILocalFile);
4212                     if (fileObj.isDirectory()) {
4213                         file.deleteEmptyDirs(fileObj, true);
4214                     }
4215                 }
4217                 //If the directory is empty now, delete it.
4218                 dirFileArray = topDir.directoryEntries;
4219                 if (!dirFileArray.hasMoreElements()) {
4220                     file.deleteFile(topDir.path);
4221                 }
4222             }
4223         }
4224     };
4226     return file;
4231 if(env === 'browser') {
4232 /*global process */
4233 define('browser/quit', function () {
4234     'use strict';
4235     return function (code) {
4236     };
4240 if(env === 'node') {
4241 /*global process */
4242 define('node/quit', function () {
4243     'use strict';
4244     return function (code) {
4245         var draining = 0;
4246         var exit = function () {
4247             if (draining === 0) {
4248                 process.exit(code);
4249             } else {
4250                 draining -= 1;
4251             }
4252         };
4253         if (process.stdout.bufferSize) {
4254             draining += 1;
4255             process.stdout.once('drain', exit);
4256         }
4257         if (process.stderr.bufferSize) {
4258             draining += 1;
4259             process.stderr.once('drain', exit);
4260         }
4261         exit();
4262     };
4267 if(env === 'rhino') {
4268 /*global quit */
4269 define('rhino/quit', function () {
4270     'use strict';
4271     return function (code) {
4272         return quit(code);
4273     };
4278 if(env === 'xpconnect') {
4279 /*global quit */
4280 define('xpconnect/quit', function () {
4281     'use strict';
4282     return function (code) {
4283         return quit(code);
4284     };
4289 if(env === 'browser') {
4291  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
4292  * Available via the MIT or new BSD license.
4293  * see: http://github.com/jrburke/requirejs for details
4294  */
4296 /*jslint strict: false */
4297 /*global define: false, console: false */
4299 define('browser/print', function () {
4300     function print(msg) {
4301         console.log(msg);
4302     }
4304     return print;
4309 if(env === 'node') {
4311  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
4312  * Available via the MIT or new BSD license.
4313  * see: http://github.com/jrburke/requirejs for details
4314  */
4316 /*jslint strict: false */
4317 /*global define: false, console: false */
4319 define('node/print', function () {
4320     function print(msg) {
4321         console.log(msg);
4322     }
4324     return print;
4329 if(env === 'rhino') {
4331  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
4332  * Available via the MIT or new BSD license.
4333  * see: http://github.com/jrburke/requirejs for details
4334  */
4336 /*jslint strict: false */
4337 /*global define: false, print: false */
4339 define('rhino/print', function () {
4340     return print;
4345 if(env === 'xpconnect') {
4347  * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved.
4348  * Available via the MIT or new BSD license.
4349  * see: http://github.com/jrburke/requirejs for details
4350  */
4352 /*jslint strict: false */
4353 /*global define: false, print: false */
4355 define('xpconnect/print', function () {
4356     return print;
4361  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
4362  * Available via the MIT or new BSD license.
4363  * see: http://github.com/jrburke/requirejs for details
4364  */
4366 /*jslint nomen: false, strict: false */
4367 /*global define: false */
4369 define('logger', ['env!env/print'], function (print) {
4370     var logger = {
4371         TRACE: 0,
4372         INFO: 1,
4373         WARN: 2,
4374         ERROR: 3,
4375         SILENT: 4,
4376         level: 0,
4377         logPrefix: "",
4379         logLevel: function( level ) {
4380             this.level = level;
4381         },
4383         trace: function (message) {
4384             if (this.level <= this.TRACE) {
4385                 this._print(message);
4386             }
4387         },
4389         info: function (message) {
4390             if (this.level <= this.INFO) {
4391                 this._print(message);
4392             }
4393         },
4395         warn: function (message) {
4396             if (this.level <= this.WARN) {
4397                 this._print(message);
4398             }
4399         },
4401         error: function (message) {
4402             if (this.level <= this.ERROR) {
4403                 this._print(message);
4404             }
4405         },
4407         _print: function (message) {
4408             this._sysPrint((this.logPrefix ? (this.logPrefix + " ") : "") + message);
4409         },
4411         _sysPrint: function (message) {
4412             print(message);
4413         }
4414     };
4416     return logger;
4418 //Just a blank file to use when building the optimizer with the optimizer,
4419 //so that the build does not attempt to inline some env modules,
4420 //like Node's fs and path.
4423   Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
4424   Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
4425   Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
4426   Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
4427   Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
4428   Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
4429   Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
4431   Redistribution and use in source and binary forms, with or without
4432   modification, are permitted provided that the following conditions are met:
4434     * Redistributions of source code must retain the above copyright
4435       notice, this list of conditions and the following disclaimer.
4436     * Redistributions in binary form must reproduce the above copyright
4437       notice, this list of conditions and the following disclaimer in the
4438       documentation and/or other materials provided with the distribution.
4440   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4441   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4442   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4443   ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
4444   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
4445   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4446   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
4447   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4448   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
4449   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4452 /*jslint bitwise:true plusplus:true */
4453 /*global esprima:true, define:true, exports:true, window: true,
4454 throwError: true, createLiteral: true, generateStatement: true,
4455 parseAssignmentExpression: true, parseBlock: true, parseExpression: true,
4456 parseFunctionDeclaration: true, parseFunctionExpression: true,
4457 parseFunctionSourceElements: true, parseVariableIdentifier: true,
4458 parseLeftHandSideExpression: true,
4459 parseStatement: true, parseSourceElement: true */
4461 (function (root, factory) {
4462     'use strict';
4464     // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
4465     // Rhino, and plain browser loading.
4466     if (typeof define === 'function' && define.amd) {
4467         define('esprima', ['exports'], factory);
4468     } else if (typeof exports !== 'undefined') {
4469         factory(exports);
4470     } else {
4471         factory((root.esprima = {}));
4472     }
4473 }(this, function (exports) {
4474     'use strict';
4476     var Token,
4477         TokenName,
4478         Syntax,
4479         PropertyKind,
4480         Messages,
4481         Regex,
4482         source,
4483         strict,
4484         index,
4485         lineNumber,
4486         lineStart,
4487         length,
4488         buffer,
4489         state,
4490         extra;
4492     Token = {
4493         BooleanLiteral: 1,
4494         EOF: 2,
4495         Identifier: 3,
4496         Keyword: 4,
4497         NullLiteral: 5,
4498         NumericLiteral: 6,
4499         Punctuator: 7,
4500         StringLiteral: 8
4501     };
4503     TokenName = {};
4504     TokenName[Token.BooleanLiteral] = 'Boolean';
4505     TokenName[Token.EOF] = '<end>';
4506     TokenName[Token.Identifier] = 'Identifier';
4507     TokenName[Token.Keyword] = 'Keyword';
4508     TokenName[Token.NullLiteral] = 'Null';
4509     TokenName[Token.NumericLiteral] = 'Numeric';
4510     TokenName[Token.Punctuator] = 'Punctuator';
4511     TokenName[Token.StringLiteral] = 'String';
4513     Syntax = {
4514         AssignmentExpression: 'AssignmentExpression',
4515         ArrayExpression: 'ArrayExpression',
4516         BlockStatement: 'BlockStatement',
4517         BinaryExpression: 'BinaryExpression',
4518         BreakStatement: 'BreakStatement',
4519         CallExpression: 'CallExpression',
4520         CatchClause: 'CatchClause',
4521         ConditionalExpression: 'ConditionalExpression',
4522         ContinueStatement: 'ContinueStatement',
4523         DoWhileStatement: 'DoWhileStatement',
4524         DebuggerStatement: 'DebuggerStatement',
4525         EmptyStatement: 'EmptyStatement',
4526         ExpressionStatement: 'ExpressionStatement',
4527         ForStatement: 'ForStatement',
4528         ForInStatement: 'ForInStatement',
4529         FunctionDeclaration: 'FunctionDeclaration',
4530         FunctionExpression: 'FunctionExpression',
4531         Identifier: 'Identifier',
4532         IfStatement: 'IfStatement',
4533         Literal: 'Literal',
4534         LabeledStatement: 'LabeledStatement',
4535         LogicalExpression: 'LogicalExpression',
4536         MemberExpression: 'MemberExpression',
4537         NewExpression: 'NewExpression',
4538         ObjectExpression: 'ObjectExpression',
4539         Program: 'Program',
4540         Property: 'Property',
4541         ReturnStatement: 'ReturnStatement',
4542         SequenceExpression: 'SequenceExpression',
4543         SwitchStatement: 'SwitchStatement',
4544         SwitchCase: 'SwitchCase',
4545         ThisExpression: 'ThisExpression',
4546         ThrowStatement: 'ThrowStatement',
4547         TryStatement: 'TryStatement',
4548         UnaryExpression: 'UnaryExpression',
4549         UpdateExpression: 'UpdateExpression',
4550         VariableDeclaration: 'VariableDeclaration',
4551         VariableDeclarator: 'VariableDeclarator',
4552         WhileStatement: 'WhileStatement',
4553         WithStatement: 'WithStatement'
4554     };
4556     PropertyKind = {
4557         Data: 1,
4558         Get: 2,
4559         Set: 4
4560     };
4562     // Error messages should be identical to V8.
4563     Messages = {
4564         UnexpectedToken:  'Unexpected token %0',
4565         UnexpectedNumber:  'Unexpected number',
4566         UnexpectedString:  'Unexpected string',
4567         UnexpectedIdentifier:  'Unexpected identifier',
4568         UnexpectedReserved:  'Unexpected reserved word',
4569         UnexpectedEOS:  'Unexpected end of input',
4570         NewlineAfterThrow:  'Illegal newline after throw',
4571         InvalidRegExp: 'Invalid regular expression',
4572         UnterminatedRegExp:  'Invalid regular expression: missing /',
4573         InvalidLHSInAssignment:  'Invalid left-hand side in assignment',
4574         InvalidLHSInForIn:  'Invalid left-hand side in for-in',
4575         MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
4576         NoCatchOrFinally:  'Missing catch or finally after try',
4577         UnknownLabel: 'Undefined label \'%0\'',
4578         Redeclaration: '%0 \'%1\' has already been declared',
4579         IllegalContinue: 'Illegal continue statement',
4580         IllegalBreak: 'Illegal break statement',
4581         IllegalReturn: 'Illegal return statement',
4582         StrictModeWith:  'Strict mode code may not include a with statement',
4583         StrictCatchVariable:  'Catch variable may not be eval or arguments in strict mode',
4584         StrictVarName:  'Variable name may not be eval or arguments in strict mode',
4585         StrictParamName:  'Parameter name eval or arguments is not allowed in strict mode',
4586         StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
4587         StrictFunctionName:  'Function name may not be eval or arguments in strict mode',
4588         StrictOctalLiteral:  'Octal literals are not allowed in strict mode.',
4589         StrictDelete:  'Delete of an unqualified identifier in strict mode.',
4590         StrictDuplicateProperty:  'Duplicate data property in object literal not allowed in strict mode',
4591         AccessorDataProperty:  'Object literal may not have data and accessor property with the same name',
4592         AccessorGetSet:  'Object literal may not have multiple get/set accessors with the same name',
4593         StrictLHSAssignment:  'Assignment to eval or arguments is not allowed in strict mode',
4594         StrictLHSPostfix:  'Postfix increment/decrement may not have eval or arguments operand in strict mode',
4595         StrictLHSPrefix:  'Prefix increment/decrement may not have eval or arguments operand in strict mode',
4596         StrictReservedWord:  'Use of future reserved word in strict mode'
4597     };
4599     // See also tools/generate-unicode-regex.py.
4600     Regex = {
4601         NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\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\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\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-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\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-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\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-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\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]'),
4602         NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\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\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\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\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]')
4603     };
4605     // Ensure the condition is true, otherwise throw an error.
4606     // This is only to have a better contract semantic, i.e. another safety net
4607     // to catch a logic error. The condition shall be fulfilled in normal case.
4608     // Do NOT use this to enforce a certain condition on any user input.
4610     function assert(condition, message) {
4611         if (!condition) {
4612             throw new Error('ASSERT: ' + message);
4613         }
4614     }
4616     function sliceSource(from, to) {
4617         return source.slice(from, to);
4618     }
4620     if (typeof 'esprima'[0] === 'undefined') {
4621         sliceSource = function sliceArraySource(from, to) {
4622             return source.slice(from, to).join('');
4623         };
4624     }
4626     function isDecimalDigit(ch) {
4627         return '0123456789'.indexOf(ch) >= 0;
4628     }
4630     function isHexDigit(ch) {
4631         return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
4632     }
4634     function isOctalDigit(ch) {
4635         return '01234567'.indexOf(ch) >= 0;
4636     }
4639     // 7.2 White Space
4641     function isWhiteSpace(ch) {
4642         return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') ||
4643             (ch === '\u000C') || (ch === '\u00A0') ||
4644             (ch.charCodeAt(0) >= 0x1680 &&
4645              '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0);
4646     }
4648     // 7.3 Line Terminators
4650     function isLineTerminator(ch) {
4651         return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029');
4652     }
4654     // 7.6 Identifier Names and Identifiers
4656     function isIdentifierStart(ch) {
4657         return (ch === '$') || (ch === '_') || (ch === '\\') ||
4658             (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
4659             ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch));
4660     }
4662     function isIdentifierPart(ch) {
4663         return (ch === '$') || (ch === '_') || (ch === '\\') ||
4664             (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
4665             ((ch >= '0') && (ch <= '9')) ||
4666             ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
4667     }
4669     // 7.6.1.2 Future Reserved Words
4671     function isFutureReservedWord(id) {
4672         switch (id) {
4674         // Future reserved words.
4675         case 'class':
4676         case 'enum':
4677         case 'export':
4678         case 'extends':
4679         case 'import':
4680         case 'super':
4681             return true;
4682         }
4684         return false;
4685     }
4687     function isStrictModeReservedWord(id) {
4688         switch (id) {
4690         // Strict Mode reserved words.
4691         case 'implements':
4692         case 'interface':
4693         case 'package':
4694         case 'private':
4695         case 'protected':
4696         case 'public':
4697         case 'static':
4698         case 'yield':
4699         case 'let':
4700             return true;
4701         }
4703         return false;
4704     }
4706     function isRestrictedWord(id) {
4707         return id === 'eval' || id === 'arguments';
4708     }
4710     // 7.6.1.1 Keywords
4712     function isKeyword(id) {
4713         var keyword = false;
4714         switch (id.length) {
4715         case 2:
4716             keyword = (id === 'if') || (id === 'in') || (id === 'do');
4717             break;
4718         case 3:
4719             keyword = (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try');
4720             break;
4721         case 4:
4722             keyword = (id === 'this') || (id === 'else') || (id === 'case') || (id === 'void') || (id === 'with');
4723             break;
4724         case 5:
4725             keyword = (id === 'while') || (id === 'break') || (id === 'catch') || (id === 'throw');
4726             break;
4727         case 6:
4728             keyword = (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch');
4729             break;
4730         case 7:
4731             keyword = (id === 'default') || (id === 'finally');
4732             break;
4733         case 8:
4734             keyword = (id === 'function') || (id === 'continue') || (id === 'debugger');
4735             break;
4736         case 10:
4737             keyword = (id === 'instanceof');
4738             break;
4739         }
4741         if (keyword) {
4742             return true;
4743         }
4745         switch (id) {
4746         // Future reserved words.
4747         // 'const' is specialized as Keyword in V8.
4748         case 'const':
4749             return true;
4751         // For compatiblity to SpiderMonkey and ES.next
4752         case 'yield':
4753         case 'let':
4754             return true;
4755         }
4757         if (strict && isStrictModeReservedWord(id)) {
4758             return true;
4759         }
4761         return isFutureReservedWord(id);
4762     }
4764     // 7.4 Comments
4766     function skipComment() {
4767         var ch, blockComment, lineComment;
4769         blockComment = false;
4770         lineComment = false;
4772         while (index < length) {
4773             ch = source[index];
4775             if (lineComment) {
4776                 ch = source[index++];
4777                 if (isLineTerminator(ch)) {
4778                     lineComment = false;
4779                     if (ch === '\r' && source[index] === '\n') {
4780                         ++index;
4781                     }
4782                     ++lineNumber;
4783                     lineStart = index;
4784                 }
4785             } else if (blockComment) {
4786                 if (isLineTerminator(ch)) {
4787                     if (ch === '\r' && source[index + 1] === '\n') {
4788                         ++index;
4789                     }
4790                     ++lineNumber;
4791                     ++index;
4792                     lineStart = index;
4793                     if (index >= length) {
4794                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
4795                     }
4796                 } else {
4797                     ch = source[index++];
4798                     if (index >= length) {
4799                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
4800                     }
4801                     if (ch === '*') {
4802                         ch = source[index];
4803                         if (ch === '/') {
4804                             ++index;
4805                             blockComment = false;
4806                         }
4807                     }
4808                 }
4809             } else if (ch === '/') {
4810                 ch = source[index + 1];
4811                 if (ch === '/') {
4812                     index += 2;
4813                     lineComment = true;
4814                 } else if (ch === '*') {
4815                     index += 2;
4816                     blockComment = true;
4817                     if (index >= length) {
4818                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
4819                     }
4820                 } else {
4821                     break;
4822                 }
4823             } else if (isWhiteSpace(ch)) {
4824                 ++index;
4825             } else if (isLineTerminator(ch)) {
4826                 ++index;
4827                 if (ch ===  '\r' && source[index] === '\n') {
4828                     ++index;
4829                 }
4830                 ++lineNumber;
4831                 lineStart = index;
4832             } else {
4833                 break;
4834             }
4835         }
4836     }
4838     function scanHexEscape(prefix) {
4839         var i, len, ch, code = 0;
4841         len = (prefix === 'u') ? 4 : 2;
4842         for (i = 0; i < len; ++i) {
4843             if (index < length && isHexDigit(source[index])) {
4844                 ch = source[index++];
4845                 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
4846             } else {
4847                 return '';
4848             }
4849         }
4850         return String.fromCharCode(code);
4851     }
4853     function scanIdentifier() {
4854         var ch, start, id, restore;
4856         ch = source[index];
4857         if (!isIdentifierStart(ch)) {
4858             return;
4859         }
4861         start = index;
4862         if (ch === '\\') {
4863             ++index;
4864             if (source[index] !== 'u') {
4865                 return;
4866             }
4867             ++index;
4868             restore = index;
4869             ch = scanHexEscape('u');
4870             if (ch) {
4871                 if (ch === '\\' || !isIdentifierStart(ch)) {
4872                     return;
4873                 }
4874                 id = ch;
4875             } else {
4876                 index = restore;
4877                 id = 'u';
4878             }
4879         } else {
4880             id = source[index++];
4881         }
4883         while (index < length) {
4884             ch = source[index];
4885             if (!isIdentifierPart(ch)) {
4886                 break;
4887             }
4888             if (ch === '\\') {
4889                 ++index;
4890                 if (source[index] !== 'u') {
4891                     return;
4892                 }
4893                 ++index;
4894                 restore = index;
4895                 ch = scanHexEscape('u');
4896                 if (ch) {
4897                     if (ch === '\\' || !isIdentifierPart(ch)) {
4898                         return;
4899                     }
4900                     id += ch;
4901                 } else {
4902                     index = restore;
4903                     id += 'u';
4904                 }
4905             } else {
4906                 id += source[index++];
4907             }
4908         }
4910         // There is no keyword or literal with only one character.
4911         // Thus, it must be an identifier.
4912         if (id.length === 1) {
4913             return {
4914                 type: Token.Identifier,
4915                 value: id,
4916                 lineNumber: lineNumber,
4917                 lineStart: lineStart,
4918                 range: [start, index]
4919             };
4920         }
4922         if (isKeyword(id)) {
4923             return {
4924                 type: Token.Keyword,
4925                 value: id,
4926                 lineNumber: lineNumber,
4927                 lineStart: lineStart,
4928                 range: [start, index]
4929             };
4930         }
4932         // 7.8.1 Null Literals
4934         if (id === 'null') {
4935             return {
4936                 type: Token.NullLiteral,
4937                 value: id,
4938                 lineNumber: lineNumber,
4939                 lineStart: lineStart,
4940                 range: [start, index]
4941             };
4942         }
4944         // 7.8.2 Boolean Literals
4946         if (id === 'true' || id === 'false') {
4947             return {
4948                 type: Token.BooleanLiteral,
4949                 value: id,
4950                 lineNumber: lineNumber,
4951                 lineStart: lineStart,
4952                 range: [start, index]
4953             };
4954         }
4956         return {
4957             type: Token.Identifier,
4958             value: id,
4959             lineNumber: lineNumber,
4960             lineStart: lineStart,
4961             range: [start, index]
4962         };
4963     }
4965     // 7.7 Punctuators
4967     function scanPunctuator() {
4968         var start = index,
4969             ch1 = source[index],
4970             ch2,
4971             ch3,
4972             ch4;
4974         // Check for most common single-character punctuators.
4976         if (ch1 === ';' || ch1 === '{' || ch1 === '}') {
4977             ++index;
4978             return {
4979                 type: Token.Punctuator,
4980                 value: ch1,
4981                 lineNumber: lineNumber,
4982                 lineStart: lineStart,
4983                 range: [start, index]
4984             };
4985         }
4987         if (ch1 === ',' || ch1 === '(' || ch1 === ')') {
4988             ++index;
4989             return {
4990                 type: Token.Punctuator,
4991                 value: ch1,
4992                 lineNumber: lineNumber,
4993                 lineStart: lineStart,
4994                 range: [start, index]
4995             };
4996         }
4998         // Dot (.) can also start a floating-point number, hence the need
4999         // to check the next character.
5001         ch2 = source[index + 1];
5002         if (ch1 === '.' && !isDecimalDigit(ch2)) {
5003             return {
5004                 type: Token.Punctuator,
5005                 value: source[index++],
5006                 lineNumber: lineNumber,
5007                 lineStart: lineStart,
5008                 range: [start, index]
5009             };
5010         }
5012         // Peek more characters.
5014         ch3 = source[index + 2];
5015         ch4 = source[index + 3];
5017         // 4-character punctuator: >>>=
5019         if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
5020             if (ch4 === '=') {
5021                 index += 4;
5022                 return {
5023                     type: Token.Punctuator,
5024                     value: '>>>=',
5025                     lineNumber: lineNumber,
5026                     lineStart: lineStart,
5027                     range: [start, index]
5028                 };
5029             }
5030         }
5032         // 3-character punctuators: === !== >>> <<= >>=
5034         if (ch1 === '=' && ch2 === '=' && ch3 === '=') {
5035             index += 3;
5036             return {
5037                 type: Token.Punctuator,
5038                 value: '===',
5039                 lineNumber: lineNumber,
5040                 lineStart: lineStart,
5041                 range: [start, index]
5042             };
5043         }
5045         if (ch1 === '!' && ch2 === '=' && ch3 === '=') {
5046             index += 3;
5047             return {
5048                 type: Token.Punctuator,
5049                 value: '!==',
5050                 lineNumber: lineNumber,
5051                 lineStart: lineStart,
5052                 range: [start, index]
5053             };
5054         }
5056         if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
5057             index += 3;
5058             return {
5059                 type: Token.Punctuator,
5060                 value: '>>>',
5061                 lineNumber: lineNumber,
5062                 lineStart: lineStart,
5063                 range: [start, index]
5064             };
5065         }
5067         if (ch1 === '<' && ch2 === '<' && ch3 === '=') {
5068             index += 3;
5069             return {
5070                 type: Token.Punctuator,
5071                 value: '<<=',
5072                 lineNumber: lineNumber,
5073                 lineStart: lineStart,
5074                 range: [start, index]
5075             };
5076         }
5078         if (ch1 === '>' && ch2 === '>' && ch3 === '=') {
5079             index += 3;
5080             return {
5081                 type: Token.Punctuator,
5082                 value: '>>=',
5083                 lineNumber: lineNumber,
5084                 lineStart: lineStart,
5085                 range: [start, index]
5086             };
5087         }
5089         // 2-character punctuators: <= >= == != ++ -- << >> && ||
5090         // += -= *= %= &= |= ^= /=
5092         if (ch2 === '=') {
5093             if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
5094                 index += 2;
5095                 return {
5096                     type: Token.Punctuator,
5097                     value: ch1 + ch2,
5098                     lineNumber: lineNumber,
5099                     lineStart: lineStart,
5100                     range: [start, index]
5101                 };
5102             }
5103         }
5105         if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) {
5106             if ('+-<>&|'.indexOf(ch2) >= 0) {
5107                 index += 2;
5108                 return {
5109                     type: Token.Punctuator,
5110                     value: ch1 + ch2,
5111                     lineNumber: lineNumber,
5112                     lineStart: lineStart,
5113                     range: [start, index]
5114                 };
5115             }
5116         }
5118         // The remaining 1-character punctuators.
5120         if ('[]<>+-*%&|^!~?:=/'.indexOf(ch1) >= 0) {
5121             return {
5122                 type: Token.Punctuator,
5123                 value: source[index++],
5124                 lineNumber: lineNumber,
5125                 lineStart: lineStart,
5126                 range: [start, index]
5127             };
5128         }
5129     }
5131     // 7.8.3 Numeric Literals
5133     function scanNumericLiteral() {
5134         var number, start, ch;
5136         ch = source[index];
5137         assert(isDecimalDigit(ch) || (ch === '.'),
5138             'Numeric literal must start with a decimal digit or a decimal point');
5140         start = index;
5141         number = '';
5142         if (ch !== '.') {
5143             number = source[index++];
5144             ch = source[index];
5146             // Hex number starts with '0x'.
5147             // Octal number starts with '0'.
5148             if (number === '0') {
5149                 if (ch === 'x' || ch === 'X') {
5150                     number += source[index++];
5151                     while (index < length) {
5152                         ch = source[index];
5153                         if (!isHexDigit(ch)) {
5154                             break;
5155                         }
5156                         number += source[index++];
5157                     }
5159                     if (number.length <= 2) {
5160                         // only 0x
5161                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5162                     }
5164                     if (index < length) {
5165                         ch = source[index];
5166                         if (isIdentifierStart(ch)) {
5167                             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5168                         }
5169                     }
5170                     return {
5171                         type: Token.NumericLiteral,
5172                         value: parseInt(number, 16),
5173                         lineNumber: lineNumber,
5174                         lineStart: lineStart,
5175                         range: [start, index]
5176                     };
5177                 } else if (isOctalDigit(ch)) {
5178                     number += source[index++];
5179                     while (index < length) {
5180                         ch = source[index];
5181                         if (!isOctalDigit(ch)) {
5182                             break;
5183                         }
5184                         number += source[index++];
5185                     }
5187                     if (index < length) {
5188                         ch = source[index];
5189                         if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
5190                             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5191                         }
5192                     }
5193                     return {
5194                         type: Token.NumericLiteral,
5195                         value: parseInt(number, 8),
5196                         octal: true,
5197                         lineNumber: lineNumber,
5198                         lineStart: lineStart,
5199                         range: [start, index]
5200                     };
5201                 }
5203                 // decimal number starts with '0' such as '09' is illegal.
5204                 if (isDecimalDigit(ch)) {
5205                     throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5206                 }
5207             }
5209             while (index < length) {
5210                 ch = source[index];
5211                 if (!isDecimalDigit(ch)) {
5212                     break;
5213                 }
5214                 number += source[index++];
5215             }
5216         }
5218         if (ch === '.') {
5219             number += source[index++];
5220             while (index < length) {
5221                 ch = source[index];
5222                 if (!isDecimalDigit(ch)) {
5223                     break;
5224                 }
5225                 number += source[index++];
5226             }
5227         }
5229         if (ch === 'e' || ch === 'E') {
5230             number += source[index++];
5232             ch = source[index];
5233             if (ch === '+' || ch === '-') {
5234                 number += source[index++];
5235             }
5237             ch = source[index];
5238             if (isDecimalDigit(ch)) {
5239                 number += source[index++];
5240                 while (index < length) {
5241                     ch = source[index];
5242                     if (!isDecimalDigit(ch)) {
5243                         break;
5244                     }
5245                     number += source[index++];
5246                 }
5247             } else {
5248                 ch = 'character ' + ch;
5249                 if (index >= length) {
5250                     ch = '<end>';
5251                 }
5252                 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5253             }
5254         }
5256         if (index < length) {
5257             ch = source[index];
5258             if (isIdentifierStart(ch)) {
5259                 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5260             }
5261         }
5263         return {
5264             type: Token.NumericLiteral,
5265             value: parseFloat(number),
5266             lineNumber: lineNumber,
5267             lineStart: lineStart,
5268             range: [start, index]
5269         };
5270     }
5272     // 7.8.4 String Literals
5274     function scanStringLiteral() {
5275         var str = '', quote, start, ch, code, unescaped, restore, octal = false;
5277         quote = source[index];
5278         assert((quote === '\'' || quote === '"'),
5279             'String literal must starts with a quote');
5281         start = index;
5282         ++index;
5284         while (index < length) {
5285             ch = source[index++];
5287             if (ch === quote) {
5288                 quote = '';
5289                 break;
5290             } else if (ch === '\\') {
5291                 ch = source[index++];
5292                 if (!isLineTerminator(ch)) {
5293                     switch (ch) {
5294                     case 'n':
5295                         str += '\n';
5296                         break;
5297                     case 'r':
5298                         str += '\r';
5299                         break;
5300                     case 't':
5301                         str += '\t';
5302                         break;
5303                     case 'u':
5304                     case 'x':
5305                         restore = index;
5306                         unescaped = scanHexEscape(ch);
5307                         if (unescaped) {
5308                             str += unescaped;
5309                         } else {
5310                             index = restore;
5311                             str += ch;
5312                         }
5313                         break;
5314                     case 'b':
5315                         str += '\b';
5316                         break;
5317                     case 'f':
5318                         str += '\f';
5319                         break;
5320                     case 'v':
5321                         str += '\x0B';
5322                         break;
5324                     default:
5325                         if (isOctalDigit(ch)) {
5326                             code = '01234567'.indexOf(ch);
5328                             // \0 is not octal escape sequence
5329                             if (code !== 0) {
5330                                 octal = true;
5331                             }
5333                             if (index < length && isOctalDigit(source[index])) {
5334                                 octal = true;
5335                                 code = code * 8 + '01234567'.indexOf(source[index++]);
5337                                 // 3 digits are only allowed when string starts
5338                                 // with 0, 1, 2, 3
5339                                 if ('0123'.indexOf(ch) >= 0 &&
5340                                         index < length &&
5341                                         isOctalDigit(source[index])) {
5342                                     code = code * 8 + '01234567'.indexOf(source[index++]);
5343                                 }
5344                             }
5345                             str += String.fromCharCode(code);
5346                         } else {
5347                             str += ch;
5348                         }
5349                         break;
5350                     }
5351                 } else {
5352                     ++lineNumber;
5353                     if (ch ===  '\r' && source[index] === '\n') {
5354                         ++index;
5355                     }
5356                 }
5357             } else if (isLineTerminator(ch)) {
5358                 break;
5359             } else {
5360                 str += ch;
5361             }
5362         }
5364         if (quote !== '') {
5365             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5366         }
5368         return {
5369             type: Token.StringLiteral,
5370             value: str,
5371             octal: octal,
5372             lineNumber: lineNumber,
5373             lineStart: lineStart,
5374             range: [start, index]
5375         };
5376     }
5378     function scanRegExp() {
5379         var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false;
5381         buffer = null;
5382         skipComment();
5384         start = index;
5385         ch = source[index];
5386         assert(ch === '/', 'Regular expression literal must start with a slash');
5387         str = source[index++];
5389         while (index < length) {
5390             ch = source[index++];
5391             str += ch;
5392             if (classMarker) {
5393                 if (ch === ']') {
5394                     classMarker = false;
5395                 }
5396             } else {
5397                 if (ch === '\\') {
5398                     ch = source[index++];
5399                     // ECMA-262 7.8.5
5400                     if (isLineTerminator(ch)) {
5401                         throwError({}, Messages.UnterminatedRegExp);
5402                     }
5403                     str += ch;
5404                 } else if (ch === '/') {
5405                     terminated = true;
5406                     break;
5407                 } else if (ch === '[') {
5408                     classMarker = true;
5409                 } else if (isLineTerminator(ch)) {
5410                     throwError({}, Messages.UnterminatedRegExp);
5411                 }
5412             }
5413         }
5415         if (!terminated) {
5416             throwError({}, Messages.UnterminatedRegExp);
5417         }
5419         // Exclude leading and trailing slash.
5420         pattern = str.substr(1, str.length - 2);
5422         flags = '';
5423         while (index < length) {
5424             ch = source[index];
5425             if (!isIdentifierPart(ch)) {
5426                 break;
5427             }
5429             ++index;
5430             if (ch === '\\' && index < length) {
5431                 ch = source[index];
5432                 if (ch === 'u') {
5433                     ++index;
5434                     restore = index;
5435                     ch = scanHexEscape('u');
5436                     if (ch) {
5437                         flags += ch;
5438                         str += '\\u';
5439                         for (; restore < index; ++restore) {
5440                             str += source[restore];
5441                         }
5442                     } else {
5443                         index = restore;
5444                         flags += 'u';
5445                         str += '\\u';
5446                     }
5447                 } else {
5448                     str += '\\';
5449                 }
5450             } else {
5451                 flags += ch;
5452                 str += ch;
5453             }
5454         }
5456         try {
5457             value = new RegExp(pattern, flags);
5458         } catch (e) {
5459             throwError({}, Messages.InvalidRegExp);
5460         }
5462         return {
5463             literal: str,
5464             value: value,
5465             range: [start, index]
5466         };
5467     }
5469     function isIdentifierName(token) {
5470         return token.type === Token.Identifier ||
5471             token.type === Token.Keyword ||
5472             token.type === Token.BooleanLiteral ||
5473             token.type === Token.NullLiteral;
5474     }
5476     function advance() {
5477         var ch, token;
5479         skipComment();
5481         if (index >= length) {
5482             return {
5483                 type: Token.EOF,
5484                 lineNumber: lineNumber,
5485                 lineStart: lineStart,
5486                 range: [index, index]
5487             };
5488         }
5490         token = scanPunctuator();
5491         if (typeof token !== 'undefined') {
5492             return token;
5493         }
5495         ch = source[index];
5497         if (ch === '\'' || ch === '"') {
5498             return scanStringLiteral();
5499         }
5501         if (ch === '.' || isDecimalDigit(ch)) {
5502             return scanNumericLiteral();
5503         }
5505         token = scanIdentifier();
5506         if (typeof token !== 'undefined') {
5507             return token;
5508         }
5510         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
5511     }
5513     function lex() {
5514         var token;
5516         if (buffer) {
5517             index = buffer.range[1];
5518             lineNumber = buffer.lineNumber;
5519             lineStart = buffer.lineStart;
5520             token = buffer;
5521             buffer = null;
5522             return token;
5523         }
5525         buffer = null;
5526         return advance();
5527     }
5529     function lookahead() {
5530         var pos, line, start;
5532         if (buffer !== null) {
5533             return buffer;
5534         }
5536         pos = index;
5537         line = lineNumber;
5538         start = lineStart;
5539         buffer = advance();
5540         index = pos;
5541         lineNumber = line;
5542         lineStart = start;
5544         return buffer;
5545     }
5547     // Return true if there is a line terminator before the next token.
5549     function peekLineTerminator() {
5550         var pos, line, start, found;
5552         pos = index;
5553         line = lineNumber;
5554         start = lineStart;
5555         skipComment();
5556         found = lineNumber !== line;
5557         index = pos;
5558         lineNumber = line;
5559         lineStart = start;
5561         return found;
5562     }
5564     // Throw an exception
5566     function throwError(token, messageFormat) {
5567         var error,
5568             args = Array.prototype.slice.call(arguments, 2),
5569             msg = messageFormat.replace(
5570                 /%(\d)/g,
5571                 function (whole, index) {
5572                     return args[index] || '';
5573                 }
5574             );
5576         if (typeof token.lineNumber === 'number') {
5577             error = new Error('Line ' + token.lineNumber + ': ' + msg);
5578             error.index = token.range[0];
5579             error.lineNumber = token.lineNumber;
5580             error.column = token.range[0] - lineStart + 1;
5581         } else {
5582             error = new Error('Line ' + lineNumber + ': ' + msg);
5583             error.index = index;
5584             error.lineNumber = lineNumber;
5585             error.column = index - lineStart + 1;
5586         }
5588         throw error;
5589     }
5591     function throwErrorTolerant() {
5592         try {
5593             throwError.apply(null, arguments);
5594         } catch (e) {
5595             if (extra.errors) {
5596                 extra.errors.push(e);
5597             } else {
5598                 throw e;
5599             }
5600         }
5601     }
5604     // Throw an exception because of the token.
5606     function throwUnexpected(token) {
5607         if (token.type === Token.EOF) {
5608             throwError(token, Messages.UnexpectedEOS);
5609         }
5611         if (token.type === Token.NumericLiteral) {
5612             throwError(token, Messages.UnexpectedNumber);
5613         }
5615         if (token.type === Token.StringLiteral) {
5616             throwError(token, Messages.UnexpectedString);
5617         }
5619         if (token.type === Token.Identifier) {
5620             throwError(token, Messages.UnexpectedIdentifier);
5621         }
5623         if (token.type === Token.Keyword) {
5624             if (isFutureReservedWord(token.value)) {
5625                 throwError(token, Messages.UnexpectedReserved);
5626             } else if (strict && isStrictModeReservedWord(token.value)) {
5627                 throwErrorTolerant(token, Messages.StrictReservedWord);
5628                 return;
5629             }
5630             throwError(token, Messages.UnexpectedToken, token.value);
5631         }
5633         // BooleanLiteral, NullLiteral, or Punctuator.
5634         throwError(token, Messages.UnexpectedToken, token.value);
5635     }
5637     // Expect the next token to match the specified punctuator.
5638     // If not, an exception will be thrown.
5640     function expect(value) {
5641         var token = lex();
5642         if (token.type !== Token.Punctuator || token.value !== value) {
5643             throwUnexpected(token);
5644         }
5645     }
5647     // Expect the next token to match the specified keyword.
5648     // If not, an exception will be thrown.
5650     function expectKeyword(keyword) {
5651         var token = lex();
5652         if (token.type !== Token.Keyword || token.value !== keyword) {
5653             throwUnexpected(token);
5654         }
5655     }
5657     // Return true if the next token matches the specified punctuator.
5659     function match(value) {
5660         var token = lookahead();
5661         return token.type === Token.Punctuator && token.value === value;
5662     }
5664     // Return true if the next token matches the specified keyword
5666     function matchKeyword(keyword) {
5667         var token = lookahead();
5668         return token.type === Token.Keyword && token.value === keyword;
5669     }
5671     // Return true if the next token is an assignment operator
5673     function matchAssign() {
5674         var token = lookahead(),
5675             op = token.value;
5677         if (token.type !== Token.Punctuator) {
5678             return false;
5679         }
5680         return op === '=' ||
5681             op === '*=' ||
5682             op === '/=' ||
5683             op === '%=' ||
5684             op === '+=' ||
5685             op === '-=' ||
5686             op === '<<=' ||
5687             op === '>>=' ||
5688             op === '>>>=' ||
5689             op === '&=' ||
5690             op === '^=' ||
5691             op === '|=';
5692     }
5694     function consumeSemicolon() {
5695         var token, line;
5697         // Catch the very common case first.
5698         if (source[index] === ';') {
5699             lex();
5700             return;
5701         }
5703         line = lineNumber;
5704         skipComment();
5705         if (lineNumber !== line) {
5706             return;
5707         }
5709         if (match(';')) {
5710             lex();
5711             return;
5712         }
5714         token = lookahead();
5715         if (token.type !== Token.EOF && !match('}')) {
5716             throwUnexpected(token);
5717         }
5718     }
5720     // Return true if provided expression is LeftHandSideExpression
5722     function isLeftHandSide(expr) {
5723         return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
5724     }
5726     // 11.1.4 Array Initialiser
5728     function parseArrayInitialiser() {
5729         var elements = [];
5731         expect('[');
5733         while (!match(']')) {
5734             if (match(',')) {
5735                 lex();
5736                 elements.push(null);
5737             } else {
5738                 elements.push(parseAssignmentExpression());
5740                 if (!match(']')) {
5741                     expect(',');
5742                 }
5743             }
5744         }
5746         expect(']');
5748         return {
5749             type: Syntax.ArrayExpression,
5750             elements: elements
5751         };
5752     }
5754     // 11.1.5 Object Initialiser
5756     function parsePropertyFunction(param, first) {
5757         var previousStrict, body;
5759         previousStrict = strict;
5760         body = parseFunctionSourceElements();
5761         if (first && strict && isRestrictedWord(param[0].name)) {
5762             throwErrorTolerant(first, Messages.StrictParamName);
5763         }
5764         strict = previousStrict;
5766         return {
5767             type: Syntax.FunctionExpression,
5768             id: null,
5769             params: param,
5770             defaults: [],
5771             body: body,
5772             rest: null,
5773             generator: false,
5774             expression: false
5775         };
5776     }
5778     function parseObjectPropertyKey() {
5779         var token = lex();
5781         // Note: This function is called only from parseObjectProperty(), where
5782         // EOF and Punctuator tokens are already filtered out.
5784         if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
5785             if (strict && token.octal) {
5786                 throwErrorTolerant(token, Messages.StrictOctalLiteral);
5787             }
5788             return createLiteral(token);
5789         }
5791         return {
5792             type: Syntax.Identifier,
5793             name: token.value
5794         };
5795     }
5797     function parseObjectProperty() {
5798         var token, key, id, param;
5800         token = lookahead();
5802         if (token.type === Token.Identifier) {
5804             id = parseObjectPropertyKey();
5806             // Property Assignment: Getter and Setter.
5808             if (token.value === 'get' && !match(':')) {
5809                 key = parseObjectPropertyKey();
5810                 expect('(');
5811                 expect(')');
5812                 return {
5813                     type: Syntax.Property,
5814                     key: key,
5815                     value: parsePropertyFunction([]),
5816                     kind: 'get'
5817                 };
5818             } else if (token.value === 'set' && !match(':')) {
5819                 key = parseObjectPropertyKey();
5820                 expect('(');
5821                 token = lookahead();
5822                 if (token.type !== Token.Identifier) {
5823                     expect(')');
5824                     throwErrorTolerant(token, Messages.UnexpectedToken, token.value);
5825                     return {
5826                         type: Syntax.Property,
5827                         key: key,
5828                         value: parsePropertyFunction([]),
5829                         kind: 'set'
5830                     };
5831                 } else {
5832                     param = [ parseVariableIdentifier() ];
5833                     expect(')');
5834                     return {
5835                         type: Syntax.Property,
5836                         key: key,
5837                         value: parsePropertyFunction(param, token),
5838                         kind: 'set'
5839                     };
5840                 }
5841             } else {
5842                 expect(':');
5843                 return {
5844                     type: Syntax.Property,
5845                     key: id,
5846                     value: parseAssignmentExpression(),
5847                     kind: 'init'
5848                 };
5849             }
5850         } else if (token.type === Token.EOF || token.type === Token.Punctuator) {
5851             throwUnexpected(token);
5852         } else {
5853             key = parseObjectPropertyKey();
5854             expect(':');
5855             return {
5856                 type: Syntax.Property,
5857                 key: key,
5858                 value: parseAssignmentExpression(),
5859                 kind: 'init'
5860             };
5861         }
5862     }
5864     function parseObjectInitialiser() {
5865         var properties = [], property, name, kind, map = {}, toString = String;
5867         expect('{');
5869         while (!match('}')) {
5870             property = parseObjectProperty();
5872             if (property.key.type === Syntax.Identifier) {
5873                 name = property.key.name;
5874             } else {
5875                 name = toString(property.key.value);
5876             }
5877             kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
5878             if (Object.prototype.hasOwnProperty.call(map, name)) {
5879                 if (map[name] === PropertyKind.Data) {
5880                     if (strict && kind === PropertyKind.Data) {
5881                         throwErrorTolerant({}, Messages.StrictDuplicateProperty);
5882                     } else if (kind !== PropertyKind.Data) {
5883                         throwErrorTolerant({}, Messages.AccessorDataProperty);
5884                     }
5885                 } else {
5886                     if (kind === PropertyKind.Data) {
5887                         throwErrorTolerant({}, Messages.AccessorDataProperty);
5888                     } else if (map[name] & kind) {
5889                         throwErrorTolerant({}, Messages.AccessorGetSet);
5890                     }
5891                 }
5892                 map[name] |= kind;
5893             } else {
5894                 map[name] = kind;
5895             }
5897             properties.push(property);
5899             if (!match('}')) {
5900                 expect(',');
5901             }
5902         }
5904         expect('}');
5906         return {
5907             type: Syntax.ObjectExpression,
5908             properties: properties
5909         };
5910     }
5912     // 11.1.6 The Grouping Operator
5914     function parseGroupExpression() {
5915         var expr;
5917         expect('(');
5919         expr = parseExpression();
5921         expect(')');
5923         return expr;
5924     }
5927     // 11.1 Primary Expressions
5929     function parsePrimaryExpression() {
5930         var token = lookahead(),
5931             type = token.type;
5933         if (type === Token.Identifier) {
5934             return {
5935                 type: Syntax.Identifier,
5936                 name: lex().value
5937             };
5938         }
5940         if (type === Token.StringLiteral || type === Token.NumericLiteral) {
5941             if (strict && token.octal) {
5942                 throwErrorTolerant(token, Messages.StrictOctalLiteral);
5943             }
5944             return createLiteral(lex());
5945         }
5947         if (type === Token.Keyword) {
5948             if (matchKeyword('this')) {
5949                 lex();
5950                 return {
5951                     type: Syntax.ThisExpression
5952                 };
5953             }
5955             if (matchKeyword('function')) {
5956                 return parseFunctionExpression();
5957             }
5958         }
5960         if (type === Token.BooleanLiteral) {
5961             lex();
5962             token.value = (token.value === 'true');
5963             return createLiteral(token);
5964         }
5966         if (type === Token.NullLiteral) {
5967             lex();
5968             token.value = null;
5969             return createLiteral(token);
5970         }
5972         if (match('[')) {
5973             return parseArrayInitialiser();
5974         }
5976         if (match('{')) {
5977             return parseObjectInitialiser();
5978         }
5980         if (match('(')) {
5981             return parseGroupExpression();
5982         }
5984         if (match('/') || match('/=')) {
5985             return createLiteral(scanRegExp());
5986         }
5988         return throwUnexpected(lex());
5989     }
5991     // 11.2 Left-Hand-Side Expressions
5993     function parseArguments() {
5994         var args = [];
5996         expect('(');
5998         if (!match(')')) {
5999             while (index < length) {
6000                 args.push(parseAssignmentExpression());
6001                 if (match(')')) {
6002                     break;
6003                 }
6004                 expect(',');
6005             }
6006         }
6008         expect(')');
6010         return args;
6011     }
6013     function parseNonComputedProperty() {
6014         var token = lex();
6016         if (!isIdentifierName(token)) {
6017             throwUnexpected(token);
6018         }
6020         return {
6021             type: Syntax.Identifier,
6022             name: token.value
6023         };
6024     }
6026     function parseNonComputedMember() {
6027         expect('.');
6029         return parseNonComputedProperty();
6030     }
6032     function parseComputedMember() {
6033         var expr;
6035         expect('[');
6037         expr = parseExpression();
6039         expect(']');
6041         return expr;
6042     }
6044     function parseNewExpression() {
6045         var expr;
6047         expectKeyword('new');
6049         expr = {
6050             type: Syntax.NewExpression,
6051             callee: parseLeftHandSideExpression(),
6052             'arguments': []
6053         };
6055         if (match('(')) {
6056             expr['arguments'] = parseArguments();
6057         }
6059         return expr;
6060     }
6062     function parseLeftHandSideExpressionAllowCall() {
6063         var expr;
6065         expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
6067         while (match('.') || match('[') || match('(')) {
6068             if (match('(')) {
6069                 expr = {
6070                     type: Syntax.CallExpression,
6071                     callee: expr,
6072                     'arguments': parseArguments()
6073                 };
6074             } else if (match('[')) {
6075                 expr = {
6076                     type: Syntax.MemberExpression,
6077                     computed: true,
6078                     object: expr,
6079                     property: parseComputedMember()
6080                 };
6081             } else {
6082                 expr = {
6083                     type: Syntax.MemberExpression,
6084                     computed: false,
6085                     object: expr,
6086                     property: parseNonComputedMember()
6087                 };
6088             }
6089         }
6091         return expr;
6092     }
6095     function parseLeftHandSideExpression() {
6096         var expr;
6098         expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
6100         while (match('.') || match('[')) {
6101             if (match('[')) {
6102                 expr = {
6103                     type: Syntax.MemberExpression,
6104                     computed: true,
6105                     object: expr,
6106                     property: parseComputedMember()
6107                 };
6108             } else {
6109                 expr = {
6110                     type: Syntax.MemberExpression,
6111                     computed: false,
6112                     object: expr,
6113                     property: parseNonComputedMember()
6114                 };
6115             }
6116         }
6118         return expr;
6119     }
6121     // 11.3 Postfix Expressions
6123     function parsePostfixExpression() {
6124         var expr = parseLeftHandSideExpressionAllowCall(), token;
6126         token = lookahead();
6127         if (token.type !== Token.Punctuator) {
6128             return expr;
6129         }
6131         if ((match('++') || match('--')) && !peekLineTerminator()) {
6132             // 11.3.1, 11.3.2
6133             if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
6134                 throwErrorTolerant({}, Messages.StrictLHSPostfix);
6135             }
6137             if (!isLeftHandSide(expr)) {
6138                 throwError({}, Messages.InvalidLHSInAssignment);
6139             }
6141             expr = {
6142                 type: Syntax.UpdateExpression,
6143                 operator: lex().value,
6144                 argument: expr,
6145                 prefix: false
6146             };
6147         }
6149         return expr;
6150     }
6152     // 11.4 Unary Operators
6154     function parseUnaryExpression() {
6155         var token, expr;
6157         token = lookahead();
6158         if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
6159             return parsePostfixExpression();
6160         }
6162         if (match('++') || match('--')) {
6163             token = lex();
6164             expr = parseUnaryExpression();
6165             // 11.4.4, 11.4.5
6166             if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
6167                 throwErrorTolerant({}, Messages.StrictLHSPrefix);
6168             }
6170             if (!isLeftHandSide(expr)) {
6171                 throwError({}, Messages.InvalidLHSInAssignment);
6172             }
6174             expr = {
6175                 type: Syntax.UpdateExpression,
6176                 operator: token.value,
6177                 argument: expr,
6178                 prefix: true
6179             };
6180             return expr;
6181         }
6183         if (match('+') || match('-') || match('~') || match('!')) {
6184             expr = {
6185                 type: Syntax.UnaryExpression,
6186                 operator: lex().value,
6187                 argument: parseUnaryExpression(),
6188                 prefix: true
6189             };
6190             return expr;
6191         }
6193         if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
6194             expr = {
6195                 type: Syntax.UnaryExpression,
6196                 operator: lex().value,
6197                 argument: parseUnaryExpression(),
6198                 prefix: true
6199             };
6200             if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
6201                 throwErrorTolerant({}, Messages.StrictDelete);
6202             }
6203             return expr;
6204         }
6206         return parsePostfixExpression();
6207     }
6209     // 11.5 Multiplicative Operators
6211     function parseMultiplicativeExpression() {
6212         var expr = parseUnaryExpression();
6214         while (match('*') || match('/') || match('%')) {
6215             expr = {
6216                 type: Syntax.BinaryExpression,
6217                 operator: lex().value,
6218                 left: expr,
6219                 right: parseUnaryExpression()
6220             };
6221         }
6223         return expr;
6224     }
6226     // 11.6 Additive Operators
6228     function parseAdditiveExpression() {
6229         var expr = parseMultiplicativeExpression();
6231         while (match('+') || match('-')) {
6232             expr = {
6233                 type: Syntax.BinaryExpression,
6234                 operator: lex().value,
6235                 left: expr,
6236                 right: parseMultiplicativeExpression()
6237             };
6238         }
6240         return expr;
6241     }
6243     // 11.7 Bitwise Shift Operators
6245     function parseShiftExpression() {
6246         var expr = parseAdditiveExpression();
6248         while (match('<<') || match('>>') || match('>>>')) {
6249             expr = {
6250                 type: Syntax.BinaryExpression,
6251                 operator: lex().value,
6252                 left: expr,
6253                 right: parseAdditiveExpression()
6254             };
6255         }
6257         return expr;
6258     }
6259     // 11.8 Relational Operators
6261     function parseRelationalExpression() {
6262         var expr, previousAllowIn;
6264         previousAllowIn = state.allowIn;
6265         state.allowIn = true;
6267         expr = parseShiftExpression();
6269         while (match('<') || match('>') || match('<=') || match('>=') || (previousAllowIn && matchKeyword('in')) || matchKeyword('instanceof')) {
6270             expr = {
6271                 type: Syntax.BinaryExpression,
6272                 operator: lex().value,
6273                 left: expr,
6274                 right: parseShiftExpression()
6275             };
6276         }
6278         state.allowIn = previousAllowIn;
6279         return expr;
6280     }
6282     // 11.9 Equality Operators
6284     function parseEqualityExpression() {
6285         var expr = parseRelationalExpression();
6287         while (match('==') || match('!=') || match('===') || match('!==')) {
6288             expr = {
6289                 type: Syntax.BinaryExpression,
6290                 operator: lex().value,
6291                 left: expr,
6292                 right: parseRelationalExpression()
6293             };
6294         }
6296         return expr;
6297     }
6299     // 11.10 Binary Bitwise Operators
6301     function parseBitwiseANDExpression() {
6302         var expr = parseEqualityExpression();
6304         while (match('&')) {
6305             lex();
6306             expr = {
6307                 type: Syntax.BinaryExpression,
6308                 operator: '&',
6309                 left: expr,
6310                 right: parseEqualityExpression()
6311             };
6312         }
6314         return expr;
6315     }
6317     function parseBitwiseXORExpression() {
6318         var expr = parseBitwiseANDExpression();
6320         while (match('^')) {
6321             lex();
6322             expr = {
6323                 type: Syntax.BinaryExpression,
6324                 operator: '^',
6325                 left: expr,
6326                 right: parseBitwiseANDExpression()
6327             };
6328         }
6330         return expr;
6331     }
6333     function parseBitwiseORExpression() {
6334         var expr = parseBitwiseXORExpression();
6336         while (match('|')) {
6337             lex();
6338             expr = {
6339                 type: Syntax.BinaryExpression,
6340                 operator: '|',
6341                 left: expr,
6342                 right: parseBitwiseXORExpression()
6343             };
6344         }
6346         return expr;
6347     }
6349     // 11.11 Binary Logical Operators
6351     function parseLogicalANDExpression() {
6352         var expr = parseBitwiseORExpression();
6354         while (match('&&')) {
6355             lex();
6356             expr = {
6357                 type: Syntax.LogicalExpression,
6358                 operator: '&&',
6359                 left: expr,
6360                 right: parseBitwiseORExpression()
6361             };
6362         }
6364         return expr;
6365     }
6367     function parseLogicalORExpression() {
6368         var expr = parseLogicalANDExpression();
6370         while (match('||')) {
6371             lex();
6372             expr = {
6373                 type: Syntax.LogicalExpression,
6374                 operator: '||',
6375                 left: expr,
6376                 right: parseLogicalANDExpression()
6377             };
6378         }
6380         return expr;
6381     }
6383     // 11.12 Conditional Operator
6385     function parseConditionalExpression() {
6386         var expr, previousAllowIn, consequent;
6388         expr = parseLogicalORExpression();
6390         if (match('?')) {
6391             lex();
6392             previousAllowIn = state.allowIn;
6393             state.allowIn = true;
6394             consequent = parseAssignmentExpression();
6395             state.allowIn = previousAllowIn;
6396             expect(':');
6398             expr = {
6399                 type: Syntax.ConditionalExpression,
6400                 test: expr,
6401                 consequent: consequent,
6402                 alternate: parseAssignmentExpression()
6403             };
6404         }
6406         return expr;
6407     }
6409     // 11.13 Assignment Operators
6411     function parseAssignmentExpression() {
6412         var token, expr;
6414         token = lookahead();
6415         expr = parseConditionalExpression();
6417         if (matchAssign()) {
6418             // LeftHandSideExpression
6419             if (!isLeftHandSide(expr)) {
6420                 throwError({}, Messages.InvalidLHSInAssignment);
6421             }
6423             // 11.13.1
6424             if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
6425                 throwErrorTolerant(token, Messages.StrictLHSAssignment);
6426             }
6428             expr = {
6429                 type: Syntax.AssignmentExpression,
6430                 operator: lex().value,
6431                 left: expr,
6432                 right: parseAssignmentExpression()
6433             };
6434         }
6436         return expr;
6437     }
6439     // 11.14 Comma Operator
6441     function parseExpression() {
6442         var expr = parseAssignmentExpression();
6444         if (match(',')) {
6445             expr = {
6446                 type: Syntax.SequenceExpression,
6447                 expressions: [ expr ]
6448             };
6450             while (index < length) {
6451                 if (!match(',')) {
6452                     break;
6453                 }
6454                 lex();
6455                 expr.expressions.push(parseAssignmentExpression());
6456             }
6458         }
6459         return expr;
6460     }
6462     // 12.1 Block
6464     function parseStatementList() {
6465         var list = [],
6466             statement;
6468         while (index < length) {
6469             if (match('}')) {
6470                 break;
6471             }
6472             statement = parseSourceElement();
6473             if (typeof statement === 'undefined') {
6474                 break;
6475             }
6476             list.push(statement);
6477         }
6479         return list;
6480     }
6482     function parseBlock() {
6483         var block;
6485         expect('{');
6487         block = parseStatementList();
6489         expect('}');
6491         return {
6492             type: Syntax.BlockStatement,
6493             body: block
6494         };
6495     }
6497     // 12.2 Variable Statement
6499     function parseVariableIdentifier() {
6500         var token = lex();
6502         if (token.type !== Token.Identifier) {
6503             throwUnexpected(token);
6504         }
6506         return {
6507             type: Syntax.Identifier,
6508             name: token.value
6509         };
6510     }
6512     function parseVariableDeclaration(kind) {
6513         var id = parseVariableIdentifier(),
6514             init = null;
6516         // 12.2.1
6517         if (strict && isRestrictedWord(id.name)) {
6518             throwErrorTolerant({}, Messages.StrictVarName);
6519         }
6521         if (kind === 'const') {
6522             expect('=');
6523             init = parseAssignmentExpression();
6524         } else if (match('=')) {
6525             lex();
6526             init = parseAssignmentExpression();
6527         }
6529         return {
6530             type: Syntax.VariableDeclarator,
6531             id: id,
6532             init: init
6533         };
6534     }
6536     function parseVariableDeclarationList(kind) {
6537         var list = [];
6539         do {
6540             list.push(parseVariableDeclaration(kind));
6541             if (!match(',')) {
6542                 break;
6543             }
6544             lex();
6545         } while (index < length);
6547         return list;
6548     }
6550     function parseVariableStatement() {
6551         var declarations;
6553         expectKeyword('var');
6555         declarations = parseVariableDeclarationList();
6557         consumeSemicolon();
6559         return {
6560             type: Syntax.VariableDeclaration,
6561             declarations: declarations,
6562             kind: 'var'
6563         };
6564     }
6566     // kind may be `const` or `let`
6567     // Both are experimental and not in the specification yet.
6568     // see http://wiki.ecmascript.org/doku.php?id=harmony:const
6569     // and http://wiki.ecmascript.org/doku.php?id=harmony:let
6570     function parseConstLetDeclaration(kind) {
6571         var declarations;
6573         expectKeyword(kind);
6575         declarations = parseVariableDeclarationList(kind);
6577         consumeSemicolon();
6579         return {
6580             type: Syntax.VariableDeclaration,
6581             declarations: declarations,
6582             kind: kind
6583         };
6584     }
6586     // 12.3 Empty Statement
6588     function parseEmptyStatement() {
6589         expect(';');
6591         return {
6592             type: Syntax.EmptyStatement
6593         };
6594     }
6596     // 12.4 Expression Statement
6598     function parseExpressionStatement() {
6599         var expr = parseExpression();
6601         consumeSemicolon();
6603         return {
6604             type: Syntax.ExpressionStatement,
6605             expression: expr
6606         };
6607     }
6609     // 12.5 If statement
6611     function parseIfStatement() {
6612         var test, consequent, alternate;
6614         expectKeyword('if');
6616         expect('(');
6618         test = parseExpression();
6620         expect(')');
6622         consequent = parseStatement();
6624         if (matchKeyword('else')) {
6625             lex();
6626             alternate = parseStatement();
6627         } else {
6628             alternate = null;
6629         }
6631         return {
6632             type: Syntax.IfStatement,
6633             test: test,
6634             consequent: consequent,
6635             alternate: alternate
6636         };
6637     }
6639     // 12.6 Iteration Statements
6641     function parseDoWhileStatement() {
6642         var body, test, oldInIteration;
6644         expectKeyword('do');
6646         oldInIteration = state.inIteration;
6647         state.inIteration = true;
6649         body = parseStatement();
6651         state.inIteration = oldInIteration;
6653         expectKeyword('while');
6655         expect('(');
6657         test = parseExpression();
6659         expect(')');
6661         if (match(';')) {
6662             lex();
6663         }
6665         return {
6666             type: Syntax.DoWhileStatement,
6667             body: body,
6668             test: test
6669         };
6670     }
6672     function parseWhileStatement() {
6673         var test, body, oldInIteration;
6675         expectKeyword('while');
6677         expect('(');
6679         test = parseExpression();
6681         expect(')');
6683         oldInIteration = state.inIteration;
6684         state.inIteration = true;
6686         body = parseStatement();
6688         state.inIteration = oldInIteration;
6690         return {
6691             type: Syntax.WhileStatement,
6692             test: test,
6693             body: body
6694         };
6695     }
6697     function parseForVariableDeclaration() {
6698         var token = lex();
6700         return {
6701             type: Syntax.VariableDeclaration,
6702             declarations: parseVariableDeclarationList(),
6703             kind: token.value
6704         };
6705     }
6707     function parseForStatement() {
6708         var init, test, update, left, right, body, oldInIteration;
6710         init = test = update = null;
6712         expectKeyword('for');
6714         expect('(');
6716         if (match(';')) {
6717             lex();
6718         } else {
6719             if (matchKeyword('var') || matchKeyword('let')) {
6720                 state.allowIn = false;
6721                 init = parseForVariableDeclaration();
6722                 state.allowIn = true;
6724                 if (init.declarations.length === 1 && matchKeyword('in')) {
6725                     lex();
6726                     left = init;
6727                     right = parseExpression();
6728                     init = null;
6729                 }
6730             } else {
6731                 state.allowIn = false;
6732                 init = parseExpression();
6733                 state.allowIn = true;
6735                 if (matchKeyword('in')) {
6736                     // LeftHandSideExpression
6737                     if (!isLeftHandSide(init)) {
6738                         throwError({}, Messages.InvalidLHSInForIn);
6739                     }
6741                     lex();
6742                     left = init;
6743                     right = parseExpression();
6744                     init = null;
6745                 }
6746             }
6748             if (typeof left === 'undefined') {
6749                 expect(';');
6750             }
6751         }
6753         if (typeof left === 'undefined') {
6755             if (!match(';')) {
6756                 test = parseExpression();
6757             }
6758             expect(';');
6760             if (!match(')')) {
6761                 update = parseExpression();
6762             }
6763         }
6765         expect(')');
6767         oldInIteration = state.inIteration;
6768         state.inIteration = true;
6770         body = parseStatement();
6772         state.inIteration = oldInIteration;
6774         if (typeof left === 'undefined') {
6775             return {
6776                 type: Syntax.ForStatement,
6777                 init: init,
6778                 test: test,
6779                 update: update,
6780                 body: body
6781             };
6782         }
6784         return {
6785             type: Syntax.ForInStatement,
6786             left: left,
6787             right: right,
6788             body: body,
6789             each: false
6790         };
6791     }
6793     // 12.7 The continue statement
6795     function parseContinueStatement() {
6796         var token, label = null;
6798         expectKeyword('continue');
6800         // Optimize the most common form: 'continue;'.
6801         if (source[index] === ';') {
6802             lex();
6804             if (!state.inIteration) {
6805                 throwError({}, Messages.IllegalContinue);
6806             }
6808             return {
6809                 type: Syntax.ContinueStatement,
6810                 label: null
6811             };
6812         }
6814         if (peekLineTerminator()) {
6815             if (!state.inIteration) {
6816                 throwError({}, Messages.IllegalContinue);
6817             }
6819             return {
6820                 type: Syntax.ContinueStatement,
6821                 label: null
6822             };
6823         }
6825         token = lookahead();
6826         if (token.type === Token.Identifier) {
6827             label = parseVariableIdentifier();
6829             if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
6830                 throwError({}, Messages.UnknownLabel, label.name);
6831             }
6832         }
6834         consumeSemicolon();
6836         if (label === null && !state.inIteration) {
6837             throwError({}, Messages.IllegalContinue);
6838         }
6840         return {
6841             type: Syntax.ContinueStatement,
6842             label: label
6843         };
6844     }
6846     // 12.8 The break statement
6848     function parseBreakStatement() {
6849         var token, label = null;
6851         expectKeyword('break');
6853         // Optimize the most common form: 'break;'.
6854         if (source[index] === ';') {
6855             lex();
6857             if (!(state.inIteration || state.inSwitch)) {
6858                 throwError({}, Messages.IllegalBreak);
6859             }
6861             return {
6862                 type: Syntax.BreakStatement,
6863                 label: null
6864             };
6865         }
6867         if (peekLineTerminator()) {
6868             if (!(state.inIteration || state.inSwitch)) {
6869                 throwError({}, Messages.IllegalBreak);
6870             }
6872             return {
6873                 type: Syntax.BreakStatement,
6874                 label: null
6875             };
6876         }
6878         token = lookahead();
6879         if (token.type === Token.Identifier) {
6880             label = parseVariableIdentifier();
6882             if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
6883                 throwError({}, Messages.UnknownLabel, label.name);
6884             }
6885         }
6887         consumeSemicolon();
6889         if (label === null && !(state.inIteration || state.inSwitch)) {
6890             throwError({}, Messages.IllegalBreak);
6891         }
6893         return {
6894             type: Syntax.BreakStatement,
6895             label: label
6896         };
6897     }
6899     // 12.9 The return statement
6901     function parseReturnStatement() {
6902         var token, argument = null;
6904         expectKeyword('return');
6906         if (!state.inFunctionBody) {
6907             throwErrorTolerant({}, Messages.IllegalReturn);
6908         }
6910         // 'return' followed by a space and an identifier is very common.
6911         if (source[index] === ' ') {
6912             if (isIdentifierStart(source[index + 1])) {
6913                 argument = parseExpression();
6914                 consumeSemicolon();
6915                 return {
6916                     type: Syntax.ReturnStatement,
6917                     argument: argument
6918                 };
6919             }
6920         }
6922         if (peekLineTerminator()) {
6923             return {
6924                 type: Syntax.ReturnStatement,
6925                 argument: null
6926             };
6927         }
6929         if (!match(';')) {
6930             token = lookahead();
6931             if (!match('}') && token.type !== Token.EOF) {
6932                 argument = parseExpression();
6933             }
6934         }
6936         consumeSemicolon();
6938         return {
6939             type: Syntax.ReturnStatement,
6940             argument: argument
6941         };
6942     }
6944     // 12.10 The with statement
6946     function parseWithStatement() {
6947         var object, body;
6949         if (strict) {
6950             throwErrorTolerant({}, Messages.StrictModeWith);
6951         }
6953         expectKeyword('with');
6955         expect('(');
6957         object = parseExpression();
6959         expect(')');
6961         body = parseStatement();
6963         return {
6964             type: Syntax.WithStatement,
6965             object: object,
6966             body: body
6967         };
6968     }
6970     // 12.10 The swith statement
6972     function parseSwitchCase() {
6973         var test,
6974             consequent = [],
6975             statement;
6977         if (matchKeyword('default')) {
6978             lex();
6979             test = null;
6980         } else {
6981             expectKeyword('case');
6982             test = parseExpression();
6983         }
6984         expect(':');
6986         while (index < length) {
6987             if (match('}') || matchKeyword('default') || matchKeyword('case')) {
6988                 break;
6989             }
6990             statement = parseStatement();
6991             if (typeof statement === 'undefined') {
6992                 break;
6993             }
6994             consequent.push(statement);
6995         }
6997         return {
6998             type: Syntax.SwitchCase,
6999             test: test,
7000             consequent: consequent
7001         };
7002     }
7004     function parseSwitchStatement() {
7005         var discriminant, cases, clause, oldInSwitch, defaultFound;
7007         expectKeyword('switch');
7009         expect('(');
7011         discriminant = parseExpression();
7013         expect(')');
7015         expect('{');
7017         if (match('}')) {
7018             lex();
7019             return {
7020                 type: Syntax.SwitchStatement,
7021                 discriminant: discriminant
7022             };
7023         }
7025         cases = [];
7027         oldInSwitch = state.inSwitch;
7028         state.inSwitch = true;
7029         defaultFound = false;
7031         while (index < length) {
7032             if (match('}')) {
7033                 break;
7034             }
7035             clause = parseSwitchCase();
7036             if (clause.test === null) {
7037                 if (defaultFound) {
7038                     throwError({}, Messages.MultipleDefaultsInSwitch);
7039                 }
7040                 defaultFound = true;
7041             }
7042             cases.push(clause);
7043         }
7045         state.inSwitch = oldInSwitch;
7047         expect('}');
7049         return {
7050             type: Syntax.SwitchStatement,
7051             discriminant: discriminant,
7052             cases: cases
7053         };
7054     }
7056     // 12.13 The throw statement
7058     function parseThrowStatement() {
7059         var argument;
7061         expectKeyword('throw');
7063         if (peekLineTerminator()) {
7064             throwError({}, Messages.NewlineAfterThrow);
7065         }
7067         argument = parseExpression();
7069         consumeSemicolon();
7071         return {
7072             type: Syntax.ThrowStatement,
7073             argument: argument
7074         };
7075     }
7077     // 12.14 The try statement
7079     function parseCatchClause() {
7080         var param;
7082         expectKeyword('catch');
7084         expect('(');
7085         if (match(')')) {
7086             throwUnexpected(lookahead());
7087         }
7089         param = parseVariableIdentifier();
7090         // 12.14.1
7091         if (strict && isRestrictedWord(param.name)) {
7092             throwErrorTolerant({}, Messages.StrictCatchVariable);
7093         }
7095         expect(')');
7097         return {
7098             type: Syntax.CatchClause,
7099             param: param,
7100             body: parseBlock()
7101         };
7102     }
7104     function parseTryStatement() {
7105         var block, handlers = [], finalizer = null;
7107         expectKeyword('try');
7109         block = parseBlock();
7111         if (matchKeyword('catch')) {
7112             handlers.push(parseCatchClause());
7113         }
7115         if (matchKeyword('finally')) {
7116             lex();
7117             finalizer = parseBlock();
7118         }
7120         if (handlers.length === 0 && !finalizer) {
7121             throwError({}, Messages.NoCatchOrFinally);
7122         }
7124         return {
7125             type: Syntax.TryStatement,
7126             block: block,
7127             guardedHandlers: [],
7128             handlers: handlers,
7129             finalizer: finalizer
7130         };
7131     }
7133     // 12.15 The debugger statement
7135     function parseDebuggerStatement() {
7136         expectKeyword('debugger');
7138         consumeSemicolon();
7140         return {
7141             type: Syntax.DebuggerStatement
7142         };
7143     }
7145     // 12 Statements
7147     function parseStatement() {
7148         var token = lookahead(),
7149             expr,
7150             labeledBody;
7152         if (token.type === Token.EOF) {
7153             throwUnexpected(token);
7154         }
7156         if (token.type === Token.Punctuator) {
7157             switch (token.value) {
7158             case ';':
7159                 return parseEmptyStatement();
7160             case '{':
7161                 return parseBlock();
7162             case '(':
7163                 return parseExpressionStatement();
7164             default:
7165                 break;
7166             }
7167         }
7169         if (token.type === Token.Keyword) {
7170             switch (token.value) {
7171             case 'break':
7172                 return parseBreakStatement();
7173             case 'continue':
7174                 return parseContinueStatement();
7175             case 'debugger':
7176                 return parseDebuggerStatement();
7177             case 'do':
7178                 return parseDoWhileStatement();
7179             case 'for':
7180                 return parseForStatement();
7181             case 'function':
7182                 return parseFunctionDeclaration();
7183             case 'if':
7184                 return parseIfStatement();
7185             case 'return':
7186                 return parseReturnStatement();
7187             case 'switch':
7188                 return parseSwitchStatement();
7189             case 'throw':
7190                 return parseThrowStatement();
7191             case 'try':
7192                 return parseTryStatement();
7193             case 'var':
7194                 return parseVariableStatement();
7195             case 'while':
7196                 return parseWhileStatement();
7197             case 'with':
7198                 return parseWithStatement();
7199             default:
7200                 break;
7201             }
7202         }
7204         expr = parseExpression();
7206         // 12.12 Labelled Statements
7207         if ((expr.type === Syntax.Identifier) && match(':')) {
7208             lex();
7210             if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) {
7211                 throwError({}, Messages.Redeclaration, 'Label', expr.name);
7212             }
7214             state.labelSet[expr.name] = true;
7215             labeledBody = parseStatement();
7216             delete state.labelSet[expr.name];
7218             return {
7219                 type: Syntax.LabeledStatement,
7220                 label: expr,
7221                 body: labeledBody
7222             };
7223         }
7225         consumeSemicolon();
7227         return {
7228             type: Syntax.ExpressionStatement,
7229             expression: expr
7230         };
7231     }
7233     // 13 Function Definition
7235     function parseFunctionSourceElements() {
7236         var sourceElement, sourceElements = [], token, directive, firstRestricted,
7237             oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody;
7239         expect('{');
7241         while (index < length) {
7242             token = lookahead();
7243             if (token.type !== Token.StringLiteral) {
7244                 break;
7245             }
7247             sourceElement = parseSourceElement();
7248             sourceElements.push(sourceElement);
7249             if (sourceElement.expression.type !== Syntax.Literal) {
7250                 // this is not directive
7251                 break;
7252             }
7253             directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
7254             if (directive === 'use strict') {
7255                 strict = true;
7256                 if (firstRestricted) {
7257                     throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
7258                 }
7259             } else {
7260                 if (!firstRestricted && token.octal) {
7261                     firstRestricted = token;
7262                 }
7263             }
7264         }
7266         oldLabelSet = state.labelSet;
7267         oldInIteration = state.inIteration;
7268         oldInSwitch = state.inSwitch;
7269         oldInFunctionBody = state.inFunctionBody;
7271         state.labelSet = {};
7272         state.inIteration = false;
7273         state.inSwitch = false;
7274         state.inFunctionBody = true;
7276         while (index < length) {
7277             if (match('}')) {
7278                 break;
7279             }
7280             sourceElement = parseSourceElement();
7281             if (typeof sourceElement === 'undefined') {
7282                 break;
7283             }
7284             sourceElements.push(sourceElement);
7285         }
7287         expect('}');
7289         state.labelSet = oldLabelSet;
7290         state.inIteration = oldInIteration;
7291         state.inSwitch = oldInSwitch;
7292         state.inFunctionBody = oldInFunctionBody;
7294         return {
7295             type: Syntax.BlockStatement,
7296             body: sourceElements
7297         };
7298     }
7300     function parseFunctionDeclaration() {
7301         var id, param, params = [], body, token, stricted, firstRestricted, message, previousStrict, paramSet;
7303         expectKeyword('function');
7304         token = lookahead();
7305         id = parseVariableIdentifier();
7306         if (strict) {
7307             if (isRestrictedWord(token.value)) {
7308                 throwErrorTolerant(token, Messages.StrictFunctionName);
7309             }
7310         } else {
7311             if (isRestrictedWord(token.value)) {
7312                 firstRestricted = token;
7313                 message = Messages.StrictFunctionName;
7314             } else if (isStrictModeReservedWord(token.value)) {
7315                 firstRestricted = token;
7316                 message = Messages.StrictReservedWord;
7317             }
7318         }
7320         expect('(');
7322         if (!match(')')) {
7323             paramSet = {};
7324             while (index < length) {
7325                 token = lookahead();
7326                 param = parseVariableIdentifier();
7327                 if (strict) {
7328                     if (isRestrictedWord(token.value)) {
7329                         stricted = token;
7330                         message = Messages.StrictParamName;
7331                     }
7332                     if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
7333                         stricted = token;
7334                         message = Messages.StrictParamDupe;
7335                     }
7336                 } else if (!firstRestricted) {
7337                     if (isRestrictedWord(token.value)) {
7338                         firstRestricted = token;
7339                         message = Messages.StrictParamName;
7340                     } else if (isStrictModeReservedWord(token.value)) {
7341                         firstRestricted = token;
7342                         message = Messages.StrictReservedWord;
7343                     } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
7344                         firstRestricted = token;
7345                         message = Messages.StrictParamDupe;
7346                     }
7347                 }
7348                 params.push(param);
7349                 paramSet[param.name] = true;
7350                 if (match(')')) {
7351                     break;
7352                 }
7353                 expect(',');
7354             }
7355         }
7357         expect(')');
7359         previousStrict = strict;
7360         body = parseFunctionSourceElements();
7361         if (strict && firstRestricted) {
7362             throwError(firstRestricted, message);
7363         }
7364         if (strict && stricted) {
7365             throwErrorTolerant(stricted, message);
7366         }
7367         strict = previousStrict;
7369         return {
7370             type: Syntax.FunctionDeclaration,
7371             id: id,
7372             params: params,
7373             defaults: [],
7374             body: body,
7375             rest: null,
7376             generator: false,
7377             expression: false
7378         };
7379     }
7381     function parseFunctionExpression() {
7382         var token, id = null, stricted, firstRestricted, message, param, params = [], body, previousStrict, paramSet;
7384         expectKeyword('function');
7386         if (!match('(')) {
7387             token = lookahead();
7388             id = parseVariableIdentifier();
7389             if (strict) {
7390                 if (isRestrictedWord(token.value)) {
7391                     throwErrorTolerant(token, Messages.StrictFunctionName);
7392                 }
7393             } else {
7394                 if (isRestrictedWord(token.value)) {
7395                     firstRestricted = token;
7396                     message = Messages.StrictFunctionName;
7397                 } else if (isStrictModeReservedWord(token.value)) {
7398                     firstRestricted = token;
7399                     message = Messages.StrictReservedWord;
7400                 }
7401             }
7402         }
7404         expect('(');
7406         if (!match(')')) {
7407             paramSet = {};
7408             while (index < length) {
7409                 token = lookahead();
7410                 param = parseVariableIdentifier();
7411                 if (strict) {
7412                     if (isRestrictedWord(token.value)) {
7413                         stricted = token;
7414                         message = Messages.StrictParamName;
7415                     }
7416                     if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
7417                         stricted = token;
7418                         message = Messages.StrictParamDupe;
7419                     }
7420                 } else if (!firstRestricted) {
7421                     if (isRestrictedWord(token.value)) {
7422                         firstRestricted = token;
7423                         message = Messages.StrictParamName;
7424                     } else if (isStrictModeReservedWord(token.value)) {
7425                         firstRestricted = token;
7426                         message = Messages.StrictReservedWord;
7427                     } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
7428                         firstRestricted = token;
7429                         message = Messages.StrictParamDupe;
7430                     }
7431                 }
7432                 params.push(param);
7433                 paramSet[param.name] = true;
7434                 if (match(')')) {
7435                     break;
7436                 }
7437                 expect(',');
7438             }
7439         }
7441         expect(')');
7443         previousStrict = strict;
7444         body = parseFunctionSourceElements();
7445         if (strict && firstRestricted) {
7446             throwError(firstRestricted, message);
7447         }
7448         if (strict && stricted) {
7449             throwErrorTolerant(stricted, message);
7450         }
7451         strict = previousStrict;
7453         return {
7454             type: Syntax.FunctionExpression,
7455             id: id,
7456             params: params,
7457             defaults: [],
7458             body: body,
7459             rest: null,
7460             generator: false,
7461             expression: false
7462         };
7463     }
7465     // 14 Program
7467     function parseSourceElement() {
7468         var token = lookahead();
7470         if (token.type === Token.Keyword) {
7471             switch (token.value) {
7472             case 'const':
7473             case 'let':
7474                 return parseConstLetDeclaration(token.value);
7475             case 'function':
7476                 return parseFunctionDeclaration();
7477             default:
7478                 return parseStatement();
7479             }
7480         }
7482         if (token.type !== Token.EOF) {
7483             return parseStatement();
7484         }
7485     }
7487     function parseSourceElements() {
7488         var sourceElement, sourceElements = [], token, directive, firstRestricted;
7490         while (index < length) {
7491             token = lookahead();
7492             if (token.type !== Token.StringLiteral) {
7493                 break;
7494             }
7496             sourceElement = parseSourceElement();
7497             sourceElements.push(sourceElement);
7498             if (sourceElement.expression.type !== Syntax.Literal) {
7499                 // this is not directive
7500                 break;
7501             }
7502             directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
7503             if (directive === 'use strict') {
7504                 strict = true;
7505                 if (firstRestricted) {
7506                     throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
7507                 }
7508             } else {
7509                 if (!firstRestricted && token.octal) {
7510                     firstRestricted = token;
7511                 }
7512             }
7513         }
7515         while (index < length) {
7516             sourceElement = parseSourceElement();
7517             if (typeof sourceElement === 'undefined') {
7518                 break;
7519             }
7520             sourceElements.push(sourceElement);
7521         }
7522         return sourceElements;
7523     }
7525     function parseProgram() {
7526         var program;
7527         strict = false;
7528         program = {
7529             type: Syntax.Program,
7530             body: parseSourceElements()
7531         };
7532         return program;
7533     }
7535     // The following functions are needed only when the option to preserve
7536     // the comments is active.
7538     function addComment(type, value, start, end, loc) {
7539         assert(typeof start === 'number', 'Comment must have valid position');
7541         // Because the way the actual token is scanned, often the comments
7542         // (if any) are skipped twice during the lexical analysis.
7543         // Thus, we need to skip adding a comment if the comment array already
7544         // handled it.
7545         if (extra.comments.length > 0) {
7546             if (extra.comments[extra.comments.length - 1].range[1] > start) {
7547                 return;
7548             }
7549         }
7551         extra.comments.push({
7552             type: type,
7553             value: value,
7554             range: [start, end],
7555             loc: loc
7556         });
7557     }
7559     function scanComment() {
7560         var comment, ch, loc, start, blockComment, lineComment;
7562         comment = '';
7563         blockComment = false;
7564         lineComment = false;
7566         while (index < length) {
7567             ch = source[index];
7569             if (lineComment) {
7570                 ch = source[index++];
7571                 if (isLineTerminator(ch)) {
7572                     loc.end = {
7573                         line: lineNumber,
7574                         column: index - lineStart - 1
7575                     };
7576                     lineComment = false;
7577                     addComment('Line', comment, start, index - 1, loc);
7578                     if (ch === '\r' && source[index] === '\n') {
7579                         ++index;
7580                     }
7581                     ++lineNumber;
7582                     lineStart = index;
7583                     comment = '';
7584                 } else if (index >= length) {
7585                     lineComment = false;
7586                     comment += ch;
7587                     loc.end = {
7588                         line: lineNumber,
7589                         column: length - lineStart
7590                     };
7591                     addComment('Line', comment, start, length, loc);
7592                 } else {
7593                     comment += ch;
7594                 }
7595             } else if (blockComment) {
7596                 if (isLineTerminator(ch)) {
7597                     if (ch === '\r' && source[index + 1] === '\n') {
7598                         ++index;
7599                         comment += '\r\n';
7600                     } else {
7601                         comment += ch;
7602                     }
7603                     ++lineNumber;
7604                     ++index;
7605                     lineStart = index;
7606                     if (index >= length) {
7607                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
7608                     }
7609                 } else {
7610                     ch = source[index++];
7611                     if (index >= length) {
7612                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
7613                     }
7614                     comment += ch;
7615                     if (ch === '*') {
7616                         ch = source[index];
7617                         if (ch === '/') {
7618                             comment = comment.substr(0, comment.length - 1);
7619                             blockComment = false;
7620                             ++index;
7621                             loc.end = {
7622                                 line: lineNumber,
7623                                 column: index - lineStart
7624                             };
7625                             addComment('Block', comment, start, index, loc);
7626                             comment = '';
7627                         }
7628                     }
7629                 }
7630             } else if (ch === '/') {
7631                 ch = source[index + 1];
7632                 if (ch === '/') {
7633                     loc = {
7634                         start: {
7635                             line: lineNumber,
7636                             column: index - lineStart
7637                         }
7638                     };
7639                     start = index;
7640                     index += 2;
7641                     lineComment = true;
7642                     if (index >= length) {
7643                         loc.end = {
7644                             line: lineNumber,
7645                             column: index - lineStart
7646                         };
7647                         lineComment = false;
7648                         addComment('Line', comment, start, index, loc);
7649                     }
7650                 } else if (ch === '*') {
7651                     start = index;
7652                     index += 2;
7653                     blockComment = true;
7654                     loc = {
7655                         start: {
7656                             line: lineNumber,
7657                             column: index - lineStart - 2
7658                         }
7659                     };
7660                     if (index >= length) {
7661                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
7662                     }
7663                 } else {
7664                     break;
7665                 }
7666             } else if (isWhiteSpace(ch)) {
7667                 ++index;
7668             } else if (isLineTerminator(ch)) {
7669                 ++index;
7670                 if (ch ===  '\r' && source[index] === '\n') {
7671                     ++index;
7672                 }
7673                 ++lineNumber;
7674                 lineStart = index;
7675             } else {
7676                 break;
7677             }
7678         }
7679     }
7681     function filterCommentLocation() {
7682         var i, entry, comment, comments = [];
7684         for (i = 0; i < extra.comments.length; ++i) {
7685             entry = extra.comments[i];
7686             comment = {
7687                 type: entry.type,
7688                 value: entry.value
7689             };
7690             if (extra.range) {
7691                 comment.range = entry.range;
7692             }
7693             if (extra.loc) {
7694                 comment.loc = entry.loc;
7695             }
7696             comments.push(comment);
7697         }
7699         extra.comments = comments;
7700     }
7702     function collectToken() {
7703         var start, loc, token, range, value;
7705         skipComment();
7706         start = index;
7707         loc = {
7708             start: {
7709                 line: lineNumber,
7710                 column: index - lineStart
7711             }
7712         };
7714         token = extra.advance();
7715         loc.end = {
7716             line: lineNumber,
7717             column: index - lineStart
7718         };
7720         if (token.type !== Token.EOF) {
7721             range = [token.range[0], token.range[1]];
7722             value = sliceSource(token.range[0], token.range[1]);
7723             extra.tokens.push({
7724                 type: TokenName[token.type],
7725                 value: value,
7726                 range: range,
7727                 loc: loc
7728             });
7729         }
7731         return token;
7732     }
7734     function collectRegex() {
7735         var pos, loc, regex, token;
7737         skipComment();
7739         pos = index;
7740         loc = {
7741             start: {
7742                 line: lineNumber,
7743                 column: index - lineStart
7744             }
7745         };
7747         regex = extra.scanRegExp();
7748         loc.end = {
7749             line: lineNumber,
7750             column: index - lineStart
7751         };
7753         // Pop the previous token, which is likely '/' or '/='
7754         if (extra.tokens.length > 0) {
7755             token = extra.tokens[extra.tokens.length - 1];
7756             if (token.range[0] === pos && token.type === 'Punctuator') {
7757                 if (token.value === '/' || token.value === '/=') {
7758                     extra.tokens.pop();
7759                 }
7760             }
7761         }
7763         extra.tokens.push({
7764             type: 'RegularExpression',
7765             value: regex.literal,
7766             range: [pos, index],
7767             loc: loc
7768         });
7770         return regex;
7771     }
7773     function filterTokenLocation() {
7774         var i, entry, token, tokens = [];
7776         for (i = 0; i < extra.tokens.length; ++i) {
7777             entry = extra.tokens[i];
7778             token = {
7779                 type: entry.type,
7780                 value: entry.value
7781             };
7782             if (extra.range) {
7783                 token.range = entry.range;
7784             }
7785             if (extra.loc) {
7786                 token.loc = entry.loc;
7787             }
7788             tokens.push(token);
7789         }
7791         extra.tokens = tokens;
7792     }
7794     function createLiteral(token) {
7795         return {
7796             type: Syntax.Literal,
7797             value: token.value
7798         };
7799     }
7801     function createRawLiteral(token) {
7802         return {
7803             type: Syntax.Literal,
7804             value: token.value,
7805             raw: sliceSource(token.range[0], token.range[1])
7806         };
7807     }
7809     function createLocationMarker() {
7810         var marker = {};
7812         marker.range = [index, index];
7813         marker.loc = {
7814             start: {
7815                 line: lineNumber,
7816                 column: index - lineStart
7817             },
7818             end: {
7819                 line: lineNumber,
7820                 column: index - lineStart
7821             }
7822         };
7824         marker.end = function () {
7825             this.range[1] = index;
7826             this.loc.end.line = lineNumber;
7827             this.loc.end.column = index - lineStart;
7828         };
7830         marker.applyGroup = function (node) {
7831             if (extra.range) {
7832                 node.groupRange = [this.range[0], this.range[1]];
7833             }
7834             if (extra.loc) {
7835                 node.groupLoc = {
7836                     start: {
7837                         line: this.loc.start.line,
7838                         column: this.loc.start.column
7839                     },
7840                     end: {
7841                         line: this.loc.end.line,
7842                         column: this.loc.end.column
7843                     }
7844                 };
7845             }
7846         };
7848         marker.apply = function (node) {
7849             if (extra.range) {
7850                 node.range = [this.range[0], this.range[1]];
7851             }
7852             if (extra.loc) {
7853                 node.loc = {
7854                     start: {
7855                         line: this.loc.start.line,
7856                         column: this.loc.start.column
7857                     },
7858                     end: {
7859                         line: this.loc.end.line,
7860                         column: this.loc.end.column
7861                     }
7862                 };
7863             }
7864         };
7866         return marker;
7867     }
7869     function trackGroupExpression() {
7870         var marker, expr;
7872         skipComment();
7873         marker = createLocationMarker();
7874         expect('(');
7876         expr = parseExpression();
7878         expect(')');
7880         marker.end();
7881         marker.applyGroup(expr);
7883         return expr;
7884     }
7886     function trackLeftHandSideExpression() {
7887         var marker, expr;
7889         skipComment();
7890         marker = createLocationMarker();
7892         expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
7894         while (match('.') || match('[')) {
7895             if (match('[')) {
7896                 expr = {
7897                     type: Syntax.MemberExpression,
7898                     computed: true,
7899                     object: expr,
7900                     property: parseComputedMember()
7901                 };
7902                 marker.end();
7903                 marker.apply(expr);
7904             } else {
7905                 expr = {
7906                     type: Syntax.MemberExpression,
7907                     computed: false,
7908                     object: expr,
7909                     property: parseNonComputedMember()
7910                 };
7911                 marker.end();
7912                 marker.apply(expr);
7913             }
7914         }
7916         return expr;
7917     }
7919     function trackLeftHandSideExpressionAllowCall() {
7920         var marker, expr;
7922         skipComment();
7923         marker = createLocationMarker();
7925         expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
7927         while (match('.') || match('[') || match('(')) {
7928             if (match('(')) {
7929                 expr = {
7930                     type: Syntax.CallExpression,
7931                     callee: expr,
7932                     'arguments': parseArguments()
7933                 };
7934                 marker.end();
7935                 marker.apply(expr);
7936             } else if (match('[')) {
7937                 expr = {
7938                     type: Syntax.MemberExpression,
7939                     computed: true,
7940                     object: expr,
7941                     property: parseComputedMember()
7942                 };
7943                 marker.end();
7944                 marker.apply(expr);
7945             } else {
7946                 expr = {
7947                     type: Syntax.MemberExpression,
7948                     computed: false,
7949                     object: expr,
7950                     property: parseNonComputedMember()
7951                 };
7952                 marker.end();
7953                 marker.apply(expr);
7954             }
7955         }
7957         return expr;
7958     }
7960     function filterGroup(node) {
7961         var n, i, entry;
7963         n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {};
7964         for (i in node) {
7965             if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') {
7966                 entry = node[i];
7967                 if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) {
7968                     n[i] = entry;
7969                 } else {
7970                     n[i] = filterGroup(entry);
7971                 }
7972             }
7973         }
7974         return n;
7975     }
7977     function wrapTrackingFunction(range, loc) {
7979         return function (parseFunction) {
7981             function isBinary(node) {
7982                 return node.type === Syntax.LogicalExpression ||
7983                     node.type === Syntax.BinaryExpression;
7984             }
7986             function visit(node) {
7987                 var start, end;
7989                 if (isBinary(node.left)) {
7990                     visit(node.left);
7991                 }
7992                 if (isBinary(node.right)) {
7993                     visit(node.right);
7994                 }
7996                 if (range) {
7997                     if (node.left.groupRange || node.right.groupRange) {
7998                         start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0];
7999                         end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1];
8000                         node.range = [start, end];
8001                     } else if (typeof node.range === 'undefined') {
8002                         start = node.left.range[0];
8003                         end = node.right.range[1];
8004                         node.range = [start, end];
8005                     }
8006                 }
8007                 if (loc) {
8008                     if (node.left.groupLoc || node.right.groupLoc) {
8009                         start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start;
8010                         end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end;
8011                         node.loc = {
8012                             start: start,
8013                             end: end
8014                         };
8015                     } else if (typeof node.loc === 'undefined') {
8016                         node.loc = {
8017                             start: node.left.loc.start,
8018                             end: node.right.loc.end
8019                         };
8020                     }
8021                 }
8022             }
8024             return function () {
8025                 var marker, node;
8027                 skipComment();
8029                 marker = createLocationMarker();
8030                 node = parseFunction.apply(null, arguments);
8031                 marker.end();
8033                 if (range && typeof node.range === 'undefined') {
8034                     marker.apply(node);
8035                 }
8037                 if (loc && typeof node.loc === 'undefined') {
8038                     marker.apply(node);
8039                 }
8041                 if (isBinary(node)) {
8042                     visit(node);
8043                 }
8045                 return node;
8046             };
8047         };
8048     }
8050     function patch() {
8052         var wrapTracking;
8054         if (extra.comments) {
8055             extra.skipComment = skipComment;
8056             skipComment = scanComment;
8057         }
8059         if (extra.raw) {
8060             extra.createLiteral = createLiteral;
8061             createLiteral = createRawLiteral;
8062         }
8064         if (extra.range || extra.loc) {
8066             extra.parseGroupExpression = parseGroupExpression;
8067             extra.parseLeftHandSideExpression = parseLeftHandSideExpression;
8068             extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall;
8069             parseGroupExpression = trackGroupExpression;
8070             parseLeftHandSideExpression = trackLeftHandSideExpression;
8071             parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall;
8073             wrapTracking = wrapTrackingFunction(extra.range, extra.loc);
8075             extra.parseAdditiveExpression = parseAdditiveExpression;
8076             extra.parseAssignmentExpression = parseAssignmentExpression;
8077             extra.parseBitwiseANDExpression = parseBitwiseANDExpression;
8078             extra.parseBitwiseORExpression = parseBitwiseORExpression;
8079             extra.parseBitwiseXORExpression = parseBitwiseXORExpression;
8080             extra.parseBlock = parseBlock;
8081             extra.parseFunctionSourceElements = parseFunctionSourceElements;
8082             extra.parseCatchClause = parseCatchClause;
8083             extra.parseComputedMember = parseComputedMember;
8084             extra.parseConditionalExpression = parseConditionalExpression;
8085             extra.parseConstLetDeclaration = parseConstLetDeclaration;
8086             extra.parseEqualityExpression = parseEqualityExpression;
8087             extra.parseExpression = parseExpression;
8088             extra.parseForVariableDeclaration = parseForVariableDeclaration;
8089             extra.parseFunctionDeclaration = parseFunctionDeclaration;
8090             extra.parseFunctionExpression = parseFunctionExpression;
8091             extra.parseLogicalANDExpression = parseLogicalANDExpression;
8092             extra.parseLogicalORExpression = parseLogicalORExpression;
8093             extra.parseMultiplicativeExpression = parseMultiplicativeExpression;
8094             extra.parseNewExpression = parseNewExpression;
8095             extra.parseNonComputedProperty = parseNonComputedProperty;
8096             extra.parseObjectProperty = parseObjectProperty;
8097             extra.parseObjectPropertyKey = parseObjectPropertyKey;
8098             extra.parsePostfixExpression = parsePostfixExpression;
8099             extra.parsePrimaryExpression = parsePrimaryExpression;
8100             extra.parseProgram = parseProgram;
8101             extra.parsePropertyFunction = parsePropertyFunction;
8102             extra.parseRelationalExpression = parseRelationalExpression;
8103             extra.parseStatement = parseStatement;
8104             extra.parseShiftExpression = parseShiftExpression;
8105             extra.parseSwitchCase = parseSwitchCase;
8106             extra.parseUnaryExpression = parseUnaryExpression;
8107             extra.parseVariableDeclaration = parseVariableDeclaration;
8108             extra.parseVariableIdentifier = parseVariableIdentifier;
8110             parseAdditiveExpression = wrapTracking(extra.parseAdditiveExpression);
8111             parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression);
8112             parseBitwiseANDExpression = wrapTracking(extra.parseBitwiseANDExpression);
8113             parseBitwiseORExpression = wrapTracking(extra.parseBitwiseORExpression);
8114             parseBitwiseXORExpression = wrapTracking(extra.parseBitwiseXORExpression);
8115             parseBlock = wrapTracking(extra.parseBlock);
8116             parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements);
8117             parseCatchClause = wrapTracking(extra.parseCatchClause);
8118             parseComputedMember = wrapTracking(extra.parseComputedMember);
8119             parseConditionalExpression = wrapTracking(extra.parseConditionalExpression);
8120             parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration);
8121             parseEqualityExpression = wrapTracking(extra.parseEqualityExpression);
8122             parseExpression = wrapTracking(extra.parseExpression);
8123             parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration);
8124             parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration);
8125             parseFunctionExpression = wrapTracking(extra.parseFunctionExpression);
8126             parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression);
8127             parseLogicalANDExpression = wrapTracking(extra.parseLogicalANDExpression);
8128             parseLogicalORExpression = wrapTracking(extra.parseLogicalORExpression);
8129             parseMultiplicativeExpression = wrapTracking(extra.parseMultiplicativeExpression);
8130             parseNewExpression = wrapTracking(extra.parseNewExpression);
8131             parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty);
8132             parseObjectProperty = wrapTracking(extra.parseObjectProperty);
8133             parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey);
8134             parsePostfixExpression = wrapTracking(extra.parsePostfixExpression);
8135             parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression);
8136             parseProgram = wrapTracking(extra.parseProgram);
8137             parsePropertyFunction = wrapTracking(extra.parsePropertyFunction);
8138             parseRelationalExpression = wrapTracking(extra.parseRelationalExpression);
8139             parseStatement = wrapTracking(extra.parseStatement);
8140             parseShiftExpression = wrapTracking(extra.parseShiftExpression);
8141             parseSwitchCase = wrapTracking(extra.parseSwitchCase);
8142             parseUnaryExpression = wrapTracking(extra.parseUnaryExpression);
8143             parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration);
8144             parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier);
8145         }
8147         if (typeof extra.tokens !== 'undefined') {
8148             extra.advance = advance;
8149             extra.scanRegExp = scanRegExp;
8151             advance = collectToken;
8152             scanRegExp = collectRegex;
8153         }
8154     }
8156     function unpatch() {
8157         if (typeof extra.skipComment === 'function') {
8158             skipComment = extra.skipComment;
8159         }
8161         if (extra.raw) {
8162             createLiteral = extra.createLiteral;
8163         }
8165         if (extra.range || extra.loc) {
8166             parseAdditiveExpression = extra.parseAdditiveExpression;
8167             parseAssignmentExpression = extra.parseAssignmentExpression;
8168             parseBitwiseANDExpression = extra.parseBitwiseANDExpression;
8169             parseBitwiseORExpression = extra.parseBitwiseORExpression;
8170             parseBitwiseXORExpression = extra.parseBitwiseXORExpression;
8171             parseBlock = extra.parseBlock;
8172             parseFunctionSourceElements = extra.parseFunctionSourceElements;
8173             parseCatchClause = extra.parseCatchClause;
8174             parseComputedMember = extra.parseComputedMember;
8175             parseConditionalExpression = extra.parseConditionalExpression;
8176             parseConstLetDeclaration = extra.parseConstLetDeclaration;
8177             parseEqualityExpression = extra.parseEqualityExpression;
8178             parseExpression = extra.parseExpression;
8179             parseForVariableDeclaration = extra.parseForVariableDeclaration;
8180             parseFunctionDeclaration = extra.parseFunctionDeclaration;
8181             parseFunctionExpression = extra.parseFunctionExpression;
8182             parseGroupExpression = extra.parseGroupExpression;
8183             parseLeftHandSideExpression = extra.parseLeftHandSideExpression;
8184             parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall;
8185             parseLogicalANDExpression = extra.parseLogicalANDExpression;
8186             parseLogicalORExpression = extra.parseLogicalORExpression;
8187             parseMultiplicativeExpression = extra.parseMultiplicativeExpression;
8188             parseNewExpression = extra.parseNewExpression;
8189             parseNonComputedProperty = extra.parseNonComputedProperty;
8190             parseObjectProperty = extra.parseObjectProperty;
8191             parseObjectPropertyKey = extra.parseObjectPropertyKey;
8192             parsePrimaryExpression = extra.parsePrimaryExpression;
8193             parsePostfixExpression = extra.parsePostfixExpression;
8194             parseProgram = extra.parseProgram;
8195             parsePropertyFunction = extra.parsePropertyFunction;
8196             parseRelationalExpression = extra.parseRelationalExpression;
8197             parseStatement = extra.parseStatement;
8198             parseShiftExpression = extra.parseShiftExpression;
8199             parseSwitchCase = extra.parseSwitchCase;
8200             parseUnaryExpression = extra.parseUnaryExpression;
8201             parseVariableDeclaration = extra.parseVariableDeclaration;
8202             parseVariableIdentifier = extra.parseVariableIdentifier;
8203         }
8205         if (typeof extra.scanRegExp === 'function') {
8206             advance = extra.advance;
8207             scanRegExp = extra.scanRegExp;
8208         }
8209     }
8211     function stringToArray(str) {
8212         var length = str.length,
8213             result = [],
8214             i;
8215         for (i = 0; i < length; ++i) {
8216             result[i] = str.charAt(i);
8217         }
8218         return result;
8219     }
8221     function parse(code, options) {
8222         var program, toString;
8224         toString = String;
8225         if (typeof code !== 'string' && !(code instanceof String)) {
8226             code = toString(code);
8227         }
8229         source = code;
8230         index = 0;
8231         lineNumber = (source.length > 0) ? 1 : 0;
8232         lineStart = 0;
8233         length = source.length;
8234         buffer = null;
8235         state = {
8236             allowIn: true,
8237             labelSet: {},
8238             inFunctionBody: false,
8239             inIteration: false,
8240             inSwitch: false
8241         };
8243         extra = {};
8244         if (typeof options !== 'undefined') {
8245             extra.range = (typeof options.range === 'boolean') && options.range;
8246             extra.loc = (typeof options.loc === 'boolean') && options.loc;
8247             extra.raw = (typeof options.raw === 'boolean') && options.raw;
8248             if (typeof options.tokens === 'boolean' && options.tokens) {
8249                 extra.tokens = [];
8250             }
8251             if (typeof options.comment === 'boolean' && options.comment) {
8252                 extra.comments = [];
8253             }
8254             if (typeof options.tolerant === 'boolean' && options.tolerant) {
8255                 extra.errors = [];
8256             }
8257         }
8259         if (length > 0) {
8260             if (typeof source[0] === 'undefined') {
8261                 // Try first to convert to a string. This is good as fast path
8262                 // for old IE which understands string indexing for string
8263                 // literals only and not for string object.
8264                 if (code instanceof String) {
8265                     source = code.valueOf();
8266                 }
8268                 // Force accessing the characters via an array.
8269                 if (typeof source[0] === 'undefined') {
8270                     source = stringToArray(code);
8271                 }
8272             }
8273         }
8275         patch();
8276         try {
8277             program = parseProgram();
8278             if (typeof extra.comments !== 'undefined') {
8279                 filterCommentLocation();
8280                 program.comments = extra.comments;
8281             }
8282             if (typeof extra.tokens !== 'undefined') {
8283                 filterTokenLocation();
8284                 program.tokens = extra.tokens;
8285             }
8286             if (typeof extra.errors !== 'undefined') {
8287                 program.errors = extra.errors;
8288             }
8289             if (extra.range || extra.loc) {
8290                 program.body = filterGroup(program.body);
8291             }
8292         } catch (e) {
8293             throw e;
8294         } finally {
8295             unpatch();
8296             extra = {};
8297         }
8299         return program;
8300     }
8302     // Sync with package.json.
8303     exports.version = '1.0.3';
8305     exports.parse = parse;
8307     // Deep copy.
8308     exports.Syntax = (function () {
8309         var name, types = {};
8311         if (typeof Object.create === 'function') {
8312             types = Object.create(null);
8313         }
8315         for (name in Syntax) {
8316             if (Syntax.hasOwnProperty(name)) {
8317                 types[name] = Syntax[name];
8318             }
8319         }
8321         if (typeof Object.freeze === 'function') {
8322             Object.freeze(types);
8323         }
8325         return types;
8326     }());
8328 }));
8329 /* vim: set sw=4 ts=4 et tw=80 : */
8331  * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
8332  * Available via the MIT or new BSD license.
8333  * see: http://github.com/jrburke/requirejs for details
8334  */
8336 /*global define, Reflect */
8339  * xpcshell has a smaller stack on linux and windows (1MB vs 9MB on mac),
8340  * and the recursive nature of esprima can cause it to overflow pretty
8341  * quickly. So favor it built in Reflect parser:
8342  * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
8343  */
8344 define('esprimaAdapter', ['./esprima', 'env'], function (esprima, env) {
8345     if (env.get() === 'xpconnect' && typeof Reflect !== 'undefined') {
8346         return Reflect;
8347     } else {
8348         return esprima;
8349     }
8351 define('uglifyjs/consolidator', ["require", "exports", "module", "./parse-js", "./process"], function(require, exports, module) {
8353  * @preserve Copyright 2012 Robert Gust-Bardon <http://robert.gust-bardon.org/>.
8354  * All rights reserved.
8356  * Redistribution and use in source and binary forms, with or without
8357  * modification, are permitted provided that the following conditions
8358  * are met:
8360  *     * Redistributions of source code must retain the above
8361  *       copyright notice, this list of conditions and the following
8362  *       disclaimer.
8364  *     * Redistributions in binary form must reproduce the above
8365  *       copyright notice, this list of conditions and the following
8366  *       disclaimer in the documentation and/or other materials
8367  *       provided with the distribution.
8369  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
8370  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8371  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
8372  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
8373  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
8374  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
8375  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
8376  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
8377  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
8378  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
8379  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8380  * SUCH DAMAGE.
8381  */
8384  * @fileoverview Enhances <a href="https://github.com/mishoo/UglifyJS/"
8385  * >UglifyJS</a> with consolidation of null, Boolean, and String values.
8386  * <p>Also known as aliasing, this feature has been deprecated in <a href=
8387  * "http://closure-compiler.googlecode.com/">the Closure Compiler</a> since its
8388  * initial release, where it is unavailable from the <abbr title=
8389  * "command line interface">CLI</a>. The Closure Compiler allows one to log and
8390  * influence this process. In contrast, this implementation does not introduce
8391  * any variable declarations in global code and derives String values from
8392  * identifier names used as property accessors.</p>
8393  * <p>Consolidating literals may worsen the data compression ratio when an <a
8394  * href="http://tools.ietf.org/html/rfc2616#section-3.5">encoding
8395  * transformation</a> is applied. For instance, <a href=
8396  * "http://code.jquery.com/jquery-1.7.1.js">jQuery 1.7.1</a> takes 248235 bytes.
8397  * Building it with <a href="https://github.com/mishoo/UglifyJS/tarball/v1.2.5">
8398  * UglifyJS v1.2.5</a> results in 93647 bytes (37.73% of the original) which are
8399  * then compressed to 33154 bytes (13.36% of the original) using <a href=
8400  * "http://linux.die.net/man/1/gzip">gzip(1)</a>. Building it with the same
8401  * version of UglifyJS 1.2.5 patched with the implementation of consolidation
8402  * results in 80784 bytes (a decrease of 12863 bytes, i.e. 13.74%, in comparison
8403  * to the aforementioned 93647 bytes) which are then compressed to 34013 bytes
8404  * (an increase of 859 bytes, i.e. 2.59%, in comparison to the aforementioned
8405  * 33154 bytes).</p>
8406  * <p>Written in <a href="http://es5.github.com/#x4.2.2">the strict variant</a>
8407  * of <a href="http://es5.github.com/">ECMA-262 5.1 Edition</a>. Encoded in <a
8408  * href="http://tools.ietf.org/html/rfc3629">UTF-8</a>. Follows <a href=
8409  * "http://google-styleguide.googlecode.com/svn-history/r76/trunk/javascriptguide.xml"
8410  * >Revision 2.28 of the Google JavaScript Style Guide</a> (except for the
8411  * discouraged use of the {@code function} tag and the {@code namespace} tag).
8412  * 100% typed for the <a href=
8413  * "http://closure-compiler.googlecode.com/files/compiler-20120123.tar.gz"
8414  * >Closure Compiler Version 1741</a>.</p>
8415  * <p>Should you find this software useful, please consider <a href=
8416  * "https://paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=JZLW72X8FD4WG"
8417  * >a donation</a>.</p>
8418  * @author follow.me@RGustBardon (Robert Gust-Bardon)
8419  * @supported Tested with:
8420  *     <ul>
8421  *     <li><a href="http://nodejs.org/dist/v0.6.10/">Node v0.6.10</a>,</li>
8422  *     <li><a href="https://github.com/mishoo/UglifyJS/tarball/v1.2.5">UglifyJS
8423  *       v1.2.5</a>.</li>
8424  *     </ul>
8425  */
8427 /*global console:false, exports:true, module:false, require:false */
8428 /*jshint sub:true */
8430  * Consolidates null, Boolean, and String values found inside an <abbr title=
8431  * "abstract syntax tree">AST</abbr>.
8432  * @param {!TSyntacticCodeUnit} oAbstractSyntaxTree An array-like object
8433  *     representing an <abbr title="abstract syntax tree">AST</abbr>.
8434  * @return {!TSyntacticCodeUnit} An array-like object representing an <abbr
8435  *     title="abstract syntax tree">AST</abbr> with its null, Boolean, and
8436  *     String values consolidated.
8437  */
8438 // TODO(user) Consolidation of mathematical values found in numeric literals.
8439 // TODO(user) Unconsolidation.
8440 // TODO(user) Consolidation of ECMA-262 6th Edition programs.
8441 // TODO(user) Rewrite in ECMA-262 6th Edition.
8442 exports['ast_consolidate'] = function(oAbstractSyntaxTree) {
8443   'use strict';
8444   /*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true,
8445         latedef:true, newcap:true, noarge:true, noempty:true, nonew:true,
8446         onevar:true, plusplus:true, regexp:true, undef:true, strict:true,
8447         sub:false, trailing:true */
8449   var _,
8450       /**
8451        * A record consisting of data about one or more source elements.
8452        * @constructor
8453        * @nosideeffects
8454        */
8455       TSourceElementsData = function() {
8456         /**
8457          * The category of the elements.
8458          * @type {number}
8459          * @see ESourceElementCategories
8460          */
8461         this.nCategory = ESourceElementCategories.N_OTHER;
8462         /**
8463          * The number of occurrences (within the elements) of each primitive
8464          * value that could be consolidated.
8465          * @type {!Array.<!Object.<string, number>>}
8466          */
8467         this.aCount = [];
8468         this.aCount[EPrimaryExpressionCategories.N_IDENTIFIER_NAMES] = {};
8469         this.aCount[EPrimaryExpressionCategories.N_STRING_LITERALS] = {};
8470         this.aCount[EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS] =
8471             {};
8472         /**
8473          * Identifier names found within the elements.
8474          * @type {!Array.<string>}
8475          */
8476         this.aIdentifiers = [];
8477         /**
8478          * Prefixed representation Strings of each primitive value that could be
8479          * consolidated within the elements.
8480          * @type {!Array.<string>}
8481          */
8482         this.aPrimitiveValues = [];
8483       },
8484       /**
8485        * A record consisting of data about a primitive value that could be
8486        * consolidated.
8487        * @constructor
8488        * @nosideeffects
8489        */
8490       TPrimitiveValue = function() {
8491         /**
8492          * The difference in the number of terminal symbols between the original
8493          * source text and the one with the primitive value consolidated. If the
8494          * difference is positive, the primitive value is considered worthwhile.
8495          * @type {number}
8496          */
8497         this.nSaving = 0;
8498         /**
8499          * An identifier name of the variable that will be declared and assigned
8500          * the primitive value if the primitive value is consolidated.
8501          * @type {string}
8502          */
8503         this.sName = '';
8504       },
8505       /**
8506        * A record consisting of data on what to consolidate within the range of
8507        * source elements that is currently being considered.
8508        * @constructor
8509        * @nosideeffects
8510        */
8511       TSolution = function() {
8512         /**
8513          * An object whose keys are prefixed representation Strings of each
8514          * primitive value that could be consolidated within the elements and
8515          * whose values are corresponding data about those primitive values.
8516          * @type {!Object.<string, {nSaving: number, sName: string}>}
8517          * @see TPrimitiveValue
8518          */
8519         this.oPrimitiveValues = {};
8520         /**
8521          * The difference in the number of terminal symbols between the original
8522          * source text and the one with all the worthwhile primitive values
8523          * consolidated.
8524          * @type {number}
8525          * @see TPrimitiveValue#nSaving
8526          */
8527         this.nSavings = 0;
8528       },
8529       /**
8530        * The processor of <abbr title="abstract syntax tree">AST</abbr>s found
8531        * in UglifyJS.
8532        * @namespace
8533        * @type {!TProcessor}
8534        */
8535       oProcessor = (/** @type {!TProcessor} */ require('./process')),
8536       /**
8537        * A record consisting of a number of constants that represent the
8538        * difference in the number of terminal symbols between a source text with
8539        * a modified syntactic code unit and the original one.
8540        * @namespace
8541        * @type {!Object.<string, number>}
8542        */
8543       oWeights = {
8544         /**
8545          * The difference in the number of punctuators required by the bracket
8546          * notation and the dot notation.
8547          * <p><code>'[]'.length - '.'.length</code></p>
8548          * @const
8549          * @type {number}
8550          */
8551         N_PROPERTY_ACCESSOR: 1,
8552         /**
8553          * The number of punctuators required by a variable declaration with an
8554          * initialiser.
8555          * <p><code>':'.length + ';'.length</code></p>
8556          * @const
8557          * @type {number}
8558          */
8559         N_VARIABLE_DECLARATION: 2,
8560         /**
8561          * The number of terminal symbols required to introduce a variable
8562          * statement (excluding its variable declaration list).
8563          * <p><code>'var '.length</code></p>
8564          * @const
8565          * @type {number}
8566          */
8567         N_VARIABLE_STATEMENT_AFFIXATION: 4,
8568         /**
8569          * The number of terminal symbols needed to enclose source elements
8570          * within a function call with no argument values to a function with an
8571          * empty parameter list.
8572          * <p><code>'(function(){}());'.length</code></p>
8573          * @const
8574          * @type {number}
8575          */
8576         N_CLOSURE: 17
8577       },
8578       /**
8579        * Categories of primary expressions from which primitive values that
8580        * could be consolidated are derivable.
8581        * @namespace
8582        * @enum {number}
8583        */
8584       EPrimaryExpressionCategories = {
8585         /**
8586          * Identifier names used as property accessors.
8587          * @type {number}
8588          */
8589         N_IDENTIFIER_NAMES: 0,
8590         /**
8591          * String literals.
8592          * @type {number}
8593          */
8594         N_STRING_LITERALS: 1,
8595         /**
8596          * Null and Boolean literals.
8597          * @type {number}
8598          */
8599         N_NULL_AND_BOOLEAN_LITERALS: 2
8600       },
8601       /**
8602        * Prefixes of primitive values that could be consolidated.
8603        * The String values of the prefixes must have same number of characters.
8604        * The prefixes must not be used in any properties defined in any version
8605        * of <a href=
8606        * "http://www.ecma-international.org/publications/standards/Ecma-262.htm"
8607        * >ECMA-262</a>.
8608        * @namespace
8609        * @enum {string}
8610        */
8611       EValuePrefixes = {
8612         /**
8613          * Identifies String values.
8614          * @type {string}
8615          */
8616         S_STRING: '#S',
8617         /**
8618          * Identifies null and Boolean values.
8619          * @type {string}
8620          */
8621         S_SYMBOLIC: '#O'
8622       },
8623       /**
8624        * Categories of source elements in terms of their appropriateness of
8625        * having their primitive values consolidated.
8626        * @namespace
8627        * @enum {number}
8628        */
8629       ESourceElementCategories = {
8630         /**
8631          * Identifies a source element that includes the <a href=
8632          * "http://es5.github.com/#x12.10">{@code with}</a> statement.
8633          * @type {number}
8634          */
8635         N_WITH: 0,
8636         /**
8637          * Identifies a source element that includes the <a href=
8638          * "http://es5.github.com/#x15.1.2.1">{@code eval}</a> identifier name.
8639          * @type {number}
8640          */
8641         N_EVAL: 1,
8642         /**
8643          * Identifies a source element that must be excluded from the process
8644          * unless its whole scope is examined.
8645          * @type {number}
8646          */
8647         N_EXCLUDABLE: 2,
8648         /**
8649          * Identifies source elements not posing any problems.
8650          * @type {number}
8651          */
8652         N_OTHER: 3
8653       },
8654       /**
8655        * The list of literals (other than the String ones) whose primitive
8656        * values can be consolidated.
8657        * @const
8658        * @type {!Array.<string>}
8659        */
8660       A_OTHER_SUBSTITUTABLE_LITERALS = [
8661         'null',   // The null literal.
8662         'false',  // The Boolean literal {@code false}.
8663         'true'    // The Boolean literal {@code true}.
8664       ];
8666   (/**
8667     * Consolidates all worthwhile primitive values in a syntactic code unit.
8668     * @param {!TSyntacticCodeUnit} oSyntacticCodeUnit An array-like object
8669     *     representing the branch of the abstract syntax tree representing the
8670     *     syntactic code unit along with its scope.
8671     * @see TPrimitiveValue#nSaving
8672     */
8673    function fExamineSyntacticCodeUnit(oSyntacticCodeUnit) {
8674      var _,
8675          /**
8676           * Indicates whether the syntactic code unit represents global code.
8677           * @type {boolean}
8678           */
8679          bIsGlobal = 'toplevel' === oSyntacticCodeUnit[0],
8680          /**
8681           * Indicates whether the whole scope is being examined.
8682           * @type {boolean}
8683           */
8684          bIsWhollyExaminable = !bIsGlobal,
8685          /**
8686           * An array-like object representing source elements that constitute a
8687           * syntactic code unit.
8688           * @type {!TSyntacticCodeUnit}
8689           */
8690          oSourceElements,
8691          /**
8692           * A record consisting of data about the source element that is
8693           * currently being examined.
8694           * @type {!TSourceElementsData}
8695           */
8696          oSourceElementData,
8697          /**
8698           * The scope of the syntactic code unit.
8699           * @type {!TScope}
8700           */
8701          oScope,
8702          /**
8703           * An instance of an object that allows the traversal of an <abbr
8704           * title="abstract syntax tree">AST</abbr>.
8705           * @type {!TWalker}
8706           */
8707          oWalker,
8708          /**
8709           * An object encompassing collections of functions used during the
8710           * traversal of an <abbr title="abstract syntax tree">AST</abbr>.
8711           * @namespace
8712           * @type {!Object.<string, !Object.<string, function(...[*])>>}
8713           */
8714          oWalkers = {
8715            /**
8716             * A collection of functions used during the surveyance of source
8717             * elements.
8718             * @namespace
8719             * @type {!Object.<string, function(...[*])>}
8720             */
8721            oSurveySourceElement: {
8722              /**#nocode+*/  // JsDoc Toolkit 2.4.0 hides some of the keys.
8723              /**
8724               * Classifies the source element as excludable if it does not
8725               * contain a {@code with} statement or the {@code eval} identifier
8726               * name. Adds the identifier of the function and its formal
8727               * parameters to the list of identifier names found.
8728               * @param {string} sIdentifier The identifier of the function.
8729               * @param {!Array.<string>} aFormalParameterList Formal parameters.
8730               * @param {!TSyntacticCodeUnit} oFunctionBody Function code.
8731               */
8732              'defun': function(
8733                  sIdentifier,
8734                  aFormalParameterList,
8735                  oFunctionBody) {
8736                fClassifyAsExcludable();
8737                fAddIdentifier(sIdentifier);
8738                aFormalParameterList.forEach(fAddIdentifier);
8739              },
8740              /**
8741               * Increments the count of the number of occurrences of the String
8742               * value that is equivalent to the sequence of terminal symbols
8743               * that constitute the encountered identifier name.
8744               * @param {!TSyntacticCodeUnit} oExpression The nonterminal
8745               *     MemberExpression.
8746               * @param {string} sIdentifierName The identifier name used as the
8747               *     property accessor.
8748               * @return {!Array} The encountered branch of an <abbr title=
8749               *     "abstract syntax tree">AST</abbr> with its nonterminal
8750               *     MemberExpression traversed.
8751               */
8752              'dot': function(oExpression, sIdentifierName) {
8753                fCountPrimaryExpression(
8754                    EPrimaryExpressionCategories.N_IDENTIFIER_NAMES,
8755                    EValuePrefixes.S_STRING + sIdentifierName);
8756                return ['dot', oWalker.walk(oExpression), sIdentifierName];
8757              },
8758              /**
8759               * Adds the optional identifier of the function and its formal
8760               * parameters to the list of identifier names found.
8761               * @param {?string} sIdentifier The optional identifier of the
8762               *     function.
8763               * @param {!Array.<string>} aFormalParameterList Formal parameters.
8764               * @param {!TSyntacticCodeUnit} oFunctionBody Function code.
8765               */
8766              'function': function(
8767                  sIdentifier,
8768                  aFormalParameterList,
8769                  oFunctionBody) {
8770                if ('string' === typeof sIdentifier) {
8771                  fAddIdentifier(sIdentifier);
8772                }
8773                aFormalParameterList.forEach(fAddIdentifier);
8774              },
8775              /**
8776               * Either increments the count of the number of occurrences of the
8777               * encountered null or Boolean value or classifies a source element
8778               * as containing the {@code eval} identifier name.
8779               * @param {string} sIdentifier The identifier encountered.
8780               */
8781              'name': function(sIdentifier) {
8782                if (-1 !== A_OTHER_SUBSTITUTABLE_LITERALS.indexOf(sIdentifier)) {
8783                  fCountPrimaryExpression(
8784                      EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS,
8785                      EValuePrefixes.S_SYMBOLIC + sIdentifier);
8786                } else {
8787                  if ('eval' === sIdentifier) {
8788                    oSourceElementData.nCategory =
8789                        ESourceElementCategories.N_EVAL;
8790                  }
8791                  fAddIdentifier(sIdentifier);
8792                }
8793              },
8794              /**
8795               * Classifies the source element as excludable if it does not
8796               * contain a {@code with} statement or the {@code eval} identifier
8797               * name.
8798               * @param {TSyntacticCodeUnit} oExpression The expression whose
8799               *     value is to be returned.
8800               */
8801              'return': function(oExpression) {
8802                fClassifyAsExcludable();
8803              },
8804              /**
8805               * Increments the count of the number of occurrences of the
8806               * encountered String value.
8807               * @param {string} sStringValue The String value of the string
8808               *     literal encountered.
8809               */
8810              'string': function(sStringValue) {
8811                if (sStringValue.length > 0) {
8812                  fCountPrimaryExpression(
8813                      EPrimaryExpressionCategories.N_STRING_LITERALS,
8814                      EValuePrefixes.S_STRING + sStringValue);
8815                }
8816              },
8817              /**
8818               * Adds the identifier reserved for an exception to the list of
8819               * identifier names found.
8820               * @param {!TSyntacticCodeUnit} oTry A block of code in which an
8821               *     exception can occur.
8822               * @param {Array} aCatch The identifier reserved for an exception
8823               *     and a block of code to handle the exception.
8824               * @param {TSyntacticCodeUnit} oFinally An optional block of code
8825               *     to be evaluated regardless of whether an exception occurs.
8826               */
8827              'try': function(oTry, aCatch, oFinally) {
8828                if (Array.isArray(aCatch)) {
8829                  fAddIdentifier(aCatch[0]);
8830                }
8831              },
8832              /**
8833               * Classifies the source element as excludable if it does not
8834               * contain a {@code with} statement or the {@code eval} identifier
8835               * name. Adds the identifier of each declared variable to the list
8836               * of identifier names found.
8837               * @param {!Array.<!Array>} aVariableDeclarationList Variable
8838               *     declarations.
8839               */
8840              'var': function(aVariableDeclarationList) {
8841                fClassifyAsExcludable();
8842                aVariableDeclarationList.forEach(fAddVariable);
8843              },
8844              /**
8845               * Classifies a source element as containing the {@code with}
8846               * statement.
8847               * @param {!TSyntacticCodeUnit} oExpression An expression whose
8848               *     value is to be converted to a value of type Object and
8849               *     become the binding object of a new object environment
8850               *     record of a new lexical environment in which the statement
8851               *     is to be executed.
8852               * @param {!TSyntacticCodeUnit} oStatement The statement to be
8853               *     executed in the augmented lexical environment.
8854               * @return {!Array} An empty array to stop the traversal.
8855               */
8856              'with': function(oExpression, oStatement) {
8857                oSourceElementData.nCategory = ESourceElementCategories.N_WITH;
8858                return [];
8859              }
8860              /**#nocode-*/  // JsDoc Toolkit 2.4.0 hides some of the keys.
8861            },
8862            /**
8863             * A collection of functions used while looking for nested functions.
8864             * @namespace
8865             * @type {!Object.<string, function(...[*])>}
8866             */
8867            oExamineFunctions: {
8868              /**#nocode+*/  // JsDoc Toolkit 2.4.0 hides some of the keys.
8869              /**
8870               * Orders an examination of a nested function declaration.
8871               * @this {!TSyntacticCodeUnit} An array-like object representing
8872               *     the branch of an <abbr title="abstract syntax tree"
8873               *     >AST</abbr> representing the syntactic code unit along with
8874               *     its scope.
8875               * @return {!Array} An empty array to stop the traversal.
8876               */
8877              'defun': function() {
8878                fExamineSyntacticCodeUnit(this);
8879                return [];
8880              },
8881              /**
8882               * Orders an examination of a nested function expression.
8883               * @this {!TSyntacticCodeUnit} An array-like object representing
8884               *     the branch of an <abbr title="abstract syntax tree"
8885               *     >AST</abbr> representing the syntactic code unit along with
8886               *     its scope.
8887               * @return {!Array} An empty array to stop the traversal.
8888               */
8889              'function': function() {
8890                fExamineSyntacticCodeUnit(this);
8891                return [];
8892              }
8893              /**#nocode-*/  // JsDoc Toolkit 2.4.0 hides some of the keys.
8894            }
8895          },
8896          /**
8897           * Records containing data about source elements.
8898           * @type {Array.<TSourceElementsData>}
8899           */
8900          aSourceElementsData = [],
8901          /**
8902           * The index (in the source text order) of the source element
8903           * immediately following a <a href="http://es5.github.com/#x14.1"
8904           * >Directive Prologue</a>.
8905           * @type {number}
8906           */
8907          nAfterDirectivePrologue = 0,
8908          /**
8909           * The index (in the source text order) of the source element that is
8910           * currently being considered.
8911           * @type {number}
8912           */
8913          nPosition,
8914          /**
8915           * The index (in the source text order) of the source element that is
8916           * the last element of the range of source elements that is currently
8917           * being considered.
8918           * @type {(undefined|number)}
8919           */
8920          nTo,
8921          /**
8922           * Initiates the traversal of a source element.
8923           * @param {!TWalker} oWalker An instance of an object that allows the
8924           *     traversal of an abstract syntax tree.
8925           * @param {!TSyntacticCodeUnit} oSourceElement A source element from
8926           *     which the traversal should commence.
8927           * @return {function(): !TSyntacticCodeUnit} A function that is able to
8928           *     initiate the traversal from a given source element.
8929           */
8930          cContext = function(oWalker, oSourceElement) {
8931            /**
8932             * @return {!TSyntacticCodeUnit} A function that is able to
8933             *     initiate the traversal from a given source element.
8934             */
8935            var fLambda = function() {
8936              return oWalker.walk(oSourceElement);
8937            };
8939            return fLambda;
8940          },
8941          /**
8942           * Classifies the source element as excludable if it does not
8943           * contain a {@code with} statement or the {@code eval} identifier
8944           * name.
8945           */
8946          fClassifyAsExcludable = function() {
8947            if (oSourceElementData.nCategory ===
8948                ESourceElementCategories.N_OTHER) {
8949              oSourceElementData.nCategory =
8950                  ESourceElementCategories.N_EXCLUDABLE;
8951            }
8952          },
8953          /**
8954           * Adds an identifier to the list of identifier names found.
8955           * @param {string} sIdentifier The identifier to be added.
8956           */
8957          fAddIdentifier = function(sIdentifier) {
8958            if (-1 === oSourceElementData.aIdentifiers.indexOf(sIdentifier)) {
8959              oSourceElementData.aIdentifiers.push(sIdentifier);
8960            }
8961          },
8962          /**
8963           * Adds the identifier of a variable to the list of identifier names
8964           * found.
8965           * @param {!Array} aVariableDeclaration A variable declaration.
8966           */
8967          fAddVariable = function(aVariableDeclaration) {
8968            fAddIdentifier(/** @type {string} */ aVariableDeclaration[0]);
8969          },
8970          /**
8971           * Increments the count of the number of occurrences of the prefixed
8972           * String representation attributed to the primary expression.
8973           * @param {number} nCategory The category of the primary expression.
8974           * @param {string} sName The prefixed String representation attributed
8975           *     to the primary expression.
8976           */
8977          fCountPrimaryExpression = function(nCategory, sName) {
8978            if (!oSourceElementData.aCount[nCategory].hasOwnProperty(sName)) {
8979              oSourceElementData.aCount[nCategory][sName] = 0;
8980              if (-1 === oSourceElementData.aPrimitiveValues.indexOf(sName)) {
8981                oSourceElementData.aPrimitiveValues.push(sName);
8982              }
8983            }
8984            oSourceElementData.aCount[nCategory][sName] += 1;
8985          },
8986          /**
8987           * Consolidates all worthwhile primitive values in a range of source
8988           *     elements.
8989           * @param {number} nFrom The index (in the source text order) of the
8990           *     source element that is the first element of the range.
8991           * @param {number} nTo The index (in the source text order) of the
8992           *     source element that is the last element of the range.
8993           * @param {boolean} bEnclose Indicates whether the range should be
8994           *     enclosed within a function call with no argument values to a
8995           *     function with an empty parameter list if any primitive values
8996           *     are consolidated.
8997           * @see TPrimitiveValue#nSaving
8998           */
8999          fExamineSourceElements = function(nFrom, nTo, bEnclose) {
9000            var _,
9001                /**
9002                 * The index of the last mangled name.
9003                 * @type {number}
9004                 */
9005                nIndex = oScope.cname,
9006                /**
9007                 * The index of the source element that is currently being
9008                 * considered.
9009                 * @type {number}
9010                 */
9011                nPosition,
9012                /**
9013                 * A collection of functions used during the consolidation of
9014                 * primitive values and identifier names used as property
9015                 * accessors.
9016                 * @namespace
9017                 * @type {!Object.<string, function(...[*])>}
9018                 */
9019                oWalkersTransformers = {
9020                  /**
9021                   * If the String value that is equivalent to the sequence of
9022                   * terminal symbols that constitute the encountered identifier
9023                   * name is worthwhile, a syntactic conversion from the dot
9024                   * notation to the bracket notation ensues with that sequence
9025                   * being substituted by an identifier name to which the value
9026                   * is assigned.
9027                   * Applies to property accessors that use the dot notation.
9028                   * @param {!TSyntacticCodeUnit} oExpression The nonterminal
9029                   *     MemberExpression.
9030                   * @param {string} sIdentifierName The identifier name used as
9031                   *     the property accessor.
9032                   * @return {!Array} A syntactic code unit that is equivalent to
9033                   *     the one encountered.
9034                   * @see TPrimitiveValue#nSaving
9035                   */
9036                  'dot': function(oExpression, sIdentifierName) {
9037                    /**
9038                     * The prefixed String value that is equivalent to the
9039                     * sequence of terminal symbols that constitute the
9040                     * encountered identifier name.
9041                     * @type {string}
9042                     */
9043                    var sPrefixed = EValuePrefixes.S_STRING + sIdentifierName;
9045                    return oSolutionBest.oPrimitiveValues.hasOwnProperty(
9046                        sPrefixed) &&
9047                        oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ?
9048                        ['sub',
9049                         oWalker.walk(oExpression),
9050                         ['name',
9051                          oSolutionBest.oPrimitiveValues[sPrefixed].sName]] :
9052                        ['dot', oWalker.walk(oExpression), sIdentifierName];
9053                  },
9054                  /**
9055                   * If the encountered identifier is a null or Boolean literal
9056                   * and its value is worthwhile, the identifier is substituted
9057                   * by an identifier name to which that value is assigned.
9058                   * Applies to identifier names.
9059                   * @param {string} sIdentifier The identifier encountered.
9060                   * @return {!Array} A syntactic code unit that is equivalent to
9061                   *     the one encountered.
9062                   * @see TPrimitiveValue#nSaving
9063                   */
9064                  'name': function(sIdentifier) {
9065                    /**
9066                     * The prefixed representation String of the identifier.
9067                     * @type {string}
9068                     */
9069                    var sPrefixed = EValuePrefixes.S_SYMBOLIC + sIdentifier;
9071                    return [
9072                      'name',
9073                      oSolutionBest.oPrimitiveValues.hasOwnProperty(sPrefixed) &&
9074                      oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ?
9075                      oSolutionBest.oPrimitiveValues[sPrefixed].sName :
9076                      sIdentifier
9077                    ];
9078                  },
9079                  /**
9080                   * If the encountered String value is worthwhile, it is
9081                   * substituted by an identifier name to which that value is
9082                   * assigned.
9083                   * Applies to String values.
9084                   * @param {string} sStringValue The String value of the string
9085                   *     literal encountered.
9086                   * @return {!Array} A syntactic code unit that is equivalent to
9087                   *     the one encountered.
9088                   * @see TPrimitiveValue#nSaving
9089                   */
9090                  'string': function(sStringValue) {
9091                    /**
9092                     * The prefixed representation String of the primitive value
9093                     * of the literal.
9094                     * @type {string}
9095                     */
9096                    var sPrefixed =
9097                        EValuePrefixes.S_STRING + sStringValue;
9099                    return oSolutionBest.oPrimitiveValues.hasOwnProperty(
9100                        sPrefixed) &&
9101                        oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ?
9102                        ['name',
9103                         oSolutionBest.oPrimitiveValues[sPrefixed].sName] :
9104                        ['string', sStringValue];
9105                  }
9106                },
9107                /**
9108                 * Such data on what to consolidate within the range of source
9109                 * elements that is currently being considered that lead to the
9110                 * greatest known reduction of the number of the terminal symbols
9111                 * in comparison to the original source text.
9112                 * @type {!TSolution}
9113                 */
9114                oSolutionBest = new TSolution(),
9115                /**
9116                 * Data representing an ongoing attempt to find a better
9117                 * reduction of the number of the terminal symbols in comparison
9118                 * to the original source text than the best one that is
9119                 * currently known.
9120                 * @type {!TSolution}
9121                 * @see oSolutionBest
9122                 */
9123                oSolutionCandidate = new TSolution(),
9124                /**
9125                 * A record consisting of data about the range of source elements
9126                 * that is currently being examined.
9127                 * @type {!TSourceElementsData}
9128                 */
9129                oSourceElementsData = new TSourceElementsData(),
9130                /**
9131                 * Variable declarations for each primitive value that is to be
9132                 * consolidated within the elements.
9133                 * @type {!Array.<!Array>}
9134                 */
9135                aVariableDeclarations = [],
9136                /**
9137                 * Augments a list with a prefixed representation String.
9138                 * @param {!Array.<string>} aList A list that is to be augmented.
9139                 * @return {function(string)} A function that augments a list
9140                 *     with a prefixed representation String.
9141                 */
9142                cAugmentList = function(aList) {
9143                  /**
9144                   * @param {string} sPrefixed Prefixed representation String of
9145                   *     a primitive value that could be consolidated within the
9146                   *     elements.
9147                   */
9148                  var fLambda = function(sPrefixed) {
9149                    if (-1 === aList.indexOf(sPrefixed)) {
9150                      aList.push(sPrefixed);
9151                    }
9152                  };
9154                  return fLambda;
9155                },
9156                /**
9157                 * Adds the number of occurrences of a primitive value of a given
9158                 * category that could be consolidated in the source element with
9159                 * a given index to the count of occurrences of that primitive
9160                 * value within the range of source elements that is currently
9161                 * being considered.
9162                 * @param {number} nPosition The index (in the source text order)
9163                 *     of a source element.
9164                 * @param {number} nCategory The category of the primary
9165                 *     expression from which the primitive value is derived.
9166                 * @return {function(string)} A function that performs the
9167                 *     addition.
9168                 * @see cAddOccurrencesInCategory
9169                 */
9170                cAddOccurrences = function(nPosition, nCategory) {
9171                  /**
9172                   * @param {string} sPrefixed The prefixed representation String
9173                   *     of a primitive value.
9174                   */
9175                  var fLambda = function(sPrefixed) {
9176                    if (!oSourceElementsData.aCount[nCategory].hasOwnProperty(
9177                            sPrefixed)) {
9178                      oSourceElementsData.aCount[nCategory][sPrefixed] = 0;
9179                    }
9180                    oSourceElementsData.aCount[nCategory][sPrefixed] +=
9181                        aSourceElementsData[nPosition].aCount[nCategory][
9182                            sPrefixed];
9183                  };
9185                  return fLambda;
9186                },
9187                /**
9188                 * Adds the number of occurrences of each primitive value of a
9189                 * given category that could be consolidated in the source
9190                 * element with a given index to the count of occurrences of that
9191                 * primitive values within the range of source elements that is
9192                 * currently being considered.
9193                 * @param {number} nPosition The index (in the source text order)
9194                 *     of a source element.
9195                 * @return {function(number)} A function that performs the
9196                 *     addition.
9197                 * @see fAddOccurrences
9198                 */
9199                cAddOccurrencesInCategory = function(nPosition) {
9200                  /**
9201                   * @param {number} nCategory The category of the primary
9202                   *     expression from which the primitive value is derived.
9203                   */
9204                  var fLambda = function(nCategory) {
9205                    Object.keys(
9206                        aSourceElementsData[nPosition].aCount[nCategory]
9207                    ).forEach(cAddOccurrences(nPosition, nCategory));
9208                  };
9210                  return fLambda;
9211                },
9212                /**
9213                 * Adds the number of occurrences of each primitive value that
9214                 * could be consolidated in the source element with a given index
9215                 * to the count of occurrences of that primitive values within
9216                 * the range of source elements that is currently being
9217                 * considered.
9218                 * @param {number} nPosition The index (in the source text order)
9219                 *     of a source element.
9220                 */
9221                fAddOccurrences = function(nPosition) {
9222                  Object.keys(aSourceElementsData[nPosition].aCount).forEach(
9223                      cAddOccurrencesInCategory(nPosition));
9224                },
9225                /**
9226                 * Creates a variable declaration for a primitive value if that
9227                 * primitive value is to be consolidated within the elements.
9228                 * @param {string} sPrefixed Prefixed representation String of a
9229                 *     primitive value that could be consolidated within the
9230                 *     elements.
9231                 * @see aVariableDeclarations
9232                 */
9233                cAugmentVariableDeclarations = function(sPrefixed) {
9234                  if (oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0) {
9235                    aVariableDeclarations.push([
9236                      oSolutionBest.oPrimitiveValues[sPrefixed].sName,
9237                      [0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC) ?
9238                       'name' : 'string',
9239                       sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length)]
9240                    ]);
9241                  }
9242                },
9243                /**
9244                 * Sorts primitive values with regard to the difference in the
9245                 * number of terminal symbols between the original source text
9246                 * and the one with those primitive values consolidated.
9247                 * @param {string} sPrefixed0 The prefixed representation String
9248                 *     of the first of the two primitive values that are being
9249                 *     compared.
9250                 * @param {string} sPrefixed1 The prefixed representation String
9251                 *     of the second of the two primitive values that are being
9252                 *     compared.
9253                 * @return {number}
9254                 *     <dl>
9255                 *         <dt>-1</dt>
9256                 *         <dd>if the first primitive value must be placed before
9257                 *              the other one,</dd>
9258                 *         <dt>0</dt>
9259                 *         <dd>if the first primitive value may be placed before
9260                 *              the other one,</dd>
9261                 *         <dt>1</dt>
9262                 *         <dd>if the first primitive value must not be placed
9263                 *              before the other one.</dd>
9264                 *     </dl>
9265                 * @see TSolution.oPrimitiveValues
9266                 */
9267                cSortPrimitiveValues = function(sPrefixed0, sPrefixed1) {
9268                  /**
9269                   * The difference between:
9270                   * <ol>
9271                   * <li>the difference in the number of terminal symbols
9272                   *     between the original source text and the one with the
9273                   *     first primitive value consolidated, and</li>
9274                   * <li>the difference in the number of terminal symbols
9275                   *     between the original source text and the one with the
9276                   *     second primitive value consolidated.</li>
9277                   * </ol>
9278                   * @type {number}
9279                   */
9280                  var nDifference =
9281                      oSolutionCandidate.oPrimitiveValues[sPrefixed0].nSaving -
9282                      oSolutionCandidate.oPrimitiveValues[sPrefixed1].nSaving;
9284                  return nDifference > 0 ? -1 : nDifference < 0 ? 1 : 0;
9285                },
9286                /**
9287                 * Assigns an identifier name to a primitive value and calculates
9288                 * whether instances of that primitive value are worth
9289                 * consolidating.
9290                 * @param {string} sPrefixed The prefixed representation String
9291                 *     of a primitive value that is being evaluated.
9292                 */
9293                fEvaluatePrimitiveValue = function(sPrefixed) {
9294                  var _,
9295                      /**
9296                       * The index of the last mangled name.
9297                       * @type {number}
9298                       */
9299                      nIndex,
9300                      /**
9301                       * The representation String of the primitive value that is
9302                       * being evaluated.
9303                       * @type {string}
9304                       */
9305                      sName =
9306                          sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length),
9307                      /**
9308                       * The number of source characters taken up by the
9309                       * representation String of the primitive value that is
9310                       * being evaluated.
9311                       * @type {number}
9312                       */
9313                      nLengthOriginal = sName.length,
9314                      /**
9315                       * The number of source characters taken up by the
9316                       * identifier name that could substitute the primitive
9317                       * value that is being evaluated.
9318                       * substituted.
9319                       * @type {number}
9320                       */
9321                      nLengthSubstitution,
9322                      /**
9323                       * The number of source characters taken up by by the
9324                       * representation String of the primitive value that is
9325                       * being evaluated when it is represented by a string
9326                       * literal.
9327                       * @type {number}
9328                       */
9329                      nLengthString = oProcessor.make_string(sName).length;
9331                  oSolutionCandidate.oPrimitiveValues[sPrefixed] =
9332                      new TPrimitiveValue();
9333                  do {  // Find an identifier unused in this or any nested scope.
9334                    nIndex = oScope.cname;
9335                    oSolutionCandidate.oPrimitiveValues[sPrefixed].sName =
9336                        oScope.next_mangled();
9337                  } while (-1 !== oSourceElementsData.aIdentifiers.indexOf(
9338                      oSolutionCandidate.oPrimitiveValues[sPrefixed].sName));
9339                  nLengthSubstitution = oSolutionCandidate.oPrimitiveValues[
9340                      sPrefixed].sName.length;
9341                  if (0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC)) {
9342                    // foo:null, or foo:null;
9343                    oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -=
9344                        nLengthSubstitution + nLengthOriginal +
9345                        oWeights.N_VARIABLE_DECLARATION;
9346                    // null vs foo
9347                    oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving +=
9348                        oSourceElementsData.aCount[
9349                            EPrimaryExpressionCategories.
9350                                N_NULL_AND_BOOLEAN_LITERALS][sPrefixed] *
9351                        (nLengthOriginal - nLengthSubstitution);
9352                  } else {
9353                    // foo:'fromCharCode';
9354                    oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -=
9355                        nLengthSubstitution + nLengthString +
9356                        oWeights.N_VARIABLE_DECLARATION;
9357                    // .fromCharCode vs [foo]
9358                    if (oSourceElementsData.aCount[
9359                            EPrimaryExpressionCategories.N_IDENTIFIER_NAMES
9360                        ].hasOwnProperty(sPrefixed)) {
9361                      oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving +=
9362                          oSourceElementsData.aCount[
9363                              EPrimaryExpressionCategories.N_IDENTIFIER_NAMES
9364                          ][sPrefixed] *
9365                          (nLengthOriginal - nLengthSubstitution -
9366                           oWeights.N_PROPERTY_ACCESSOR);
9367                    }
9368                    // 'fromCharCode' vs foo
9369                    if (oSourceElementsData.aCount[
9370                            EPrimaryExpressionCategories.N_STRING_LITERALS
9371                        ].hasOwnProperty(sPrefixed)) {
9372                      oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving +=
9373                          oSourceElementsData.aCount[
9374                              EPrimaryExpressionCategories.N_STRING_LITERALS
9375                          ][sPrefixed] *
9376                          (nLengthString - nLengthSubstitution);
9377                    }
9378                  }
9379                  if (oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving >
9380                      0) {
9381                    oSolutionCandidate.nSavings +=
9382                        oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving;
9383                  } else {
9384                    oScope.cname = nIndex; // Free the identifier name.
9385                  }
9386                },
9387                /**
9388                 * Adds a variable declaration to an existing variable statement.
9389                 * @param {!Array} aVariableDeclaration A variable declaration
9390                 *     with an initialiser.
9391                 */
9392                cAddVariableDeclaration = function(aVariableDeclaration) {
9393                  (/** @type {!Array} */ oSourceElements[nFrom][1]).unshift(
9394                      aVariableDeclaration);
9395                };
9397            if (nFrom > nTo) {
9398              return;
9399            }
9400            // If the range is a closure, reuse the closure.
9401            if (nFrom === nTo &&
9402                'stat' === oSourceElements[nFrom][0] &&
9403                'call' === oSourceElements[nFrom][1][0] &&
9404                'function' === oSourceElements[nFrom][1][1][0]) {
9405              fExamineSyntacticCodeUnit(oSourceElements[nFrom][1][1]);
9406              return;
9407            }
9408            // Create a list of all derived primitive values within the range.
9409            for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) {
9410              aSourceElementsData[nPosition].aPrimitiveValues.forEach(
9411                  cAugmentList(oSourceElementsData.aPrimitiveValues));
9412            }
9413            if (0 === oSourceElementsData.aPrimitiveValues.length) {
9414              return;
9415            }
9416            for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) {
9417              // Add the number of occurrences to the total count.
9418              fAddOccurrences(nPosition);
9419              // Add identifiers of this or any nested scope to the list.
9420              aSourceElementsData[nPosition].aIdentifiers.forEach(
9421                  cAugmentList(oSourceElementsData.aIdentifiers));
9422            }
9423            // Distribute identifier names among derived primitive values.
9424            do {  // If there was any progress, find a better distribution.
9425              oSolutionBest = oSolutionCandidate;
9426              if (Object.keys(oSolutionCandidate.oPrimitiveValues).length > 0) {
9427                // Sort primitive values descending by their worthwhileness.
9428                oSourceElementsData.aPrimitiveValues.sort(cSortPrimitiveValues);
9429              }
9430              oSolutionCandidate = new TSolution();
9431              oSourceElementsData.aPrimitiveValues.forEach(
9432                  fEvaluatePrimitiveValue);
9433              oScope.cname = nIndex;
9434            } while (oSolutionCandidate.nSavings > oSolutionBest.nSavings);
9435            // Take the necessity of adding a variable statement into account.
9436            if ('var' !== oSourceElements[nFrom][0]) {
9437              oSolutionBest.nSavings -= oWeights.N_VARIABLE_STATEMENT_AFFIXATION;
9438            }
9439            if (bEnclose) {
9440              // Take the necessity of forming a closure into account.
9441              oSolutionBest.nSavings -= oWeights.N_CLOSURE;
9442            }
9443            if (oSolutionBest.nSavings > 0) {
9444              // Create variable declarations suitable for UglifyJS.
9445              Object.keys(oSolutionBest.oPrimitiveValues).forEach(
9446                  cAugmentVariableDeclarations);
9447              // Rewrite expressions that contain worthwhile primitive values.
9448              for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) {
9449                oWalker = oProcessor.ast_walker();
9450                oSourceElements[nPosition] =
9451                    oWalker.with_walkers(
9452                        oWalkersTransformers,
9453                        cContext(oWalker, oSourceElements[nPosition]));
9454              }
9455              if ('var' === oSourceElements[nFrom][0]) {  // Reuse the statement.
9456                (/** @type {!Array.<!Array>} */ aVariableDeclarations.reverse(
9457                    )).forEach(cAddVariableDeclaration);
9458              } else {  // Add a variable statement.
9459                Array.prototype.splice.call(
9460                    oSourceElements,
9461                    nFrom,
9462                    0,
9463                    ['var', aVariableDeclarations]);
9464                nTo += 1;
9465              }
9466              if (bEnclose) {
9467                // Add a closure.
9468                Array.prototype.splice.call(
9469                    oSourceElements,
9470                    nFrom,
9471                    0,
9472                    ['stat', ['call', ['function', null, [], []], []]]);
9473                // Copy source elements into the closure.
9474                for (nPosition = nTo + 1; nPosition > nFrom; nPosition -= 1) {
9475                  Array.prototype.unshift.call(
9476                      oSourceElements[nFrom][1][1][3],
9477                      oSourceElements[nPosition]);
9478                }
9479                // Remove source elements outside the closure.
9480                Array.prototype.splice.call(
9481                    oSourceElements,
9482                    nFrom + 1,
9483                    nTo - nFrom + 1);
9484              }
9485            }
9486            if (bEnclose) {
9487              // Restore the availability of identifier names.
9488              oScope.cname = nIndex;
9489            }
9490          };
9492      oSourceElements = (/** @type {!TSyntacticCodeUnit} */
9493          oSyntacticCodeUnit[bIsGlobal ? 1 : 3]);
9494      if (0 === oSourceElements.length) {
9495        return;
9496      }
9497      oScope = bIsGlobal ? oSyntacticCodeUnit.scope : oSourceElements.scope;
9498      // Skip a Directive Prologue.
9499      while (nAfterDirectivePrologue < oSourceElements.length &&
9500             'directive' === oSourceElements[nAfterDirectivePrologue][0]) {
9501        nAfterDirectivePrologue += 1;
9502        aSourceElementsData.push(null);
9503      }
9504      if (oSourceElements.length === nAfterDirectivePrologue) {
9505        return;
9506      }
9507      for (nPosition = nAfterDirectivePrologue;
9508           nPosition < oSourceElements.length;
9509           nPosition += 1) {
9510        oSourceElementData = new TSourceElementsData();
9511        oWalker = oProcessor.ast_walker();
9512        // Classify a source element.
9513        // Find its derived primitive values and count their occurrences.
9514        // Find all identifiers used (including nested scopes).
9515        oWalker.with_walkers(
9516            oWalkers.oSurveySourceElement,
9517            cContext(oWalker, oSourceElements[nPosition]));
9518        // Establish whether the scope is still wholly examinable.
9519        bIsWhollyExaminable = bIsWhollyExaminable &&
9520            ESourceElementCategories.N_WITH !== oSourceElementData.nCategory &&
9521            ESourceElementCategories.N_EVAL !== oSourceElementData.nCategory;
9522        aSourceElementsData.push(oSourceElementData);
9523      }
9524      if (bIsWhollyExaminable) {  // Examine the whole scope.
9525        fExamineSourceElements(
9526            nAfterDirectivePrologue,
9527            oSourceElements.length - 1,
9528            false);
9529      } else {  // Examine unexcluded ranges of source elements.
9530        for (nPosition = oSourceElements.length - 1;
9531             nPosition >= nAfterDirectivePrologue;
9532             nPosition -= 1) {
9533          oSourceElementData = (/** @type {!TSourceElementsData} */
9534              aSourceElementsData[nPosition]);
9535          if (ESourceElementCategories.N_OTHER ===
9536              oSourceElementData.nCategory) {
9537            if ('undefined' === typeof nTo) {
9538              nTo = nPosition;  // Indicate the end of a range.
9539            }
9540            // Examine the range if it immediately follows a Directive Prologue.
9541            if (nPosition === nAfterDirectivePrologue) {
9542              fExamineSourceElements(nPosition, nTo, true);
9543            }
9544          } else {
9545            if ('undefined' !== typeof nTo) {
9546              // Examine the range that immediately follows this source element.
9547              fExamineSourceElements(nPosition + 1, nTo, true);
9548              nTo = void 0;  // Obliterate the range.
9549            }
9550            // Examine nested functions.
9551            oWalker = oProcessor.ast_walker();
9552            oWalker.with_walkers(
9553                oWalkers.oExamineFunctions,
9554                cContext(oWalker, oSourceElements[nPosition]));
9555          }
9556        }
9557      }
9558    }(oAbstractSyntaxTree = oProcessor.ast_add_scope(oAbstractSyntaxTree)));
9559   return oAbstractSyntaxTree;
9561 /*jshint sub:false */
9563 /* Local Variables:      */
9564 /* mode: js              */
9565 /* coding: utf-8         */
9566 /* indent-tabs-mode: nil */
9567 /* tab-width: 2          */
9568 /* End:                  */
9569 /* vim: set ft=javascript fenc=utf-8 et ts=2 sts=2 sw=2: */
9570 /* :mode=javascript:noTabs=true:tabSize=2:indentSize=2:deepIndent=true: */
9572 define('uglifyjs/parse-js', ["exports"], function(exports) {
9573 /***********************************************************************
9575   A JavaScript tokenizer / parser / beautifier / compressor.
9577   This version is suitable for Node.js.  With minimal changes (the
9578   exports stuff) it should work on any JS platform.
9580   This file contains the tokenizer/parser.  It is a port to JavaScript
9581   of parse-js [1], a JavaScript parser library written in Common Lisp
9582   by Marijn Haverbeke.  Thank you Marijn!
9584   [1] http://marijn.haverbeke.nl/parse-js/
9586   Exported functions:
9588     - tokenizer(code) -- returns a function.  Call the returned
9589       function to fetch the next token.
9591     - parse(code) -- returns an AST of the given JavaScript code.
9593   -------------------------------- (C) ---------------------------------
9595                            Author: Mihai Bazon
9596                          <mihai.bazon@gmail.com>
9597                        http://mihai.bazon.net/blog
9599   Distributed under the BSD license:
9601     Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
9602     Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
9604     Redistribution and use in source and binary forms, with or without
9605     modification, are permitted provided that the following conditions
9606     are met:
9608         * Redistributions of source code must retain the above
9609           copyright notice, this list of conditions and the following
9610           disclaimer.
9612         * Redistributions in binary form must reproduce the above
9613           copyright notice, this list of conditions and the following
9614           disclaimer in the documentation and/or other materials
9615           provided with the distribution.
9617     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
9618     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9619     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
9620     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
9621     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
9622     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9623     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9624     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
9625     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
9626     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
9627     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9628     SUCH DAMAGE.
9630  ***********************************************************************/
9632 /* -----[ Tokenizer (constants) ]----- */
9634 var KEYWORDS = array_to_hash([
9635     "break",
9636     "case",
9637     "catch",
9638     "const",
9639     "continue",
9640     "debugger",
9641     "default",
9642     "delete",
9643     "do",
9644     "else",
9645     "finally",
9646     "for",
9647     "function",
9648     "if",
9649     "in",
9650     "instanceof",
9651     "new",
9652     "return",
9653     "switch",
9654     "throw",
9655     "try",
9656     "typeof",
9657     "var",
9658     "void",
9659     "while",
9660     "with"
9663 var RESERVED_WORDS = array_to_hash([
9664     "abstract",
9665     "boolean",
9666     "byte",
9667     "char",
9668     "class",
9669     "double",
9670     "enum",
9671     "export",
9672     "extends",
9673     "final",
9674     "float",
9675     "goto",
9676     "implements",
9677     "import",
9678     "int",
9679     "interface",
9680     "long",
9681     "native",
9682     "package",
9683     "private",
9684     "protected",
9685     "public",
9686     "short",
9687     "static",
9688     "super",
9689     "synchronized",
9690     "throws",
9691     "transient",
9692     "volatile"
9695 var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([
9696     "return",
9697     "new",
9698     "delete",
9699     "throw",
9700     "else",
9701     "case"
9704 var KEYWORDS_ATOM = array_to_hash([
9705     "false",
9706     "null",
9707     "true",
9708     "undefined"
9711 var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^"));
9713 var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
9714 var RE_OCT_NUMBER = /^0[0-7]+$/;
9715 var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
9717 var OPERATORS = array_to_hash([
9718     "in",
9719     "instanceof",
9720     "typeof",
9721     "new",
9722     "void",
9723     "delete",
9724     "++",
9725     "--",
9726     "+",
9727     "-",
9728     "!",
9729     "~",
9730     "&",
9731     "|",
9732     "^",
9733     "*",
9734     "/",
9735     "%",
9736     ">>",
9737     "<<",
9738     ">>>",
9739     "<",
9740     ">",
9741     "<=",
9742     ">=",
9743     "==",
9744     "===",
9745     "!=",
9746     "!==",
9747     "?",
9748     "=",
9749     "+=",
9750     "-=",
9751     "/=",
9752     "*=",
9753     "%=",
9754     ">>=",
9755     "<<=",
9756     ">>>=",
9757     "|=",
9758     "^=",
9759     "&=",
9760     "&&",
9761     "||"
9764 var WHITESPACE_CHARS = array_to_hash(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\uFEFF"));
9766 var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{(,.;:"));
9768 var PUNC_CHARS = array_to_hash(characters("[]{}(),;:"));
9770 var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy"));
9772 /* -----[ Tokenizer ]----- */
9774 var UNICODE = {  // Unicode 6.1
9775     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-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\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\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\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-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\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-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F0\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\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-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\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]"),
9776     combining_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065F\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0859-\\u085B\\u08E4-\\u08FE\\u0900-\\u0903\\u093A-\\u093C\\u093E-\\u094F\\u0951-\\u0957\\u0962\\u0963\\u0981-\\u0983\\u09BC\\u09BE-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CD\\u09D7\\u09E2\\u09E3\\u0A01-\\u0A03\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81-\\u0A83\\u0ABC\\u0ABE-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AE2\\u0AE3\\u0B01-\\u0B03\\u0B3C\\u0B3E-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B62\\u0B63\\u0B82\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD7\\u0C01-\\u0C03\\u0C3E-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0C82\\u0C83\\u0CBC\\u0CBE-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CE2\\u0CE3\\u0D02\\u0D03\\u0D3E-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4D\\u0D57\\u0D62\\u0D63\\u0D82\\u0D83\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F3E\\u0F3F\\u0F71-\\u0F84\\u0F86\\u0F87\\u0F8D-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102B-\\u103E\\u1056-\\u1059\\u105E-\\u1060\\u1062-\\u1064\\u1067-\\u106D\\u1071-\\u1074\\u1082-\\u108D\\u108F\\u109A-\\u109D\\u135D-\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B4-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u192B\\u1930-\\u193B\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A17-\\u1A1B\\u1A55-\\u1A5E\\u1A60-\\u1A7C\\u1A7F\\u1B00-\\u1B04\\u1B34-\\u1B44\\u1B6B-\\u1B73\\u1B80-\\u1B82\\u1BA1-\\u1BAD\\u1BE6-\\u1BF3\\u1C24-\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE8\\u1CED\\u1CF2-\\u1CF4\\u1DC0-\\u1DE6\\u1DFC-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2D7F\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA674-\\uA67D\\uA69F\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA823-\\uA827\\uA880\\uA881\\uA8B4-\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA953\\uA980-\\uA983\\uA9B3-\\uA9C0\\uAA29-\\uAA36\\uAA43\\uAA4C\\uAA4D\\uAA7B\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uAAEB-\\uAAEF\\uAAF5\\uAAF6\\uABE3-\\uABEA\\uABEC\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"),
9777     connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]"),
9778     digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]")
9781 function is_letter(ch) {
9782     return UNICODE.letter.test(ch);
9785 function is_digit(ch) {
9786     ch = ch.charCodeAt(0);
9787     return ch >= 48 && ch <= 57;
9790 function is_unicode_digit(ch) {
9791     return UNICODE.digit.test(ch);
9794 function is_alphanumeric_char(ch) {
9795     return is_digit(ch) || is_letter(ch);
9798 function is_unicode_combining_mark(ch) {
9799     return UNICODE.combining_mark.test(ch);
9802 function is_unicode_connector_punctuation(ch) {
9803     return UNICODE.connector_punctuation.test(ch);
9806 function is_identifier_start(ch) {
9807     return ch == "$" || ch == "_" || is_letter(ch);
9810 function is_identifier_char(ch) {
9811     return is_identifier_start(ch)
9812         || is_unicode_combining_mark(ch)
9813         || is_unicode_digit(ch)
9814         || is_unicode_connector_punctuation(ch)
9815         || ch == "\u200c" // zero-width non-joiner <ZWNJ>
9816         || ch == "\u200d" // zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
9817     ;
9820 function parse_js_number(num) {
9821     if (RE_HEX_NUMBER.test(num)) {
9822         return parseInt(num.substr(2), 16);
9823     } else if (RE_OCT_NUMBER.test(num)) {
9824         return parseInt(num.substr(1), 8);
9825     } else if (RE_DEC_NUMBER.test(num)) {
9826         return parseFloat(num);
9827     }
9830 function JS_Parse_Error(message, line, col, pos) {
9831     this.message = message;
9832     this.line = line + 1;
9833     this.col = col + 1;
9834     this.pos = pos + 1;
9835     this.stack = new Error().stack;
9838 JS_Parse_Error.prototype.toString = function() {
9839     return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
9842 function js_error(message, line, col, pos) {
9843     throw new JS_Parse_Error(message, line, col, pos);
9846 function is_token(token, type, val) {
9847     return token.type == type && (val == null || token.value == val);
9850 var EX_EOF = {};
9852 function tokenizer($TEXT) {
9854     var S = {
9855         text            : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''),
9856         pos             : 0,
9857         tokpos          : 0,
9858         line            : 0,
9859         tokline         : 0,
9860         col             : 0,
9861         tokcol          : 0,
9862         newline_before  : false,
9863         regex_allowed   : false,
9864         comments_before : []
9865     };
9867     function peek() { return S.text.charAt(S.pos); };
9869     function next(signal_eof, in_string) {
9870         var ch = S.text.charAt(S.pos++);
9871         if (signal_eof && !ch)
9872             throw EX_EOF;
9873         if (ch == "\n") {
9874             S.newline_before = S.newline_before || !in_string;
9875             ++S.line;
9876             S.col = 0;
9877         } else {
9878             ++S.col;
9879         }
9880         return ch;
9881     };
9883     function eof() {
9884         return !S.peek();
9885     };
9887     function find(what, signal_eof) {
9888         var pos = S.text.indexOf(what, S.pos);
9889         if (signal_eof && pos == -1) throw EX_EOF;
9890         return pos;
9891     };
9893     function start_token() {
9894         S.tokline = S.line;
9895         S.tokcol = S.col;
9896         S.tokpos = S.pos;
9897     };
9899     function token(type, value, is_comment) {
9900         S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) ||
9901                            (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) ||
9902                            (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value)));
9903         var ret = {
9904             type   : type,
9905             value  : value,
9906             line   : S.tokline,
9907             col    : S.tokcol,
9908             pos    : S.tokpos,
9909             endpos : S.pos,
9910             nlb    : S.newline_before
9911         };
9912         if (!is_comment) {
9913             ret.comments_before = S.comments_before;
9914             S.comments_before = [];
9915             // make note of any newlines in the comments that came before
9916             for (var i = 0, len = ret.comments_before.length; i < len; i++) {
9917                 ret.nlb = ret.nlb || ret.comments_before[i].nlb;
9918             }
9919         }
9920         S.newline_before = false;
9921         return ret;
9922     };
9924     function skip_whitespace() {
9925         while (HOP(WHITESPACE_CHARS, peek()))
9926             next();
9927     };
9929     function read_while(pred) {
9930         var ret = "", ch = peek(), i = 0;
9931         while (ch && pred(ch, i++)) {
9932             ret += next();
9933             ch = peek();
9934         }
9935         return ret;
9936     };
9938     function parse_error(err) {
9939         js_error(err, S.tokline, S.tokcol, S.tokpos);
9940     };
9942     function read_num(prefix) {
9943         var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
9944         var num = read_while(function(ch, i){
9945             if (ch == "x" || ch == "X") {
9946                 if (has_x) return false;
9947                 return has_x = true;
9948             }
9949             if (!has_x && (ch == "E" || ch == "e")) {
9950                 if (has_e) return false;
9951                 return has_e = after_e = true;
9952             }
9953             if (ch == "-") {
9954                 if (after_e || (i == 0 && !prefix)) return true;
9955                 return false;
9956             }
9957             if (ch == "+") return after_e;
9958             after_e = false;
9959             if (ch == ".") {
9960                 if (!has_dot && !has_x && !has_e)
9961                     return has_dot = true;
9962                 return false;
9963             }
9964             return is_alphanumeric_char(ch);
9965         });
9966         if (prefix)
9967             num = prefix + num;
9968         var valid = parse_js_number(num);
9969         if (!isNaN(valid)) {
9970             return token("num", valid);
9971         } else {
9972             parse_error("Invalid syntax: " + num);
9973         }
9974     };
9976     function read_escaped_char(in_string) {
9977         var ch = next(true, in_string);
9978         switch (ch) {
9979           case "n" : return "\n";
9980           case "r" : return "\r";
9981           case "t" : return "\t";
9982           case "b" : return "\b";
9983           case "v" : return "\u000b";
9984           case "f" : return "\f";
9985           case "0" : return "\0";
9986           case "x" : return String.fromCharCode(hex_bytes(2));
9987           case "u" : return String.fromCharCode(hex_bytes(4));
9988           case "\n": return "";
9989           default  : return ch;
9990         }
9991     };
9993     function hex_bytes(n) {
9994         var num = 0;
9995         for (; n > 0; --n) {
9996             var digit = parseInt(next(true), 16);
9997             if (isNaN(digit))
9998                 parse_error("Invalid hex-character pattern in string");
9999             num = (num << 4) | digit;
10000         }
10001         return num;
10002     };
10004     function read_string() {
10005         return with_eof_error("Unterminated string constant", function(){
10006             var quote = next(), ret = "";
10007             for (;;) {
10008                 var ch = next(true);
10009                 if (ch == "\\") {
10010                     // read OctalEscapeSequence (XXX: deprecated if "strict mode")
10011                     // https://github.com/mishoo/UglifyJS/issues/178
10012                     var octal_len = 0, first = null;
10013                     ch = read_while(function(ch){
10014                         if (ch >= "0" && ch <= "7") {
10015                             if (!first) {
10016                                 first = ch;
10017                                 return ++octal_len;
10018                             }
10019                             else if (first <= "3" && octal_len <= 2) return ++octal_len;
10020                             else if (first >= "4" && octal_len <= 1) return ++octal_len;
10021                         }
10022                         return false;
10023                     });
10024                     if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));
10025                     else ch = read_escaped_char(true);
10026                 }
10027                 else if (ch == quote) break;
10028                 else if (ch == "\n") throw EX_EOF;
10029                 ret += ch;
10030             }
10031             return token("string", ret);
10032         });
10033     };
10035     function read_line_comment() {
10036         next();
10037         var i = find("\n"), ret;
10038         if (i == -1) {
10039             ret = S.text.substr(S.pos);
10040             S.pos = S.text.length;
10041         } else {
10042             ret = S.text.substring(S.pos, i);
10043             S.pos = i;
10044         }
10045         return token("comment1", ret, true);
10046     };
10048     function read_multiline_comment() {
10049         next();
10050         return with_eof_error("Unterminated multiline comment", function(){
10051             var i = find("*/", true),
10052             text = S.text.substring(S.pos, i);
10053             S.pos = i + 2;
10054             S.line += text.split("\n").length - 1;
10055             S.newline_before = S.newline_before || text.indexOf("\n") >= 0;
10057             // https://github.com/mishoo/UglifyJS/issues/#issue/100
10058             if (/^@cc_on/i.test(text)) {
10059                 warn("WARNING: at line " + S.line);
10060                 warn("*** Found \"conditional comment\": " + text);
10061                 warn("*** UglifyJS DISCARDS ALL COMMENTS.  This means your code might no longer work properly in Internet Explorer.");
10062             }
10064             return token("comment2", text, true);
10065         });
10066     };
10068     function read_name() {
10069         var backslash = false, name = "", ch, escaped = false, hex;
10070         while ((ch = peek()) != null) {
10071             if (!backslash) {
10072                 if (ch == "\\") escaped = backslash = true, next();
10073                 else if (is_identifier_char(ch)) name += next();
10074                 else break;
10075             }
10076             else {
10077                 if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
10078                 ch = read_escaped_char();
10079                 if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
10080                 name += ch;
10081                 backslash = false;
10082             }
10083         }
10084         if (HOP(KEYWORDS, name) && escaped) {
10085             hex = name.charCodeAt(0).toString(16).toUpperCase();
10086             name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
10087         }
10088         return name;
10089     };
10091     function read_regexp(regexp) {
10092         return with_eof_error("Unterminated regular expression", function(){
10093             var prev_backslash = false, ch, in_class = false;
10094             while ((ch = next(true))) if (prev_backslash) {
10095                 regexp += "\\" + ch;
10096                 prev_backslash = false;
10097             } else if (ch == "[") {
10098                 in_class = true;
10099                 regexp += ch;
10100             } else if (ch == "]" && in_class) {
10101                 in_class = false;
10102                 regexp += ch;
10103             } else if (ch == "/" && !in_class) {
10104                 break;
10105             } else if (ch == "\\") {
10106                 prev_backslash = true;
10107             } else {
10108                 regexp += ch;
10109             }
10110             var mods = read_name();
10111             return token("regexp", [ regexp, mods ]);
10112         });
10113     };
10115     function read_operator(prefix) {
10116         function grow(op) {
10117             if (!peek()) return op;
10118             var bigger = op + peek();
10119             if (HOP(OPERATORS, bigger)) {
10120                 next();
10121                 return grow(bigger);
10122             } else {
10123                 return op;
10124             }
10125         };
10126         return token("operator", grow(prefix || next()));
10127     };
10129     function handle_slash() {
10130         next();
10131         var regex_allowed = S.regex_allowed;
10132         switch (peek()) {
10133           case "/":
10134             S.comments_before.push(read_line_comment());
10135             S.regex_allowed = regex_allowed;
10136             return next_token();
10137           case "*":
10138             S.comments_before.push(read_multiline_comment());
10139             S.regex_allowed = regex_allowed;
10140             return next_token();
10141         }
10142         return S.regex_allowed ? read_regexp("") : read_operator("/");
10143     };
10145     function handle_dot() {
10146         next();
10147         return is_digit(peek())
10148             ? read_num(".")
10149             : token("punc", ".");
10150     };
10152     function read_word() {
10153         var word = read_name();
10154         return !HOP(KEYWORDS, word)
10155             ? token("name", word)
10156             : HOP(OPERATORS, word)
10157             ? token("operator", word)
10158             : HOP(KEYWORDS_ATOM, word)
10159             ? token("atom", word)
10160             : token("keyword", word);
10161     };
10163     function with_eof_error(eof_error, cont) {
10164         try {
10165             return cont();
10166         } catch(ex) {
10167             if (ex === EX_EOF) parse_error(eof_error);
10168             else throw ex;
10169         }
10170     };
10172     function next_token(force_regexp) {
10173         if (force_regexp != null)
10174             return read_regexp(force_regexp);
10175         skip_whitespace();
10176         start_token();
10177         var ch = peek();
10178         if (!ch) return token("eof");
10179         if (is_digit(ch)) return read_num();
10180         if (ch == '"' || ch == "'") return read_string();
10181         if (HOP(PUNC_CHARS, ch)) return token("punc", next());
10182         if (ch == ".") return handle_dot();
10183         if (ch == "/") return handle_slash();
10184         if (HOP(OPERATOR_CHARS, ch)) return read_operator();
10185         if (ch == "\\" || is_identifier_start(ch)) return read_word();
10186         parse_error("Unexpected character '" + ch + "'");
10187     };
10189     next_token.context = function(nc) {
10190         if (nc) S = nc;
10191         return S;
10192     };
10194     return next_token;
10198 /* -----[ Parser (constants) ]----- */
10200 var UNARY_PREFIX = array_to_hash([
10201     "typeof",
10202     "void",
10203     "delete",
10204     "--",
10205     "++",
10206     "!",
10207     "~",
10208     "-",
10209     "+"
10212 var UNARY_POSTFIX = array_to_hash([ "--", "++" ]);
10214 var ASSIGNMENT = (function(a, ret, i){
10215     while (i < a.length) {
10216         ret[a[i]] = a[i].substr(0, a[i].length - 1);
10217         i++;
10218     }
10219     return ret;
10221     ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="],
10222     { "=": true },
10223     0
10226 var PRECEDENCE = (function(a, ret){
10227     for (var i = 0, n = 1; i < a.length; ++i, ++n) {
10228         var b = a[i];
10229         for (var j = 0; j < b.length; ++j) {
10230             ret[b[j]] = n;
10231         }
10232     }
10233     return ret;
10235     [
10236         ["||"],
10237         ["&&"],
10238         ["|"],
10239         ["^"],
10240         ["&"],
10241         ["==", "===", "!=", "!=="],
10242         ["<", ">", "<=", ">=", "in", "instanceof"],
10243         [">>", "<<", ">>>"],
10244         ["+", "-"],
10245         ["*", "/", "%"]
10246     ],
10247     {}
10250 var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
10252 var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
10254 /* -----[ Parser ]----- */
10256 function NodeWithToken(str, start, end) {
10257     this.name = str;
10258     this.start = start;
10259     this.end = end;
10262 NodeWithToken.prototype.toString = function() { return this.name; };
10264 function parse($TEXT, exigent_mode, embed_tokens) {
10266     var S = {
10267         input         : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT,
10268         token         : null,
10269         prev          : null,
10270         peeked        : null,
10271         in_function   : 0,
10272         in_directives : true,
10273         in_loop       : 0,
10274         labels        : []
10275     };
10277     S.token = next();
10279     function is(type, value) {
10280         return is_token(S.token, type, value);
10281     };
10283     function peek() { return S.peeked || (S.peeked = S.input()); };
10285     function next() {
10286         S.prev = S.token;
10287         if (S.peeked) {
10288             S.token = S.peeked;
10289             S.peeked = null;
10290         } else {
10291             S.token = S.input();
10292         }
10293         S.in_directives = S.in_directives && (
10294             S.token.type == "string" || is("punc", ";")
10295         );
10296         return S.token;
10297     };
10299     function prev() {
10300         return S.prev;
10301     };
10303     function croak(msg, line, col, pos) {
10304         var ctx = S.input.context();
10305         js_error(msg,
10306                  line != null ? line : ctx.tokline,
10307                  col != null ? col : ctx.tokcol,
10308                  pos != null ? pos : ctx.tokpos);
10309     };
10311     function token_error(token, msg) {
10312         croak(msg, token.line, token.col);
10313     };
10315     function unexpected(token) {
10316         if (token == null)
10317             token = S.token;
10318         token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
10319     };
10321     function expect_token(type, val) {
10322         if (is(type, val)) {
10323             return next();
10324         }
10325         token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type);
10326     };
10328     function expect(punc) { return expect_token("punc", punc); };
10330     function can_insert_semicolon() {
10331         return !exigent_mode && (
10332             S.token.nlb || is("eof") || is("punc", "}")
10333         );
10334     };
10336     function semicolon() {
10337         if (is("punc", ";")) next();
10338         else if (!can_insert_semicolon()) unexpected();
10339     };
10341     function as() {
10342         return slice(arguments);
10343     };
10345     function parenthesised() {
10346         expect("(");
10347         var ex = expression();
10348         expect(")");
10349         return ex;
10350     };
10352     function add_tokens(str, start, end) {
10353         return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);
10354     };
10356     function maybe_embed_tokens(parser) {
10357         if (embed_tokens) return function() {
10358             var start = S.token;
10359             var ast = parser.apply(this, arguments);
10360             ast[0] = add_tokens(ast[0], start, prev());
10361             return ast;
10362         };
10363         else return parser;
10364     };
10366     var statement = maybe_embed_tokens(function() {
10367         if (is("operator", "/") || is("operator", "/=")) {
10368             S.peeked = null;
10369             S.token = S.input(S.token.value.substr(1)); // force regexp
10370         }
10371         switch (S.token.type) {
10372           case "string":
10373             var dir = S.in_directives, stat = simple_statement();
10374             if (dir && stat[1][0] == "string" && !is("punc", ","))
10375                 return as("directive", stat[1][1]);
10376             return stat;
10377           case "num":
10378           case "regexp":
10379           case "operator":
10380           case "atom":
10381             return simple_statement();
10383           case "name":
10384             return is_token(peek(), "punc", ":")
10385                 ? labeled_statement(prog1(S.token.value, next, next))
10386                 : simple_statement();
10388           case "punc":
10389             switch (S.token.value) {
10390               case "{":
10391                 return as("block", block_());
10392               case "[":
10393               case "(":
10394                 return simple_statement();
10395               case ";":
10396                 next();
10397                 return as("block");
10398               default:
10399                 unexpected();
10400             }
10402           case "keyword":
10403             switch (prog1(S.token.value, next)) {
10404               case "break":
10405                 return break_cont("break");
10407               case "continue":
10408                 return break_cont("continue");
10410               case "debugger":
10411                 semicolon();
10412                 return as("debugger");
10414               case "do":
10415                 return (function(body){
10416                     expect_token("keyword", "while");
10417                     return as("do", prog1(parenthesised, semicolon), body);
10418                 })(in_loop(statement));
10420               case "for":
10421                 return for_();
10423               case "function":
10424                 return function_(true);
10426               case "if":
10427                 return if_();
10429               case "return":
10430                 if (S.in_function == 0)
10431                     croak("'return' outside of function");
10432                 return as("return",
10433                           is("punc", ";")
10434                           ? (next(), null)
10435                           : can_insert_semicolon()
10436                           ? null
10437                           : prog1(expression, semicolon));
10439               case "switch":
10440                 return as("switch", parenthesised(), switch_block_());
10442               case "throw":
10443                 if (S.token.nlb)
10444                     croak("Illegal newline after 'throw'");
10445                 return as("throw", prog1(expression, semicolon));
10447               case "try":
10448                 return try_();
10450               case "var":
10451                 return prog1(var_, semicolon);
10453               case "const":
10454                 return prog1(const_, semicolon);
10456               case "while":
10457                 return as("while", parenthesised(), in_loop(statement));
10459               case "with":
10460                 return as("with", parenthesised(), statement());
10462               default:
10463                 unexpected();
10464             }
10465         }
10466     });
10468     function labeled_statement(label) {
10469         S.labels.push(label);
10470         var start = S.token, stat = statement();
10471         if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))
10472             unexpected(start);
10473         S.labels.pop();
10474         return as("label", label, stat);
10475     };
10477     function simple_statement() {
10478         return as("stat", prog1(expression, semicolon));
10479     };
10481     function break_cont(type) {
10482         var name;
10483         if (!can_insert_semicolon()) {
10484             name = is("name") ? S.token.value : null;
10485         }
10486         if (name != null) {
10487             next();
10488             if (!member(name, S.labels))
10489                 croak("Label " + name + " without matching loop or statement");
10490         }
10491         else if (S.in_loop == 0)
10492             croak(type + " not inside a loop or switch");
10493         semicolon();
10494         return as(type, name);
10495     };
10497     function for_() {
10498         expect("(");
10499         var init = null;
10500         if (!is("punc", ";")) {
10501             init = is("keyword", "var")
10502                 ? (next(), var_(true))
10503                 : expression(true, true);
10504             if (is("operator", "in")) {
10505                 if (init[0] == "var" && init[1].length > 1)
10506                     croak("Only one variable declaration allowed in for..in loop");
10507                 return for_in(init);
10508             }
10509         }
10510         return regular_for(init);
10511     };
10513     function regular_for(init) {
10514         expect(";");
10515         var test = is("punc", ";") ? null : expression();
10516         expect(";");
10517         var step = is("punc", ")") ? null : expression();
10518         expect(")");
10519         return as("for", init, test, step, in_loop(statement));
10520     };
10522     function for_in(init) {
10523         var lhs = init[0] == "var" ? as("name", init[1][0]) : init;
10524         next();
10525         var obj = expression();
10526         expect(")");
10527         return as("for-in", init, lhs, obj, in_loop(statement));
10528     };
10530     var function_ = function(in_statement) {
10531         var name = is("name") ? prog1(S.token.value, next) : null;
10532         if (in_statement && !name)
10533             unexpected();
10534         expect("(");
10535         return as(in_statement ? "defun" : "function",
10536                   name,
10537                   // arguments
10538                   (function(first, a){
10539                       while (!is("punc", ")")) {
10540                           if (first) first = false; else expect(",");
10541                           if (!is("name")) unexpected();
10542                           a.push(S.token.value);
10543                           next();
10544                       }
10545                       next();
10546                       return a;
10547                   })(true, []),
10548                   // body
10549                   (function(){
10550                       ++S.in_function;
10551                       var loop = S.in_loop;
10552                       S.in_directives = true;
10553                       S.in_loop = 0;
10554                       var a = block_();
10555                       --S.in_function;
10556                       S.in_loop = loop;
10557                       return a;
10558                   })());
10559     };
10561     function if_() {
10562         var cond = parenthesised(), body = statement(), belse;
10563         if (is("keyword", "else")) {
10564             next();
10565             belse = statement();
10566         }
10567         return as("if", cond, body, belse);
10568     };
10570     function block_() {
10571         expect("{");
10572         var a = [];
10573         while (!is("punc", "}")) {
10574             if (is("eof")) unexpected();
10575             a.push(statement());
10576         }
10577         next();
10578         return a;
10579     };
10581     var switch_block_ = curry(in_loop, function(){
10582         expect("{");
10583         var a = [], cur = null;
10584         while (!is("punc", "}")) {
10585             if (is("eof")) unexpected();
10586             if (is("keyword", "case")) {
10587                 next();
10588                 cur = [];
10589                 a.push([ expression(), cur ]);
10590                 expect(":");
10591             }
10592             else if (is("keyword", "default")) {
10593                 next();
10594                 expect(":");
10595                 cur = [];
10596                 a.push([ null, cur ]);
10597             }
10598             else {
10599                 if (!cur) unexpected();
10600                 cur.push(statement());
10601             }
10602         }
10603         next();
10604         return a;
10605     });
10607     function try_() {
10608         var body = block_(), bcatch, bfinally;
10609         if (is("keyword", "catch")) {
10610             next();
10611             expect("(");
10612             if (!is("name"))
10613                 croak("Name expected");
10614             var name = S.token.value;
10615             next();
10616             expect(")");
10617             bcatch = [ name, block_() ];
10618         }
10619         if (is("keyword", "finally")) {
10620             next();
10621             bfinally = block_();
10622         }
10623         if (!bcatch && !bfinally)
10624             croak("Missing catch/finally blocks");
10625         return as("try", body, bcatch, bfinally);
10626     };
10628     function vardefs(no_in) {
10629         var a = [];
10630         for (;;) {
10631             if (!is("name"))
10632                 unexpected();
10633             var name = S.token.value;
10634             next();
10635             if (is("operator", "=")) {
10636                 next();
10637                 a.push([ name, expression(false, no_in) ]);
10638             } else {
10639                 a.push([ name ]);
10640             }
10641             if (!is("punc", ","))
10642                 break;
10643             next();
10644         }
10645         return a;
10646     };
10648     function var_(no_in) {
10649         return as("var", vardefs(no_in));
10650     };
10652     function const_() {
10653         return as("const", vardefs());
10654     };
10656     function new_() {
10657         var newexp = expr_atom(false), args;
10658         if (is("punc", "(")) {
10659             next();
10660             args = expr_list(")");
10661         } else {
10662             args = [];
10663         }
10664         return subscripts(as("new", newexp, args), true);
10665     };
10667     var expr_atom = maybe_embed_tokens(function(allow_calls) {
10668         if (is("operator", "new")) {
10669             next();
10670             return new_();
10671         }
10672         if (is("punc")) {
10673             switch (S.token.value) {
10674               case "(":
10675                 next();
10676                 return subscripts(prog1(expression, curry(expect, ")")), allow_calls);
10677               case "[":
10678                 next();
10679                 return subscripts(array_(), allow_calls);
10680               case "{":
10681                 next();
10682                 return subscripts(object_(), allow_calls);
10683             }
10684             unexpected();
10685         }
10686         if (is("keyword", "function")) {
10687             next();
10688             return subscripts(function_(false), allow_calls);
10689         }
10690         if (HOP(ATOMIC_START_TOKEN, S.token.type)) {
10691             var atom = S.token.type == "regexp"
10692                 ? as("regexp", S.token.value[0], S.token.value[1])
10693                 : as(S.token.type, S.token.value);
10694             return subscripts(prog1(atom, next), allow_calls);
10695         }
10696         unexpected();
10697     });
10699     function expr_list(closing, allow_trailing_comma, allow_empty) {
10700         var first = true, a = [];
10701         while (!is("punc", closing)) {
10702             if (first) first = false; else expect(",");
10703             if (allow_trailing_comma && is("punc", closing)) break;
10704             if (is("punc", ",") && allow_empty) {
10705                 a.push([ "atom", "undefined" ]);
10706             } else {
10707                 a.push(expression(false));
10708             }
10709         }
10710         next();
10711         return a;
10712     };
10714     function array_() {
10715         return as("array", expr_list("]", !exigent_mode, true));
10716     };
10718     function object_() {
10719         var first = true, a = [];
10720         while (!is("punc", "}")) {
10721             if (first) first = false; else expect(",");
10722             if (!exigent_mode && is("punc", "}"))
10723                 // allow trailing comma
10724                 break;
10725             var type = S.token.type;
10726             var name = as_property_name();
10727             if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) {
10728                 a.push([ as_name(), function_(false), name ]);
10729             } else {
10730                 expect(":");
10731                 a.push([ name, expression(false) ]);
10732             }
10733         }
10734         next();
10735         return as("object", a);
10736     };
10738     function as_property_name() {
10739         switch (S.token.type) {
10740           case "num":
10741           case "string":
10742             return prog1(S.token.value, next);
10743         }
10744         return as_name();
10745     };
10747     function as_name() {
10748         switch (S.token.type) {
10749           case "name":
10750           case "operator":
10751           case "keyword":
10752           case "atom":
10753             return prog1(S.token.value, next);
10754           default:
10755             unexpected();
10756         }
10757     };
10759     function subscripts(expr, allow_calls) {
10760         if (is("punc", ".")) {
10761             next();
10762             return subscripts(as("dot", expr, as_name()), allow_calls);
10763         }
10764         if (is("punc", "[")) {
10765             next();
10766             return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls);
10767         }
10768         if (allow_calls && is("punc", "(")) {
10769             next();
10770             return subscripts(as("call", expr, expr_list(")")), true);
10771         }
10772         return expr;
10773     };
10775     function maybe_unary(allow_calls) {
10776         if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) {
10777             return make_unary("unary-prefix",
10778                               prog1(S.token.value, next),
10779                               maybe_unary(allow_calls));
10780         }
10781         var val = expr_atom(allow_calls);
10782         while (is("operator") && HOP(UNARY_POSTFIX, S.token.value) && !S.token.nlb) {
10783             val = make_unary("unary-postfix", S.token.value, val);
10784             next();
10785         }
10786         return val;
10787     };
10789     function make_unary(tag, op, expr) {
10790         if ((op == "++" || op == "--") && !is_assignable(expr))
10791             croak("Invalid use of " + op + " operator");
10792         return as(tag, op, expr);
10793     };
10795     function expr_op(left, min_prec, no_in) {
10796         var op = is("operator") ? S.token.value : null;
10797         if (op && op == "in" && no_in) op = null;
10798         var prec = op != null ? PRECEDENCE[op] : null;
10799         if (prec != null && prec > min_prec) {
10800             next();
10801             var right = expr_op(maybe_unary(true), prec, no_in);
10802             return expr_op(as("binary", op, left, right), min_prec, no_in);
10803         }
10804         return left;
10805     };
10807     function expr_ops(no_in) {
10808         return expr_op(maybe_unary(true), 0, no_in);
10809     };
10811     function maybe_conditional(no_in) {
10812         var expr = expr_ops(no_in);
10813         if (is("operator", "?")) {
10814             next();
10815             var yes = expression(false);
10816             expect(":");
10817             return as("conditional", expr, yes, expression(false, no_in));
10818         }
10819         return expr;
10820     };
10822     function is_assignable(expr) {
10823         if (!exigent_mode) return true;
10824         switch (expr[0]+"") {
10825           case "dot":
10826           case "sub":
10827           case "new":
10828           case "call":
10829             return true;
10830           case "name":
10831             return expr[1] != "this";
10832         }
10833     };
10835     function maybe_assign(no_in) {
10836         var left = maybe_conditional(no_in), val = S.token.value;
10837         if (is("operator") && HOP(ASSIGNMENT, val)) {
10838             if (is_assignable(left)) {
10839                 next();
10840                 return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in));
10841             }
10842             croak("Invalid assignment");
10843         }
10844         return left;
10845     };
10847     var expression = maybe_embed_tokens(function(commas, no_in) {
10848         if (arguments.length == 0)
10849             commas = true;
10850         var expr = maybe_assign(no_in);
10851         if (commas && is("punc", ",")) {
10852             next();
10853             return as("seq", expr, expression(true, no_in));
10854         }
10855         return expr;
10856     });
10858     function in_loop(cont) {
10859         try {
10860             ++S.in_loop;
10861             return cont();
10862         } finally {
10863             --S.in_loop;
10864         }
10865     };
10867     return as("toplevel", (function(a){
10868         while (!is("eof"))
10869             a.push(statement());
10870         return a;
10871     })([]));
10875 /* -----[ Utilities ]----- */
10877 function curry(f) {
10878     var args = slice(arguments, 1);
10879     return function() { return f.apply(this, args.concat(slice(arguments))); };
10882 function prog1(ret) {
10883     if (ret instanceof Function)
10884         ret = ret();
10885     for (var i = 1, n = arguments.length; --n > 0; ++i)
10886         arguments[i]();
10887     return ret;
10890 function array_to_hash(a) {
10891     var ret = {};
10892     for (var i = 0; i < a.length; ++i)
10893         ret[a[i]] = true;
10894     return ret;
10897 function slice(a, start) {
10898     return Array.prototype.slice.call(a, start || 0);
10901 function characters(str) {
10902     return str.split("");
10905 function member(name, array) {
10906     for (var i = array.length; --i >= 0;)
10907         if (array[i] == name)
10908             return true;
10909     return false;
10912 function HOP(obj, prop) {
10913     return Object.prototype.hasOwnProperty.call(obj, prop);
10916 var warn = function() {};
10918 /* -----[ Exports ]----- */
10920 exports.tokenizer = tokenizer;
10921 exports.parse = parse;
10922 exports.slice = slice;
10923 exports.curry = curry;
10924 exports.member = member;
10925 exports.array_to_hash = array_to_hash;
10926 exports.PRECEDENCE = PRECEDENCE;
10927 exports.KEYWORDS_ATOM = KEYWORDS_ATOM;
10928 exports.RESERVED_WORDS = RESERVED_WORDS;
10929 exports.KEYWORDS = KEYWORDS;
10930 exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN;
10931 exports.OPERATORS = OPERATORS;
10932 exports.is_alphanumeric_char = is_alphanumeric_char;
10933 exports.is_identifier_start = is_identifier_start;
10934 exports.is_identifier_char = is_identifier_char;
10935 exports.set_logger = function(logger) {
10936     warn = logger;
10939 // Local variables:
10940 // js-indent-level: 4
10941 // End:
10942 });define('uglifyjs/squeeze-more', ["require", "exports", "module", "./parse-js", "./squeeze-more"], function(require, exports, module) {
10943 var jsp = require("./parse-js"),
10944     pro = require("./process"),
10945     slice = jsp.slice,
10946     member = jsp.member,
10947     curry = jsp.curry,
10948     MAP = pro.MAP,
10949     PRECEDENCE = jsp.PRECEDENCE,
10950     OPERATORS = jsp.OPERATORS;
10952 function ast_squeeze_more(ast) {
10953     var w = pro.ast_walker(), walk = w.walk, scope;
10954     function with_scope(s, cont) {
10955         var save = scope, ret;
10956         scope = s;
10957         ret = cont();
10958         scope = save;
10959         return ret;
10960     };
10961     function _lambda(name, args, body) {
10962         return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ];
10963     };
10964     return w.with_walkers({
10965         "toplevel": function(body) {
10966             return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ];
10967         },
10968         "function": _lambda,
10969         "defun": _lambda,
10970         "new": function(ctor, args) {
10971             if (ctor[0] == "name") {
10972                 if (ctor[1] == "Array" && !scope.has("Array")) {
10973                     if (args.length != 1) {
10974                         return [ "array", args ];
10975                     } else {
10976                         return walk([ "call", [ "name", "Array" ], args ]);
10977                     }
10978                 } else if (ctor[1] == "Object" && !scope.has("Object")) {
10979                     if (!args.length) {
10980                         return [ "object", [] ];
10981                     } else {
10982                         return walk([ "call", [ "name", "Object" ], args ]);
10983                     }
10984                 } else if ((ctor[1] == "RegExp" || ctor[1] == "Function" || ctor[1] == "Error") && !scope.has(ctor[1])) {
10985                     return walk([ "call", [ "name", ctor[1] ], args]);
10986                 }
10987             }
10988         },
10989         "call": function(expr, args) {
10990             if (expr[0] == "dot" && expr[1][0] == "string" && args.length == 1
10991                 && (args[0][1] > 0 && expr[2] == "substring" || expr[2] == "substr")) {
10992                 return [ "call", [ "dot", expr[1], "slice"], args];
10993             }
10994             if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) {
10995                 // foo.toString()  ==>  foo+""
10996                 if (expr[1][0] == "string") return expr[1];
10997                 return [ "binary", "+", expr[1], [ "string", "" ]];
10998             }
10999             if (expr[0] == "name") {
11000                 if (expr[1] == "Array" && args.length != 1 && !scope.has("Array")) {
11001                     return [ "array", args ];
11002                 }
11003                 if (expr[1] == "Object" && !args.length && !scope.has("Object")) {
11004                     return [ "object", [] ];
11005                 }
11006                 if (expr[1] == "String" && !scope.has("String")) {
11007                     return [ "binary", "+", args[0], [ "string", "" ]];
11008                 }
11009             }
11010         }
11011     }, function() {
11012         return walk(pro.ast_add_scope(ast));
11013     });
11016 exports.ast_squeeze_more = ast_squeeze_more;
11018 // Local variables:
11019 // js-indent-level: 4
11020 // End:
11022 define('uglifyjs/process', ["require", "exports", "module", "./parse-js", "./squeeze-more"], function(require, exports, module) {
11023 /***********************************************************************
11025   A JavaScript tokenizer / parser / beautifier / compressor.
11027   This version is suitable for Node.js.  With minimal changes (the
11028   exports stuff) it should work on any JS platform.
11030   This file implements some AST processors.  They work on data built
11031   by parse-js.
11033   Exported functions:
11035     - ast_mangle(ast, options) -- mangles the variable/function names
11036       in the AST.  Returns an AST.
11038     - ast_squeeze(ast) -- employs various optimizations to make the
11039       final generated code even smaller.  Returns an AST.
11041     - gen_code(ast, options) -- generates JS code from the AST.  Pass
11042       true (or an object, see the code for some options) as second
11043       argument to get "pretty" (indented) code.
11045   -------------------------------- (C) ---------------------------------
11047                            Author: Mihai Bazon
11048                          <mihai.bazon@gmail.com>
11049                        http://mihai.bazon.net/blog
11051   Distributed under the BSD license:
11053     Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
11055     Redistribution and use in source and binary forms, with or without
11056     modification, are permitted provided that the following conditions
11057     are met:
11059         * Redistributions of source code must retain the above
11060           copyright notice, this list of conditions and the following
11061           disclaimer.
11063         * Redistributions in binary form must reproduce the above
11064           copyright notice, this list of conditions and the following
11065           disclaimer in the documentation and/or other materials
11066           provided with the distribution.
11068     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
11069     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
11070     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
11071     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
11072     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
11073     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
11074     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
11075     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11076     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
11077     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
11078     THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
11079     SUCH DAMAGE.
11081  ***********************************************************************/
11083 var jsp = require("./parse-js"),
11084     curry = jsp.curry,
11085     slice = jsp.slice,
11086     member = jsp.member,
11087     is_identifier_char = jsp.is_identifier_char,
11088     PRECEDENCE = jsp.PRECEDENCE,
11089     OPERATORS = jsp.OPERATORS;
11091 /* -----[ helper for AST traversal ]----- */
11093 function ast_walker() {
11094     function _vardefs(defs) {
11095         return [ this[0], MAP(defs, function(def){
11096             var a = [ def[0] ];
11097             if (def.length > 1)
11098                 a[1] = walk(def[1]);
11099             return a;
11100         }) ];
11101     };
11102     function _block(statements) {
11103         var out = [ this[0] ];
11104         if (statements != null)
11105             out.push(MAP(statements, walk));
11106         return out;
11107     };
11108     var walkers = {
11109         "string": function(str) {
11110             return [ this[0], str ];
11111         },
11112         "num": function(num) {
11113             return [ this[0], num ];
11114         },
11115         "name": function(name) {
11116             return [ this[0], name ];
11117         },
11118         "toplevel": function(statements) {
11119             return [ this[0], MAP(statements, walk) ];
11120         },
11121         "block": _block,
11122         "splice": _block,
11123         "var": _vardefs,
11124         "const": _vardefs,
11125         "try": function(t, c, f) {
11126             return [
11127                 this[0],
11128                 MAP(t, walk),
11129                 c != null ? [ c[0], MAP(c[1], walk) ] : null,
11130                 f != null ? MAP(f, walk) : null
11131             ];
11132         },
11133         "throw": function(expr) {
11134             return [ this[0], walk(expr) ];
11135         },
11136         "new": function(ctor, args) {
11137             return [ this[0], walk(ctor), MAP(args, walk) ];
11138         },
11139         "switch": function(expr, body) {
11140             return [ this[0], walk(expr), MAP(body, function(branch){
11141                 return [ branch[0] ? walk(branch[0]) : null,
11142                          MAP(branch[1], walk) ];
11143             }) ];
11144         },
11145         "break": function(label) {
11146             return [ this[0], label ];
11147         },
11148         "continue": function(label) {
11149             return [ this[0], label ];
11150         },
11151         "conditional": function(cond, t, e) {
11152             return [ this[0], walk(cond), walk(t), walk(e) ];
11153         },
11154         "assign": function(op, lvalue, rvalue) {
11155             return [ this[0], op, walk(lvalue), walk(rvalue) ];
11156         },
11157         "dot": function(expr) {
11158             return [ this[0], walk(expr) ].concat(slice(arguments, 1));
11159         },
11160         "call": function(expr, args) {
11161             return [ this[0], walk(expr), MAP(args, walk) ];
11162         },
11163         "function": function(name, args, body) {
11164             return [ this[0], name, args.slice(), MAP(body, walk) ];
11165         },
11166         "debugger": function() {
11167             return [ this[0] ];
11168         },
11169         "defun": function(name, args, body) {
11170             return [ this[0], name, args.slice(), MAP(body, walk) ];
11171         },
11172         "if": function(conditional, t, e) {
11173             return [ this[0], walk(conditional), walk(t), walk(e) ];
11174         },
11175         "for": function(init, cond, step, block) {
11176             return [ this[0], walk(init), walk(cond), walk(step), walk(block) ];
11177         },
11178         "for-in": function(vvar, key, hash, block) {
11179             return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ];
11180         },
11181         "while": function(cond, block) {
11182             return [ this[0], walk(cond), walk(block) ];
11183         },
11184         "do": function(cond, block) {
11185             return [ this[0], walk(cond), walk(block) ];
11186         },
11187         "return": function(expr) {
11188             return [ this[0], walk(expr) ];
11189         },
11190         "binary": function(op, left, right) {
11191             return [ this[0], op, walk(left), walk(right) ];
11192         },
11193         "unary-prefix": function(op, expr) {
11194             return [ this[0], op, walk(expr) ];
11195         },
11196         "unary-postfix": function(op, expr) {
11197             return [ this[0], op, walk(expr) ];
11198         },
11199         "sub": function(expr, subscript) {
11200             return [ this[0], walk(expr), walk(subscript) ];
11201         },
11202         "object": function(props) {
11203             return [ this[0], MAP(props, function(p){
11204                 return p.length == 2
11205                     ? [ p[0], walk(p[1]) ]
11206                     : [ p[0], walk(p[1]), p[2] ]; // get/set-ter
11207             }) ];
11208         },
11209         "regexp": function(rx, mods) {
11210             return [ this[0], rx, mods ];
11211         },
11212         "array": function(elements) {
11213             return [ this[0], MAP(elements, walk) ];
11214         },
11215         "stat": function(stat) {
11216             return [ this[0], walk(stat) ];
11217         },
11218         "seq": function() {
11219             return [ this[0] ].concat(MAP(slice(arguments), walk));
11220         },
11221         "label": function(name, block) {
11222             return [ this[0], name, walk(block) ];
11223         },
11224         "with": function(expr, block) {
11225             return [ this[0], walk(expr), walk(block) ];
11226         },
11227         "atom": function(name) {
11228             return [ this[0], name ];
11229         },
11230         "directive": function(dir) {
11231             return [ this[0], dir ];
11232         }
11233     };
11235     var user = {};
11236     var stack = [];
11237     function walk(ast) {
11238         if (ast == null)
11239             return null;
11240         try {
11241             stack.push(ast);
11242             var type = ast[0];
11243             var gen = user[type];
11244             if (gen) {
11245                 var ret = gen.apply(ast, ast.slice(1));
11246                 if (ret != null)
11247                     return ret;
11248             }
11249             gen = walkers[type];
11250             return gen.apply(ast, ast.slice(1));
11251         } finally {
11252             stack.pop();
11253         }
11254     };
11256     function dive(ast) {
11257         if (ast == null)
11258             return null;
11259         try {
11260             stack.push(ast);
11261             return walkers[ast[0]].apply(ast, ast.slice(1));
11262         } finally {
11263             stack.pop();
11264         }
11265     };
11267     function with_walkers(walkers, cont){
11268         var save = {}, i;
11269         for (i in walkers) if (HOP(walkers, i)) {
11270             save[i] = user[i];
11271             user[i] = walkers[i];
11272         }
11273         var ret = cont();
11274         for (i in save) if (HOP(save, i)) {
11275             if (!save[i]) delete user[i];
11276             else user[i] = save[i];
11277         }
11278         return ret;
11279     };
11281     return {
11282         walk: walk,
11283         dive: dive,
11284         with_walkers: with_walkers,
11285         parent: function() {
11286             return stack[stack.length - 2]; // last one is current node
11287         },
11288         stack: function() {
11289             return stack;
11290         }
11291     };
11294 /* -----[ Scope and mangling ]----- */
11296 function Scope(parent) {
11297     this.names = {};        // names defined in this scope
11298     this.mangled = {};      // mangled names (orig.name => mangled)
11299     this.rev_mangled = {};  // reverse lookup (mangled => orig.name)
11300     this.cname = -1;        // current mangled name
11301     this.refs = {};         // names referenced from this scope
11302     this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes
11303     this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes
11304     this.directives = [];   // directives activated from this scope
11305     this.parent = parent;   // parent scope
11306     this.children = [];     // sub-scopes
11307     if (parent) {
11308         this.level = parent.level + 1;
11309         parent.children.push(this);
11310     } else {
11311         this.level = 0;
11312     }
11315 function base54_digits() {
11316     if (typeof DIGITS_OVERRIDE_FOR_TESTING != "undefined")
11317         return DIGITS_OVERRIDE_FOR_TESTING;
11318     else
11319         return "etnrisouaflchpdvmgybwESxTNCkLAOM_DPHBjFIqRUzWXV$JKQGYZ0516372984";
11322 var base54 = (function(){
11323     var DIGITS = base54_digits();
11324     return function(num) {
11325         var ret = "", base = 54;
11326         do {
11327             ret += DIGITS.charAt(num % base);
11328             num = Math.floor(num / base);
11329             base = 64;
11330         } while (num > 0);
11331         return ret;
11332     };
11333 })();
11335 Scope.prototype = {
11336     has: function(name) {
11337         for (var s = this; s; s = s.parent)
11338             if (HOP(s.names, name))
11339                 return s;
11340     },
11341     has_mangled: function(mname) {
11342         for (var s = this; s; s = s.parent)
11343             if (HOP(s.rev_mangled, mname))
11344                 return s;
11345     },
11346     toJSON: function() {
11347         return {
11348             names: this.names,
11349             uses_eval: this.uses_eval,
11350             uses_with: this.uses_with
11351         };
11352     },
11354     next_mangled: function() {
11355         // we must be careful that the new mangled name:
11356         //
11357         // 1. doesn't shadow a mangled name from a parent
11358         //    scope, unless we don't reference the original
11359         //    name from this scope OR from any sub-scopes!
11360         //    This will get slow.
11361         //
11362         // 2. doesn't shadow an original name from a parent
11363         //    scope, in the event that the name is not mangled
11364         //    in the parent scope and we reference that name
11365         //    here OR IN ANY SUBSCOPES!
11366         //
11367         // 3. doesn't shadow a name that is referenced but not
11368         //    defined (possibly global defined elsewhere).
11369         for (;;) {
11370             var m = base54(++this.cname), prior;
11372             // case 1.
11373             prior = this.has_mangled(m);
11374             if (prior && this.refs[prior.rev_mangled[m]] === prior)
11375                 continue;
11377             // case 2.
11378             prior = this.has(m);
11379             if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m))
11380                 continue;
11382             // case 3.
11383             if (HOP(this.refs, m) && this.refs[m] == null)
11384                 continue;
11386             // I got "do" once. :-/
11387             if (!is_identifier(m))
11388                 continue;
11390             return m;
11391         }
11392     },
11393     set_mangle: function(name, m) {
11394         this.rev_mangled[m] = name;
11395         return this.mangled[name] = m;
11396     },
11397     get_mangled: function(name, newMangle) {
11398         if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use
11399         var s = this.has(name);
11400         if (!s) return name; // not in visible scope, no mangle
11401         if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope
11402         if (!newMangle) return name;                      // not found and no mangling requested
11403         return s.set_mangle(name, s.next_mangled());
11404     },
11405     references: function(name) {
11406         return name && !this.parent || this.uses_with || this.uses_eval || this.refs[name];
11407     },
11408     define: function(name, type) {
11409         if (name != null) {
11410             if (type == "var" || !HOP(this.names, name))
11411                 this.names[name] = type || "var";
11412             return name;
11413         }
11414     },
11415     active_directive: function(dir) {
11416         return member(dir, this.directives) || this.parent && this.parent.active_directive(dir);
11417     }
11420 function ast_add_scope(ast) {
11422     var current_scope = null;
11423     var w = ast_walker(), walk = w.walk;
11424     var having_eval = [];
11426     function with_new_scope(cont) {
11427         current_scope = new Scope(current_scope);
11428         current_scope.labels = new Scope();
11429         var ret = current_scope.body = cont();
11430         ret.scope = current_scope;
11431         current_scope = current_scope.parent;
11432         return ret;
11433     };
11435     function define(name, type) {
11436         return current_scope.define(name, type);
11437     };
11439     function reference(name) {
11440         current_scope.refs[name] = true;
11441     };
11443     function _lambda(name, args, body) {
11444         var is_defun = this[0] == "defun";
11445         return [ this[0], is_defun ? define(name, "defun") : name, args, with_new_scope(function(){
11446             if (!is_defun) define(name, "lambda");
11447             MAP(args, function(name){ define(name, "arg") });
11448             return MAP(body, walk);
11449         })];
11450     };
11452     function _vardefs(type) {
11453         return function(defs) {
11454             MAP(defs, function(d){
11455                 define(d[0], type);
11456                 if (d[1]) reference(d[0]);
11457             });
11458         };
11459     };
11461     function _breacont(label) {
11462         if (label)
11463             current_scope.labels.refs[label] = true;
11464     };
11466     return with_new_scope(function(){
11467         // process AST
11468         var ret = w.with_walkers({
11469             "function": _lambda,
11470             "defun": _lambda,
11471             "label": function(name, stat) { current_scope.labels.define(name) },
11472             "break": _breacont,
11473             "continue": _breacont,
11474             "with": function(expr, block) {
11475                 for (var s = current_scope; s; s = s.parent)
11476                     s.uses_with = true;
11477             },
11478             "var": _vardefs("var"),
11479             "const": _vardefs("const"),
11480             "try": function(t, c, f) {
11481                 if (c != null) return [
11482                     this[0],
11483                     MAP(t, walk),
11484                     [ define(c[0], "catch"), MAP(c[1], walk) ],
11485                     f != null ? MAP(f, walk) : null
11486                 ];
11487             },
11488             "name": function(name) {
11489                 if (name == "eval")
11490                     having_eval.push(current_scope);
11491                 reference(name);
11492             }
11493         }, function(){
11494             return walk(ast);
11495         });
11497         // the reason why we need an additional pass here is
11498         // that names can be used prior to their definition.
11500         // scopes where eval was detected and their parents
11501         // are marked with uses_eval, unless they define the
11502         // "eval" name.
11503         MAP(having_eval, function(scope){
11504             if (!scope.has("eval")) while (scope) {
11505                 scope.uses_eval = true;
11506                 scope = scope.parent;
11507             }
11508         });
11510         // for referenced names it might be useful to know
11511         // their origin scope.  current_scope here is the
11512         // toplevel one.
11513         function fixrefs(scope, i) {
11514             // do children first; order shouldn't matter
11515             for (i = scope.children.length; --i >= 0;)
11516                 fixrefs(scope.children[i]);
11517             for (i in scope.refs) if (HOP(scope.refs, i)) {
11518                 // find origin scope and propagate the reference to origin
11519                 for (var origin = scope.has(i), s = scope; s; s = s.parent) {
11520                     s.refs[i] = origin;
11521                     if (s === origin) break;
11522                 }
11523             }
11524         };
11525         fixrefs(current_scope);
11527         return ret;
11528     });
11532 /* -----[ mangle names ]----- */
11534 function ast_mangle(ast, options) {
11535     var w = ast_walker(), walk = w.walk, scope;
11536     options = defaults(options, {
11537         mangle       : true,
11538         toplevel     : false,
11539         defines      : null,
11540         except       : null,
11541         no_functions : false
11542     });
11544     function get_mangled(name, newMangle) {
11545         if (!options.mangle) return name;
11546         if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel
11547         if (options.except && member(name, options.except))
11548             return name;
11549         if (options.no_functions && HOP(scope.names, name) &&
11550             (scope.names[name] == 'defun' || scope.names[name] == 'lambda'))
11551             return name;
11552         return scope.get_mangled(name, newMangle);
11553     };
11555     function get_define(name) {
11556         if (options.defines) {
11557             // we always lookup a defined symbol for the current scope FIRST, so declared
11558             // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value
11559             if (!scope.has(name)) {
11560                 if (HOP(options.defines, name)) {
11561                     return options.defines[name];
11562                 }
11563             }
11564             return null;
11565         }
11566     };
11568     function _lambda(name, args, body) {
11569         if (!options.no_functions && options.mangle) {
11570             var is_defun = this[0] == "defun", extra;
11571             if (name) {
11572                 if (is_defun) name = get_mangled(name);
11573                 else if (body.scope.references(name)) {
11574                     extra = {};
11575                     if (!(scope.uses_eval || scope.uses_with))
11576                         name = extra[name] = scope.next_mangled();
11577                     else
11578                         extra[name] = name;
11579                 }
11580                 else name = null;
11581             }
11582         }
11583         body = with_scope(body.scope, function(){
11584             args = MAP(args, function(name){ return get_mangled(name) });
11585             return MAP(body, walk);
11586         }, extra);
11587         return [ this[0], name, args, body ];
11588     };
11590     function with_scope(s, cont, extra) {
11591         var _scope = scope;
11592         scope = s;
11593         if (extra) for (var i in extra) if (HOP(extra, i)) {
11594             s.set_mangle(i, extra[i]);
11595         }
11596         for (var i in s.names) if (HOP(s.names, i)) {
11597             get_mangled(i, true);
11598         }
11599         var ret = cont();
11600         ret.scope = s;
11601         scope = _scope;
11602         return ret;
11603     };
11605     function _vardefs(defs) {
11606         return [ this[0], MAP(defs, function(d){
11607             return [ get_mangled(d[0]), walk(d[1]) ];
11608         }) ];
11609     };
11611     function _breacont(label) {
11612         if (label) return [ this[0], scope.labels.get_mangled(label) ];
11613     };
11615     return w.with_walkers({
11616         "function": _lambda,
11617         "defun": function() {
11618             // move function declarations to the top when
11619             // they are not in some block.
11620             var ast = _lambda.apply(this, arguments);
11621             switch (w.parent()[0]) {
11622               case "toplevel":
11623               case "function":
11624               case "defun":
11625                 return MAP.at_top(ast);
11626             }
11627             return ast;
11628         },
11629         "label": function(label, stat) {
11630             if (scope.labels.refs[label]) return [
11631                 this[0],
11632                 scope.labels.get_mangled(label, true),
11633                 walk(stat)
11634             ];
11635             return walk(stat);
11636         },
11637         "break": _breacont,
11638         "continue": _breacont,
11639         "var": _vardefs,
11640         "const": _vardefs,
11641         "name": function(name) {
11642             return get_define(name) || [ this[0], get_mangled(name) ];
11643         },
11644         "try": function(t, c, f) {
11645             return [ this[0],
11646                      MAP(t, walk),
11647                      c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null,
11648                      f != null ? MAP(f, walk) : null ];
11649         },
11650         "toplevel": function(body) {
11651             var self = this;
11652             return with_scope(self.scope, function(){
11653                 return [ self[0], MAP(body, walk) ];
11654             });
11655         },
11656         "directive": function() {
11657             return MAP.at_top(this);
11658         }
11659     }, function() {
11660         return walk(ast_add_scope(ast));
11661     });
11664 /* -----[
11665    - compress foo["bar"] into foo.bar,
11666    - remove block brackets {} where possible
11667    - join consecutive var declarations
11668    - various optimizations for IFs:
11669    - if (cond) foo(); else bar();  ==>  cond?foo():bar();
11670    - if (cond) foo();  ==>  cond&&foo();
11671    - if (foo) return bar(); else return baz();  ==> return foo?bar():baz(); // also for throw
11672    - if (foo) return bar(); else something();  ==> {if(foo)return bar();something()}
11673    ]----- */
11675 var warn = function(){};
11677 function best_of(ast1, ast2) {
11678     return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1;
11681 function last_stat(b) {
11682     if (b[0] == "block" && b[1] && b[1].length > 0)
11683         return b[1][b[1].length - 1];
11684     return b;
11687 function aborts(t) {
11688     if (t) switch (last_stat(t)[0]) {
11689       case "return":
11690       case "break":
11691       case "continue":
11692       case "throw":
11693         return true;
11694     }
11697 function boolean_expr(expr) {
11698     return ( (expr[0] == "unary-prefix"
11699               && member(expr[1], [ "!", "delete" ])) ||
11701              (expr[0] == "binary"
11702               && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) ||
11704              (expr[0] == "binary"
11705               && member(expr[1], [ "&&", "||" ])
11706               && boolean_expr(expr[2])
11707               && boolean_expr(expr[3])) ||
11709              (expr[0] == "conditional"
11710               && boolean_expr(expr[2])
11711               && boolean_expr(expr[3])) ||
11713              (expr[0] == "assign"
11714               && expr[1] === true
11715               && boolean_expr(expr[3])) ||
11717              (expr[0] == "seq"
11718               && boolean_expr(expr[expr.length - 1]))
11719            );
11722 function empty(b) {
11723     return !b || (b[0] == "block" && (!b[1] || b[1].length == 0));
11726 function is_string(node) {
11727     return (node[0] == "string" ||
11728             node[0] == "unary-prefix" && node[1] == "typeof" ||
11729             node[0] == "binary" && node[1] == "+" &&
11730             (is_string(node[2]) || is_string(node[3])));
11733 var when_constant = (function(){
11735     var $NOT_CONSTANT = {};
11737     // this can only evaluate constant expressions.  If it finds anything
11738     // not constant, it throws $NOT_CONSTANT.
11739     function evaluate(expr) {
11740         switch (expr[0]) {
11741           case "string":
11742           case "num":
11743             return expr[1];
11744           case "name":
11745           case "atom":
11746             switch (expr[1]) {
11747               case "true": return true;
11748               case "false": return false;
11749               case "null": return null;
11750             }
11751             break;
11752           case "unary-prefix":
11753             switch (expr[1]) {
11754               case "!": return !evaluate(expr[2]);
11755               case "typeof": return typeof evaluate(expr[2]);
11756               case "~": return ~evaluate(expr[2]);
11757               case "-": return -evaluate(expr[2]);
11758               case "+": return +evaluate(expr[2]);
11759             }
11760             break;
11761           case "binary":
11762             var left = expr[2], right = expr[3];
11763             switch (expr[1]) {
11764               case "&&"         : return evaluate(left) &&         evaluate(right);
11765               case "||"         : return evaluate(left) ||         evaluate(right);
11766               case "|"          : return evaluate(left) |          evaluate(right);
11767               case "&"          : return evaluate(left) &          evaluate(right);
11768               case "^"          : return evaluate(left) ^          evaluate(right);
11769               case "+"          : return evaluate(left) +          evaluate(right);
11770               case "*"          : return evaluate(left) *          evaluate(right);
11771               case "/"          : return evaluate(left) /          evaluate(right);
11772               case "%"          : return evaluate(left) %          evaluate(right);
11773               case "-"          : return evaluate(left) -          evaluate(right);
11774               case "<<"         : return evaluate(left) <<         evaluate(right);
11775               case ">>"         : return evaluate(left) >>         evaluate(right);
11776               case ">>>"        : return evaluate(left) >>>        evaluate(right);
11777               case "=="         : return evaluate(left) ==         evaluate(right);
11778               case "==="        : return evaluate(left) ===        evaluate(right);
11779               case "!="         : return evaluate(left) !=         evaluate(right);
11780               case "!=="        : return evaluate(left) !==        evaluate(right);
11781               case "<"          : return evaluate(left) <          evaluate(right);
11782               case "<="         : return evaluate(left) <=         evaluate(right);
11783               case ">"          : return evaluate(left) >          evaluate(right);
11784               case ">="         : return evaluate(left) >=         evaluate(right);
11785               case "in"         : return evaluate(left) in         evaluate(right);
11786               case "instanceof" : return evaluate(left) instanceof evaluate(right);
11787             }
11788         }
11789         throw $NOT_CONSTANT;
11790     };
11792     return function(expr, yes, no) {
11793         try {
11794             var val = evaluate(expr), ast;
11795             switch (typeof val) {
11796               case "string": ast =  [ "string", val ]; break;
11797               case "number": ast =  [ "num", val ]; break;
11798               case "boolean": ast =  [ "name", String(val) ]; break;
11799               default:
11800                 if (val === null) { ast = [ "atom", "null" ]; break; }
11801                 throw new Error("Can't handle constant of type: " + (typeof val));
11802             }
11803             return yes.call(expr, ast, val);
11804         } catch(ex) {
11805             if (ex === $NOT_CONSTANT) {
11806                 if (expr[0] == "binary"
11807                     && (expr[1] == "===" || expr[1] == "!==")
11808                     && ((is_string(expr[2]) && is_string(expr[3]))
11809                         || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) {
11810                     expr[1] = expr[1].substr(0, 2);
11811                 }
11812                 else if (no && expr[0] == "binary"
11813                          && (expr[1] == "||" || expr[1] == "&&")) {
11814                     // the whole expression is not constant but the lval may be...
11815                     try {
11816                         var lval = evaluate(expr[2]);
11817                         expr = ((expr[1] == "&&" && (lval ? expr[3] : lval))    ||
11818                                 (expr[1] == "||" && (lval ? lval    : expr[3])) ||
11819                                 expr);
11820                     } catch(ex2) {
11821                         // IGNORE... lval is not constant
11822                     }
11823                 }
11824                 return no ? no.call(expr, expr) : null;
11825             }
11826             else throw ex;
11827         }
11828     };
11830 })();
11832 function warn_unreachable(ast) {
11833     if (!empty(ast))
11834         warn("Dropping unreachable code: " + gen_code(ast, true));
11837 function prepare_ifs(ast) {
11838     var w = ast_walker(), walk = w.walk;
11839     // In this first pass, we rewrite ifs which abort with no else with an
11840     // if-else.  For example:
11841     //
11842     // if (x) {
11843     //     blah();
11844     //     return y;
11845     // }
11846     // foobar();
11847     //
11848     // is rewritten into:
11849     //
11850     // if (x) {
11851     //     blah();
11852     //     return y;
11853     // } else {
11854     //     foobar();
11855     // }
11856     function redo_if(statements) {
11857         statements = MAP(statements, walk);
11859         for (var i = 0; i < statements.length; ++i) {
11860             var fi = statements[i];
11861             if (fi[0] != "if") continue;
11863             if (fi[3]) continue;
11865             var t = fi[2];
11866             if (!aborts(t)) continue;
11868             var conditional = walk(fi[1]);
11870             var e_body = redo_if(statements.slice(i + 1));
11871             var e = e_body.length == 1 ? e_body[0] : [ "block", e_body ];
11873             return statements.slice(0, i).concat([ [
11874                 fi[0],          // "if"
11875                 conditional,    // conditional
11876                 t,              // then
11877                 e               // else
11878             ] ]);
11879         }
11881         return statements;
11882     };
11884     function redo_if_lambda(name, args, body) {
11885         body = redo_if(body);
11886         return [ this[0], name, args, body ];
11887     };
11889     function redo_if_block(statements) {
11890         return [ this[0], statements != null ? redo_if(statements) : null ];
11891     };
11893     return w.with_walkers({
11894         "defun": redo_if_lambda,
11895         "function": redo_if_lambda,
11896         "block": redo_if_block,
11897         "splice": redo_if_block,
11898         "toplevel": function(statements) {
11899             return [ this[0], redo_if(statements) ];
11900         },
11901         "try": function(t, c, f) {
11902             return [
11903                 this[0],
11904                 redo_if(t),
11905                 c != null ? [ c[0], redo_if(c[1]) ] : null,
11906                 f != null ? redo_if(f) : null
11907             ];
11908         }
11909     }, function() {
11910         return walk(ast);
11911     });
11914 function for_side_effects(ast, handler) {
11915     var w = ast_walker(), walk = w.walk;
11916     var $stop = {}, $restart = {};
11917     function stop() { throw $stop };
11918     function restart() { throw $restart };
11919     function found(){ return handler.call(this, this, w, stop, restart) };
11920     function unary(op) {
11921         if (op == "++" || op == "--")
11922             return found.apply(this, arguments);
11923     };
11924     function binary(op) {
11925         if (op == "&&" || op == "||")
11926             return found.apply(this, arguments);
11927     };
11928     return w.with_walkers({
11929         "try": found,
11930         "throw": found,
11931         "return": found,
11932         "new": found,
11933         "switch": found,
11934         "break": found,
11935         "continue": found,
11936         "assign": found,
11937         "call": found,
11938         "if": found,
11939         "for": found,
11940         "for-in": found,
11941         "while": found,
11942         "do": found,
11943         "return": found,
11944         "unary-prefix": unary,
11945         "unary-postfix": unary,
11946         "conditional": found,
11947         "binary": binary,
11948         "defun": found
11949     }, function(){
11950         while (true) try {
11951             walk(ast);
11952             break;
11953         } catch(ex) {
11954             if (ex === $stop) break;
11955             if (ex === $restart) continue;
11956             throw ex;
11957         }
11958     });
11961 function ast_lift_variables(ast) {
11962     var w = ast_walker(), walk = w.walk, scope;
11963     function do_body(body, env) {
11964         var _scope = scope;
11965         scope = env;
11966         body = MAP(body, walk);
11967         var hash = {}, names = MAP(env.names, function(type, name){
11968             if (type != "var") return MAP.skip;
11969             if (!env.references(name)) return MAP.skip;
11970             hash[name] = true;
11971             return [ name ];
11972         });
11973         if (names.length > 0) {
11974             // looking for assignments to any of these variables.
11975             // we can save considerable space by moving the definitions
11976             // in the var declaration.
11977             for_side_effects([ "block", body ], function(ast, walker, stop, restart) {
11978                 if (ast[0] == "assign"
11979                     && ast[1] === true
11980                     && ast[2][0] == "name"
11981                     && HOP(hash, ast[2][1])) {
11982                     // insert the definition into the var declaration
11983                     for (var i = names.length; --i >= 0;) {
11984                         if (names[i][0] == ast[2][1]) {
11985                             if (names[i][1]) // this name already defined, we must stop
11986                                 stop();
11987                             names[i][1] = ast[3]; // definition
11988                             names.push(names.splice(i, 1)[0]);
11989                             break;
11990                         }
11991                     }
11992                     // remove this assignment from the AST.
11993                     var p = walker.parent();
11994                     if (p[0] == "seq") {
11995                         var a = p[2];
11996                         a.unshift(0, p.length);
11997                         p.splice.apply(p, a);
11998                     }
11999                     else if (p[0] == "stat") {
12000                         p.splice(0, p.length, "block"); // empty statement
12001                     }
12002                     else {
12003                         stop();
12004                     }
12005                     restart();
12006                 }
12007                 stop();
12008             });
12009             body.unshift([ "var", names ]);
12010         }
12011         scope = _scope;
12012         return body;
12013     };
12014     function _vardefs(defs) {
12015         var ret = null;
12016         for (var i = defs.length; --i >= 0;) {
12017             var d = defs[i];
12018             if (!d[1]) continue;
12019             d = [ "assign", true, [ "name", d[0] ], d[1] ];
12020             if (ret == null) ret = d;
12021             else ret = [ "seq", d, ret ];
12022         }
12023         if (ret == null && w.parent()[0] != "for") {
12024             if (w.parent()[0] == "for-in")
12025                 return [ "name", defs[0][0] ];
12026             return MAP.skip;
12027         }
12028         return [ "stat", ret ];
12029     };
12030     function _toplevel(body) {
12031         return [ this[0], do_body(body, this.scope) ];
12032     };
12033     return w.with_walkers({
12034         "function": function(name, args, body){
12035             for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);)
12036                 args.pop();
12037             if (!body.scope.references(name)) name = null;
12038             return [ this[0], name, args, do_body(body, body.scope) ];
12039         },
12040         "defun": function(name, args, body){
12041             if (!scope.references(name)) return MAP.skip;
12042             for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);)
12043                 args.pop();
12044             return [ this[0], name, args, do_body(body, body.scope) ];
12045         },
12046         "var": _vardefs,
12047         "toplevel": _toplevel
12048     }, function(){
12049         return walk(ast_add_scope(ast));
12050     });
12053 function ast_squeeze(ast, options) {
12054     ast = squeeze_1(ast, options);
12055     ast = squeeze_2(ast, options);
12056     return ast;
12059 function squeeze_1(ast, options) {
12060     options = defaults(options, {
12061         make_seqs   : true,
12062         dead_code   : true,
12063         no_warnings : false,
12064         keep_comps  : true,
12065         unsafe      : false
12066     });
12068     var w = ast_walker(), walk = w.walk, scope;
12070     function negate(c) {
12071         var not_c = [ "unary-prefix", "!", c ];
12072         switch (c[0]) {
12073           case "unary-prefix":
12074             return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c;
12075           case "seq":
12076             c = slice(c);
12077             c[c.length - 1] = negate(c[c.length - 1]);
12078             return c;
12079           case "conditional":
12080             return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]);
12081           case "binary":
12082             var op = c[1], left = c[2], right = c[3];
12083             if (!options.keep_comps) switch (op) {
12084               case "<="  : return [ "binary", ">", left, right ];
12085               case "<"   : return [ "binary", ">=", left, right ];
12086               case ">="  : return [ "binary", "<", left, right ];
12087               case ">"   : return [ "binary", "<=", left, right ];
12088             }
12089             switch (op) {
12090               case "=="  : return [ "binary", "!=", left, right ];
12091               case "!="  : return [ "binary", "==", left, right ];
12092               case "===" : return [ "binary", "!==", left, right ];
12093               case "!==" : return [ "binary", "===", left, right ];
12094               case "&&"  : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]);
12095               case "||"  : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]);
12096             }
12097             break;
12098         }
12099         return not_c;
12100     };
12102     function make_conditional(c, t, e) {
12103         var make_real_conditional = function() {
12104             if (c[0] == "unary-prefix" && c[1] == "!") {
12105                 return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ];
12106             } else {
12107                 return e ? best_of(
12108                     [ "conditional", c, t, e ],
12109                     [ "conditional", negate(c), e, t ]
12110                 ) : [ "binary", "&&", c, t ];
12111             }
12112         };
12113         // shortcut the conditional if the expression has a constant value
12114         return when_constant(c, function(ast, val){
12115             warn_unreachable(val ? e : t);
12116             return          (val ? t : e);
12117         }, make_real_conditional);
12118     };
12120     function rmblock(block) {
12121         if (block != null && block[0] == "block" && block[1]) {
12122             if (block[1].length == 1)
12123                 block = block[1][0];
12124             else if (block[1].length == 0)
12125                 block = [ "block" ];
12126         }
12127         return block;
12128     };
12130     function _lambda(name, args, body) {
12131         return [ this[0], name, args, tighten(body, "lambda") ];
12132     };
12134     // this function does a few things:
12135     // 1. discard useless blocks
12136     // 2. join consecutive var declarations
12137     // 3. remove obviously dead code
12138     // 4. transform consecutive statements using the comma operator
12139     // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... }
12140     function tighten(statements, block_type) {
12141         statements = MAP(statements, walk);
12143         statements = statements.reduce(function(a, stat){
12144             if (stat[0] == "block") {
12145                 if (stat[1]) {
12146                     a.push.apply(a, stat[1]);
12147                 }
12148             } else {
12149                 a.push(stat);
12150             }
12151             return a;
12152         }, []);
12154         statements = (function(a, prev){
12155             statements.forEach(function(cur){
12156                 if (prev && ((cur[0] == "var" && prev[0] == "var") ||
12157                              (cur[0] == "const" && prev[0] == "const"))) {
12158                     prev[1] = prev[1].concat(cur[1]);
12159                 } else {
12160                     a.push(cur);
12161                     prev = cur;
12162                 }
12163             });
12164             return a;
12165         })([]);
12167         if (options.dead_code) statements = (function(a, has_quit){
12168             statements.forEach(function(st){
12169                 if (has_quit) {
12170                     if (st[0] == "function" || st[0] == "defun") {
12171                         a.push(st);
12172                     }
12173                     else if (st[0] == "var" || st[0] == "const") {
12174                         if (!options.no_warnings)
12175                             warn("Variables declared in unreachable code");
12176                         st[1] = MAP(st[1], function(def){
12177                             if (def[1] && !options.no_warnings)
12178                                 warn_unreachable([ "assign", true, [ "name", def[0] ], def[1] ]);
12179                             return [ def[0] ];
12180                         });
12181                         a.push(st);
12182                     }
12183                     else if (!options.no_warnings)
12184                         warn_unreachable(st);
12185                 }
12186                 else {
12187                     a.push(st);
12188                     if (member(st[0], [ "return", "throw", "break", "continue" ]))
12189                         has_quit = true;
12190                 }
12191             });
12192             return a;
12193         })([]);
12195         if (options.make_seqs) statements = (function(a, prev) {
12196             statements.forEach(function(cur){
12197                 if (prev && prev[0] == "stat" && cur[0] == "stat") {
12198                     prev[1] = [ "seq", prev[1], cur[1] ];
12199                 } else {
12200                     a.push(cur);
12201                     prev = cur;
12202                 }
12203             });
12204             if (a.length >= 2
12205                 && a[a.length-2][0] == "stat"
12206                 && (a[a.length-1][0] == "return" || a[a.length-1][0] == "throw")
12207                 && a[a.length-1][1])
12208             {
12209                 a.splice(a.length - 2, 2,
12210                          [ a[a.length-1][0],
12211                            [ "seq", a[a.length-2][1], a[a.length-1][1] ]]);
12212             }
12213             return a;
12214         })([]);
12216         // this increases jQuery by 1K.  Probably not such a good idea after all..
12217         // part of this is done in prepare_ifs anyway.
12218         // if (block_type == "lambda") statements = (function(i, a, stat){
12219         //         while (i < statements.length) {
12220         //                 stat = statements[i++];
12221         //                 if (stat[0] == "if" && !stat[3]) {
12222         //                         if (stat[2][0] == "return" && stat[2][1] == null) {
12223         //                                 a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ]));
12224         //                                 break;
12225         //                         }
12226         //                         var last = last_stat(stat[2]);
12227         //                         if (last[0] == "return" && last[1] == null) {
12228         //                                 a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ]));
12229         //                                 break;
12230         //                         }
12231         //                 }
12232         //                 a.push(stat);
12233         //         }
12234         //         return a;
12235         // })(0, []);
12237         return statements;
12238     };
12240     function make_if(c, t, e) {
12241         return when_constant(c, function(ast, val){
12242             if (val) {
12243                 t = walk(t);
12244                 warn_unreachable(e);
12245                 return t || [ "block" ];
12246             } else {
12247                 e = walk(e);
12248                 warn_unreachable(t);
12249                 return e || [ "block" ];
12250             }
12251         }, function() {
12252             return make_real_if(c, t, e);
12253         });
12254     };
12256     function abort_else(c, t, e) {
12257         var ret = [ [ "if", negate(c), e ] ];
12258         if (t[0] == "block") {
12259             if (t[1]) ret = ret.concat(t[1]);
12260         } else {
12261             ret.push(t);
12262         }
12263         return walk([ "block", ret ]);
12264     };
12266     function make_real_if(c, t, e) {
12267         c = walk(c);
12268         t = walk(t);
12269         e = walk(e);
12271         if (empty(e) && empty(t))
12272             return [ "stat", c ];
12274         if (empty(t)) {
12275             c = negate(c);
12276             t = e;
12277             e = null;
12278         } else if (empty(e)) {
12279             e = null;
12280         } else {
12281             // if we have both else and then, maybe it makes sense to switch them?
12282             (function(){
12283                 var a = gen_code(c);
12284                 var n = negate(c);
12285                 var b = gen_code(n);
12286                 if (b.length < a.length) {
12287                     var tmp = t;
12288                     t = e;
12289                     e = tmp;
12290                     c = n;
12291                 }
12292             })();
12293         }
12294         var ret = [ "if", c, t, e ];
12295         if (t[0] == "if" && empty(t[3]) && empty(e)) {
12296             ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ]));
12297         }
12298         else if (t[0] == "stat") {
12299             if (e) {
12300                 if (e[0] == "stat")
12301                     ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]);
12302                 else if (aborts(e))
12303                     ret = abort_else(c, t, e);
12304             }
12305             else {
12306                 ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]);
12307             }
12308         }
12309         else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw") && t[1] && e[1]) {
12310             ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]);
12311         }
12312         else if (e && aborts(t)) {
12313             ret = [ [ "if", c, t ] ];
12314             if (e[0] == "block") {
12315                 if (e[1]) ret = ret.concat(e[1]);
12316             }
12317             else {
12318                 ret.push(e);
12319             }
12320             ret = walk([ "block", ret ]);
12321         }
12322         else if (t && aborts(e)) {
12323             ret = abort_else(c, t, e);
12324         }
12325         return ret;
12326     };
12328     function _do_while(cond, body) {
12329         return when_constant(cond, function(cond, val){
12330             if (!val) {
12331                 warn_unreachable(body);
12332                 return [ "block" ];
12333             } else {
12334                 return [ "for", null, null, null, walk(body) ];
12335             }
12336         });
12337     };
12339     return w.with_walkers({
12340         "sub": function(expr, subscript) {
12341             if (subscript[0] == "string") {
12342                 var name = subscript[1];
12343                 if (is_identifier(name))
12344                     return [ "dot", walk(expr), name ];
12345                 else if (/^[1-9][0-9]*$/.test(name) || name === "0")
12346                     return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ];
12347             }
12348         },
12349         "if": make_if,
12350         "toplevel": function(body) {
12351             return [ "toplevel", tighten(body) ];
12352         },
12353         "switch": function(expr, body) {
12354             var last = body.length - 1;
12355             return [ "switch", walk(expr), MAP(body, function(branch, i){
12356                 var block = tighten(branch[1]);
12357                 if (i == last && block.length > 0) {
12358                     var node = block[block.length - 1];
12359                     if (node[0] == "break" && !node[1])
12360                         block.pop();
12361                 }
12362                 return [ branch[0] ? walk(branch[0]) : null, block ];
12363             }) ];
12364         },
12365         "function": _lambda,
12366         "defun": _lambda,
12367         "block": function(body) {
12368             if (body) return rmblock([ "block", tighten(body) ]);
12369         },
12370         "binary": function(op, left, right) {
12371             return when_constant([ "binary", op, walk(left), walk(right) ], function yes(c){
12372                 return best_of(walk(c), this);
12373             }, function no() {
12374                 return function(){
12375                     if(op != "==" && op != "!=") return;
12376                     var l = walk(left), r = walk(right);
12377                     if(l && l[0] == "unary-prefix" && l[1] == "!" && l[2][0] == "num")
12378                         left = ['num', +!l[2][1]];
12379                     else if (r && r[0] == "unary-prefix" && r[1] == "!" && r[2][0] == "num")
12380                         right = ['num', +!r[2][1]];
12381                     return ["binary", op, left, right];
12382                 }() || this;
12383             });
12384         },
12385         "conditional": function(c, t, e) {
12386             return make_conditional(walk(c), walk(t), walk(e));
12387         },
12388         "try": function(t, c, f) {
12389             return [
12390                 "try",
12391                 tighten(t),
12392                 c != null ? [ c[0], tighten(c[1]) ] : null,
12393                 f != null ? tighten(f) : null
12394             ];
12395         },
12396         "unary-prefix": function(op, expr) {
12397             expr = walk(expr);
12398             var ret = [ "unary-prefix", op, expr ];
12399             if (op == "!")
12400                 ret = best_of(ret, negate(expr));
12401             return when_constant(ret, function(ast, val){
12402                 return walk(ast); // it's either true or false, so minifies to !0 or !1
12403             }, function() { return ret });
12404         },
12405         "name": function(name) {
12406             switch (name) {
12407               case "true": return [ "unary-prefix", "!", [ "num", 0 ]];
12408               case "false": return [ "unary-prefix", "!", [ "num", 1 ]];
12409             }
12410         },
12411         "while": _do_while,
12412         "assign": function(op, lvalue, rvalue) {
12413             lvalue = walk(lvalue);
12414             rvalue = walk(rvalue);
12415             var okOps = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
12416             if (op === true && lvalue[0] === "name" && rvalue[0] === "binary" &&
12417                 ~okOps.indexOf(rvalue[1]) && rvalue[2][0] === "name" &&
12418                 rvalue[2][1] === lvalue[1]) {
12419                 return [ this[0], rvalue[1], lvalue, rvalue[3] ]
12420             }
12421             return [ this[0], op, lvalue, rvalue ];
12422         },
12423         "call": function(expr, args) {
12424             expr = walk(expr);
12425             if (options.unsafe && expr[0] == "dot" && expr[1][0] == "string" && expr[2] == "toString") {
12426                 return expr[1];
12427             }
12428             return [ this[0], expr,  MAP(args, walk) ];
12429         },
12430         "num": function (num) {
12431             if (!isFinite(num))
12432                 return [ "binary", "/", num === 1 / 0
12433                          ? [ "num", 1 ] : num === -1 / 0
12434                          ? [ "unary-prefix", "-", [ "num", 1 ] ]
12435                          : [ "num", 0 ], [ "num", 0 ] ];
12437             return [ this[0], num ];
12438         }
12439     }, function() {
12440         return walk(prepare_ifs(walk(prepare_ifs(ast))));
12441     });
12444 function squeeze_2(ast, options) {
12445     var w = ast_walker(), walk = w.walk, scope;
12446     function with_scope(s, cont) {
12447         var save = scope, ret;
12448         scope = s;
12449         ret = cont();
12450         scope = save;
12451         return ret;
12452     };
12453     function lambda(name, args, body) {
12454         return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ];
12455     };
12456     return w.with_walkers({
12457         "directive": function(dir) {
12458             if (scope.active_directive(dir))
12459                 return [ "block" ];
12460             scope.directives.push(dir);
12461         },
12462         "toplevel": function(body) {
12463             return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ];
12464         },
12465         "function": lambda,
12466         "defun": lambda
12467     }, function(){
12468         return walk(ast_add_scope(ast));
12469     });
12472 /* -----[ re-generate code from the AST ]----- */
12474 var DOT_CALL_NO_PARENS = jsp.array_to_hash([
12475     "name",
12476     "array",
12477     "object",
12478     "string",
12479     "dot",
12480     "sub",
12481     "call",
12482     "regexp",
12483     "defun"
12486 function make_string(str, ascii_only) {
12487     var dq = 0, sq = 0;
12488     str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){
12489         switch (s) {
12490           case "\\": return "\\\\";
12491           case "\b": return "\\b";
12492           case "\f": return "\\f";
12493           case "\n": return "\\n";
12494           case "\r": return "\\r";
12495           case "\u2028": return "\\u2028";
12496           case "\u2029": return "\\u2029";
12497           case '"': ++dq; return '"';
12498           case "'": ++sq; return "'";
12499           case "\0": return "\\0";
12500         }
12501         return s;
12502     });
12503     if (ascii_only) str = to_ascii(str);
12504     if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'";
12505     else return '"' + str.replace(/\x22/g, '\\"') + '"';
12508 function to_ascii(str) {
12509     return str.replace(/[\u0080-\uffff]/g, function(ch) {
12510         var code = ch.charCodeAt(0).toString(16);
12511         while (code.length < 4) code = "0" + code;
12512         return "\\u" + code;
12513     });
12516 var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]);
12518 function gen_code(ast, options) {
12519     options = defaults(options, {
12520         indent_start : 0,
12521         indent_level : 4,
12522         quote_keys   : false,
12523         space_colon  : false,
12524         beautify     : false,
12525         ascii_only   : false,
12526         inline_script: false
12527     });
12528     var beautify = !!options.beautify;
12529     var indentation = 0,
12530     newline = beautify ? "\n" : "",
12531     space = beautify ? " " : "";
12533     function encode_string(str) {
12534         var ret = make_string(str, options.ascii_only);
12535         if (options.inline_script)
12536             ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
12537         return ret;
12538     };
12540     function make_name(name) {
12541         name = name.toString();
12542         if (options.ascii_only)
12543             name = to_ascii(name);
12544         return name;
12545     };
12547     function indent(line) {
12548         if (line == null)
12549             line = "";
12550         if (beautify)
12551             line = repeat_string(" ", options.indent_start + indentation * options.indent_level) + line;
12552         return line;
12553     };
12555     function with_indent(cont, incr) {
12556         if (incr == null) incr = 1;
12557         indentation += incr;
12558         try { return cont.apply(null, slice(arguments, 1)); }
12559         finally { indentation -= incr; }
12560     };
12562     function last_char(str) {
12563         str = str.toString();
12564         return str.charAt(str.length - 1);
12565     };
12567     function first_char(str) {
12568         return str.toString().charAt(0);
12569     };
12571     function add_spaces(a) {
12572         if (beautify)
12573             return a.join(" ");
12574         var b = [];
12575         for (var i = 0; i < a.length; ++i) {
12576             var next = a[i + 1];
12577             b.push(a[i]);
12578             if (next &&
12579                 ((is_identifier_char(last_char(a[i])) && (is_identifier_char(first_char(next))
12580                                                           || first_char(next) == "\\")) ||
12581                  (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString()) ||
12582                  last_char(a[i]) == "/" && first_char(next) == "/"))) {
12583                 b.push(" ");
12584             }
12585         }
12586         return b.join("");
12587     };
12589     function add_commas(a) {
12590         return a.join("," + space);
12591     };
12593     function parenthesize(expr) {
12594         var gen = make(expr);
12595         for (var i = 1; i < arguments.length; ++i) {
12596             var el = arguments[i];
12597             if ((el instanceof Function && el(expr)) || expr[0] == el)
12598                 return "(" + gen + ")";
12599         }
12600         return gen;
12601     };
12603     function best_of(a) {
12604         if (a.length == 1) {
12605             return a[0];
12606         }
12607         if (a.length == 2) {
12608             var b = a[1];
12609             a = a[0];
12610             return a.length <= b.length ? a : b;
12611         }
12612         return best_of([ a[0], best_of(a.slice(1)) ]);
12613     };
12615     function needs_parens(expr) {
12616         if (expr[0] == "function" || expr[0] == "object") {
12617             // dot/call on a literal function requires the
12618             // function literal itself to be parenthesized
12619             // only if it's the first "thing" in a
12620             // statement.  This means that the parent is
12621             // "stat", but it could also be a "seq" and
12622             // we're the first in this "seq" and the
12623             // parent is "stat", and so on.  Messy stuff,
12624             // but it worths the trouble.
12625             var a = slice(w.stack()), self = a.pop(), p = a.pop();
12626             while (p) {
12627                 if (p[0] == "stat") return true;
12628                 if (((p[0] == "seq" || p[0] == "call" || p[0] == "dot" || p[0] == "sub" || p[0] == "conditional") && p[1] === self) ||
12629                     ((p[0] == "binary" || p[0] == "assign" || p[0] == "unary-postfix") && p[2] === self)) {
12630                     self = p;
12631                     p = a.pop();
12632                 } else {
12633                     return false;
12634                 }
12635             }
12636         }
12637         return !HOP(DOT_CALL_NO_PARENS, expr[0]);
12638     };
12640     function make_num(num) {
12641         var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m;
12642         if (Math.floor(num) === num) {
12643             if (num >= 0) {
12644                 a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
12645                        "0" + num.toString(8)); // same.
12646             } else {
12647                 a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless
12648                        "-0" + (-num).toString(8)); // same.
12649             }
12650             if ((m = /^(.*?)(0+)$/.exec(num))) {
12651                 a.push(m[1] + "e" + m[2].length);
12652             }
12653         } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
12654             a.push(m[2] + "e-" + (m[1].length + m[2].length),
12655                    str.substr(str.indexOf(".")));
12656         }
12657         return best_of(a);
12658     };
12660     var w = ast_walker();
12661     var make = w.walk;
12662     return w.with_walkers({
12663         "string": encode_string,
12664         "num": make_num,
12665         "name": make_name,
12666         "debugger": function(){ return "debugger;" },
12667         "toplevel": function(statements) {
12668             return make_block_statements(statements)
12669                 .join(newline + newline);
12670         },
12671         "splice": function(statements) {
12672             var parent = w.parent();
12673             if (HOP(SPLICE_NEEDS_BRACKETS, parent)) {
12674                 // we need block brackets in this case
12675                 return make_block.apply(this, arguments);
12676             } else {
12677                 return MAP(make_block_statements(statements, true),
12678                            function(line, i) {
12679                                // the first line is already indented
12680                                return i > 0 ? indent(line) : line;
12681                            }).join(newline);
12682             }
12683         },
12684         "block": make_block,
12685         "var": function(defs) {
12686             return "var " + add_commas(MAP(defs, make_1vardef)) + ";";
12687         },
12688         "const": function(defs) {
12689             return "const " + add_commas(MAP(defs, make_1vardef)) + ";";
12690         },
12691         "try": function(tr, ca, fi) {
12692             var out = [ "try", make_block(tr) ];
12693             if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1]));
12694             if (fi) out.push("finally", make_block(fi));
12695             return add_spaces(out);
12696         },
12697         "throw": function(expr) {
12698             return add_spaces([ "throw", make(expr) ]) + ";";
12699         },
12700         "new": function(ctor, args) {
12701             args = args.length > 0 ? "(" + add_commas(MAP(args, function(expr){
12702                 return parenthesize(expr, "seq");
12703             })) + ")" : "";
12704             return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){
12705                 var w = ast_walker(), has_call = {};
12706                 try {
12707                     w.with_walkers({
12708                         "call": function() { throw has_call },
12709                         "function": function() { return this }
12710                     }, function(){
12711                         w.walk(expr);
12712                     });
12713                 } catch(ex) {
12714                     if (ex === has_call)
12715                         return true;
12716                     throw ex;
12717                 }
12718             }) + args ]);
12719         },
12720         "switch": function(expr, body) {
12721             return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]);
12722         },
12723         "break": function(label) {
12724             var out = "break";
12725             if (label != null)
12726                 out += " " + make_name(label);
12727             return out + ";";
12728         },
12729         "continue": function(label) {
12730             var out = "continue";
12731             if (label != null)
12732                 out += " " + make_name(label);
12733             return out + ";";
12734         },
12735         "conditional": function(co, th, el) {
12736             return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?",
12737                                 parenthesize(th, "seq"), ":",
12738                                 parenthesize(el, "seq") ]);
12739         },
12740         "assign": function(op, lvalue, rvalue) {
12741             if (op && op !== true) op += "=";
12742             else op = "=";
12743             return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]);
12744         },
12745         "dot": function(expr) {
12746             var out = make(expr), i = 1;
12747             if (expr[0] == "num") {
12748                 if (!/[a-f.]/i.test(out))
12749                     out += ".";
12750             } else if (expr[0] != "function" && needs_parens(expr))
12751                 out = "(" + out + ")";
12752             while (i < arguments.length)
12753                 out += "." + make_name(arguments[i++]);
12754             return out;
12755         },
12756         "call": function(func, args) {
12757             var f = make(func);
12758             if (f.charAt(0) != "(" && needs_parens(func))
12759                 f = "(" + f + ")";
12760             return f + "(" + add_commas(MAP(args, function(expr){
12761                 return parenthesize(expr, "seq");
12762             })) + ")";
12763         },
12764         "function": make_function,
12765         "defun": make_function,
12766         "if": function(co, th, el) {
12767             var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ];
12768             if (el) {
12769                 out.push("else", make(el));
12770             }
12771             return add_spaces(out);
12772         },
12773         "for": function(init, cond, step, block) {
12774             var out = [ "for" ];
12775             init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space);
12776             cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space);
12777             step = (step != null ? make(step) : "").replace(/;*\s*$/, "");
12778             var args = init + cond + step;
12779             if (args == "; ; ") args = ";;";
12780             out.push("(" + args + ")", make(block));
12781             return add_spaces(out);
12782         },
12783         "for-in": function(vvar, key, hash, block) {
12784             return add_spaces([ "for", "(" +
12785                                 (vvar ? make(vvar).replace(/;+$/, "") : make(key)),
12786                                 "in",
12787                                 make(hash) + ")", make(block) ]);
12788         },
12789         "while": function(condition, block) {
12790             return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]);
12791         },
12792         "do": function(condition, block) {
12793             return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";";
12794         },
12795         "return": function(expr) {
12796             var out = [ "return" ];
12797             if (expr != null) out.push(make(expr));
12798             return add_spaces(out) + ";";
12799         },
12800         "binary": function(operator, lvalue, rvalue) {
12801             var left = make(lvalue), right = make(rvalue);
12802             // XXX: I'm pretty sure other cases will bite here.
12803             //      we need to be smarter.
12804             //      adding parens all the time is the safest bet.
12805             if (member(lvalue[0], [ "assign", "conditional", "seq" ]) ||
12806                 lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]] ||
12807                 lvalue[0] == "function" && needs_parens(this)) {
12808                 left = "(" + left + ")";
12809             }
12810             if (member(rvalue[0], [ "assign", "conditional", "seq" ]) ||
12811                 rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] &&
12812                 !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) {
12813                 right = "(" + right + ")";
12814             }
12815             else if (!beautify && options.inline_script && (operator == "<" || operator == "<<")
12816                      && rvalue[0] == "regexp" && /^script/i.test(rvalue[1])) {
12817                 right = " " + right;
12818             }
12819             return add_spaces([ left, operator, right ]);
12820         },
12821         "unary-prefix": function(operator, expr) {
12822             var val = make(expr);
12823             if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))
12824                 val = "(" + val + ")";
12825             return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val;
12826         },
12827         "unary-postfix": function(operator, expr) {
12828             var val = make(expr);
12829             if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))
12830                 val = "(" + val + ")";
12831             return val + operator;
12832         },
12833         "sub": function(expr, subscript) {
12834             var hash = make(expr);
12835             if (needs_parens(expr))
12836                 hash = "(" + hash + ")";
12837             return hash + "[" + make(subscript) + "]";
12838         },
12839         "object": function(props) {
12840             var obj_needs_parens = needs_parens(this);
12841             if (props.length == 0)
12842                 return obj_needs_parens ? "({})" : "{}";
12843             var out = "{" + newline + with_indent(function(){
12844                 return MAP(props, function(p){
12845                     if (p.length == 3) {
12846                         // getter/setter.  The name is in p[0], the arg.list in p[1][2], the
12847                         // body in p[1][3] and type ("get" / "set") in p[2].
12848                         return indent(make_function(p[0], p[1][2], p[1][3], p[2], true));
12849                     }
12850                     var key = p[0], val = parenthesize(p[1], "seq");
12851                     if (options.quote_keys) {
12852                         key = encode_string(key);
12853                     } else if ((typeof key == "number" || !beautify && +key + "" == key)
12854                                && parseFloat(key) >= 0) {
12855                         key = make_num(+key);
12856                     } else if (!is_identifier(key)) {
12857                         key = encode_string(key);
12858                     }
12859                     return indent(add_spaces(beautify && options.space_colon
12860                                              ? [ key, ":", val ]
12861                                              : [ key + ":", val ]));
12862                 }).join("," + newline);
12863             }) + newline + indent("}");
12864             return obj_needs_parens ? "(" + out + ")" : out;
12865         },
12866         "regexp": function(rx, mods) {
12867             if (options.ascii_only) rx = to_ascii(rx);
12868             return "/" + rx + "/" + mods;
12869         },
12870         "array": function(elements) {
12871             if (elements.length == 0) return "[]";
12872             return add_spaces([ "[", add_commas(MAP(elements, function(el, i){
12873                 if (!beautify && el[0] == "atom" && el[1] == "undefined") return i === elements.length - 1 ? "," : "";
12874                 return parenthesize(el, "seq");
12875             })), "]" ]);
12876         },
12877         "stat": function(stmt) {
12878             return stmt != null
12879                 ? make(stmt).replace(/;*\s*$/, ";")
12880                 : ";";
12881         },
12882         "seq": function() {
12883             return add_commas(MAP(slice(arguments), make));
12884         },
12885         "label": function(name, block) {
12886             return add_spaces([ make_name(name), ":", make(block) ]);
12887         },
12888         "with": function(expr, block) {
12889             return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]);
12890         },
12891         "atom": function(name) {
12892             return make_name(name);
12893         },
12894         "directive": function(dir) {
12895             return make_string(dir) + ";";
12896         }
12897     }, function(){ return make(ast) });
12899     // The squeezer replaces "block"-s that contain only a single
12900     // statement with the statement itself; technically, the AST
12901     // is correct, but this can create problems when we output an
12902     // IF having an ELSE clause where the THEN clause ends in an
12903     // IF *without* an ELSE block (then the outer ELSE would refer
12904     // to the inner IF).  This function checks for this case and
12905     // adds the block brackets if needed.
12906     function make_then(th) {
12907         if (th == null) return ";";
12908         if (th[0] == "do") {
12909             // https://github.com/mishoo/UglifyJS/issues/#issue/57
12910             // IE croaks with "syntax error" on code like this:
12911             //     if (foo) do ... while(cond); else ...
12912             // we need block brackets around do/while
12913             return make_block([ th ]);
12914         }
12915         var b = th;
12916         while (true) {
12917             var type = b[0];
12918             if (type == "if") {
12919                 if (!b[3])
12920                     // no else, we must add the block
12921                     return make([ "block", [ th ]]);
12922                 b = b[3];
12923             }
12924             else if (type == "while" || type == "do") b = b[2];
12925             else if (type == "for" || type == "for-in") b = b[4];
12926             else break;
12927         }
12928         return make(th);
12929     };
12931     function make_function(name, args, body, keyword, no_parens) {
12932         var out = keyword || "function";
12933         if (name) {
12934             out += " " + make_name(name);
12935         }
12936         out += "(" + add_commas(MAP(args, make_name)) + ")";
12937         out = add_spaces([ out, make_block(body) ]);
12938         return (!no_parens && needs_parens(this)) ? "(" + out + ")" : out;
12939     };
12941     function must_has_semicolon(node) {
12942         switch (node[0]) {
12943           case "with":
12944           case "while":
12945             return empty(node[2]) || must_has_semicolon(node[2]);
12946           case "for":
12947           case "for-in":
12948             return empty(node[4]) || must_has_semicolon(node[4]);
12949           case "if":
12950             if (empty(node[2]) && !node[3]) return true; // `if' with empty `then' and no `else'
12951             if (node[3]) {
12952                 if (empty(node[3])) return true; // `else' present but empty
12953                 return must_has_semicolon(node[3]); // dive into the `else' branch
12954             }
12955             return must_has_semicolon(node[2]); // dive into the `then' branch
12956           case "directive":
12957             return true;
12958         }
12959     };
12961     function make_block_statements(statements, noindent) {
12962         for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) {
12963             var stat = statements[i];
12964             var code = make(stat);
12965             if (code != ";") {
12966                 if (!beautify && i == last && !must_has_semicolon(stat)) {
12967                     code = code.replace(/;+\s*$/, "");
12968                 }
12969                 a.push(code);
12970             }
12971         }
12972         return noindent ? a : MAP(a, indent);
12973     };
12975     function make_switch_block(body) {
12976         var n = body.length;
12977         if (n == 0) return "{}";
12978         return "{" + newline + MAP(body, function(branch, i){
12979             var has_body = branch[1].length > 0, code = with_indent(function(){
12980                 return indent(branch[0]
12981                               ? add_spaces([ "case", make(branch[0]) + ":" ])
12982                               : "default:");
12983             }, 0.5) + (has_body ? newline + with_indent(function(){
12984                 return make_block_statements(branch[1]).join(newline);
12985             }) : "");
12986             if (!beautify && has_body && i < n - 1)
12987                 code += ";";
12988             return code;
12989         }).join(newline) + newline + indent("}");
12990     };
12992     function make_block(statements) {
12993         if (!statements) return ";";
12994         if (statements.length == 0) return "{}";
12995         return "{" + newline + with_indent(function(){
12996             return make_block_statements(statements).join(newline);
12997         }) + newline + indent("}");
12998     };
13000     function make_1vardef(def) {
13001         var name = def[0], val = def[1];
13002         if (val != null)
13003             name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]);
13004         return name;
13005     };
13009 function split_lines(code, max_line_length) {
13010     var splits = [ 0 ];
13011     jsp.parse(function(){
13012         var next_token = jsp.tokenizer(code);
13013         var last_split = 0;
13014         var prev_token;
13015         function current_length(tok) {
13016             return tok.pos - last_split;
13017         };
13018         function split_here(tok) {
13019             last_split = tok.pos;
13020             splits.push(last_split);
13021         };
13022         function custom(){
13023             var tok = next_token.apply(this, arguments);
13024             out: {
13025                 if (prev_token) {
13026                     if (prev_token.type == "keyword") break out;
13027                 }
13028                 if (current_length(tok) > max_line_length) {
13029                     switch (tok.type) {
13030                       case "keyword":
13031                       case "atom":
13032                       case "name":
13033                       case "punc":
13034                         split_here(tok);
13035                         break out;
13036                     }
13037                 }
13038             }
13039             prev_token = tok;
13040             return tok;
13041         };
13042         custom.context = function() {
13043             return next_token.context.apply(this, arguments);
13044         };
13045         return custom;
13046     }());
13047     return splits.map(function(pos, i){
13048         return code.substring(pos, splits[i + 1] || code.length);
13049     }).join("\n");
13052 /* -----[ Utilities ]----- */
13054 function repeat_string(str, i) {
13055     if (i <= 0) return "";
13056     if (i == 1) return str;
13057     var d = repeat_string(str, i >> 1);
13058     d += d;
13059     if (i & 1) d += str;
13060     return d;
13063 function defaults(args, defs) {
13064     var ret = {};
13065     if (args === true)
13066         args = {};
13067     for (var i in defs) if (HOP(defs, i)) {
13068         ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
13069     }
13070     return ret;
13073 function is_identifier(name) {
13074     return /^[a-z_$][a-z0-9_$]*$/i.test(name)
13075         && name != "this"
13076         && !HOP(jsp.KEYWORDS_ATOM, name)
13077         && !HOP(jsp.RESERVED_WORDS, name)
13078         && !HOP(jsp.KEYWORDS, name);
13081 function HOP(obj, prop) {
13082     return Object.prototype.hasOwnProperty.call(obj, prop);
13085 // some utilities
13087 var MAP;
13089 (function(){
13090     MAP = function(a, f, o) {
13091         var ret = [], top = [], i;
13092         function doit() {
13093             var val = f.call(o, a[i], i);
13094             if (val instanceof AtTop) {
13095                 val = val.v;
13096                 if (val instanceof Splice) {
13097                     top.push.apply(top, val.v);
13098                 } else {
13099                     top.push(val);
13100                 }
13101             }
13102             else if (val != skip) {
13103                 if (val instanceof Splice) {
13104                     ret.push.apply(ret, val.v);
13105                 } else {
13106                     ret.push(val);
13107                 }
13108             }
13109         };
13110         if (a instanceof Array) for (i = 0; i < a.length; ++i) doit();
13111         else for (i in a) if (HOP(a, i)) doit();
13112         return top.concat(ret);
13113     };
13114     MAP.at_top = function(val) { return new AtTop(val) };
13115     MAP.splice = function(val) { return new Splice(val) };
13116     var skip = MAP.skip = {};
13117     function AtTop(val) { this.v = val };
13118     function Splice(val) { this.v = val };
13119 })();
13121 /* -----[ Exports ]----- */
13123 exports.ast_walker = ast_walker;
13124 exports.ast_mangle = ast_mangle;
13125 exports.ast_squeeze = ast_squeeze;
13126 exports.ast_lift_variables = ast_lift_variables;
13127 exports.gen_code = gen_code;
13128 exports.ast_add_scope = ast_add_scope;
13129 exports.set_logger = function(logger) { warn = logger };
13130 exports.make_string = make_string;
13131 exports.split_lines = split_lines;
13132 exports.MAP = MAP;
13134 // keep this last!
13135 exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more;
13137 // Local variables:
13138 // js-indent-level: 4
13139 // End:
13141 define('uglifyjs/index', ["require", "exports", "module", "./parse-js", "./process", "./consolidator"], function(require, exports, module) {
13142 //convienence function(src, [options]);
13143 function uglify(orig_code, options){
13144   options || (options = {});
13145   var jsp = uglify.parser;
13146   var pro = uglify.uglify;
13148   var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST
13149   ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names
13150   ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations
13151   var final_code = pro.gen_code(ast, options.gen_options); // compressed code here
13152   return final_code;
13155 uglify.parser = require("./parse-js");
13156 uglify.uglify = require("./process");
13157 uglify.consolidator = require("./consolidator");
13159 module.exports = uglify
13160 });/* -*- Mode: js; js-indent-level: 2; -*- */
13162  * Copyright 2011 Mozilla Foundation and contributors
13163  * Licensed under the New BSD license. See LICENSE or:
13164  * http://opensource.org/licenses/BSD-3-Clause
13165  */
13167 define('source-map/array-set', function (require, exports, module) {
13169   var util = require('./util');
13171   /**
13172    * A data structure which is a combination of an array and a set. Adding a new
13173    * member is O(1), testing for membership is O(1), and finding the index of an
13174    * element is O(1). Removing elements from the set is not supported. Only
13175    * strings are supported for membership.
13176    */
13177   function ArraySet() {
13178     this._array = [];
13179     this._set = {};
13180   }
13182   /**
13183    * Static method for creating ArraySet instances from an existing array.
13184    */
13185   ArraySet.fromArray = function ArraySet_fromArray(aArray) {
13186     var set = new ArraySet();
13187     for (var i = 0, len = aArray.length; i < len; i++) {
13188       set.add(aArray[i]);
13189     }
13190     return set;
13191   };
13193   /**
13194    * Add the given string to this set.
13195    *
13196    * @param String aStr
13197    */
13198   ArraySet.prototype.add = function ArraySet_add(aStr) {
13199     if (this.has(aStr)) {
13200       // Already a member; nothing to do.
13201       return;
13202     }
13203     var idx = this._array.length;
13204     this._array.push(aStr);
13205     this._set[util.toSetString(aStr)] = idx;
13206   };
13208   /**
13209    * Is the given string a member of this set?
13210    *
13211    * @param String aStr
13212    */
13213   ArraySet.prototype.has = function ArraySet_has(aStr) {
13214     return Object.prototype.hasOwnProperty.call(this._set,
13215                                                 util.toSetString(aStr));
13216   };
13218   /**
13219    * What is the index of the given string in the array?
13220    *
13221    * @param String aStr
13222    */
13223   ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
13224     if (this.has(aStr)) {
13225       return this._set[util.toSetString(aStr)];
13226     }
13227     throw new Error('"' + aStr + '" is not in the set.');
13228   };
13230   /**
13231    * What is the element at the given index?
13232    *
13233    * @param Number aIdx
13234    */
13235   ArraySet.prototype.at = function ArraySet_at(aIdx) {
13236     if (aIdx >= 0 && aIdx < this._array.length) {
13237       return this._array[aIdx];
13238     }
13239     throw new Error('No element indexed by ' + aIdx);
13240   };
13242   /**
13243    * Returns the array representation of this set (which has the proper indices
13244    * indicated by indexOf). Note that this is a copy of the internal array used
13245    * for storing the members so that no one can mess with internal state.
13246    */
13247   ArraySet.prototype.toArray = function ArraySet_toArray() {
13248     return this._array.slice();
13249   };
13251   exports.ArraySet = ArraySet;
13254 /* -*- Mode: js; js-indent-level: 2; -*- */
13256  * Copyright 2011 Mozilla Foundation and contributors
13257  * Licensed under the New BSD license. See LICENSE or:
13258  * http://opensource.org/licenses/BSD-3-Clause
13260  * Based on the Base 64 VLQ implementation in Closure Compiler:
13261  * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
13263  * Copyright 2011 The Closure Compiler Authors. All rights reserved.
13264  * Redistribution and use in source and binary forms, with or without
13265  * modification, are permitted provided that the following conditions are
13266  * met:
13268  *  * Redistributions of source code must retain the above copyright
13269  *    notice, this list of conditions and the following disclaimer.
13270  *  * Redistributions in binary form must reproduce the above
13271  *    copyright notice, this list of conditions and the following
13272  *    disclaimer in the documentation and/or other materials provided
13273  *    with the distribution.
13274  *  * Neither the name of Google Inc. nor the names of its
13275  *    contributors may be used to endorse or promote products derived
13276  *    from this software without specific prior written permission.
13278  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
13279  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
13280  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
13281  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
13282  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
13283  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
13284  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
13285  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13286  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13287  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13288  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13289  */
13291 define('source-map/base64-vlq', function (require, exports, module) {
13293   var base64 = require('./base64');
13295   // A single base 64 digit can contain 6 bits of data. For the base 64 variable
13296   // length quantities we use in the source map spec, the first bit is the sign,
13297   // the next four bits are the actual value, and the 6th bit is the
13298   // continuation bit. The continuation bit tells us whether there are more
13299   // digits in this value following this digit.
13300   //
13301   //   Continuation
13302   //   |    Sign
13303   //   |    |
13304   //   V    V
13305   //   101011
13307   var VLQ_BASE_SHIFT = 5;
13309   // binary: 100000
13310   var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
13312   // binary: 011111
13313   var VLQ_BASE_MASK = VLQ_BASE - 1;
13315   // binary: 100000
13316   var VLQ_CONTINUATION_BIT = VLQ_BASE;
13318   /**
13319    * Converts from a two-complement value to a value where the sign bit is
13320    * is placed in the least significant bit.  For example, as decimals:
13321    *   1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
13322    *   2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
13323    */
13324   function toVLQSigned(aValue) {
13325     return aValue < 0
13326       ? ((-aValue) << 1) + 1
13327       : (aValue << 1) + 0;
13328   }
13330   /**
13331    * Converts to a two-complement value from a value where the sign bit is
13332    * is placed in the least significant bit.  For example, as decimals:
13333    *   2 (10 binary) becomes 1, 3 (11 binary) becomes -1
13334    *   4 (100 binary) becomes 2, 5 (101 binary) becomes -2
13335    */
13336   function fromVLQSigned(aValue) {
13337     var isNegative = (aValue & 1) === 1;
13338     var shifted = aValue >> 1;
13339     return isNegative
13340       ? -shifted
13341       : shifted;
13342   }
13344   /**
13345    * Returns the base 64 VLQ encoded value.
13346    */
13347   exports.encode = function base64VLQ_encode(aValue) {
13348     var encoded = "";
13349     var digit;
13351     var vlq = toVLQSigned(aValue);
13353     do {
13354       digit = vlq & VLQ_BASE_MASK;
13355       vlq >>>= VLQ_BASE_SHIFT;
13356       if (vlq > 0) {
13357         // There are still more digits in this value, so we must make sure the
13358         // continuation bit is marked.
13359         digit |= VLQ_CONTINUATION_BIT;
13360       }
13361       encoded += base64.encode(digit);
13362     } while (vlq > 0);
13364     return encoded;
13365   };
13367   /**
13368    * Decodes the next base 64 VLQ value from the given string and returns the
13369    * value and the rest of the string.
13370    */
13371   exports.decode = function base64VLQ_decode(aStr) {
13372     var i = 0;
13373     var strLen = aStr.length;
13374     var result = 0;
13375     var shift = 0;
13376     var continuation, digit;
13378     do {
13379       if (i >= strLen) {
13380         throw new Error("Expected more digits in base 64 VLQ value.");
13381       }
13382       digit = base64.decode(aStr.charAt(i++));
13383       continuation = !!(digit & VLQ_CONTINUATION_BIT);
13384       digit &= VLQ_BASE_MASK;
13385       result = result + (digit << shift);
13386       shift += VLQ_BASE_SHIFT;
13387     } while (continuation);
13389     return {
13390       value: fromVLQSigned(result),
13391       rest: aStr.slice(i)
13392     };
13393   };
13396 /* -*- Mode: js; js-indent-level: 2; -*- */
13398  * Copyright 2011 Mozilla Foundation and contributors
13399  * Licensed under the New BSD license. See LICENSE or:
13400  * http://opensource.org/licenses/BSD-3-Clause
13401  */
13403 define('source-map/base64', function (require, exports, module) {
13405   var charToIntMap = {};
13406   var intToCharMap = {};
13408   'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
13409     .split('')
13410     .forEach(function (ch, index) {
13411       charToIntMap[ch] = index;
13412       intToCharMap[index] = ch;
13413     });
13415   /**
13416    * Encode an integer in the range of 0 to 63 to a single base 64 digit.
13417    */
13418   exports.encode = function base64_encode(aNumber) {
13419     if (aNumber in intToCharMap) {
13420       return intToCharMap[aNumber];
13421     }
13422     throw new TypeError("Must be between 0 and 63: " + aNumber);
13423   };
13425   /**
13426    * Decode a single base 64 digit to an integer.
13427    */
13428   exports.decode = function base64_decode(aChar) {
13429     if (aChar in charToIntMap) {
13430       return charToIntMap[aChar];
13431     }
13432     throw new TypeError("Not a valid base 64 digit: " + aChar);
13433   };
13436 /* -*- Mode: js; js-indent-level: 2; -*- */
13438  * Copyright 2011 Mozilla Foundation and contributors
13439  * Licensed under the New BSD license. See LICENSE or:
13440  * http://opensource.org/licenses/BSD-3-Clause
13441  */
13443 define('source-map/binary-search', function (require, exports, module) {
13445   /**
13446    * Recursive implementation of binary search.
13447    *
13448    * @param aLow Indices here and lower do not contain the needle.
13449    * @param aHigh Indices here and higher do not contain the needle.
13450    * @param aNeedle The element being searched for.
13451    * @param aHaystack The non-empty array being searched.
13452    * @param aCompare Function which takes two elements and returns -1, 0, or 1.
13453    */
13454   function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) {
13455     // This function terminates when one of the following is true:
13456     //
13457     //   1. We find the exact element we are looking for.
13458     //
13459     //   2. We did not find the exact element, but we can return the next
13460     //      closest element that is less than that element.
13461     //
13462     //   3. We did not find the exact element, and there is no next-closest
13463     //      element which is less than the one we are searching for, so we
13464     //      return null.
13465     var mid = Math.floor((aHigh - aLow) / 2) + aLow;
13466     var cmp = aCompare(aNeedle, aHaystack[mid]);
13467     if (cmp === 0) {
13468       // Found the element we are looking for.
13469       return aHaystack[mid];
13470     }
13471     else if (cmp > 0) {
13472       // aHaystack[mid] is greater than our needle.
13473       if (aHigh - mid > 1) {
13474         // The element is in the upper half.
13475         return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare);
13476       }
13477       // We did not find an exact match, return the next closest one
13478       // (termination case 2).
13479       return aHaystack[mid];
13480     }
13481     else {
13482       // aHaystack[mid] is less than our needle.
13483       if (mid - aLow > 1) {
13484         // The element is in the lower half.
13485         return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare);
13486       }
13487       // The exact needle element was not found in this haystack. Determine if
13488       // we are in termination case (2) or (3) and return the appropriate thing.
13489       return aLow < 0
13490         ? null
13491         : aHaystack[aLow];
13492     }
13493   }
13495   /**
13496    * This is an implementation of binary search which will always try and return
13497    * the next lowest value checked if there is no exact hit. This is because
13498    * mappings between original and generated line/col pairs are single points,
13499    * and there is an implicit region between each of them, so a miss just means
13500    * that you aren't on the very start of a region.
13501    *
13502    * @param aNeedle The element you are looking for.
13503    * @param aHaystack The array that is being searched.
13504    * @param aCompare A function which takes the needle and an element in the
13505    *     array and returns -1, 0, or 1 depending on whether the needle is less
13506    *     than, equal to, or greater than the element, respectively.
13507    */
13508   exports.search = function search(aNeedle, aHaystack, aCompare) {
13509     return aHaystack.length > 0
13510       ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare)
13511       : null;
13512   };
13515 /* -*- Mode: js; js-indent-level: 2; -*- */
13517  * Copyright 2011 Mozilla Foundation and contributors
13518  * Licensed under the New BSD license. See LICENSE or:
13519  * http://opensource.org/licenses/BSD-3-Clause
13520  */
13522 define('source-map/source-map-consumer', function (require, exports, module) {
13524   var util = require('./util');
13525   var binarySearch = require('./binary-search');
13526   var ArraySet = require('./array-set').ArraySet;
13527   var base64VLQ = require('./base64-vlq');
13529   /**
13530    * A SourceMapConsumer instance represents a parsed source map which we can
13531    * query for information about the original file positions by giving it a file
13532    * position in the generated source.
13533    *
13534    * The only parameter is the raw source map (either as a JSON string, or
13535    * already parsed to an object). According to the spec, source maps have the
13536    * following attributes:
13537    *
13538    *   - version: Which version of the source map spec this map is following.
13539    *   - sources: An array of URLs to the original source files.
13540    *   - names: An array of identifiers which can be referrenced by individual mappings.
13541    *   - sourceRoot: Optional. The URL root from which all sources are relative.
13542    *   - sourcesContent: Optional. An array of contents of the original source files.
13543    *   - mappings: A string of base64 VLQs which contain the actual mappings.
13544    *   - file: The generated file this source map is associated with.
13545    *
13546    * Here is an example source map, taken from the source map spec[0]:
13547    *
13548    *     {
13549    *       version : 3,
13550    *       file: "out.js",
13551    *       sourceRoot : "",
13552    *       sources: ["foo.js", "bar.js"],
13553    *       names: ["src", "maps", "are", "fun"],
13554    *       mappings: "AA,AB;;ABCDE;"
13555    *     }
13556    *
13557    * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
13558    */
13559   function SourceMapConsumer(aSourceMap) {
13560     var sourceMap = aSourceMap;
13561     if (typeof aSourceMap === 'string') {
13562       sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
13563     }
13565     var version = util.getArg(sourceMap, 'version');
13566     var sources = util.getArg(sourceMap, 'sources');
13567     var names = util.getArg(sourceMap, 'names');
13568     var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
13569     var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
13570     var mappings = util.getArg(sourceMap, 'mappings');
13571     var file = util.getArg(sourceMap, 'file');
13573     if (version !== this._version) {
13574       throw new Error('Unsupported version: ' + version);
13575     }
13577     this._names = ArraySet.fromArray(names);
13578     this._sources = ArraySet.fromArray(sources);
13579     this.sourceRoot = sourceRoot;
13580     this.sourcesContent = sourcesContent;
13581     this.file = file;
13583     // `this._generatedMappings` and `this._originalMappings` hold the parsed
13584     // mapping coordinates from the source map's "mappings" attribute. Each
13585     // object in the array is of the form
13586     //
13587     //     {
13588     //       generatedLine: The line number in the generated code,
13589     //       generatedColumn: The column number in the generated code,
13590     //       source: The path to the original source file that generated this
13591     //               chunk of code,
13592     //       originalLine: The line number in the original source that
13593     //                     corresponds to this chunk of generated code,
13594     //       originalColumn: The column number in the original source that
13595     //                       corresponds to this chunk of generated code,
13596     //       name: The name of the original symbol which generated this chunk of
13597     //             code.
13598     //     }
13599     //
13600     // All properties except for `generatedLine` and `generatedColumn` can be
13601     // `null`.
13602     //
13603     // `this._generatedMappings` is ordered by the generated positions.
13604     //
13605     // `this._originalMappings` is ordered by the original positions.
13606     this._generatedMappings = [];
13607     this._originalMappings = [];
13608     this._parseMappings(mappings, sourceRoot);
13609   }
13611   /**
13612    * The version of the source mapping spec that we are consuming.
13613    */
13614   SourceMapConsumer.prototype._version = 3;
13616   /**
13617    * The list of original sources.
13618    */
13619   Object.defineProperty(SourceMapConsumer.prototype, 'sources', {
13620     get: function () {
13621       return this._sources.toArray().map(function (s) {
13622         return this.sourceRoot ? util.join(this.sourceRoot, s) : s;
13623       }, this);
13624     }
13625   });
13627   /**
13628    * Parse the mappings in a string in to a data structure which we can easily
13629    * query (an ordered list in this._generatedMappings).
13630    */
13631   SourceMapConsumer.prototype._parseMappings =
13632     function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
13633       var generatedLine = 1;
13634       var previousGeneratedColumn = 0;
13635       var previousOriginalLine = 0;
13636       var previousOriginalColumn = 0;
13637       var previousSource = 0;
13638       var previousName = 0;
13639       var mappingSeparator = /^[,;]/;
13640       var str = aStr;
13641       var mapping;
13642       var temp;
13644       while (str.length > 0) {
13645         if (str.charAt(0) === ';') {
13646           generatedLine++;
13647           str = str.slice(1);
13648           previousGeneratedColumn = 0;
13649         }
13650         else if (str.charAt(0) === ',') {
13651           str = str.slice(1);
13652         }
13653         else {
13654           mapping = {};
13655           mapping.generatedLine = generatedLine;
13657           // Generated column.
13658           temp = base64VLQ.decode(str);
13659           mapping.generatedColumn = previousGeneratedColumn + temp.value;
13660           previousGeneratedColumn = mapping.generatedColumn;
13661           str = temp.rest;
13663           if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {
13664             // Original source.
13665             temp = base64VLQ.decode(str);
13666             mapping.source = this._sources.at(previousSource + temp.value);
13667             previousSource += temp.value;
13668             str = temp.rest;
13669             if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {
13670               throw new Error('Found a source, but no line and column');
13671             }
13673             // Original line.
13674             temp = base64VLQ.decode(str);
13675             mapping.originalLine = previousOriginalLine + temp.value;
13676             previousOriginalLine = mapping.originalLine;
13677             // Lines are stored 0-based
13678             mapping.originalLine += 1;
13679             str = temp.rest;
13680             if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {
13681               throw new Error('Found a source and line, but no column');
13682             }
13684             // Original column.
13685             temp = base64VLQ.decode(str);
13686             mapping.originalColumn = previousOriginalColumn + temp.value;
13687             previousOriginalColumn = mapping.originalColumn;
13688             str = temp.rest;
13690             if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {
13691               // Original name.
13692               temp = base64VLQ.decode(str);
13693               mapping.name = this._names.at(previousName + temp.value);
13694               previousName += temp.value;
13695               str = temp.rest;
13696             }
13697           }
13699           this._generatedMappings.push(mapping);
13700           if (typeof mapping.originalLine === 'number') {
13701             this._originalMappings.push(mapping);
13702           }
13703         }
13704       }
13706       this._originalMappings.sort(this._compareOriginalPositions);
13707     };
13709   /**
13710    * Comparator between two mappings where the original positions are compared.
13711    */
13712   SourceMapConsumer.prototype._compareOriginalPositions =
13713     function SourceMapConsumer_compareOriginalPositions(mappingA, mappingB) {
13714       if (mappingA.source > mappingB.source) {
13715         return 1;
13716       }
13717       else if (mappingA.source < mappingB.source) {
13718         return -1;
13719       }
13720       else {
13721         var cmp = mappingA.originalLine - mappingB.originalLine;
13722         return cmp === 0
13723           ? mappingA.originalColumn - mappingB.originalColumn
13724           : cmp;
13725       }
13726     };
13728   /**
13729    * Comparator between two mappings where the generated positions are compared.
13730    */
13731   SourceMapConsumer.prototype._compareGeneratedPositions =
13732     function SourceMapConsumer_compareGeneratedPositions(mappingA, mappingB) {
13733       var cmp = mappingA.generatedLine - mappingB.generatedLine;
13734       return cmp === 0
13735         ? mappingA.generatedColumn - mappingB.generatedColumn
13736         : cmp;
13737     };
13739   /**
13740    * Find the mapping that best matches the hypothetical "needle" mapping that
13741    * we are searching for in the given "haystack" of mappings.
13742    */
13743   SourceMapConsumer.prototype._findMapping =
13744     function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,
13745                                            aColumnName, aComparator) {
13746       // To return the position we are searching for, we must first find the
13747       // mapping for the given position and then return the opposite position it
13748       // points to. Because the mappings are sorted, we can use binary search to
13749       // find the best mapping.
13751       if (aNeedle[aLineName] <= 0) {
13752         throw new TypeError('Line must be greater than or equal to 1, got '
13753                             + aNeedle[aLineName]);
13754       }
13755       if (aNeedle[aColumnName] < 0) {
13756         throw new TypeError('Column must be greater than or equal to 0, got '
13757                             + aNeedle[aColumnName]);
13758       }
13760       return binarySearch.search(aNeedle, aMappings, aComparator);
13761     };
13763   /**
13764    * Returns the original source, line, and column information for the generated
13765    * source's line and column positions provided. The only argument is an object
13766    * with the following properties:
13767    *
13768    *   - line: The line number in the generated source.
13769    *   - column: The column number in the generated source.
13770    *
13771    * and an object is returned with the following properties:
13772    *
13773    *   - source: The original source file, or null.
13774    *   - line: The line number in the original source, or null.
13775    *   - column: The column number in the original source, or null.
13776    *   - name: The original identifier, or null.
13777    */
13778   SourceMapConsumer.prototype.originalPositionFor =
13779     function SourceMapConsumer_originalPositionFor(aArgs) {
13780       var needle = {
13781         generatedLine: util.getArg(aArgs, 'line'),
13782         generatedColumn: util.getArg(aArgs, 'column')
13783       };
13785       var mapping = this._findMapping(needle,
13786                                       this._generatedMappings,
13787                                       "generatedLine",
13788                                       "generatedColumn",
13789                                       this._compareGeneratedPositions);
13791       if (mapping) {
13792         var source = util.getArg(mapping, 'source', null);
13793         if (source && this.sourceRoot) {
13794           source = util.join(this.sourceRoot, source);
13795         }
13796         return {
13797           source: source,
13798           line: util.getArg(mapping, 'originalLine', null),
13799           column: util.getArg(mapping, 'originalColumn', null),
13800           name: util.getArg(mapping, 'name', null)
13801         };
13802       }
13804       return {
13805         source: null,
13806         line: null,
13807         column: null,
13808         name: null
13809       };
13810     };
13812   /**
13813    * Returns the original source content. The only argument is the url of the
13814    * original source file. Returns null if no original source content is
13815    * availible.
13816    */
13817   SourceMapConsumer.prototype.sourceContentFor =
13818     function SourceMapConsumer_sourceContentFor(aSource) {
13819       if (!this.sourcesContent) {
13820         return null;
13821       }
13823       if (this.sourceRoot) {
13824         aSource = util.relative(this.sourceRoot, aSource);
13825       }
13827       if (this._sources.has(aSource)) {
13828         return this.sourcesContent[this._sources.indexOf(aSource)];
13829       }
13831       var url;
13832       if (this.sourceRoot
13833           && (url = util.urlParse(this.sourceRoot))) {
13834         // XXX: file:// URIs and absolute paths lead to unexpected behavior for
13835         // many users. We can help them out when they expect file:// URIs to
13836         // behave like it would if they were running a local HTTP server. See
13837         // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
13838         var fileUriAbsPath = aSource.replace(/^file:\/\//, "");
13839         if (url.scheme == "file"
13840             && this._sources.has(fileUriAbsPath)) {
13841           return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]
13842         }
13844         if ((!url.path || url.path == "/")
13845             && this._sources.has("/" + aSource)) {
13846           return this.sourcesContent[this._sources.indexOf("/" + aSource)];
13847         }
13848       }
13850       throw new Error('"' + aSource + '" is not in the SourceMap.');
13851     };
13853   /**
13854    * Returns the generated line and column information for the original source,
13855    * line, and column positions provided. The only argument is an object with
13856    * the following properties:
13857    *
13858    *   - source: The filename of the original source.
13859    *   - line: The line number in the original source.
13860    *   - column: The column number in the original source.
13861    *
13862    * and an object is returned with the following properties:
13863    *
13864    *   - line: The line number in the generated source, or null.
13865    *   - column: The column number in the generated source, or null.
13866    */
13867   SourceMapConsumer.prototype.generatedPositionFor =
13868     function SourceMapConsumer_generatedPositionFor(aArgs) {
13869       var needle = {
13870         source: util.getArg(aArgs, 'source'),
13871         originalLine: util.getArg(aArgs, 'line'),
13872         originalColumn: util.getArg(aArgs, 'column')
13873       };
13875       if (this.sourceRoot) {
13876         needle.source = util.relative(this.sourceRoot, needle.source);
13877       }
13879       var mapping = this._findMapping(needle,
13880                                       this._originalMappings,
13881                                       "originalLine",
13882                                       "originalColumn",
13883                                       this._compareOriginalPositions);
13885       if (mapping) {
13886         return {
13887           line: util.getArg(mapping, 'generatedLine', null),
13888           column: util.getArg(mapping, 'generatedColumn', null)
13889         };
13890       }
13892       return {
13893         line: null,
13894         column: null
13895       };
13896     };
13898   SourceMapConsumer.GENERATED_ORDER = 1;
13899   SourceMapConsumer.ORIGINAL_ORDER = 2;
13901   /**
13902    * Iterate over each mapping between an original source/line/column and a
13903    * generated line/column in this source map.
13904    *
13905    * @param Function aCallback
13906    *        The function that is called with each mapping.
13907    * @param Object aContext
13908    *        Optional. If specified, this object will be the value of `this` every
13909    *        time that `aCallback` is called.
13910    * @param aOrder
13911    *        Either `SourceMapConsumer.GENERATED_ORDER` or
13912    *        `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to
13913    *        iterate over the mappings sorted by the generated file's line/column
13914    *        order or the original's source/line/column order, respectively. Defaults to
13915    *        `SourceMapConsumer.GENERATED_ORDER`.
13916    */
13917   SourceMapConsumer.prototype.eachMapping =
13918     function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {
13919       var context = aContext || null;
13920       var order = aOrder || SourceMapConsumer.GENERATED_ORDER;
13922       var mappings;
13923       switch (order) {
13924       case SourceMapConsumer.GENERATED_ORDER:
13925         mappings = this._generatedMappings;
13926         break;
13927       case SourceMapConsumer.ORIGINAL_ORDER:
13928         mappings = this._originalMappings;
13929         break;
13930       default:
13931         throw new Error("Unknown order of iteration.");
13932       }
13934       var sourceRoot = this.sourceRoot;
13935       mappings.map(function (mapping) {
13936         var source = mapping.source;
13937         if (source && sourceRoot) {
13938           source = util.join(sourceRoot, source);
13939         }
13940         return {
13941           source: source,
13942           generatedLine: mapping.generatedLine,
13943           generatedColumn: mapping.generatedColumn,
13944           originalLine: mapping.originalLine,
13945           originalColumn: mapping.originalColumn,
13946           name: mapping.name
13947         };
13948       }).forEach(aCallback, context);
13949     };
13951   exports.SourceMapConsumer = SourceMapConsumer;
13954 /* -*- Mode: js; js-indent-level: 2; -*- */
13956  * Copyright 2011 Mozilla Foundation and contributors
13957  * Licensed under the New BSD license. See LICENSE or:
13958  * http://opensource.org/licenses/BSD-3-Clause
13959  */
13961 define('source-map/source-map-generator', function (require, exports, module) {
13963   var base64VLQ = require('./base64-vlq');
13964   var util = require('./util');
13965   var ArraySet = require('./array-set').ArraySet;
13967   /**
13968    * An instance of the SourceMapGenerator represents a source map which is
13969    * being built incrementally. To create a new one, you must pass an object
13970    * with the following properties:
13971    *
13972    *   - file: The filename of the generated source.
13973    *   - sourceRoot: An optional root for all URLs in this source map.
13974    */
13975   function SourceMapGenerator(aArgs) {
13976     this._file = util.getArg(aArgs, 'file');
13977     this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
13978     this._sources = new ArraySet();
13979     this._names = new ArraySet();
13980     this._mappings = [];
13981     this._sourcesContents = null;
13982   }
13984   SourceMapGenerator.prototype._version = 3;
13986   /**
13987    * Creates a new SourceMapGenerator based on a SourceMapConsumer
13988    *
13989    * @param aSourceMapConsumer The SourceMap.
13990    */
13991   SourceMapGenerator.fromSourceMap =
13992     function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
13993       var sourceRoot = aSourceMapConsumer.sourceRoot;
13994       var generator = new SourceMapGenerator({
13995         file: aSourceMapConsumer.file,
13996         sourceRoot: sourceRoot
13997       });
13998       aSourceMapConsumer.eachMapping(function (mapping) {
13999         var newMapping = {
14000           generated: {
14001             line: mapping.generatedLine,
14002             column: mapping.generatedColumn
14003           }
14004         };
14006         if (mapping.source) {
14007           newMapping.source = mapping.source;
14008           if (sourceRoot) {
14009             newMapping.source = util.relative(sourceRoot, newMapping.source);
14010           }
14012           newMapping.original = {
14013             line: mapping.originalLine,
14014             column: mapping.originalColumn
14015           };
14017           if (mapping.name) {
14018             newMapping.name = mapping.name;
14019           }
14020         }
14022         generator.addMapping(newMapping);
14023       });
14024       aSourceMapConsumer.sources.forEach(function (sourceFile) {
14025         var content = aSourceMapConsumer.sourceContentFor(sourceFile);
14026         if (content) {
14027           generator.setSourceContent(sourceFile, content);
14028         }
14029       });
14030       return generator;
14031     };
14033   /**
14034    * Add a single mapping from original source line and column to the generated
14035    * source's line and column for this source map being created. The mapping
14036    * object should have the following properties:
14037    *
14038    *   - generated: An object with the generated line and column positions.
14039    *   - original: An object with the original line and column positions.
14040    *   - source: The original source file (relative to the sourceRoot).
14041    *   - name: An optional original token name for this mapping.
14042    */
14043   SourceMapGenerator.prototype.addMapping =
14044     function SourceMapGenerator_addMapping(aArgs) {
14045       var generated = util.getArg(aArgs, 'generated');
14046       var original = util.getArg(aArgs, 'original', null);
14047       var source = util.getArg(aArgs, 'source', null);
14048       var name = util.getArg(aArgs, 'name', null);
14050       this._validateMapping(generated, original, source, name);
14052       if (source && !this._sources.has(source)) {
14053         this._sources.add(source);
14054       }
14056       if (name && !this._names.has(name)) {
14057         this._names.add(name);
14058       }
14060       this._mappings.push({
14061         generated: generated,
14062         original: original,
14063         source: source,
14064         name: name
14065       });
14066     };
14068   /**
14069    * Set the source content for a source file.
14070    */
14071   SourceMapGenerator.prototype.setSourceContent =
14072     function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
14073       var source = aSourceFile;
14074       if (this._sourceRoot) {
14075         source = util.relative(this._sourceRoot, source);
14076       }
14078       if (aSourceContent !== null) {
14079         // Add the source content to the _sourcesContents map.
14080         // Create a new _sourcesContents map if the property is null.
14081         if (!this._sourcesContents) {
14082           this._sourcesContents = {};
14083         }
14084         this._sourcesContents[util.toSetString(source)] = aSourceContent;
14085       } else {
14086         // Remove the source file from the _sourcesContents map.
14087         // If the _sourcesContents map is empty, set the property to null.
14088         delete this._sourcesContents[util.toSetString(source)];
14089         if (Object.keys(this._sourcesContents).length === 0) {
14090           this._sourcesContents = null;
14091         }
14092       }
14093     };
14095   /**
14096    * Applies the mappings of a sub-source-map for a specific source file to the
14097    * source map being generated. Each mapping to the supplied source file is
14098    * rewritten using the supplied source map. Note: The resolution for the
14099    * resulting mappings is the minimium of this map and the supplied map.
14100    *
14101    * @param aSourceMapConsumer The source map to be applied.
14102    * @param aSourceFile Optional. The filename of the source file.
14103    *        If omitted, SourceMapConsumer's file property will be used.
14104    */
14105   SourceMapGenerator.prototype.applySourceMap =
14106     function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) {
14107       // If aSourceFile is omitted, we will use the file property of the SourceMap
14108       if (!aSourceFile) {
14109         aSourceFile = aSourceMapConsumer.file;
14110       }
14111       var sourceRoot = this._sourceRoot;
14112       // Make "aSourceFile" relative if an absolute Url is passed.
14113       if (sourceRoot) {
14114         aSourceFile = util.relative(sourceRoot, aSourceFile);
14115       }
14116       // Applying the SourceMap can add and remove items from the sources and
14117       // the names array.
14118       var newSources = new ArraySet();
14119       var newNames = new ArraySet();
14121       // Find mappings for the "aSourceFile"
14122       this._mappings.forEach(function (mapping) {
14123         if (mapping.source === aSourceFile && mapping.original) {
14124           // Check if it can be mapped by the source map, then update the mapping.
14125           var original = aSourceMapConsumer.originalPositionFor({
14126             line: mapping.original.line,
14127             column: mapping.original.column
14128           });
14129           if (original.source !== null) {
14130             // Copy mapping
14131             if (sourceRoot) {
14132               mapping.source = util.relative(sourceRoot, original.source);
14133             } else {
14134               mapping.source = original.source;
14135             }
14136             mapping.original.line = original.line;
14137             mapping.original.column = original.column;
14138             if (original.name !== null && mapping.name !== null) {
14139               // Only use the identifier name if it's an identifier
14140               // in both SourceMaps
14141               mapping.name = original.name;
14142             }
14143           }
14144         }
14146         var source = mapping.source;
14147         if (source && !newSources.has(source)) {
14148           newSources.add(source);
14149         }
14151         var name = mapping.name;
14152         if (name && !newNames.has(name)) {
14153           newNames.add(name);
14154         }
14156       }, this);
14157       this._sources = newSources;
14158       this._names = newNames;
14160       // Copy sourcesContents of applied map.
14161       aSourceMapConsumer.sources.forEach(function (sourceFile) {
14162         var content = aSourceMapConsumer.sourceContentFor(sourceFile);
14163         if (content) {
14164           if (sourceRoot) {
14165             sourceFile = util.relative(sourceRoot, sourceFile);
14166           }
14167           this.setSourceContent(sourceFile, content);
14168         }
14169       }, this);
14170     };
14172   /**
14173    * A mapping can have one of the three levels of data:
14174    *
14175    *   1. Just the generated position.
14176    *   2. The Generated position, original position, and original source.
14177    *   3. Generated and original position, original source, as well as a name
14178    *      token.
14179    *
14180    * To maintain consistency, we validate that any new mapping being added falls
14181    * in to one of these categories.
14182    */
14183   SourceMapGenerator.prototype._validateMapping =
14184     function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,
14185                                                 aName) {
14186       if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
14187           && aGenerated.line > 0 && aGenerated.column >= 0
14188           && !aOriginal && !aSource && !aName) {
14189         // Case 1.
14190         return;
14191       }
14192       else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
14193                && aOriginal && 'line' in aOriginal && 'column' in aOriginal
14194                && aGenerated.line > 0 && aGenerated.column >= 0
14195                && aOriginal.line > 0 && aOriginal.column >= 0
14196                && aSource) {
14197         // Cases 2 and 3.
14198         return;
14199       }
14200       else {
14201         throw new Error('Invalid mapping.');
14202       }
14203     };
14205   function cmpLocation(loc1, loc2) {
14206     var cmp = (loc1 && loc1.line) - (loc2 && loc2.line);
14207     return cmp ? cmp : (loc1 && loc1.column) - (loc2 && loc2.column);
14208   }
14210   function strcmp(str1, str2) {
14211     str1 = str1 || '';
14212     str2 = str2 || '';
14213     return (str1 > str2) - (str1 < str2);
14214   }
14216   function cmpMapping(mappingA, mappingB) {
14217     return cmpLocation(mappingA.generated, mappingB.generated) ||
14218       cmpLocation(mappingA.original, mappingB.original) ||
14219       strcmp(mappingA.source, mappingB.source) ||
14220       strcmp(mappingA.name, mappingB.name);
14221   }
14223   /**
14224    * Serialize the accumulated mappings in to the stream of base 64 VLQs
14225    * specified by the source map format.
14226    */
14227   SourceMapGenerator.prototype._serializeMappings =
14228     function SourceMapGenerator_serializeMappings() {
14229       var previousGeneratedColumn = 0;
14230       var previousGeneratedLine = 1;
14231       var previousOriginalColumn = 0;
14232       var previousOriginalLine = 0;
14233       var previousName = 0;
14234       var previousSource = 0;
14235       var result = '';
14236       var mapping;
14238       // The mappings must be guaranteed to be in sorted order before we start
14239       // serializing them or else the generated line numbers (which are defined
14240       // via the ';' separators) will be all messed up. Note: it might be more
14241       // performant to maintain the sorting as we insert them, rather than as we
14242       // serialize them, but the big O is the same either way.
14243       this._mappings.sort(cmpMapping);
14245       for (var i = 0, len = this._mappings.length; i < len; i++) {
14246         mapping = this._mappings[i];
14248         if (mapping.generated.line !== previousGeneratedLine) {
14249           previousGeneratedColumn = 0;
14250           while (mapping.generated.line !== previousGeneratedLine) {
14251             result += ';';
14252             previousGeneratedLine++;
14253           }
14254         }
14255         else {
14256           if (i > 0) {
14257             if (!cmpMapping(mapping, this._mappings[i - 1])) {
14258               continue;
14259             }
14260             result += ',';
14261           }
14262         }
14264         result += base64VLQ.encode(mapping.generated.column
14265                                    - previousGeneratedColumn);
14266         previousGeneratedColumn = mapping.generated.column;
14268         if (mapping.source && mapping.original) {
14269           result += base64VLQ.encode(this._sources.indexOf(mapping.source)
14270                                      - previousSource);
14271           previousSource = this._sources.indexOf(mapping.source);
14273           // lines are stored 0-based in SourceMap spec version 3
14274           result += base64VLQ.encode(mapping.original.line - 1
14275                                      - previousOriginalLine);
14276           previousOriginalLine = mapping.original.line - 1;
14278           result += base64VLQ.encode(mapping.original.column
14279                                      - previousOriginalColumn);
14280           previousOriginalColumn = mapping.original.column;
14282           if (mapping.name) {
14283             result += base64VLQ.encode(this._names.indexOf(mapping.name)
14284                                        - previousName);
14285             previousName = this._names.indexOf(mapping.name);
14286           }
14287         }
14288       }
14290       return result;
14291     };
14293   /**
14294    * Externalize the source map.
14295    */
14296   SourceMapGenerator.prototype.toJSON =
14297     function SourceMapGenerator_toJSON() {
14298       var map = {
14299         version: this._version,
14300         file: this._file,
14301         sources: this._sources.toArray(),
14302         names: this._names.toArray(),
14303         mappings: this._serializeMappings()
14304       };
14305       if (this._sourceRoot) {
14306         map.sourceRoot = this._sourceRoot;
14307       }
14308       if (this._sourcesContents) {
14309         map.sourcesContent = map.sources.map(function (source) {
14310           if (map.sourceRoot) {
14311             source = util.relative(map.sourceRoot, source);
14312           }
14313           return Object.prototype.hasOwnProperty.call(
14314             this._sourcesContents, util.toSetString(source))
14315             ? this._sourcesContents[util.toSetString(source)]
14316             : null;
14317         }, this);
14318       }
14319       return map;
14320     };
14322   /**
14323    * Render the source map being generated to a string.
14324    */
14325   SourceMapGenerator.prototype.toString =
14326     function SourceMapGenerator_toString() {
14327       return JSON.stringify(this);
14328     };
14330   exports.SourceMapGenerator = SourceMapGenerator;
14333 /* -*- Mode: js; js-indent-level: 2; -*- */
14335  * Copyright 2011 Mozilla Foundation and contributors
14336  * Licensed under the New BSD license. See LICENSE or:
14337  * http://opensource.org/licenses/BSD-3-Clause
14338  */
14340 define('source-map/source-node', function (require, exports, module) {
14342   var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator;
14343   var util = require('./util');
14345   /**
14346    * SourceNodes provide a way to abstract over interpolating/concatenating
14347    * snippets of generated JavaScript source code while maintaining the line and
14348    * column information associated with the original source code.
14349    *
14350    * @param aLine The original line number.
14351    * @param aColumn The original column number.
14352    * @param aSource The original source's filename.
14353    * @param aChunks Optional. An array of strings which are snippets of
14354    *        generated JS, or other SourceNodes.
14355    * @param aName The original identifier.
14356    */
14357   function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
14358     this.children = [];
14359     this.sourceContents = {};
14360     this.line = aLine === undefined ? null : aLine;
14361     this.column = aColumn === undefined ? null : aColumn;
14362     this.source = aSource === undefined ? null : aSource;
14363     this.name = aName === undefined ? null : aName;
14364     if (aChunks != null) this.add(aChunks);
14365   }
14367   /**
14368    * Creates a SourceNode from generated code and a SourceMapConsumer.
14369    *
14370    * @param aGeneratedCode The generated code
14371    * @param aSourceMapConsumer The SourceMap for the generated code
14372    */
14373   SourceNode.fromStringWithSourceMap =
14374     function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) {
14375       // The SourceNode we want to fill with the generated code
14376       // and the SourceMap
14377       var node = new SourceNode();
14379       // The generated code
14380       // Processed fragments are removed from this array.
14381       var remainingLines = aGeneratedCode.split('\n');
14383       // We need to remember the position of "remainingLines"
14384       var lastGeneratedLine = 1, lastGeneratedColumn = 0;
14386       // The generate SourceNodes we need a code range.
14387       // To extract it current and last mapping is used.
14388       // Here we store the last mapping.
14389       var lastMapping = null;
14391       aSourceMapConsumer.eachMapping(function (mapping) {
14392         if (lastMapping === null) {
14393           // We add the generated code until the first mapping
14394           // to the SourceNode without any mapping.
14395           // Each line is added as separate string.
14396           while (lastGeneratedLine < mapping.generatedLine) {
14397             node.add(remainingLines.shift() + "\n");
14398             lastGeneratedLine++;
14399           }
14400           if (lastGeneratedColumn < mapping.generatedColumn) {
14401             var nextLine = remainingLines[0];
14402             node.add(nextLine.substr(0, mapping.generatedColumn));
14403             remainingLines[0] = nextLine.substr(mapping.generatedColumn);
14404             lastGeneratedColumn = mapping.generatedColumn;
14405           }
14406         } else {
14407           // We add the code from "lastMapping" to "mapping":
14408           // First check if there is a new line in between.
14409           if (lastGeneratedLine < mapping.generatedLine) {
14410             var code = "";
14411             // Associate full lines with "lastMapping"
14412             do {
14413               code += remainingLines.shift() + "\n";
14414               lastGeneratedLine++;
14415               lastGeneratedColumn = 0;
14416             } while (lastGeneratedLine < mapping.generatedLine);
14417             // When we reached the correct line, we add code until we
14418             // reach the correct column too.
14419             if (lastGeneratedColumn < mapping.generatedColumn) {
14420               var nextLine = remainingLines[0];
14421               code += nextLine.substr(0, mapping.generatedColumn);
14422               remainingLines[0] = nextLine.substr(mapping.generatedColumn);
14423               lastGeneratedColumn = mapping.generatedColumn;
14424             }
14425             // Create the SourceNode.
14426             addMappingWithCode(lastMapping, code);
14427           } else {
14428             // There is no new line in between.
14429             // Associate the code between "lastGeneratedColumn" and
14430             // "mapping.generatedColumn" with "lastMapping"
14431             var nextLine = remainingLines[0];
14432             var code = nextLine.substr(0, mapping.generatedColumn -
14433                                           lastGeneratedColumn);
14434             remainingLines[0] = nextLine.substr(mapping.generatedColumn -
14435                                                 lastGeneratedColumn);
14436             lastGeneratedColumn = mapping.generatedColumn;
14437             addMappingWithCode(lastMapping, code);
14438           }
14439         }
14440         lastMapping = mapping;
14441       }, this);
14442       // We have processed all mappings.
14443       // Associate the remaining code in the current line with "lastMapping"
14444       // and add the remaining lines without any mapping
14445       addMappingWithCode(lastMapping, remainingLines.join("\n"));
14447       // Copy sourcesContent into SourceNode
14448       aSourceMapConsumer.sources.forEach(function (sourceFile) {
14449         var content = aSourceMapConsumer.sourceContentFor(sourceFile);
14450         if (content) {
14451           node.setSourceContent(sourceFile, content);
14452         }
14453       });
14455       return node;
14457       function addMappingWithCode(mapping, code) {
14458         if (mapping.source === undefined) {
14459           node.add(code);
14460         } else {
14461           node.add(new SourceNode(mapping.originalLine,
14462                                   mapping.originalColumn,
14463                                   mapping.source,
14464                                   code,
14465                                   mapping.name));
14466         }
14467       }
14468     };
14470   /**
14471    * Add a chunk of generated JS to this source node.
14472    *
14473    * @param aChunk A string snippet of generated JS code, another instance of
14474    *        SourceNode, or an array where each member is one of those things.
14475    */
14476   SourceNode.prototype.add = function SourceNode_add(aChunk) {
14477     if (Array.isArray(aChunk)) {
14478       aChunk.forEach(function (chunk) {
14479         this.add(chunk);
14480       }, this);
14481     }
14482     else if (aChunk instanceof SourceNode || typeof aChunk === "string") {
14483       if (aChunk) {
14484         this.children.push(aChunk);
14485       }
14486     }
14487     else {
14488       throw new TypeError(
14489         "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
14490       );
14491     }
14492     return this;
14493   };
14495   /**
14496    * Add a chunk of generated JS to the beginning of this source node.
14497    *
14498    * @param aChunk A string snippet of generated JS code, another instance of
14499    *        SourceNode, or an array where each member is one of those things.
14500    */
14501   SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {
14502     if (Array.isArray(aChunk)) {
14503       for (var i = aChunk.length-1; i >= 0; i--) {
14504         this.prepend(aChunk[i]);
14505       }
14506     }
14507     else if (aChunk instanceof SourceNode || typeof aChunk === "string") {
14508       this.children.unshift(aChunk);
14509     }
14510     else {
14511       throw new TypeError(
14512         "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
14513       );
14514     }
14515     return this;
14516   };
14518   /**
14519    * Walk over the tree of JS snippets in this node and its children. The
14520    * walking function is called once for each snippet of JS and is passed that
14521    * snippet and the its original associated source's line/column location.
14522    *
14523    * @param aFn The traversal function.
14524    */
14525   SourceNode.prototype.walk = function SourceNode_walk(aFn) {
14526     this.children.forEach(function (chunk) {
14527       if (chunk instanceof SourceNode) {
14528         chunk.walk(aFn);
14529       }
14530       else {
14531         if (chunk !== '') {
14532           aFn(chunk, { source: this.source,
14533                        line: this.line,
14534                        column: this.column,
14535                        name: this.name });
14536         }
14537       }
14538     }, this);
14539   };
14541   /**
14542    * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between
14543    * each of `this.children`.
14544    *
14545    * @param aSep The separator.
14546    */
14547   SourceNode.prototype.join = function SourceNode_join(aSep) {
14548     var newChildren;
14549     var i;
14550     var len = this.children.length;
14551     if (len > 0) {
14552       newChildren = [];
14553       for (i = 0; i < len-1; i++) {
14554         newChildren.push(this.children[i]);
14555         newChildren.push(aSep);
14556       }
14557       newChildren.push(this.children[i]);
14558       this.children = newChildren;
14559     }
14560     return this;
14561   };
14563   /**
14564    * Call String.prototype.replace on the very right-most source snippet. Useful
14565    * for trimming whitespace from the end of a source node, etc.
14566    *
14567    * @param aPattern The pattern to replace.
14568    * @param aReplacement The thing to replace the pattern with.
14569    */
14570   SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {
14571     var lastChild = this.children[this.children.length - 1];
14572     if (lastChild instanceof SourceNode) {
14573       lastChild.replaceRight(aPattern, aReplacement);
14574     }
14575     else if (typeof lastChild === 'string') {
14576       this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
14577     }
14578     else {
14579       this.children.push(''.replace(aPattern, aReplacement));
14580     }
14581     return this;
14582   };
14584   /**
14585    * Set the source content for a source file. This will be added to the SourceMapGenerator
14586    * in the sourcesContent field.
14587    *
14588    * @param aSourceFile The filename of the source file
14589    * @param aSourceContent The content of the source file
14590    */
14591   SourceNode.prototype.setSourceContent =
14592     function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
14593       this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
14594     };
14596   /**
14597    * Walk over the tree of SourceNodes. The walking function is called for each
14598    * source file content and is passed the filename and source content.
14599    *
14600    * @param aFn The traversal function.
14601    */
14602   SourceNode.prototype.walkSourceContents =
14603     function SourceNode_walkSourceContents(aFn) {
14604       this.children.forEach(function (chunk) {
14605         if (chunk instanceof SourceNode) {
14606           chunk.walkSourceContents(aFn);
14607         }
14608       }, this);
14609       Object.keys(this.sourceContents).forEach(function (sourceFileKey) {
14610         aFn(util.fromSetString(sourceFileKey), this.sourceContents[sourceFileKey]);
14611       }, this);
14612     };
14614   /**
14615    * Return the string representation of this source node. Walks over the tree
14616    * and concatenates all the various snippets together to one string.
14617    */
14618   SourceNode.prototype.toString = function SourceNode_toString() {
14619     var str = "";
14620     this.walk(function (chunk) {
14621       str += chunk;
14622     });
14623     return str;
14624   };
14626   /**
14627    * Returns the string representation of this source node along with a source
14628    * map.
14629    */
14630   SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {
14631     var generated = {
14632       code: "",
14633       line: 1,
14634       column: 0
14635     };
14636     var map = new SourceMapGenerator(aArgs);
14637     var sourceMappingActive = false;
14638     this.walk(function (chunk, original) {
14639       generated.code += chunk;
14640       if (original.source !== null
14641           && original.line !== null
14642           && original.column !== null) {
14643         map.addMapping({
14644           source: original.source,
14645           original: {
14646             line: original.line,
14647             column: original.column
14648           },
14649           generated: {
14650             line: generated.line,
14651             column: generated.column
14652           },
14653           name: original.name
14654         });
14655         sourceMappingActive = true;
14656       } else if (sourceMappingActive) {
14657         map.addMapping({
14658           generated: {
14659             line: generated.line,
14660             column: generated.column
14661           }
14662         });
14663         sourceMappingActive = false;
14664       }
14665       chunk.split('').forEach(function (ch) {
14666         if (ch === '\n') {
14667           generated.line++;
14668           generated.column = 0;
14669         } else {
14670           generated.column++;
14671         }
14672       });
14673     });
14674     this.walkSourceContents(function (sourceFile, sourceContent) {
14675       map.setSourceContent(sourceFile, sourceContent);
14676     });
14678     return { code: generated.code, map: map };
14679   };
14681   exports.SourceNode = SourceNode;
14684 /* -*- Mode: js; js-indent-level: 2; -*- */
14686  * Copyright 2011 Mozilla Foundation and contributors
14687  * Licensed under the New BSD license. See LICENSE or:
14688  * http://opensource.org/licenses/BSD-3-Clause
14689  */
14691 define('source-map/util', function (require, exports, module) {
14693   /**
14694    * This is a helper function for getting values from parameter/options
14695    * objects.
14696    *
14697    * @param args The object we are extracting values from
14698    * @param name The name of the property we are getting.
14699    * @param defaultValue An optional value to return if the property is missing
14700    * from the object. If this is not specified and the property is missing, an
14701    * error will be thrown.
14702    */
14703   function getArg(aArgs, aName, aDefaultValue) {
14704     if (aName in aArgs) {
14705       return aArgs[aName];
14706     } else if (arguments.length === 3) {
14707       return aDefaultValue;
14708     } else {
14709       throw new Error('"' + aName + '" is a required argument.');
14710     }
14711   }
14712   exports.getArg = getArg;
14714   var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/;
14716   function urlParse(aUrl) {
14717     var match = aUrl.match(urlRegexp);
14718     if (!match) {
14719       return null;
14720     }
14721     return {
14722       scheme: match[1],
14723       auth: match[3],
14724       host: match[4],
14725       port: match[6],
14726       path: match[7]
14727     };
14728   }
14729   exports.urlParse = urlParse;
14731   function urlGenerate(aParsedUrl) {
14732     var url = aParsedUrl.scheme + "://";
14733     if (aParsedUrl.auth) {
14734       url += aParsedUrl.auth + "@"
14735     }
14736     if (aParsedUrl.host) {
14737       url += aParsedUrl.host;
14738     }
14739     if (aParsedUrl.port) {
14740       url += ":" + aParsedUrl.port
14741     }
14742     if (aParsedUrl.path) {
14743       url += aParsedUrl.path;
14744     }
14745     return url;
14746   }
14747   exports.urlGenerate = urlGenerate;
14749   function join(aRoot, aPath) {
14750     var url;
14752     if (aPath.match(urlRegexp)) {
14753       return aPath;
14754     }
14756     if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) {
14757       url.path = aPath;
14758       return urlGenerate(url);
14759     }
14761     return aRoot.replace(/\/$/, '') + '/' + aPath;
14762   }
14763   exports.join = join;
14765   /**
14766    * Because behavior goes wacky when you set `__proto__` on objects, we
14767    * have to prefix all the strings in our set with an arbitrary character.
14768    *
14769    * See https://github.com/mozilla/source-map/pull/31 and
14770    * https://github.com/mozilla/source-map/issues/30
14771    *
14772    * @param String aStr
14773    */
14774   function toSetString(aStr) {
14775     return '$' + aStr;
14776   }
14777   exports.toSetString = toSetString;
14779   function fromSetString(aStr) {
14780     return aStr.substr(1);
14781   }
14782   exports.fromSetString = fromSetString;
14784   function relative(aRoot, aPath) {
14785     aRoot = aRoot.replace(/\/$/, '');
14787     var url = urlParse(aRoot);
14788     if (aPath.charAt(0) == "/" && url && url.path == "/") {
14789       return aPath.slice(1);
14790     }
14792     return aPath.indexOf(aRoot + '/') === 0
14793       ? aPath.substr(aRoot.length + 1)
14794       : aPath;
14795   }
14796   exports.relative = relative;
14799 define('source-map', function (require, exports, module) {
14802  * Copyright 2009-2011 Mozilla Foundation and contributors
14803  * Licensed under the New BSD license. See LICENSE.txt or:
14804  * http://opensource.org/licenses/BSD-3-Clause
14805  */
14806 exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator;
14807 exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer;
14808 exports.SourceNode = require('./source-map/source-node').SourceNode;
14812 //Distributed under the BSD license:
14813 //Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
14814 define('uglifyjs2', ['exports', 'source-map', 'logger', 'env!env/file'], function (exports, MOZ_SourceMap, logger, rjsFile) {
14815 (function(exports, global) {
14816     global["UglifyJS"] = exports;
14817     "use strict";
14818     function array_to_hash(a) {
14819         var ret = Object.create(null);
14820         for (var i = 0; i < a.length; ++i) ret[a[i]] = true;
14821         return ret;
14822     }
14823     function slice(a, start) {
14824         return Array.prototype.slice.call(a, start || 0);
14825     }
14826     function characters(str) {
14827         return str.split("");
14828     }
14829     function member(name, array) {
14830         for (var i = array.length; --i >= 0; ) if (array[i] == name) return true;
14831         return false;
14832     }
14833     function find_if(func, array) {
14834         for (var i = 0, n = array.length; i < n; ++i) {
14835             if (func(array[i])) return array[i];
14836         }
14837     }
14838     function repeat_string(str, i) {
14839         if (i <= 0) return "";
14840         if (i == 1) return str;
14841         var d = repeat_string(str, i >> 1);
14842         d += d;
14843         if (i & 1) d += str;
14844         return d;
14845     }
14846     function DefaultsError(msg, defs) {
14847         this.msg = msg;
14848         this.defs = defs;
14849     }
14850     function defaults(args, defs, croak) {
14851         if (args === true) args = {};
14852         var ret = args || {};
14853         if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i)) throw new DefaultsError("`" + i + "` is not a supported option", defs);
14854         for (var i in defs) if (defs.hasOwnProperty(i)) {
14855             ret[i] = args && args.hasOwnProperty(i) ? args[i] : defs[i];
14856         }
14857         return ret;
14858     }
14859     function merge(obj, ext) {
14860         for (var i in ext) if (ext.hasOwnProperty(i)) {
14861             obj[i] = ext[i];
14862         }
14863         return obj;
14864     }
14865     function noop() {}
14866     var MAP = function() {
14867         function MAP(a, f, backwards) {
14868             var ret = [], top = [], i;
14869             function doit() {
14870                 var val = f(a[i], i);
14871                 var is_last = val instanceof Last;
14872                 if (is_last) val = val.v;
14873                 if (val instanceof AtTop) {
14874                     val = val.v;
14875                     if (val instanceof Splice) {
14876                         top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
14877                     } else {
14878                         top.push(val);
14879                     }
14880                 } else if (val !== skip) {
14881                     if (val instanceof Splice) {
14882                         ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
14883                     } else {
14884                         ret.push(val);
14885                     }
14886                 }
14887                 return is_last;
14888             }
14889             if (a instanceof Array) {
14890                 if (backwards) {
14891                     for (i = a.length; --i >= 0; ) if (doit()) break;
14892                     ret.reverse();
14893                     top.reverse();
14894                 } else {
14895                     for (i = 0; i < a.length; ++i) if (doit()) break;
14896                 }
14897             } else {
14898                 for (i in a) if (a.hasOwnProperty(i)) if (doit()) break;
14899             }
14900             return top.concat(ret);
14901         }
14902         MAP.at_top = function(val) {
14903             return new AtTop(val);
14904         };
14905         MAP.splice = function(val) {
14906             return new Splice(val);
14907         };
14908         MAP.last = function(val) {
14909             return new Last(val);
14910         };
14911         var skip = MAP.skip = {};
14912         function AtTop(val) {
14913             this.v = val;
14914         }
14915         function Splice(val) {
14916             this.v = val;
14917         }
14918         function Last(val) {
14919             this.v = val;
14920         }
14921         return MAP;
14922     }();
14923     function push_uniq(array, el) {
14924         if (array.indexOf(el) < 0) array.push(el);
14925     }
14926     function string_template(text, props) {
14927         return text.replace(/\{(.+?)\}/g, function(str, p) {
14928             return props[p];
14929         });
14930     }
14931     function remove(array, el) {
14932         for (var i = array.length; --i >= 0; ) {
14933             if (array[i] === el) array.splice(i, 1);
14934         }
14935     }
14936     function mergeSort(array, cmp) {
14937         if (array.length < 2) return array.slice();
14938         function merge(a, b) {
14939             var r = [], ai = 0, bi = 0, i = 0;
14940             while (ai < a.length && bi < b.length) {
14941                 cmp(a[ai], b[bi]) <= 0 ? r[i++] = a[ai++] : r[i++] = b[bi++];
14942             }
14943             if (ai < a.length) r.push.apply(r, a.slice(ai));
14944             if (bi < b.length) r.push.apply(r, b.slice(bi));
14945             return r;
14946         }
14947         function _ms(a) {
14948             if (a.length <= 1) return a;
14949             var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
14950             left = _ms(left);
14951             right = _ms(right);
14952             return merge(left, right);
14953         }
14954         return _ms(array);
14955     }
14956     function set_difference(a, b) {
14957         return a.filter(function(el) {
14958             return b.indexOf(el) < 0;
14959         });
14960     }
14961     function set_intersection(a, b) {
14962         return a.filter(function(el) {
14963             return b.indexOf(el) >= 0;
14964         });
14965     }
14966     function makePredicate(words) {
14967         if (!(words instanceof Array)) words = words.split(" ");
14968         var f = "", cats = [];
14969         out: for (var i = 0; i < words.length; ++i) {
14970             for (var j = 0; j < cats.length; ++j) if (cats[j][0].length == words[i].length) {
14971                 cats[j].push(words[i]);
14972                 continue out;
14973             }
14974             cats.push([ words[i] ]);
14975         }
14976         function compareTo(arr) {
14977             if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
14978             f += "switch(str){";
14979             for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
14980             f += "return true}return false;";
14981         }
14982         if (cats.length > 3) {
14983             cats.sort(function(a, b) {
14984                 return b.length - a.length;
14985             });
14986             f += "switch(str.length){";
14987             for (var i = 0; i < cats.length; ++i) {
14988                 var cat = cats[i];
14989                 f += "case " + cat[0].length + ":";
14990                 compareTo(cat);
14991             }
14992             f += "}";
14993         } else {
14994             compareTo(words);
14995         }
14996         return new Function("str", f);
14997     }
14998     function all(array, predicate) {
14999         for (var i = array.length; --i >= 0; ) if (!predicate(array[i])) return false;
15000         return true;
15001     }
15002     function Dictionary() {
15003         this._values = Object.create(null);
15004         this._size = 0;
15005     }
15006     Dictionary.prototype = {
15007         set: function(key, val) {
15008             if (!this.has(key)) ++this._size;
15009             this._values["$" + key] = val;
15010             return this;
15011         },
15012         add: function(key, val) {
15013             if (this.has(key)) {
15014                 this.get(key).push(val);
15015             } else {
15016                 this.set(key, [ val ]);
15017             }
15018             return this;
15019         },
15020         get: function(key) {
15021             return this._values["$" + key];
15022         },
15023         del: function(key) {
15024             if (this.has(key)) {
15025                 --this._size;
15026                 delete this._values["$" + key];
15027             }
15028             return this;
15029         },
15030         has: function(key) {
15031             return "$" + key in this._values;
15032         },
15033         each: function(f) {
15034             for (var i in this._values) f(this._values[i], i.substr(1));
15035         },
15036         size: function() {
15037             return this._size;
15038         },
15039         map: function(f) {
15040             var ret = [];
15041             for (var i in this._values) ret.push(f(this._values[i], i.substr(1)));
15042             return ret;
15043         }
15044     };
15045     "use strict";
15046     function DEFNODE(type, props, methods, base) {
15047         if (arguments.length < 4) base = AST_Node;
15048         if (!props) props = []; else props = props.split(/\s+/);
15049         var self_props = props;
15050         if (base && base.PROPS) props = props.concat(base.PROPS);
15051         var code = "return function AST_" + type + "(props){ if (props) { ";
15052         for (var i = props.length; --i >= 0; ) {
15053             code += "this." + props[i] + " = props." + props[i] + ";";
15054         }
15055         var proto = base && new base();
15056         if (proto && proto.initialize || methods && methods.initialize) code += "this.initialize();";
15057         code += "}}";
15058         var ctor = new Function(code)();
15059         if (proto) {
15060             ctor.prototype = proto;
15061             ctor.BASE = base;
15062         }
15063         if (base) base.SUBCLASSES.push(ctor);
15064         ctor.prototype.CTOR = ctor;
15065         ctor.PROPS = props || null;
15066         ctor.SELF_PROPS = self_props;
15067         ctor.SUBCLASSES = [];
15068         if (type) {
15069             ctor.prototype.TYPE = ctor.TYPE = type;
15070         }
15071         if (methods) for (i in methods) if (methods.hasOwnProperty(i)) {
15072             if (/^\$/.test(i)) {
15073                 ctor[i.substr(1)] = methods[i];
15074             } else {
15075                 ctor.prototype[i] = methods[i];
15076             }
15077         }
15078         ctor.DEFMETHOD = function(name, method) {
15079             this.prototype[name] = method;
15080         };
15081         return ctor;
15082     }
15083     var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", {}, null);
15084     var AST_Node = DEFNODE("Node", "start end", {
15085         clone: function() {
15086             return new this.CTOR(this);
15087         },
15088         $documentation: "Base class of all AST nodes",
15089         $propdoc: {
15090             start: "[AST_Token] The first token of this node",
15091             end: "[AST_Token] The last token of this node"
15092         },
15093         _walk: function(visitor) {
15094             return visitor._visit(this);
15095         },
15096         walk: function(visitor) {
15097             return this._walk(visitor);
15098         }
15099     }, null);
15100     AST_Node.warn_function = null;
15101     AST_Node.warn = function(txt, props) {
15102         if (AST_Node.warn_function) AST_Node.warn_function(string_template(txt, props));
15103     };
15104     var AST_Statement = DEFNODE("Statement", null, {
15105         $documentation: "Base class of all statements"
15106     });
15107     var AST_Debugger = DEFNODE("Debugger", null, {
15108         $documentation: "Represents a debugger statement"
15109     }, AST_Statement);
15110     var AST_Directive = DEFNODE("Directive", "value scope", {
15111         $documentation: 'Represents a directive, like "use strict";',
15112         $propdoc: {
15113             value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
15114             scope: "[AST_Scope/S] The scope that this directive affects"
15115         }
15116     }, AST_Statement);
15117     var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
15118         $documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
15119         $propdoc: {
15120             body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
15121         },
15122         _walk: function(visitor) {
15123             return visitor._visit(this, function() {
15124                 this.body._walk(visitor);
15125             });
15126         }
15127     }, AST_Statement);
15128     function walk_body(node, visitor) {
15129         if (node.body instanceof AST_Statement) {
15130             node.body._walk(visitor);
15131         } else node.body.forEach(function(stat) {
15132             stat._walk(visitor);
15133         });
15134     }
15135     var AST_Block = DEFNODE("Block", "body", {
15136         $documentation: "A body of statements (usually bracketed)",
15137         $propdoc: {
15138             body: "[AST_Statement*] an array of statements"
15139         },
15140         _walk: function(visitor) {
15141             return visitor._visit(this, function() {
15142                 walk_body(this, visitor);
15143             });
15144         }
15145     }, AST_Statement);
15146     var AST_BlockStatement = DEFNODE("BlockStatement", null, {
15147         $documentation: "A block statement"
15148     }, AST_Block);
15149     var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
15150         $documentation: "The empty statement (empty block or simply a semicolon)",
15151         _walk: function(visitor) {
15152             return visitor._visit(this);
15153         }
15154     }, AST_Statement);
15155     var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {
15156         $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
15157         $propdoc: {
15158             body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
15159         },
15160         _walk: function(visitor) {
15161             return visitor._visit(this, function() {
15162                 this.body._walk(visitor);
15163             });
15164         }
15165     }, AST_Statement);
15166     var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
15167         $documentation: "Statement with a label",
15168         $propdoc: {
15169             label: "[AST_Label] a label definition"
15170         },
15171         _walk: function(visitor) {
15172             return visitor._visit(this, function() {
15173                 this.label._walk(visitor);
15174                 this.body._walk(visitor);
15175             });
15176         }
15177     }, AST_StatementWithBody);
15178     var AST_DWLoop = DEFNODE("DWLoop", "condition", {
15179         $documentation: "Base class for do/while statements",
15180         $propdoc: {
15181             condition: "[AST_Node] the loop condition.  Should not be instanceof AST_Statement"
15182         },
15183         _walk: function(visitor) {
15184             return visitor._visit(this, function() {
15185                 this.condition._walk(visitor);
15186                 this.body._walk(visitor);
15187             });
15188         }
15189     }, AST_StatementWithBody);
15190     var AST_Do = DEFNODE("Do", null, {
15191         $documentation: "A `do` statement"
15192     }, AST_DWLoop);
15193     var AST_While = DEFNODE("While", null, {
15194         $documentation: "A `while` statement"
15195     }, AST_DWLoop);
15196     var AST_For = DEFNODE("For", "init condition step", {
15197         $documentation: "A `for` statement",
15198         $propdoc: {
15199             init: "[AST_Node?] the `for` initialization code, or null if empty",
15200             condition: "[AST_Node?] the `for` termination clause, or null if empty",
15201             step: "[AST_Node?] the `for` update clause, or null if empty"
15202         },
15203         _walk: function(visitor) {
15204             return visitor._visit(this, function() {
15205                 if (this.init) this.init._walk(visitor);
15206                 if (this.condition) this.condition._walk(visitor);
15207                 if (this.step) this.step._walk(visitor);
15208                 this.body._walk(visitor);
15209             });
15210         }
15211     }, AST_StatementWithBody);
15212     var AST_ForIn = DEFNODE("ForIn", "init name object", {
15213         $documentation: "A `for ... in` statement",
15214         $propdoc: {
15215             init: "[AST_Node] the `for/in` initialization code",
15216             name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
15217             object: "[AST_Node] the object that we're looping through"
15218         },
15219         _walk: function(visitor) {
15220             return visitor._visit(this, function() {
15221                 this.init._walk(visitor);
15222                 this.object._walk(visitor);
15223                 this.body._walk(visitor);
15224             });
15225         }
15226     }, AST_StatementWithBody);
15227     var AST_With = DEFNODE("With", "expression", {
15228         $documentation: "A `with` statement",
15229         $propdoc: {
15230             expression: "[AST_Node] the `with` expression"
15231         },
15232         _walk: function(visitor) {
15233             return visitor._visit(this, function() {
15234                 this.expression._walk(visitor);
15235                 this.body._walk(visitor);
15236             });
15237         }
15238     }, AST_StatementWithBody);
15239     var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
15240         $documentation: "Base class for all statements introducing a lexical scope",
15241         $propdoc: {
15242             directives: "[string*/S] an array of directives declared in this scope",
15243             variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
15244             functions: "[Object/S] like `variables`, but only lists function declarations",
15245             uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
15246             uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
15247             parent_scope: "[AST_Scope?/S] link to the parent scope",
15248             enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
15249             cname: "[integer/S] current index for mangling variables (used internally by the mangler)"
15250         }
15251     }, AST_Block);
15252     var AST_Toplevel = DEFNODE("Toplevel", "globals", {
15253         $documentation: "The toplevel scope",
15254         $propdoc: {
15255             globals: "[Object/S] a map of name -> SymbolDef for all undeclared names"
15256         },
15257         wrap_enclose: function(arg_parameter_pairs) {
15258             var self = this;
15259             var args = [];
15260             var parameters = [];
15261             arg_parameter_pairs.forEach(function(pair) {
15262                 var split = pair.split(":");
15263                 args.push(split[0]);
15264                 parameters.push(split[1]);
15265             });
15266             var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
15267             wrapped_tl = parse(wrapped_tl);
15268             wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) {
15269                 if (node instanceof AST_Directive && node.value == "$ORIG") {
15270                     return MAP.splice(self.body);
15271                 }
15272             }));
15273             return wrapped_tl;
15274         },
15275         wrap_commonjs: function(name, export_all) {
15276             var self = this;
15277             var to_export = [];
15278             if (export_all) {
15279                 self.figure_out_scope();
15280                 self.walk(new TreeWalker(function(node) {
15281                     if (node instanceof AST_SymbolDeclaration && node.definition().global) {
15282                         if (!find_if(function(n) {
15283                             return n.name == node.name;
15284                         }, to_export)) to_export.push(node);
15285                     }
15286                 }));
15287             }
15288             var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))";
15289             wrapped_tl = parse(wrapped_tl);
15290             wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) {
15291                 if (node instanceof AST_SimpleStatement) {
15292                     node = node.body;
15293                     if (node instanceof AST_String) switch (node.getValue()) {
15294                       case "$ORIG":
15295                         return MAP.splice(self.body);
15297                       case "$EXPORTS":
15298                         var body = [];
15299                         to_export.forEach(function(sym) {
15300                             body.push(new AST_SimpleStatement({
15301                                 body: new AST_Assign({
15302                                     left: new AST_Sub({
15303                                         expression: new AST_SymbolRef({
15304                                             name: "exports"
15305                                         }),
15306                                         property: new AST_String({
15307                                             value: sym.name
15308                                         })
15309                                     }),
15310                                     operator: "=",
15311                                     right: new AST_SymbolRef(sym)
15312                                 })
15313                             }));
15314                         });
15315                         return MAP.splice(body);
15316                     }
15317                 }
15318             }));
15319             return wrapped_tl;
15320         }
15321     }, AST_Scope);
15322     var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
15323         $documentation: "Base class for functions",
15324         $propdoc: {
15325             name: "[AST_SymbolDeclaration?] the name of this function",
15326             argnames: "[AST_SymbolFunarg*] array of function arguments",
15327             uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
15328         },
15329         _walk: function(visitor) {
15330             return visitor._visit(this, function() {
15331                 if (this.name) this.name._walk(visitor);
15332                 this.argnames.forEach(function(arg) {
15333                     arg._walk(visitor);
15334                 });
15335                 walk_body(this, visitor);
15336             });
15337         }
15338     }, AST_Scope);
15339     var AST_Accessor = DEFNODE("Accessor", null, {
15340         $documentation: "A setter/getter function"
15341     }, AST_Lambda);
15342     var AST_Function = DEFNODE("Function", null, {
15343         $documentation: "A function expression"
15344     }, AST_Lambda);
15345     var AST_Defun = DEFNODE("Defun", null, {
15346         $documentation: "A function definition"
15347     }, AST_Lambda);
15348     var AST_Jump = DEFNODE("Jump", null, {
15349         $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
15350     }, AST_Statement);
15351     var AST_Exit = DEFNODE("Exit", "value", {
15352         $documentation: "Base class for “exits” (`return` and `throw`)",
15353         $propdoc: {
15354             value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
15355         },
15356         _walk: function(visitor) {
15357             return visitor._visit(this, this.value && function() {
15358                 this.value._walk(visitor);
15359             });
15360         }
15361     }, AST_Jump);
15362     var AST_Return = DEFNODE("Return", null, {
15363         $documentation: "A `return` statement"
15364     }, AST_Exit);
15365     var AST_Throw = DEFNODE("Throw", null, {
15366         $documentation: "A `throw` statement"
15367     }, AST_Exit);
15368     var AST_LoopControl = DEFNODE("LoopControl", "label", {
15369         $documentation: "Base class for loop control statements (`break` and `continue`)",
15370         $propdoc: {
15371             label: "[AST_LabelRef?] the label, or null if none"
15372         },
15373         _walk: function(visitor) {
15374             return visitor._visit(this, this.label && function() {
15375                 this.label._walk(visitor);
15376             });
15377         }
15378     }, AST_Jump);
15379     var AST_Break = DEFNODE("Break", null, {
15380         $documentation: "A `break` statement"
15381     }, AST_LoopControl);
15382     var AST_Continue = DEFNODE("Continue", null, {
15383         $documentation: "A `continue` statement"
15384     }, AST_LoopControl);
15385     var AST_If = DEFNODE("If", "condition alternative", {
15386         $documentation: "A `if` statement",
15387         $propdoc: {
15388             condition: "[AST_Node] the `if` condition",
15389             alternative: "[AST_Statement?] the `else` part, or null if not present"
15390         },
15391         _walk: function(visitor) {
15392             return visitor._visit(this, function() {
15393                 this.condition._walk(visitor);
15394                 this.body._walk(visitor);
15395                 if (this.alternative) this.alternative._walk(visitor);
15396             });
15397         }
15398     }, AST_StatementWithBody);
15399     var AST_Switch = DEFNODE("Switch", "expression", {
15400         $documentation: "A `switch` statement",
15401         $propdoc: {
15402             expression: "[AST_Node] the `switch` “discriminant”"
15403         },
15404         _walk: function(visitor) {
15405             return visitor._visit(this, function() {
15406                 this.expression._walk(visitor);
15407                 walk_body(this, visitor);
15408             });
15409         }
15410     }, AST_Block);
15411     var AST_SwitchBranch = DEFNODE("SwitchBranch", null, {
15412         $documentation: "Base class for `switch` branches"
15413     }, AST_Block);
15414     var AST_Default = DEFNODE("Default", null, {
15415         $documentation: "A `default` switch branch"
15416     }, AST_SwitchBranch);
15417     var AST_Case = DEFNODE("Case", "expression", {
15418         $documentation: "A `case` switch branch",
15419         $propdoc: {
15420             expression: "[AST_Node] the `case` expression"
15421         },
15422         _walk: function(visitor) {
15423             return visitor._visit(this, function() {
15424                 this.expression._walk(visitor);
15425                 walk_body(this, visitor);
15426             });
15427         }
15428     }, AST_SwitchBranch);
15429     var AST_Try = DEFNODE("Try", "bcatch bfinally", {
15430         $documentation: "A `try` statement",
15431         $propdoc: {
15432             bcatch: "[AST_Catch?] the catch block, or null if not present",
15433             bfinally: "[AST_Finally?] the finally block, or null if not present"
15434         },
15435         _walk: function(visitor) {
15436             return visitor._visit(this, function() {
15437                 walk_body(this, visitor);
15438                 if (this.bcatch) this.bcatch._walk(visitor);
15439                 if (this.bfinally) this.bfinally._walk(visitor);
15440             });
15441         }
15442     }, AST_Block);
15443     var AST_Catch = DEFNODE("Catch", "argname", {
15444         $documentation: "A `catch` node; only makes sense as part of a `try` statement",
15445         $propdoc: {
15446             argname: "[AST_SymbolCatch] symbol for the exception"
15447         },
15448         _walk: function(visitor) {
15449             return visitor._visit(this, function() {
15450                 this.argname._walk(visitor);
15451                 walk_body(this, visitor);
15452             });
15453         }
15454     }, AST_Block);
15455     var AST_Finally = DEFNODE("Finally", null, {
15456         $documentation: "A `finally` node; only makes sense as part of a `try` statement"
15457     }, AST_Block);
15458     var AST_Definitions = DEFNODE("Definitions", "definitions", {
15459         $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
15460         $propdoc: {
15461             definitions: "[AST_VarDef*] array of variable definitions"
15462         },
15463         _walk: function(visitor) {
15464             return visitor._visit(this, function() {
15465                 this.definitions.forEach(function(def) {
15466                     def._walk(visitor);
15467                 });
15468             });
15469         }
15470     }, AST_Statement);
15471     var AST_Var = DEFNODE("Var", null, {
15472         $documentation: "A `var` statement"
15473     }, AST_Definitions);
15474     var AST_Const = DEFNODE("Const", null, {
15475         $documentation: "A `const` statement"
15476     }, AST_Definitions);
15477     var AST_VarDef = DEFNODE("VarDef", "name value", {
15478         $documentation: "A variable declaration; only appears in a AST_Definitions node",
15479         $propdoc: {
15480             name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
15481             value: "[AST_Node?] initializer, or null of there's no initializer"
15482         },
15483         _walk: function(visitor) {
15484             return visitor._visit(this, function() {
15485                 this.name._walk(visitor);
15486                 if (this.value) this.value._walk(visitor);
15487             });
15488         }
15489     });
15490     var AST_Call = DEFNODE("Call", "expression args", {
15491         $documentation: "A function call expression",
15492         $propdoc: {
15493             expression: "[AST_Node] expression to invoke as function",
15494             args: "[AST_Node*] array of arguments"
15495         },
15496         _walk: function(visitor) {
15497             return visitor._visit(this, function() {
15498                 this.expression._walk(visitor);
15499                 this.args.forEach(function(arg) {
15500                     arg._walk(visitor);
15501                 });
15502             });
15503         }
15504     });
15505     var AST_New = DEFNODE("New", null, {
15506         $documentation: "An object instantiation.  Derives from a function call since it has exactly the same properties"
15507     }, AST_Call);
15508     var AST_Seq = DEFNODE("Seq", "car cdr", {
15509         $documentation: "A sequence expression (two comma-separated expressions)",
15510         $propdoc: {
15511             car: "[AST_Node] first element in sequence",
15512             cdr: "[AST_Node] second element in sequence"
15513         },
15514         $cons: function(x, y) {
15515             var seq = new AST_Seq(x);
15516             seq.car = x;
15517             seq.cdr = y;
15518             return seq;
15519         },
15520         $from_array: function(array) {
15521             if (array.length == 0) return null;
15522             if (array.length == 1) return array[0].clone();
15523             var list = null;
15524             for (var i = array.length; --i >= 0; ) {
15525                 list = AST_Seq.cons(array[i], list);
15526             }
15527             var p = list;
15528             while (p) {
15529                 if (p.cdr && !p.cdr.cdr) {
15530                     p.cdr = p.cdr.car;
15531                     break;
15532                 }
15533                 p = p.cdr;
15534             }
15535             return list;
15536         },
15537         to_array: function() {
15538             var p = this, a = [];
15539             while (p) {
15540                 a.push(p.car);
15541                 if (p.cdr && !(p.cdr instanceof AST_Seq)) {
15542                     a.push(p.cdr);
15543                     break;
15544                 }
15545                 p = p.cdr;
15546             }
15547             return a;
15548         },
15549         add: function(node) {
15550             var p = this;
15551             while (p) {
15552                 if (!(p.cdr instanceof AST_Seq)) {
15553                     var cell = AST_Seq.cons(p.cdr, node);
15554                     return p.cdr = cell;
15555                 }
15556                 p = p.cdr;
15557             }
15558         },
15559         _walk: function(visitor) {
15560             return visitor._visit(this, function() {
15561                 this.car._walk(visitor);
15562                 if (this.cdr) this.cdr._walk(visitor);
15563             });
15564         }
15565     });
15566     var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
15567         $documentation: 'Base class for property access expressions, i.e. `a.foo` or `a["foo"]`',
15568         $propdoc: {
15569             expression: "[AST_Node] the “container” expression",
15570             property: "[AST_Node|string] the property to access.  For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"
15571         }
15572     });
15573     var AST_Dot = DEFNODE("Dot", null, {
15574         $documentation: "A dotted property access expression",
15575         _walk: function(visitor) {
15576             return visitor._visit(this, function() {
15577                 this.expression._walk(visitor);
15578             });
15579         }
15580     }, AST_PropAccess);
15581     var AST_Sub = DEFNODE("Sub", null, {
15582         $documentation: 'Index-style property access, i.e. `a["foo"]`',
15583         _walk: function(visitor) {
15584             return visitor._visit(this, function() {
15585                 this.expression._walk(visitor);
15586                 this.property._walk(visitor);
15587             });
15588         }
15589     }, AST_PropAccess);
15590     var AST_Unary = DEFNODE("Unary", "operator expression", {
15591         $documentation: "Base class for unary expressions",
15592         $propdoc: {
15593             operator: "[string] the operator",
15594             expression: "[AST_Node] expression that this unary operator applies to"
15595         },
15596         _walk: function(visitor) {
15597             return visitor._visit(this, function() {
15598                 this.expression._walk(visitor);
15599             });
15600         }
15601     });
15602     var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {
15603         $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
15604     }, AST_Unary);
15605     var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
15606         $documentation: "Unary postfix expression, i.e. `i++`"
15607     }, AST_Unary);
15608     var AST_Binary = DEFNODE("Binary", "left operator right", {
15609         $documentation: "Binary expression, i.e. `a + b`",
15610         $propdoc: {
15611             left: "[AST_Node] left-hand side expression",
15612             operator: "[string] the operator",
15613             right: "[AST_Node] right-hand side expression"
15614         },
15615         _walk: function(visitor) {
15616             return visitor._visit(this, function() {
15617                 this.left._walk(visitor);
15618                 this.right._walk(visitor);
15619             });
15620         }
15621     });
15622     var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {
15623         $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
15624         $propdoc: {
15625             condition: "[AST_Node]",
15626             consequent: "[AST_Node]",
15627             alternative: "[AST_Node]"
15628         },
15629         _walk: function(visitor) {
15630             return visitor._visit(this, function() {
15631                 this.condition._walk(visitor);
15632                 this.consequent._walk(visitor);
15633                 this.alternative._walk(visitor);
15634             });
15635         }
15636     });
15637     var AST_Assign = DEFNODE("Assign", null, {
15638         $documentation: "An assignment expression — `a = b + 5`"
15639     }, AST_Binary);
15640     var AST_Array = DEFNODE("Array", "elements", {
15641         $documentation: "An array literal",
15642         $propdoc: {
15643             elements: "[AST_Node*] array of elements"
15644         },
15645         _walk: function(visitor) {
15646             return visitor._visit(this, function() {
15647                 this.elements.forEach(function(el) {
15648                     el._walk(visitor);
15649                 });
15650             });
15651         }
15652     });
15653     var AST_Object = DEFNODE("Object", "properties", {
15654         $documentation: "An object literal",
15655         $propdoc: {
15656             properties: "[AST_ObjectProperty*] array of properties"
15657         },
15658         _walk: function(visitor) {
15659             return visitor._visit(this, function() {
15660                 this.properties.forEach(function(prop) {
15661                     prop._walk(visitor);
15662                 });
15663             });
15664         }
15665     });
15666     var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
15667         $documentation: "Base class for literal object properties",
15668         $propdoc: {
15669             key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code",
15670             value: "[AST_Node] property value.  For setters and getters this is an AST_Function."
15671         },
15672         _walk: function(visitor) {
15673             return visitor._visit(this, function() {
15674                 this.value._walk(visitor);
15675             });
15676         }
15677     });
15678     var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, {
15679         $documentation: "A key: value object property"
15680     }, AST_ObjectProperty);
15681     var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
15682         $documentation: "An object setter property"
15683     }, AST_ObjectProperty);
15684     var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
15685         $documentation: "An object getter property"
15686     }, AST_ObjectProperty);
15687     var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
15688         $propdoc: {
15689             name: "[string] name of this symbol",
15690             scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
15691             thedef: "[SymbolDef/S] the definition of this symbol"
15692         },
15693         $documentation: "Base class for all symbols"
15694     });
15695     var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
15696         $documentation: "The name of a property accessor (setter/getter function)"
15697     }, AST_Symbol);
15698     var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
15699         $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
15700         $propdoc: {
15701             init: "[AST_Node*/S] array of initializers for this declaration."
15702         }
15703     }, AST_Symbol);
15704     var AST_SymbolVar = DEFNODE("SymbolVar", null, {
15705         $documentation: "Symbol defining a variable"
15706     }, AST_SymbolDeclaration);
15707     var AST_SymbolConst = DEFNODE("SymbolConst", null, {
15708         $documentation: "A constant declaration"
15709     }, AST_SymbolDeclaration);
15710     var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
15711         $documentation: "Symbol naming a function argument"
15712     }, AST_SymbolVar);
15713     var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
15714         $documentation: "Symbol defining a function"
15715     }, AST_SymbolDeclaration);
15716     var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
15717         $documentation: "Symbol naming a function expression"
15718     }, AST_SymbolDeclaration);
15719     var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
15720         $documentation: "Symbol naming the exception in catch"
15721     }, AST_SymbolDeclaration);
15722     var AST_Label = DEFNODE("Label", "references", {
15723         $documentation: "Symbol naming a label (declaration)",
15724         $propdoc: {
15725             references: "[AST_LabelRef*] a list of nodes referring to this label"
15726         }
15727     }, AST_Symbol);
15728     var AST_SymbolRef = DEFNODE("SymbolRef", null, {
15729         $documentation: "Reference to some symbol (not definition/declaration)"
15730     }, AST_Symbol);
15731     var AST_LabelRef = DEFNODE("LabelRef", null, {
15732         $documentation: "Reference to a label symbol"
15733     }, AST_Symbol);
15734     var AST_This = DEFNODE("This", null, {
15735         $documentation: "The `this` symbol"
15736     }, AST_Symbol);
15737     var AST_Constant = DEFNODE("Constant", null, {
15738         $documentation: "Base class for all constants",
15739         getValue: function() {
15740             return this.value;
15741         }
15742     });
15743     var AST_String = DEFNODE("String", "value", {
15744         $documentation: "A string literal",
15745         $propdoc: {
15746             value: "[string] the contents of this string"
15747         }
15748     }, AST_Constant);
15749     var AST_Number = DEFNODE("Number", "value", {
15750         $documentation: "A number literal",
15751         $propdoc: {
15752             value: "[number] the numeric value"
15753         }
15754     }, AST_Constant);
15755     var AST_RegExp = DEFNODE("RegExp", "value", {
15756         $documentation: "A regexp literal",
15757         $propdoc: {
15758             value: "[RegExp] the actual regexp"
15759         }
15760     }, AST_Constant);
15761     var AST_Atom = DEFNODE("Atom", null, {
15762         $documentation: "Base class for atoms"
15763     }, AST_Constant);
15764     var AST_Null = DEFNODE("Null", null, {
15765         $documentation: "The `null` atom",
15766         value: null
15767     }, AST_Atom);
15768     var AST_NaN = DEFNODE("NaN", null, {
15769         $documentation: "The impossible value",
15770         value: 0 / 0
15771     }, AST_Atom);
15772     var AST_Undefined = DEFNODE("Undefined", null, {
15773         $documentation: "The `undefined` value",
15774         value: function() {}()
15775     }, AST_Atom);
15776     var AST_Hole = DEFNODE("Hole", null, {
15777         $documentation: "A hole in an array",
15778         value: function() {}()
15779     }, AST_Atom);
15780     var AST_Infinity = DEFNODE("Infinity", null, {
15781         $documentation: "The `Infinity` value",
15782         value: 1 / 0
15783     }, AST_Atom);
15784     var AST_Boolean = DEFNODE("Boolean", null, {
15785         $documentation: "Base class for booleans"
15786     }, AST_Atom);
15787     var AST_False = DEFNODE("False", null, {
15788         $documentation: "The `false` atom",
15789         value: false
15790     }, AST_Boolean);
15791     var AST_True = DEFNODE("True", null, {
15792         $documentation: "The `true` atom",
15793         value: true
15794     }, AST_Boolean);
15795     function TreeWalker(callback) {
15796         this.visit = callback;
15797         this.stack = [];
15798     }
15799     TreeWalker.prototype = {
15800         _visit: function(node, descend) {
15801             this.stack.push(node);
15802             var ret = this.visit(node, descend ? function() {
15803                 descend.call(node);
15804             } : noop);
15805             if (!ret && descend) {
15806                 descend.call(node);
15807             }
15808             this.stack.pop();
15809             return ret;
15810         },
15811         parent: function(n) {
15812             return this.stack[this.stack.length - 2 - (n || 0)];
15813         },
15814         push: function(node) {
15815             this.stack.push(node);
15816         },
15817         pop: function() {
15818             return this.stack.pop();
15819         },
15820         self: function() {
15821             return this.stack[this.stack.length - 1];
15822         },
15823         find_parent: function(type) {
15824             var stack = this.stack;
15825             for (var i = stack.length; --i >= 0; ) {
15826                 var x = stack[i];
15827                 if (x instanceof type) return x;
15828             }
15829         },
15830         in_boolean_context: function() {
15831             var stack = this.stack;
15832             var i = stack.length, self = stack[--i];
15833             while (i > 0) {
15834                 var p = stack[--i];
15835                 if (p instanceof AST_If && p.condition === self || p instanceof AST_Conditional && p.condition === self || p instanceof AST_DWLoop && p.condition === self || p instanceof AST_For && p.condition === self || p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
15836                     return true;
15837                 }
15838                 if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) return false;
15839                 self = p;
15840             }
15841         },
15842         loopcontrol_target: function(label) {
15843             var stack = this.stack;
15844             if (label) {
15845                 for (var i = stack.length; --i >= 0; ) {
15846                     var x = stack[i];
15847                     if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
15848                         return x.body;
15849                     }
15850                 }
15851             } else {
15852                 for (var i = stack.length; --i >= 0; ) {
15853                     var x = stack[i];
15854                     if (x instanceof AST_Switch || x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) return x;
15855                 }
15856             }
15857         }
15858     };
15859     "use strict";
15860     var KEYWORDS = "break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with";
15861     var KEYWORDS_ATOM = "false null true";
15862     var RESERVED_WORDS = "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile" + " " + KEYWORDS_ATOM + " " + KEYWORDS;
15863     var KEYWORDS_BEFORE_EXPRESSION = "return new delete throw else case";
15864     KEYWORDS = makePredicate(KEYWORDS);
15865     RESERVED_WORDS = makePredicate(RESERVED_WORDS);
15866     KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
15867     KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
15868     var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
15869     var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
15870     var RE_OCT_NUMBER = /^0[0-7]+$/;
15871     var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
15872     var OPERATORS = makePredicate([ "in", "instanceof", "typeof", "new", "void", "delete", "++", "--", "+", "-", "!", "~", "&", "|", "^", "*", "/", "%", ">>", "<<", ">>>", "<", ">", "<=", ">=", "==", "===", "!=", "!==", "?", "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=", "&&", "||" ]);
15873     var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000"));
15874     var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
15875     var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
15876     var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
15877     var UNICODE = {
15878         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]"),
15879         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]"),
15880         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]"),
15881         connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
15882     };
15883     function is_letter(code) {
15884         return code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 170 && UNICODE.letter.test(String.fromCharCode(code));
15885     }
15886     function is_digit(code) {
15887         return code >= 48 && code <= 57;
15888     }
15889     function is_alphanumeric_char(code) {
15890         return is_digit(code) || is_letter(code);
15891     }
15892     function is_unicode_combining_mark(ch) {
15893         return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
15894     }
15895     function is_unicode_connector_punctuation(ch) {
15896         return UNICODE.connector_punctuation.test(ch);
15897     }
15898     function is_identifier(name) {
15899         return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name);
15900     }
15901     function is_identifier_start(code) {
15902         return code == 36 || code == 95 || is_letter(code);
15903     }
15904     function is_identifier_char(ch) {
15905         var code = ch.charCodeAt(0);
15906         return is_identifier_start(code) || is_digit(code) || code == 8204 || code == 8205 || is_unicode_combining_mark(ch) || is_unicode_connector_punctuation(ch);
15907     }
15908     function is_identifier_string(str) {
15909         var i = str.length;
15910         if (i == 0) return false;
15911         if (is_digit(str.charCodeAt(0))) return false;
15912         while (--i >= 0) {
15913             if (!is_identifier_char(str.charAt(i))) return false;
15914         }
15915         return true;
15916     }
15917     function parse_js_number(num) {
15918         if (RE_HEX_NUMBER.test(num)) {
15919             return parseInt(num.substr(2), 16);
15920         } else if (RE_OCT_NUMBER.test(num)) {
15921             return parseInt(num.substr(1), 8);
15922         } else if (RE_DEC_NUMBER.test(num)) {
15923             return parseFloat(num);
15924         }
15925     }
15926     function JS_Parse_Error(message, line, col, pos) {
15927         this.message = message;
15928         this.line = line;
15929         this.col = col;
15930         this.pos = pos;
15931         this.stack = new Error().stack;
15932     }
15933     JS_Parse_Error.prototype.toString = function() {
15934         return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
15935     };
15936     function js_error(message, filename, line, col, pos) {
15937         throw new JS_Parse_Error(message, line, col, pos);
15938     }
15939     function is_token(token, type, val) {
15940         return token.type == type && (val == null || token.value == val);
15941     }
15942     var EX_EOF = {};
15943     function tokenizer($TEXT, filename) {
15944         var S = {
15945             text: $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ""),
15946             filename: filename,
15947             pos: 0,
15948             tokpos: 0,
15949             line: 1,
15950             tokline: 0,
15951             col: 0,
15952             tokcol: 0,
15953             newline_before: false,
15954             regex_allowed: false,
15955             comments_before: []
15956         };
15957         function peek() {
15958             return S.text.charAt(S.pos);
15959         }
15960         function next(signal_eof, in_string) {
15961             var ch = S.text.charAt(S.pos++);
15962             if (signal_eof && !ch) throw EX_EOF;
15963             if (ch == "\n") {
15964                 S.newline_before = S.newline_before || !in_string;
15965                 ++S.line;
15966                 S.col = 0;
15967             } else {
15968                 ++S.col;
15969             }
15970             return ch;
15971         }
15972         function find(what, signal_eof) {
15973             var pos = S.text.indexOf(what, S.pos);
15974             if (signal_eof && pos == -1) throw EX_EOF;
15975             return pos;
15976         }
15977         function start_token() {
15978             S.tokline = S.line;
15979             S.tokcol = S.col;
15980             S.tokpos = S.pos;
15981         }
15982         function token(type, value, is_comment) {
15983             S.regex_allowed = type == "operator" && !UNARY_POSTFIX[value] || type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value) || type == "punc" && PUNC_BEFORE_EXPRESSION(value);
15984             var ret = {
15985                 type: type,
15986                 value: value,
15987                 line: S.tokline,
15988                 col: S.tokcol,
15989                 pos: S.tokpos,
15990                 endpos: S.pos,
15991                 nlb: S.newline_before,
15992                 file: filename
15993             };
15994             if (!is_comment) {
15995                 ret.comments_before = S.comments_before;
15996                 S.comments_before = [];
15997                 for (var i = 0, len = ret.comments_before.length; i < len; i++) {
15998                     ret.nlb = ret.nlb || ret.comments_before[i].nlb;
15999                 }
16000             }
16001             S.newline_before = false;
16002             return new AST_Token(ret);
16003         }
16004         function skip_whitespace() {
16005             while (WHITESPACE_CHARS(peek())) next();
16006         }
16007         function read_while(pred) {
16008             var ret = "", ch, i = 0;
16009             while ((ch = peek()) && pred(ch, i++)) ret += next();
16010             return ret;
16011         }
16012         function parse_error(err) {
16013             js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
16014         }
16015         function read_num(prefix) {
16016             var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
16017             var num = read_while(function(ch, i) {
16018                 var code = ch.charCodeAt(0);
16019                 switch (code) {
16020                   case 120:
16021                   case 88:
16022                     return has_x ? false : has_x = true;
16024                   case 101:
16025                   case 69:
16026                     return has_x ? true : has_e ? false : has_e = after_e = true;
16028                   case 45:
16029                     return after_e || i == 0 && !prefix;
16031                   case 43:
16032                     return after_e;
16034                   case after_e = false, 46:
16035                     return !has_dot && !has_x && !has_e ? has_dot = true : false;
16036                 }
16037                 return is_alphanumeric_char(code);
16038             });
16039             if (prefix) num = prefix + num;
16040             var valid = parse_js_number(num);
16041             if (!isNaN(valid)) {
16042                 return token("num", valid);
16043             } else {
16044                 parse_error("Invalid syntax: " + num);
16045             }
16046         }
16047         function read_escaped_char(in_string) {
16048             var ch = next(true, in_string);
16049             switch (ch.charCodeAt(0)) {
16050               case 110:
16051                 return "\n";
16053               case 114:
16054                 return "\r";
16056               case 116:
16057                 return "        ";
16059               case 98:
16060                 return "\b";
16062               case 118:
16063                 return "\v";
16065               case 102:
16066                 return "\f";
16068               case 48:
16069                 return "\0";
16071               case 120:
16072                 return String.fromCharCode(hex_bytes(2));
16074               case 117:
16075                 return String.fromCharCode(hex_bytes(4));
16077               case 10:
16078                 return "";
16080               default:
16081                 return ch;
16082             }
16083         }
16084         function hex_bytes(n) {
16085             var num = 0;
16086             for (;n > 0; --n) {
16087                 var digit = parseInt(next(true), 16);
16088                 if (isNaN(digit)) parse_error("Invalid hex-character pattern in string");
16089                 num = num << 4 | digit;
16090             }
16091             return num;
16092         }
16093         var read_string = with_eof_error("Unterminated string constant", function() {
16094             var quote = next(), ret = "";
16095             for (;;) {
16096                 var ch = next(true);
16097                 if (ch == "\\") {
16098                     var octal_len = 0, first = null;
16099                     ch = read_while(function(ch) {
16100                         if (ch >= "0" && ch <= "7") {
16101                             if (!first) {
16102                                 first = ch;
16103                                 return ++octal_len;
16104                             } else if (first <= "3" && octal_len <= 2) return ++octal_len; else if (first >= "4" && octal_len <= 1) return ++octal_len;
16105                         }
16106                         return false;
16107                     });
16108                     if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); else ch = read_escaped_char(true);
16109                 } else if (ch == quote) break;
16110                 ret += ch;
16111             }
16112             return token("string", ret);
16113         });
16114         function read_line_comment() {
16115             next();
16116             var i = find("\n"), ret;
16117             if (i == -1) {
16118                 ret = S.text.substr(S.pos);
16119                 S.pos = S.text.length;
16120             } else {
16121                 ret = S.text.substring(S.pos, i);
16122                 S.pos = i;
16123             }
16124             return token("comment1", ret, true);
16125         }
16126         var read_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
16127             next();
16128             var i = find("*/", true);
16129             var text = S.text.substring(S.pos, i);
16130             var a = text.split("\n"), n = a.length;
16131             S.pos = i + 2;
16132             S.line += n - 1;
16133             if (n > 1) S.col = a[n - 1].length; else S.col += a[n - 1].length;
16134             S.col += 2;
16135             S.newline_before = S.newline_before || text.indexOf("\n") >= 0;
16136             return token("comment2", text, true);
16137         });
16138         function read_name() {
16139             var backslash = false, name = "", ch, escaped = false, hex;
16140             while ((ch = peek()) != null) {
16141                 if (!backslash) {
16142                     if (ch == "\\") escaped = backslash = true, next(); else if (is_identifier_char(ch)) name += next(); else break;
16143                 } else {
16144                     if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
16145                     ch = read_escaped_char();
16146                     if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
16147                     name += ch;
16148                     backslash = false;
16149                 }
16150             }
16151             if (KEYWORDS(name) && escaped) {
16152                 hex = name.charCodeAt(0).toString(16).toUpperCase();
16153                 name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
16154             }
16155             return name;
16156         }
16157         var read_regexp = with_eof_error("Unterminated regular expression", function(regexp) {
16158             var prev_backslash = false, ch, in_class = false;
16159             while (ch = next(true)) if (prev_backslash) {
16160                 regexp += "\\" + ch;
16161                 prev_backslash = false;
16162             } else if (ch == "[") {
16163                 in_class = true;
16164                 regexp += ch;
16165             } else if (ch == "]" && in_class) {
16166                 in_class = false;
16167                 regexp += ch;
16168             } else if (ch == "/" && !in_class) {
16169                 break;
16170             } else if (ch == "\\") {
16171                 prev_backslash = true;
16172             } else {
16173                 regexp += ch;
16174             }
16175             var mods = read_name();
16176             return token("regexp", new RegExp(regexp, mods));
16177         });
16178         function read_operator(prefix) {
16179             function grow(op) {
16180                 if (!peek()) return op;
16181                 var bigger = op + peek();
16182                 if (OPERATORS(bigger)) {
16183                     next();
16184                     return grow(bigger);
16185                 } else {
16186                     return op;
16187                 }
16188             }
16189             return token("operator", grow(prefix || next()));
16190         }
16191         function handle_slash() {
16192             next();
16193             var regex_allowed = S.regex_allowed;
16194             switch (peek()) {
16195               case "/":
16196                 S.comments_before.push(read_line_comment());
16197                 S.regex_allowed = regex_allowed;
16198                 return next_token();
16200               case "*":
16201                 S.comments_before.push(read_multiline_comment());
16202                 S.regex_allowed = regex_allowed;
16203                 return next_token();
16204             }
16205             return S.regex_allowed ? read_regexp("") : read_operator("/");
16206         }
16207         function handle_dot() {
16208             next();
16209             return is_digit(peek().charCodeAt(0)) ? read_num(".") : token("punc", ".");
16210         }
16211         function read_word() {
16212             var word = read_name();
16213             return KEYWORDS_ATOM(word) ? token("atom", word) : !KEYWORDS(word) ? token("name", word) : OPERATORS(word) ? token("operator", word) : token("keyword", word);
16214         }
16215         function with_eof_error(eof_error, cont) {
16216             return function(x) {
16217                 try {
16218                     return cont(x);
16219                 } catch (ex) {
16220                     if (ex === EX_EOF) parse_error(eof_error); else throw ex;
16221                 }
16222             };
16223         }
16224         function next_token(force_regexp) {
16225             if (force_regexp != null) return read_regexp(force_regexp);
16226             skip_whitespace();
16227             start_token();
16228             var ch = peek();
16229             if (!ch) return token("eof");
16230             var code = ch.charCodeAt(0);
16231             switch (code) {
16232               case 34:
16233               case 39:
16234                 return read_string();
16236               case 46:
16237                 return handle_dot();
16239               case 47:
16240                 return handle_slash();
16241             }
16242             if (is_digit(code)) return read_num();
16243             if (PUNC_CHARS(ch)) return token("punc", next());
16244             if (OPERATOR_CHARS(ch)) return read_operator();
16245             if (code == 92 || is_identifier_start(code)) return read_word();
16246             parse_error("Unexpected character '" + ch + "'");
16247         }
16248         next_token.context = function(nc) {
16249             if (nc) S = nc;
16250             return S;
16251         };
16252         return next_token;
16253     }
16254     var UNARY_PREFIX = makePredicate([ "typeof", "void", "delete", "--", "++", "!", "~", "-", "+" ]);
16255     var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
16256     var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
16257     var PRECEDENCE = function(a, ret) {
16258         for (var i = 0, n = 1; i < a.length; ++i, ++n) {
16259             var b = a[i];
16260             for (var j = 0; j < b.length; ++j) {
16261                 ret[b[j]] = n;
16262             }
16263         }
16264         return ret;
16265     }([ [ "||" ], [ "&&" ], [ "|" ], [ "^" ], [ "&" ], [ "==", "===", "!=", "!==" ], [ "<", ">", "<=", ">=", "in", "instanceof" ], [ ">>", "<<", ">>>" ], [ "+", "-" ], [ "*", "/", "%" ] ], {});
16266     var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
16267     var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
16268     function parse($TEXT, options) {
16269         options = defaults(options, {
16270             strict: false,
16271             filename: null,
16272             toplevel: null,
16273             expression: false
16274         });
16275         var S = {
16276             input: typeof $TEXT == "string" ? tokenizer($TEXT, options.filename) : $TEXT,
16277             token: null,
16278             prev: null,
16279             peeked: null,
16280             in_function: 0,
16281             in_directives: true,
16282             in_loop: 0,
16283             labels: []
16284         };
16285         S.token = next();
16286         function is(type, value) {
16287             return is_token(S.token, type, value);
16288         }
16289         function peek() {
16290             return S.peeked || (S.peeked = S.input());
16291         }
16292         function next() {
16293             S.prev = S.token;
16294             if (S.peeked) {
16295                 S.token = S.peeked;
16296                 S.peeked = null;
16297             } else {
16298                 S.token = S.input();
16299             }
16300             S.in_directives = S.in_directives && (S.token.type == "string" || is("punc", ";"));
16301             return S.token;
16302         }
16303         function prev() {
16304             return S.prev;
16305         }
16306         function croak(msg, line, col, pos) {
16307             var ctx = S.input.context();
16308             js_error(msg, ctx.filename, line != null ? line : ctx.tokline, col != null ? col : ctx.tokcol, pos != null ? pos : ctx.tokpos);
16309         }
16310         function token_error(token, msg) {
16311             croak(msg, token.line, token.col);
16312         }
16313         function unexpected(token) {
16314             if (token == null) token = S.token;
16315             token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
16316         }
16317         function expect_token(type, val) {
16318             if (is(type, val)) {
16319                 return next();
16320             }
16321             token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
16322         }
16323         function expect(punc) {
16324             return expect_token("punc", punc);
16325         }
16326         function can_insert_semicolon() {
16327             return !options.strict && (S.token.nlb || is("eof") || is("punc", "}"));
16328         }
16329         function semicolon() {
16330             if (is("punc", ";")) next(); else if (!can_insert_semicolon()) unexpected();
16331         }
16332         function parenthesised() {
16333             expect("(");
16334             var exp = expression(true);
16335             expect(")");
16336             return exp;
16337         }
16338         function embed_tokens(parser) {
16339             return function() {
16340                 var start = S.token;
16341                 var expr = parser();
16342                 var end = prev();
16343                 expr.start = start;
16344                 expr.end = end;
16345                 return expr;
16346             };
16347         }
16348         var statement = embed_tokens(function() {
16349             var tmp;
16350             if (is("operator", "/") || is("operator", "/=")) {
16351                 S.peeked = null;
16352                 S.token = S.input(S.token.value.substr(1));
16353             }
16354             switch (S.token.type) {
16355               case "string":
16356                 var dir = S.in_directives, stat = simple_statement();
16357                 if (dir && stat.body instanceof AST_String && !is("punc", ",")) return new AST_Directive({
16358                     value: stat.body.value
16359                 });
16360                 return stat;
16362               case "num":
16363               case "regexp":
16364               case "operator":
16365               case "atom":
16366                 return simple_statement();
16368               case "name":
16369                 return is_token(peek(), "punc", ":") ? labeled_statement() : simple_statement();
16371               case "punc":
16372                 switch (S.token.value) {
16373                   case "{":
16374                     return new AST_BlockStatement({
16375                         start: S.token,
16376                         body: block_(),
16377                         end: prev()
16378                     });
16380                   case "[":
16381                   case "(":
16382                     return simple_statement();
16384                   case ";":
16385                     next();
16386                     return new AST_EmptyStatement();
16388                   default:
16389                     unexpected();
16390                 }
16392               case "keyword":
16393                 switch (tmp = S.token.value, next(), tmp) {
16394                   case "break":
16395                     return break_cont(AST_Break);
16397                   case "continue":
16398                     return break_cont(AST_Continue);
16400                   case "debugger":
16401                     semicolon();
16402                     return new AST_Debugger();
16404                   case "do":
16405                     return new AST_Do({
16406                         body: in_loop(statement),
16407                         condition: (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(),
16408                         tmp)
16409                     });
16411                   case "while":
16412                     return new AST_While({
16413                         condition: parenthesised(),
16414                         body: in_loop(statement)
16415                     });
16417                   case "for":
16418                     return for_();
16420                   case "function":
16421                     return function_(true);
16423                   case "if":
16424                     return if_();
16426                   case "return":
16427                     if (S.in_function == 0) croak("'return' outside of function");
16428                     return new AST_Return({
16429                         value: is("punc", ";") ? (next(), null) : can_insert_semicolon() ? null : (tmp = expression(true),
16430                         semicolon(), tmp)
16431                     });
16433                   case "switch":
16434                     return new AST_Switch({
16435                         expression: parenthesised(),
16436                         body: in_loop(switch_body_)
16437                     });
16439                   case "throw":
16440                     if (S.token.nlb) croak("Illegal newline after 'throw'");
16441                     return new AST_Throw({
16442                         value: (tmp = expression(true), semicolon(), tmp)
16443                     });
16445                   case "try":
16446                     return try_();
16448                   case "var":
16449                     return tmp = var_(), semicolon(), tmp;
16451                   case "const":
16452                     return tmp = const_(), semicolon(), tmp;
16454                   case "with":
16455                     return new AST_With({
16456                         expression: parenthesised(),
16457                         body: statement()
16458                     });
16460                   default:
16461                     unexpected();
16462                 }
16463             }
16464         });
16465         function labeled_statement() {
16466             var label = as_symbol(AST_Label);
16467             if (find_if(function(l) {
16468                 return l.name == label.name;
16469             }, S.labels)) {
16470                 croak("Label " + label.name + " defined twice");
16471             }
16472             expect(":");
16473             S.labels.push(label);
16474             var stat = statement();
16475             S.labels.pop();
16476             return new AST_LabeledStatement({
16477                 body: stat,
16478                 label: label
16479             });
16480         }
16481         function simple_statement(tmp) {
16482             return new AST_SimpleStatement({
16483                 body: (tmp = expression(true), semicolon(), tmp)
16484             });
16485         }
16486         function break_cont(type) {
16487             var label = null;
16488             if (!can_insert_semicolon()) {
16489                 label = as_symbol(AST_LabelRef, true);
16490             }
16491             if (label != null) {
16492                 if (!find_if(function(l) {
16493                     return l.name == label.name;
16494                 }, S.labels)) croak("Undefined label " + label.name);
16495             } else if (S.in_loop == 0) croak(type.TYPE + " not inside a loop or switch");
16496             semicolon();
16497             return new type({
16498                 label: label
16499             });
16500         }
16501         function for_() {
16502             expect("(");
16503             var init = null;
16504             if (!is("punc", ";")) {
16505                 init = is("keyword", "var") ? (next(), var_(true)) : expression(true, true);
16506                 if (is("operator", "in")) {
16507                     if (init instanceof AST_Var && init.definitions.length > 1) croak("Only one variable declaration allowed in for..in loop");
16508                     next();
16509                     return for_in(init);
16510                 }
16511             }
16512             return regular_for(init);
16513         }
16514         function regular_for(init) {
16515             expect(";");
16516             var test = is("punc", ";") ? null : expression(true);
16517             expect(";");
16518             var step = is("punc", ")") ? null : expression(true);
16519             expect(")");
16520             return new AST_For({
16521                 init: init,
16522                 condition: test,
16523                 step: step,
16524                 body: in_loop(statement)
16525             });
16526         }
16527         function for_in(init) {
16528             var lhs = init instanceof AST_Var ? init.definitions[0].name : null;
16529             var obj = expression(true);
16530             expect(")");
16531             return new AST_ForIn({
16532                 init: init,
16533                 name: lhs,
16534                 object: obj,
16535                 body: in_loop(statement)
16536             });
16537         }
16538         var function_ = function(in_statement, ctor) {
16539             var is_accessor = ctor === AST_Accessor;
16540             var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : is_accessor ? AST_SymbolAccessor : AST_SymbolLambda) : is_accessor && (is("string") || is("num")) ? as_atom_node() : null;
16541             if (in_statement && !name) unexpected();
16542             expect("(");
16543             if (!ctor) ctor = in_statement ? AST_Defun : AST_Function;
16544             return new ctor({
16545                 name: name,
16546                 argnames: function(first, a) {
16547                     while (!is("punc", ")")) {
16548                         if (first) first = false; else expect(",");
16549                         a.push(as_symbol(AST_SymbolFunarg));
16550                     }
16551                     next();
16552                     return a;
16553                 }(true, []),
16554                 body: function(loop, labels) {
16555                     ++S.in_function;
16556                     S.in_directives = true;
16557                     S.in_loop = 0;
16558                     S.labels = [];
16559                     var a = block_();
16560                     --S.in_function;
16561                     S.in_loop = loop;
16562                     S.labels = labels;
16563                     return a;
16564                 }(S.in_loop, S.labels)
16565             });
16566         };
16567         function if_() {
16568             var cond = parenthesised(), body = statement(), belse = null;
16569             if (is("keyword", "else")) {
16570                 next();
16571                 belse = statement();
16572             }
16573             return new AST_If({
16574                 condition: cond,
16575                 body: body,
16576                 alternative: belse
16577             });
16578         }
16579         function block_() {
16580             expect("{");
16581             var a = [];
16582             while (!is("punc", "}")) {
16583                 if (is("eof")) unexpected();
16584                 a.push(statement());
16585             }
16586             next();
16587             return a;
16588         }
16589         function switch_body_() {
16590             expect("{");
16591             var a = [], cur = null, branch = null, tmp;
16592             while (!is("punc", "}")) {
16593                 if (is("eof")) unexpected();
16594                 if (is("keyword", "case")) {
16595                     if (branch) branch.end = prev();
16596                     cur = [];
16597                     branch = new AST_Case({
16598                         start: (tmp = S.token, next(), tmp),
16599                         expression: expression(true),
16600                         body: cur
16601                     });
16602                     a.push(branch);
16603                     expect(":");
16604                 } else if (is("keyword", "default")) {
16605                     if (branch) branch.end = prev();
16606                     cur = [];
16607                     branch = new AST_Default({
16608                         start: (tmp = S.token, next(), expect(":"), tmp),
16609                         body: cur
16610                     });
16611                     a.push(branch);
16612                 } else {
16613                     if (!cur) unexpected();
16614                     cur.push(statement());
16615                 }
16616             }
16617             if (branch) branch.end = prev();
16618             next();
16619             return a;
16620         }
16621         function try_() {
16622             var body = block_(), bcatch = null, bfinally = null;
16623             if (is("keyword", "catch")) {
16624                 var start = S.token;
16625                 next();
16626                 expect("(");
16627                 var name = as_symbol(AST_SymbolCatch);
16628                 expect(")");
16629                 bcatch = new AST_Catch({
16630                     start: start,
16631                     argname: name,
16632                     body: block_(),
16633                     end: prev()
16634                 });
16635             }
16636             if (is("keyword", "finally")) {
16637                 var start = S.token;
16638                 next();
16639                 bfinally = new AST_Finally({
16640                     start: start,
16641                     body: block_(),
16642                     end: prev()
16643                 });
16644             }
16645             if (!bcatch && !bfinally) croak("Missing catch/finally blocks");
16646             return new AST_Try({
16647                 body: body,
16648                 bcatch: bcatch,
16649                 bfinally: bfinally
16650             });
16651         }
16652         function vardefs(no_in, in_const) {
16653             var a = [];
16654             for (;;) {
16655                 a.push(new AST_VarDef({
16656                     start: S.token,
16657                     name: as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
16658                     value: is("operator", "=") ? (next(), expression(false, no_in)) : null,
16659                     end: prev()
16660                 }));
16661                 if (!is("punc", ",")) break;
16662                 next();
16663             }
16664             return a;
16665         }
16666         var var_ = function(no_in) {
16667             return new AST_Var({
16668                 start: prev(),
16669                 definitions: vardefs(no_in, false),
16670                 end: prev()
16671             });
16672         };
16673         var const_ = function() {
16674             return new AST_Const({
16675                 start: prev(),
16676                 definitions: vardefs(false, true),
16677                 end: prev()
16678             });
16679         };
16680         var new_ = function() {
16681             var start = S.token;
16682             expect_token("operator", "new");
16683             var newexp = expr_atom(false), args;
16684             if (is("punc", "(")) {
16685                 next();
16686                 args = expr_list(")");
16687             } else {
16688                 args = [];
16689             }
16690             return subscripts(new AST_New({
16691                 start: start,
16692                 expression: newexp,
16693                 args: args,
16694                 end: prev()
16695             }), true);
16696         };
16697         function as_atom_node() {
16698             var tok = S.token, ret;
16699             switch (tok.type) {
16700               case "name":
16701                 return as_symbol(AST_SymbolRef);
16703               case "num":
16704                 ret = new AST_Number({
16705                     start: tok,
16706                     end: tok,
16707                     value: tok.value
16708                 });
16709                 break;
16711               case "string":
16712                 ret = new AST_String({
16713                     start: tok,
16714                     end: tok,
16715                     value: tok.value
16716                 });
16717                 break;
16719               case "regexp":
16720                 ret = new AST_RegExp({
16721                     start: tok,
16722                     end: tok,
16723                     value: tok.value
16724                 });
16725                 break;
16727               case "atom":
16728                 switch (tok.value) {
16729                   case "false":
16730                     ret = new AST_False({
16731                         start: tok,
16732                         end: tok
16733                     });
16734                     break;
16736                   case "true":
16737                     ret = new AST_True({
16738                         start: tok,
16739                         end: tok
16740                     });
16741                     break;
16743                   case "null":
16744                     ret = new AST_Null({
16745                         start: tok,
16746                         end: tok
16747                     });
16748                     break;
16749                 }
16750                 break;
16751             }
16752             next();
16753             return ret;
16754         }
16755         var expr_atom = function(allow_calls) {
16756             if (is("operator", "new")) {
16757                 return new_();
16758             }
16759             var start = S.token;
16760             if (is("punc")) {
16761                 switch (start.value) {
16762                   case "(":
16763                     next();
16764                     var ex = expression(true);
16765                     ex.start = start;
16766                     ex.end = S.token;
16767                     expect(")");
16768                     return subscripts(ex, allow_calls);
16770                   case "[":
16771                     return subscripts(array_(), allow_calls);
16773                   case "{":
16774                     return subscripts(object_(), allow_calls);
16775                 }
16776                 unexpected();
16777             }
16778             if (is("keyword", "function")) {
16779                 next();
16780                 var func = function_(false);
16781                 func.start = start;
16782                 func.end = prev();
16783                 return subscripts(func, allow_calls);
16784             }
16785             if (ATOMIC_START_TOKEN[S.token.type]) {
16786                 return subscripts(as_atom_node(), allow_calls);
16787             }
16788             unexpected();
16789         };
16790         function expr_list(closing, allow_trailing_comma, allow_empty) {
16791             var first = true, a = [];
16792             while (!is("punc", closing)) {
16793                 if (first) first = false; else expect(",");
16794                 if (allow_trailing_comma && is("punc", closing)) break;
16795                 if (is("punc", ",") && allow_empty) {
16796                     a.push(new AST_Hole({
16797                         start: S.token,
16798                         end: S.token
16799                     }));
16800                 } else {
16801                     a.push(expression(false));
16802                 }
16803             }
16804             next();
16805             return a;
16806         }
16807         var array_ = embed_tokens(function() {
16808             expect("[");
16809             return new AST_Array({
16810                 elements: expr_list("]", !options.strict, true)
16811             });
16812         });
16813         var object_ = embed_tokens(function() {
16814             expect("{");
16815             var first = true, a = [];
16816             while (!is("punc", "}")) {
16817                 if (first) first = false; else expect(",");
16818                 if (!options.strict && is("punc", "}")) break;
16819                 var start = S.token;
16820                 var type = start.type;
16821                 var name = as_property_name();
16822                 if (type == "name" && !is("punc", ":")) {
16823                     if (name == "get") {
16824                         a.push(new AST_ObjectGetter({
16825                             start: start,
16826                             key: name,
16827                             value: function_(false, AST_Accessor),
16828                             end: prev()
16829                         }));
16830                         continue;
16831                     }
16832                     if (name == "set") {
16833                         a.push(new AST_ObjectSetter({
16834                             start: start,
16835                             key: name,
16836                             value: function_(false, AST_Accessor),
16837                             end: prev()
16838                         }));
16839                         continue;
16840                     }
16841                 }
16842                 expect(":");
16843                 a.push(new AST_ObjectKeyVal({
16844                     start: start,
16845                     key: name,
16846                     value: expression(false),
16847                     end: prev()
16848                 }));
16849             }
16850             next();
16851             return new AST_Object({
16852                 properties: a
16853             });
16854         });
16855         function as_property_name() {
16856             var tmp = S.token;
16857             next();
16858             switch (tmp.type) {
16859               case "num":
16860               case "string":
16861               case "name":
16862               case "operator":
16863               case "keyword":
16864               case "atom":
16865                 return tmp.value;
16867               default:
16868                 unexpected();
16869             }
16870         }
16871         function as_name() {
16872             var tmp = S.token;
16873             next();
16874             switch (tmp.type) {
16875               case "name":
16876               case "operator":
16877               case "keyword":
16878               case "atom":
16879                 return tmp.value;
16881               default:
16882                 unexpected();
16883             }
16884         }
16885         function as_symbol(type, noerror) {
16886             if (!is("name")) {
16887                 if (!noerror) croak("Name expected");
16888                 return null;
16889             }
16890             var name = S.token.value;
16891             var sym = new (name == "this" ? AST_This : type)({
16892                 name: String(S.token.value),
16893                 start: S.token,
16894                 end: S.token
16895             });
16896             next();
16897             return sym;
16898         }
16899         var subscripts = function(expr, allow_calls) {
16900             var start = expr.start;
16901             if (is("punc", ".")) {
16902                 next();
16903                 return subscripts(new AST_Dot({
16904                     start: start,
16905                     expression: expr,
16906                     property: as_name(),
16907                     end: prev()
16908                 }), allow_calls);
16909             }
16910             if (is("punc", "[")) {
16911                 next();
16912                 var prop = expression(true);
16913                 expect("]");
16914                 return subscripts(new AST_Sub({
16915                     start: start,
16916                     expression: expr,
16917                     property: prop,
16918                     end: prev()
16919                 }), allow_calls);
16920             }
16921             if (allow_calls && is("punc", "(")) {
16922                 next();
16923                 return subscripts(new AST_Call({
16924                     start: start,
16925                     expression: expr,
16926                     args: expr_list(")"),
16927                     end: prev()
16928                 }), true);
16929             }
16930             return expr;
16931         };
16932         var maybe_unary = function(allow_calls) {
16933             var start = S.token;
16934             if (is("operator") && UNARY_PREFIX(start.value)) {
16935                 next();
16936                 var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls));
16937                 ex.start = start;
16938                 ex.end = prev();
16939                 return ex;
16940             }
16941             var val = expr_atom(allow_calls);
16942             while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
16943                 val = make_unary(AST_UnaryPostfix, S.token.value, val);
16944                 val.start = start;
16945                 val.end = S.token;
16946                 next();
16947             }
16948             return val;
16949         };
16950         function make_unary(ctor, op, expr) {
16951             if ((op == "++" || op == "--") && !is_assignable(expr)) croak("Invalid use of " + op + " operator");
16952             return new ctor({
16953                 operator: op,
16954                 expression: expr
16955             });
16956         }
16957         var expr_op = function(left, min_prec, no_in) {
16958             var op = is("operator") ? S.token.value : null;
16959             if (op == "in" && no_in) op = null;
16960             var prec = op != null ? PRECEDENCE[op] : null;
16961             if (prec != null && prec > min_prec) {
16962                 next();
16963                 var right = expr_op(maybe_unary(true), prec, no_in);
16964                 return expr_op(new AST_Binary({
16965                     start: left.start,
16966                     left: left,
16967                     operator: op,
16968                     right: right,
16969                     end: right.end
16970                 }), min_prec, no_in);
16971             }
16972             return left;
16973         };
16974         function expr_ops(no_in) {
16975             return expr_op(maybe_unary(true), 0, no_in);
16976         }
16977         var maybe_conditional = function(no_in) {
16978             var start = S.token;
16979             var expr = expr_ops(no_in);
16980             if (is("operator", "?")) {
16981                 next();
16982                 var yes = expression(false);
16983                 expect(":");
16984                 return new AST_Conditional({
16985                     start: start,
16986                     condition: expr,
16987                     consequent: yes,
16988                     alternative: expression(false, no_in),
16989                     end: peek()
16990                 });
16991             }
16992             return expr;
16993         };
16994         function is_assignable(expr) {
16995             if (!options.strict) return true;
16996             if (expr instanceof AST_This) return false;
16997             return expr instanceof AST_PropAccess || expr instanceof AST_Symbol;
16998         }
16999         var maybe_assign = function(no_in) {
17000             var start = S.token;
17001             var left = maybe_conditional(no_in), val = S.token.value;
17002             if (is("operator") && ASSIGNMENT(val)) {
17003                 if (is_assignable(left)) {
17004                     next();
17005                     return new AST_Assign({
17006                         start: start,
17007                         left: left,
17008                         operator: val,
17009                         right: maybe_assign(no_in),
17010                         end: prev()
17011                     });
17012                 }
17013                 croak("Invalid assignment");
17014             }
17015             return left;
17016         };
17017         var expression = function(commas, no_in) {
17018             var start = S.token;
17019             var expr = maybe_assign(no_in);
17020             if (commas && is("punc", ",")) {
17021                 next();
17022                 return new AST_Seq({
17023                     start: start,
17024                     car: expr,
17025                     cdr: expression(true, no_in),
17026                     end: peek()
17027                 });
17028             }
17029             return expr;
17030         };
17031         function in_loop(cont) {
17032             ++S.in_loop;
17033             var ret = cont();
17034             --S.in_loop;
17035             return ret;
17036         }
17037         if (options.expression) {
17038             return expression(true);
17039         }
17040         return function() {
17041             var start = S.token;
17042             var body = [];
17043             while (!is("eof")) body.push(statement());
17044             var end = prev();
17045             var toplevel = options.toplevel;
17046             if (toplevel) {
17047                 toplevel.body = toplevel.body.concat(body);
17048                 toplevel.end = end;
17049             } else {
17050                 toplevel = new AST_Toplevel({
17051                     start: start,
17052                     body: body,
17053                     end: end
17054                 });
17055             }
17056             return toplevel;
17057         }();
17058     }
17059     "use strict";
17060     function TreeTransformer(before, after) {
17061         TreeWalker.call(this);
17062         this.before = before;
17063         this.after = after;
17064     }
17065     TreeTransformer.prototype = new TreeWalker();
17066     (function(undefined) {
17067         function _(node, descend) {
17068             node.DEFMETHOD("transform", function(tw, in_list) {
17069                 var x, y;
17070                 tw.push(this);
17071                 if (tw.before) x = tw.before(this, descend, in_list);
17072                 if (x === undefined) {
17073                     if (!tw.after) {
17074                         x = this;
17075                         descend(x, tw);
17076                     } else {
17077                         tw.stack[tw.stack.length - 1] = x = this.clone();
17078                         descend(x, tw);
17079                         y = tw.after(x, in_list);
17080                         if (y !== undefined) x = y;
17081                     }
17082                 }
17083                 tw.pop();
17084                 return x;
17085             });
17086         }
17087         function do_list(list, tw) {
17088             return MAP(list, function(node) {
17089                 return node.transform(tw, true);
17090             });
17091         }
17092         _(AST_Node, noop);
17093         _(AST_LabeledStatement, function(self, tw) {
17094             self.label = self.label.transform(tw);
17095             self.body = self.body.transform(tw);
17096         });
17097         _(AST_SimpleStatement, function(self, tw) {
17098             self.body = self.body.transform(tw);
17099         });
17100         _(AST_Block, function(self, tw) {
17101             self.body = do_list(self.body, tw);
17102         });
17103         _(AST_DWLoop, function(self, tw) {
17104             self.condition = self.condition.transform(tw);
17105             self.body = self.body.transform(tw);
17106         });
17107         _(AST_For, function(self, tw) {
17108             if (self.init) self.init = self.init.transform(tw);
17109             if (self.condition) self.condition = self.condition.transform(tw);
17110             if (self.step) self.step = self.step.transform(tw);
17111             self.body = self.body.transform(tw);
17112         });
17113         _(AST_ForIn, function(self, tw) {
17114             self.init = self.init.transform(tw);
17115             self.object = self.object.transform(tw);
17116             self.body = self.body.transform(tw);
17117         });
17118         _(AST_With, function(self, tw) {
17119             self.expression = self.expression.transform(tw);
17120             self.body = self.body.transform(tw);
17121         });
17122         _(AST_Exit, function(self, tw) {
17123             if (self.value) self.value = self.value.transform(tw);
17124         });
17125         _(AST_LoopControl, function(self, tw) {
17126             if (self.label) self.label = self.label.transform(tw);
17127         });
17128         _(AST_If, function(self, tw) {
17129             self.condition = self.condition.transform(tw);
17130             self.body = self.body.transform(tw);
17131             if (self.alternative) self.alternative = self.alternative.transform(tw);
17132         });
17133         _(AST_Switch, function(self, tw) {
17134             self.expression = self.expression.transform(tw);
17135             self.body = do_list(self.body, tw);
17136         });
17137         _(AST_Case, function(self, tw) {
17138             self.expression = self.expression.transform(tw);
17139             self.body = do_list(self.body, tw);
17140         });
17141         _(AST_Try, function(self, tw) {
17142             self.body = do_list(self.body, tw);
17143             if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
17144             if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
17145         });
17146         _(AST_Catch, function(self, tw) {
17147             self.argname = self.argname.transform(tw);
17148             self.body = do_list(self.body, tw);
17149         });
17150         _(AST_Definitions, function(self, tw) {
17151             self.definitions = do_list(self.definitions, tw);
17152         });
17153         _(AST_VarDef, function(self, tw) {
17154             if (self.value) self.value = self.value.transform(tw);
17155         });
17156         _(AST_Lambda, function(self, tw) {
17157             if (self.name) self.name = self.name.transform(tw);
17158             self.argnames = do_list(self.argnames, tw);
17159             self.body = do_list(self.body, tw);
17160         });
17161         _(AST_Call, function(self, tw) {
17162             self.expression = self.expression.transform(tw);
17163             self.args = do_list(self.args, tw);
17164         });
17165         _(AST_Seq, function(self, tw) {
17166             self.car = self.car.transform(tw);
17167             self.cdr = self.cdr.transform(tw);
17168         });
17169         _(AST_Dot, function(self, tw) {
17170             self.expression = self.expression.transform(tw);
17171         });
17172         _(AST_Sub, function(self, tw) {
17173             self.expression = self.expression.transform(tw);
17174             self.property = self.property.transform(tw);
17175         });
17176         _(AST_Unary, function(self, tw) {
17177             self.expression = self.expression.transform(tw);
17178         });
17179         _(AST_Binary, function(self, tw) {
17180             self.left = self.left.transform(tw);
17181             self.right = self.right.transform(tw);
17182         });
17183         _(AST_Conditional, function(self, tw) {
17184             self.condition = self.condition.transform(tw);
17185             self.consequent = self.consequent.transform(tw);
17186             self.alternative = self.alternative.transform(tw);
17187         });
17188         _(AST_Array, function(self, tw) {
17189             self.elements = do_list(self.elements, tw);
17190         });
17191         _(AST_Object, function(self, tw) {
17192             self.properties = do_list(self.properties, tw);
17193         });
17194         _(AST_ObjectProperty, function(self, tw) {
17195             self.value = self.value.transform(tw);
17196         });
17197     })();
17198     "use strict";
17199     function SymbolDef(scope, index, orig) {
17200         this.name = orig.name;
17201         this.orig = [ orig ];
17202         this.scope = scope;
17203         this.references = [];
17204         this.global = false;
17205         this.mangled_name = null;
17206         this.undeclared = false;
17207         this.constant = false;
17208         this.index = index;
17209     }
17210     SymbolDef.prototype = {
17211         unmangleable: function(options) {
17212             return this.global && !(options && options.toplevel) || this.undeclared || !(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with);
17213         },
17214         mangle: function(options) {
17215             if (!this.mangled_name && !this.unmangleable(options)) {
17216                 var s = this.scope;
17217                 if (this.orig[0] instanceof AST_SymbolLambda && !options.screw_ie8) s = s.parent_scope;
17218                 this.mangled_name = s.next_mangled(options);
17219             }
17220         }
17221     };
17222     AST_Toplevel.DEFMETHOD("figure_out_scope", function() {
17223         var self = this;
17224         var scope = self.parent_scope = null;
17225         var labels = new Dictionary();
17226         var nesting = 0;
17227         var tw = new TreeWalker(function(node, descend) {
17228             if (node instanceof AST_Scope) {
17229                 node.init_scope_vars(nesting);
17230                 var save_scope = node.parent_scope = scope;
17231                 var save_labels = labels;
17232                 ++nesting;
17233                 scope = node;
17234                 labels = new Dictionary();
17235                 descend();
17236                 labels = save_labels;
17237                 scope = save_scope;
17238                 --nesting;
17239                 return true;
17240             }
17241             if (node instanceof AST_Directive) {
17242                 node.scope = scope;
17243                 push_uniq(scope.directives, node.value);
17244                 return true;
17245             }
17246             if (node instanceof AST_With) {
17247                 for (var s = scope; s; s = s.parent_scope) s.uses_with = true;
17248                 return;
17249             }
17250             if (node instanceof AST_LabeledStatement) {
17251                 var l = node.label;
17252                 if (labels.has(l.name)) throw new Error(string_template("Label {name} defined twice", l));
17253                 labels.set(l.name, l);
17254                 descend();
17255                 labels.del(l.name);
17256                 return true;
17257             }
17258             if (node instanceof AST_Symbol) {
17259                 node.scope = scope;
17260             }
17261             if (node instanceof AST_Label) {
17262                 node.thedef = node;
17263                 node.init_scope_vars();
17264             }
17265             if (node instanceof AST_SymbolLambda) {
17266                 scope.def_function(node);
17267             } else if (node instanceof AST_SymbolDefun) {
17268                 (node.scope = scope.parent_scope).def_function(node);
17269             } else if (node instanceof AST_SymbolVar || node instanceof AST_SymbolConst) {
17270                 var def = scope.def_variable(node);
17271                 def.constant = node instanceof AST_SymbolConst;
17272                 def.init = tw.parent().value;
17273             } else if (node instanceof AST_SymbolCatch) {
17274                 scope.def_variable(node);
17275             }
17276             if (node instanceof AST_LabelRef) {
17277                 var sym = labels.get(node.name);
17278                 if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
17279                     name: node.name,
17280                     line: node.start.line,
17281                     col: node.start.col
17282                 }));
17283                 node.thedef = sym;
17284             }
17285         });
17286         self.walk(tw);
17287         var func = null;
17288         var globals = self.globals = new Dictionary();
17289         var tw = new TreeWalker(function(node, descend) {
17290             if (node instanceof AST_Lambda) {
17291                 var prev_func = func;
17292                 func = node;
17293                 descend();
17294                 func = prev_func;
17295                 return true;
17296             }
17297             if (node instanceof AST_LabelRef) {
17298                 node.reference();
17299                 return true;
17300             }
17301             if (node instanceof AST_SymbolRef) {
17302                 var name = node.name;
17303                 var sym = node.scope.find_variable(name);
17304                 if (!sym) {
17305                     var g;
17306                     if (globals.has(name)) {
17307                         g = globals.get(name);
17308                     } else {
17309                         g = new SymbolDef(self, globals.size(), node);
17310                         g.undeclared = true;
17311                         g.global = true;
17312                         globals.set(name, g);
17313                     }
17314                     node.thedef = g;
17315                     if (name == "eval" && tw.parent() instanceof AST_Call) {
17316                         for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) s.uses_eval = true;
17317                     }
17318                     if (name == "arguments") {
17319                         func.uses_arguments = true;
17320                     }
17321                 } else {
17322                     node.thedef = sym;
17323                 }
17324                 node.reference();
17325                 return true;
17326             }
17327         });
17328         self.walk(tw);
17329     });
17330     AST_Scope.DEFMETHOD("init_scope_vars", function(nesting) {
17331         this.directives = [];
17332         this.variables = new Dictionary();
17333         this.functions = new Dictionary();
17334         this.uses_with = false;
17335         this.uses_eval = false;
17336         this.parent_scope = null;
17337         this.enclosed = [];
17338         this.cname = -1;
17339         this.nesting = nesting;
17340     });
17341     AST_Scope.DEFMETHOD("strict", function() {
17342         return this.has_directive("use strict");
17343     });
17344     AST_Lambda.DEFMETHOD("init_scope_vars", function() {
17345         AST_Scope.prototype.init_scope_vars.apply(this, arguments);
17346         this.uses_arguments = false;
17347     });
17348     AST_SymbolRef.DEFMETHOD("reference", function() {
17349         var def = this.definition();
17350         def.references.push(this);
17351         var s = this.scope;
17352         while (s) {
17353             push_uniq(s.enclosed, def);
17354             if (s === def.scope) break;
17355             s = s.parent_scope;
17356         }
17357         this.frame = this.scope.nesting - def.scope.nesting;
17358     });
17359     AST_Label.DEFMETHOD("init_scope_vars", function() {
17360         this.references = [];
17361     });
17362     AST_LabelRef.DEFMETHOD("reference", function() {
17363         this.thedef.references.push(this);
17364     });
17365     AST_Scope.DEFMETHOD("find_variable", function(name) {
17366         if (name instanceof AST_Symbol) name = name.name;
17367         return this.variables.get(name) || this.parent_scope && this.parent_scope.find_variable(name);
17368     });
17369     AST_Scope.DEFMETHOD("has_directive", function(value) {
17370         return this.parent_scope && this.parent_scope.has_directive(value) || (this.directives.indexOf(value) >= 0 ? this : null);
17371     });
17372     AST_Scope.DEFMETHOD("def_function", function(symbol) {
17373         this.functions.set(symbol.name, this.def_variable(symbol));
17374     });
17375     AST_Scope.DEFMETHOD("def_variable", function(symbol) {
17376         var def;
17377         if (!this.variables.has(symbol.name)) {
17378             def = new SymbolDef(this, this.variables.size(), symbol);
17379             this.variables.set(symbol.name, def);
17380             def.global = !this.parent_scope;
17381         } else {
17382             def = this.variables.get(symbol.name);
17383             def.orig.push(symbol);
17384         }
17385         return symbol.thedef = def;
17386     });
17387     AST_Scope.DEFMETHOD("next_mangled", function(options) {
17388         var ext = this.enclosed;
17389         out: while (true) {
17390             var m = base54(++this.cname);
17391             if (!is_identifier(m)) continue;
17392             for (var i = ext.length; --i >= 0; ) {
17393                 var sym = ext[i];
17394                 var name = sym.mangled_name || sym.unmangleable(options) && sym.name;
17395                 if (m == name) continue out;
17396             }
17397             return m;
17398         }
17399     });
17400     AST_Scope.DEFMETHOD("references", function(sym) {
17401         if (sym instanceof AST_Symbol) sym = sym.definition();
17402         return this.enclosed.indexOf(sym) < 0 ? null : sym;
17403     });
17404     AST_Symbol.DEFMETHOD("unmangleable", function(options) {
17405         return this.definition().unmangleable(options);
17406     });
17407     AST_SymbolAccessor.DEFMETHOD("unmangleable", function() {
17408         return true;
17409     });
17410     AST_Label.DEFMETHOD("unmangleable", function() {
17411         return false;
17412     });
17413     AST_Symbol.DEFMETHOD("unreferenced", function() {
17414         return this.definition().references.length == 0 && !(this.scope.uses_eval || this.scope.uses_with);
17415     });
17416     AST_Symbol.DEFMETHOD("undeclared", function() {
17417         return this.definition().undeclared;
17418     });
17419     AST_LabelRef.DEFMETHOD("undeclared", function() {
17420         return false;
17421     });
17422     AST_Label.DEFMETHOD("undeclared", function() {
17423         return false;
17424     });
17425     AST_Symbol.DEFMETHOD("definition", function() {
17426         return this.thedef;
17427     });
17428     AST_Symbol.DEFMETHOD("global", function() {
17429         return this.definition().global;
17430     });
17431     AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
17432         return defaults(options, {
17433             except: [],
17434             eval: false,
17435             sort: false,
17436             toplevel: false,
17437             screw_ie8: false
17438         });
17439     });
17440     AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
17441         options = this._default_mangler_options(options);
17442         var lname = -1;
17443         var to_mangle = [];
17444         var tw = new TreeWalker(function(node, descend) {
17445             if (node instanceof AST_LabeledStatement) {
17446                 var save_nesting = lname;
17447                 descend();
17448                 lname = save_nesting;
17449                 return true;
17450             }
17451             if (node instanceof AST_Scope) {
17452                 var p = tw.parent(), a = [];
17453                 node.variables.each(function(symbol) {
17454                     if (options.except.indexOf(symbol.name) < 0) {
17455                         a.push(symbol);
17456                     }
17457                 });
17458                 if (options.sort) a.sort(function(a, b) {
17459                     return b.references.length - a.references.length;
17460                 });
17461                 to_mangle.push.apply(to_mangle, a);
17462                 return;
17463             }
17464             if (node instanceof AST_Label) {
17465                 var name;
17466                 do name = base54(++lname); while (!is_identifier(name));
17467                 node.mangled_name = name;
17468                 return true;
17469             }
17470         });
17471         this.walk(tw);
17472         to_mangle.forEach(function(def) {
17473             def.mangle(options);
17474         });
17475     });
17476     AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
17477         options = this._default_mangler_options(options);
17478         var tw = new TreeWalker(function(node) {
17479             if (node instanceof AST_Constant) base54.consider(node.print_to_string()); else if (node instanceof AST_Return) base54.consider("return"); else if (node instanceof AST_Throw) base54.consider("throw"); else if (node instanceof AST_Continue) base54.consider("continue"); else if (node instanceof AST_Break) base54.consider("break"); else if (node instanceof AST_Debugger) base54.consider("debugger"); else if (node instanceof AST_Directive) base54.consider(node.value); else if (node instanceof AST_While) base54.consider("while"); else if (node instanceof AST_Do) base54.consider("do while"); else if (node instanceof AST_If) {
17480                 base54.consider("if");
17481                 if (node.alternative) base54.consider("else");
17482             } else if (node instanceof AST_Var) base54.consider("var"); else if (node instanceof AST_Const) base54.consider("const"); else if (node instanceof AST_Lambda) base54.consider("function"); else if (node instanceof AST_For) base54.consider("for"); else if (node instanceof AST_ForIn) base54.consider("for in"); else if (node instanceof AST_Switch) base54.consider("switch"); else if (node instanceof AST_Case) base54.consider("case"); else if (node instanceof AST_Default) base54.consider("default"); else if (node instanceof AST_With) base54.consider("with"); else if (node instanceof AST_ObjectSetter) base54.consider("set" + node.key); else if (node instanceof AST_ObjectGetter) base54.consider("get" + node.key); else if (node instanceof AST_ObjectKeyVal) base54.consider(node.key); else if (node instanceof AST_New) base54.consider("new"); else if (node instanceof AST_This) base54.consider("this"); else if (node instanceof AST_Try) base54.consider("try"); else if (node instanceof AST_Catch) base54.consider("catch"); else if (node instanceof AST_Finally) base54.consider("finally"); else if (node instanceof AST_Symbol && node.unmangleable(options)) base54.consider(node.name); else if (node instanceof AST_Unary || node instanceof AST_Binary) base54.consider(node.operator); else if (node instanceof AST_Dot) base54.consider(node.property);
17483         });
17484         this.walk(tw);
17485         base54.sort();
17486     });
17487     var base54 = function() {
17488         var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
17489         var chars, frequency;
17490         function reset() {
17491             frequency = Object.create(null);
17492             chars = string.split("").map(function(ch) {
17493                 return ch.charCodeAt(0);
17494             });
17495             chars.forEach(function(ch) {
17496                 frequency[ch] = 0;
17497             });
17498         }
17499         base54.consider = function(str) {
17500             for (var i = str.length; --i >= 0; ) {
17501                 var code = str.charCodeAt(i);
17502                 if (code in frequency) ++frequency[code];
17503             }
17504         };
17505         base54.sort = function() {
17506             chars = mergeSort(chars, function(a, b) {
17507                 if (is_digit(a) && !is_digit(b)) return 1;
17508                 if (is_digit(b) && !is_digit(a)) return -1;
17509                 return frequency[b] - frequency[a];
17510             });
17511         };
17512         base54.reset = reset;
17513         reset();
17514         base54.get = function() {
17515             return chars;
17516         };
17517         base54.freq = function() {
17518             return frequency;
17519         };
17520         function base54(num) {
17521             var ret = "", base = 54;
17522             do {
17523                 ret += String.fromCharCode(chars[num % base]);
17524                 num = Math.floor(num / base);
17525                 base = 64;
17526             } while (num > 0);
17527             return ret;
17528         }
17529         return base54;
17530     }();
17531     AST_Toplevel.DEFMETHOD("scope_warnings", function(options) {
17532         options = defaults(options, {
17533             undeclared: false,
17534             unreferenced: true,
17535             assign_to_global: true,
17536             func_arguments: true,
17537             nested_defuns: true,
17538             eval: true
17539         });
17540         var tw = new TreeWalker(function(node) {
17541             if (options.undeclared && node instanceof AST_SymbolRef && node.undeclared()) {
17542                 AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
17543                     name: node.name,
17544                     file: node.start.file,
17545                     line: node.start.line,
17546                     col: node.start.col
17547                 });
17548             }
17549             if (options.assign_to_global) {
17550                 var sym = null;
17551                 if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) sym = node.left; else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef) sym = node.init;
17552                 if (sym && (sym.undeclared() || sym.global() && sym.scope !== sym.definition().scope)) {
17553                     AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
17554                         msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
17555                         name: sym.name,
17556                         file: sym.start.file,
17557                         line: sym.start.line,
17558                         col: sym.start.col
17559                     });
17560                 }
17561             }
17562             if (options.eval && node instanceof AST_SymbolRef && node.undeclared() && node.name == "eval") {
17563                 AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
17564             }
17565             if (options.unreferenced && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) && node.unreferenced()) {
17566                 AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
17567                     type: node instanceof AST_Label ? "Label" : "Symbol",
17568                     name: node.name,
17569                     file: node.start.file,
17570                     line: node.start.line,
17571                     col: node.start.col
17572                 });
17573             }
17574             if (options.func_arguments && node instanceof AST_Lambda && node.uses_arguments) {
17575                 AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
17576                     name: node.name ? node.name.name : "anonymous",
17577                     file: node.start.file,
17578                     line: node.start.line,
17579                     col: node.start.col
17580                 });
17581             }
17582             if (options.nested_defuns && node instanceof AST_Defun && !(tw.parent() instanceof AST_Scope)) {
17583                 AST_Node.warn('Function {name} declared in nested statement "{type}" [{file}:{line},{col}]', {
17584                     name: node.name.name,
17585                     type: tw.parent().TYPE,
17586                     file: node.start.file,
17587                     line: node.start.line,
17588                     col: node.start.col
17589                 });
17590             }
17591         });
17592         this.walk(tw);
17593     });
17594     "use strict";
17595     function OutputStream(options) {
17596         options = defaults(options, {
17597             indent_start: 0,
17598             indent_level: 4,
17599             quote_keys: false,
17600             space_colon: true,
17601             ascii_only: false,
17602             inline_script: false,
17603             width: 80,
17604             max_line_len: 32e3,
17605             ie_proof: true,
17606             beautify: false,
17607             source_map: null,
17608             bracketize: false,
17609             semicolons: true,
17610             comments: false,
17611             preserve_line: false,
17612             negate_iife: !(options && options.beautify)
17613         }, true);
17614         var indentation = 0;
17615         var current_col = 0;
17616         var current_line = 1;
17617         var current_pos = 0;
17618         var OUTPUT = "";
17619         function to_ascii(str, identifier) {
17620             return str.replace(/[\u0080-\uffff]/g, function(ch) {
17621                 var code = ch.charCodeAt(0).toString(16);
17622                 if (code.length <= 2 && !identifier) {
17623                     while (code.length < 2) code = "0" + code;
17624                     return "\\x" + code;
17625                 } else {
17626                     while (code.length < 4) code = "0" + code;
17627                     return "\\u" + code;
17628                 }
17629             });
17630         }
17631         function make_string(str) {
17632             var dq = 0, sq = 0;
17633             str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s) {
17634                 switch (s) {
17635                   case "\\":
17636                     return "\\\\";
17638                   case "\b":
17639                     return "\\b";
17641                   case "\f":
17642                     return "\\f";
17644                   case "\n":
17645                     return "\\n";
17647                   case "\r":
17648                     return "\\r";
17650                   case "\u2028":
17651                     return "\\u2028";
17653                   case "\u2029":
17654                     return "\\u2029";
17656                   case '"':
17657                     ++dq;
17658                     return '"';
17660                   case "'":
17661                     ++sq;
17662                     return "'";
17664                   case "\0":
17665                     return "\\0";
17666                 }
17667                 return s;
17668             });
17669             if (options.ascii_only) str = to_ascii(str);
17670             if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; else return '"' + str.replace(/\x22/g, '\\"') + '"';
17671         }
17672         function encode_string(str) {
17673             var ret = make_string(str);
17674             if (options.inline_script) ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
17675             return ret;
17676         }
17677         function make_name(name) {
17678             name = name.toString();
17679             if (options.ascii_only) name = to_ascii(name, true);
17680             return name;
17681         }
17682         function make_indent(back) {
17683             return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
17684         }
17685         var might_need_space = false;
17686         var might_need_semicolon = false;
17687         var last = null;
17688         function last_char() {
17689             return last.charAt(last.length - 1);
17690         }
17691         function maybe_newline() {
17692             if (options.max_line_len && current_col > options.max_line_len) print("\n");
17693         }
17694         var requireSemicolonChars = makePredicate("( [ + * / - , .");
17695         function print(str) {
17696             str = String(str);
17697             var ch = str.charAt(0);
17698             if (might_need_semicolon) {
17699                 if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
17700                     if (options.semicolons || requireSemicolonChars(ch)) {
17701                         OUTPUT += ";";
17702                         current_col++;
17703                         current_pos++;
17704                     } else {
17705                         OUTPUT += "\n";
17706                         current_pos++;
17707                         current_line++;
17708                         current_col = 0;
17709                     }
17710                     if (!options.beautify) might_need_space = false;
17711                 }
17712                 might_need_semicolon = false;
17713                 maybe_newline();
17714             }
17715             if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
17716                 var target_line = stack[stack.length - 1].start.line;
17717                 while (current_line < target_line) {
17718                     OUTPUT += "\n";
17719                     current_pos++;
17720                     current_line++;
17721                     current_col = 0;
17722                     might_need_space = false;
17723                 }
17724             }
17725             if (might_need_space) {
17726                 var prev = last_char();
17727                 if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\") || /^[\+\-\/]$/.test(ch) && ch == prev) {
17728                     OUTPUT += " ";
17729                     current_col++;
17730                     current_pos++;
17731                 }
17732                 might_need_space = false;
17733             }
17734             var a = str.split(/\r?\n/), n = a.length - 1;
17735             current_line += n;
17736             if (n == 0) {
17737                 current_col += a[n].length;
17738             } else {
17739                 current_col = a[n].length;
17740             }
17741             current_pos += str.length;
17742             last = str;
17743             OUTPUT += str;
17744         }
17745         var space = options.beautify ? function() {
17746             print(" ");
17747         } : function() {
17748             might_need_space = true;
17749         };
17750         var indent = options.beautify ? function(half) {
17751             if (options.beautify) {
17752                 print(make_indent(half ? .5 : 0));
17753             }
17754         } : noop;
17755         var with_indent = options.beautify ? function(col, cont) {
17756             if (col === true) col = next_indent();
17757             var save_indentation = indentation;
17758             indentation = col;
17759             var ret = cont();
17760             indentation = save_indentation;
17761             return ret;
17762         } : function(col, cont) {
17763             return cont();
17764         };
17765         var newline = options.beautify ? function() {
17766             print("\n");
17767         } : noop;
17768         var semicolon = options.beautify ? function() {
17769             print(";");
17770         } : function() {
17771             might_need_semicolon = true;
17772         };
17773         function force_semicolon() {
17774             might_need_semicolon = false;
17775             print(";");
17776         }
17777         function next_indent() {
17778             return indentation + options.indent_level;
17779         }
17780         function with_block(cont) {
17781             var ret;
17782             print("{");
17783             newline();
17784             with_indent(next_indent(), function() {
17785                 ret = cont();
17786             });
17787             indent();
17788             print("}");
17789             return ret;
17790         }
17791         function with_parens(cont) {
17792             print("(");
17793             var ret = cont();
17794             print(")");
17795             return ret;
17796         }
17797         function with_square(cont) {
17798             print("[");
17799             var ret = cont();
17800             print("]");
17801             return ret;
17802         }
17803         function comma() {
17804             print(",");
17805             space();
17806         }
17807         function colon() {
17808             print(":");
17809             if (options.space_colon) space();
17810         }
17811         var add_mapping = options.source_map ? function(token, name) {
17812             try {
17813                 if (token) options.source_map.add(token.file || "?", current_line, current_col, token.line, token.col, !name && token.type == "name" ? token.value : name);
17814             } catch (ex) {
17815                 AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
17816                     file: token.file,
17817                     line: token.line,
17818                     col: token.col,
17819                     cline: current_line,
17820                     ccol: current_col,
17821                     name: name || ""
17822                 });
17823             }
17824         } : noop;
17825         function get() {
17826             return OUTPUT;
17827         }
17828         var stack = [];
17829         return {
17830             get: get,
17831             toString: get,
17832             indent: indent,
17833             indentation: function() {
17834                 return indentation;
17835             },
17836             current_width: function() {
17837                 return current_col - indentation;
17838             },
17839             should_break: function() {
17840                 return options.width && this.current_width() >= options.width;
17841             },
17842             newline: newline,
17843             print: print,
17844             space: space,
17845             comma: comma,
17846             colon: colon,
17847             last: function() {
17848                 return last;
17849             },
17850             semicolon: semicolon,
17851             force_semicolon: force_semicolon,
17852             to_ascii: to_ascii,
17853             print_name: function(name) {
17854                 print(make_name(name));
17855             },
17856             print_string: function(str) {
17857                 print(encode_string(str));
17858             },
17859             next_indent: next_indent,
17860             with_indent: with_indent,
17861             with_block: with_block,
17862             with_parens: with_parens,
17863             with_square: with_square,
17864             add_mapping: add_mapping,
17865             option: function(opt) {
17866                 return options[opt];
17867             },
17868             line: function() {
17869                 return current_line;
17870             },
17871             col: function() {
17872                 return current_col;
17873             },
17874             pos: function() {
17875                 return current_pos;
17876             },
17877             push_node: function(node) {
17878                 stack.push(node);
17879             },
17880             pop_node: function() {
17881                 return stack.pop();
17882             },
17883             stack: function() {
17884                 return stack;
17885             },
17886             parent: function(n) {
17887                 return stack[stack.length - 2 - (n || 0)];
17888             }
17889         };
17890     }
17891     (function() {
17892         function DEFPRINT(nodetype, generator) {
17893             nodetype.DEFMETHOD("_codegen", generator);
17894         }
17895         AST_Node.DEFMETHOD("print", function(stream, force_parens) {
17896             var self = this, generator = self._codegen;
17897             stream.push_node(self);
17898             var needs_parens = self.needs_parens(stream);
17899             var fc = self instanceof AST_Function && stream.option("negate_iife");
17900             if (force_parens || needs_parens && !fc) {
17901                 stream.with_parens(function() {
17902                     self.add_comments(stream);
17903                     self.add_source_map(stream);
17904                     generator(self, stream);
17905                 });
17906             } else {
17907                 self.add_comments(stream);
17908                 if (needs_parens && fc) stream.print("!");
17909                 self.add_source_map(stream);
17910                 generator(self, stream);
17911             }
17912             stream.pop_node();
17913         });
17914         AST_Node.DEFMETHOD("print_to_string", function(options) {
17915             var s = OutputStream(options);
17916             this.print(s);
17917             return s.get();
17918         });
17919         AST_Node.DEFMETHOD("add_comments", function(output) {
17920             var c = output.option("comments"), self = this;
17921             if (c) {
17922                 var start = self.start;
17923                 if (start && !start._comments_dumped) {
17924                     start._comments_dumped = true;
17925                     var comments = start.comments_before;
17926                     if (self instanceof AST_Exit && self.value && self.value.start.comments_before.length > 0) {
17927                         comments = (comments || []).concat(self.value.start.comments_before);
17928                         self.value.start.comments_before = [];
17929                     }
17930                     if (c.test) {
17931                         comments = comments.filter(function(comment) {
17932                             return c.test(comment.value);
17933                         });
17934                     } else if (typeof c == "function") {
17935                         comments = comments.filter(function(comment) {
17936                             return c(self, comment);
17937                         });
17938                     }
17939                     comments.forEach(function(c) {
17940                         if (c.type == "comment1") {
17941                             output.print("//" + c.value + "\n");
17942                             output.indent();
17943                         } else if (c.type == "comment2") {
17944                             output.print("/*" + c.value + "*/");
17945                             if (start.nlb) {
17946                                 output.print("\n");
17947                                 output.indent();
17948                             } else {
17949                                 output.space();
17950                             }
17951                         }
17952                     });
17953                 }
17954             }
17955         });
17956         function PARENS(nodetype, func) {
17957             nodetype.DEFMETHOD("needs_parens", func);
17958         }
17959         PARENS(AST_Node, function() {
17960             return false;
17961         });
17962         PARENS(AST_Function, function(output) {
17963             return first_in_statement(output);
17964         });
17965         PARENS(AST_Object, function(output) {
17966             return first_in_statement(output);
17967         });
17968         PARENS(AST_Unary, function(output) {
17969             var p = output.parent();
17970             return p instanceof AST_PropAccess && p.expression === this;
17971         });
17972         PARENS(AST_Seq, function(output) {
17973             var p = output.parent();
17974             return p instanceof AST_Call || p instanceof AST_Unary || p instanceof AST_Binary || p instanceof AST_VarDef || p instanceof AST_Dot || p instanceof AST_Array || p instanceof AST_ObjectProperty || p instanceof AST_Conditional;
17975         });
17976         PARENS(AST_Binary, function(output) {
17977             var p = output.parent();
17978             if (p instanceof AST_Call && p.expression === this) return true;
17979             if (p instanceof AST_Unary) return true;
17980             if (p instanceof AST_PropAccess && p.expression === this) return true;
17981             if (p instanceof AST_Binary) {
17982                 var po = p.operator, pp = PRECEDENCE[po];
17983                 var so = this.operator, sp = PRECEDENCE[so];
17984                 if (pp > sp || pp == sp && this === p.right && !(so == po && (so == "*" || so == "&&" || so == "||"))) {
17985                     return true;
17986                 }
17987             }
17988         });
17989         PARENS(AST_PropAccess, function(output) {
17990             var p = output.parent();
17991             if (p instanceof AST_New && p.expression === this) {
17992                 try {
17993                     this.walk(new TreeWalker(function(node) {
17994                         if (node instanceof AST_Call) throw p;
17995                     }));
17996                 } catch (ex) {
17997                     if (ex !== p) throw ex;
17998                     return true;
17999                 }
18000             }
18001         });
18002         PARENS(AST_Call, function(output) {
18003             var p = output.parent();
18004             return p instanceof AST_New && p.expression === this;
18005         });
18006         PARENS(AST_New, function(output) {
18007             var p = output.parent();
18008             if (no_constructor_parens(this, output) && (p instanceof AST_PropAccess || p instanceof AST_Call && p.expression === this)) return true;
18009         });
18010         PARENS(AST_Number, function(output) {
18011             var p = output.parent();
18012             if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) return true;
18013         });
18014         PARENS(AST_NaN, function(output) {
18015             var p = output.parent();
18016             if (p instanceof AST_PropAccess && p.expression === this) return true;
18017         });
18018         function assign_and_conditional_paren_rules(output) {
18019             var p = output.parent();
18020             if (p instanceof AST_Unary) return true;
18021             if (p instanceof AST_Binary && !(p instanceof AST_Assign)) return true;
18022             if (p instanceof AST_Call && p.expression === this) return true;
18023             if (p instanceof AST_Conditional && p.condition === this) return true;
18024             if (p instanceof AST_PropAccess && p.expression === this) return true;
18025         }
18026         PARENS(AST_Assign, assign_and_conditional_paren_rules);
18027         PARENS(AST_Conditional, assign_and_conditional_paren_rules);
18028         DEFPRINT(AST_Directive, function(self, output) {
18029             output.print_string(self.value);
18030             output.semicolon();
18031         });
18032         DEFPRINT(AST_Debugger, function(self, output) {
18033             output.print("debugger");
18034             output.semicolon();
18035         });
18036         function display_body(body, is_toplevel, output) {
18037             var last = body.length - 1;
18038             body.forEach(function(stmt, i) {
18039                 if (!(stmt instanceof AST_EmptyStatement)) {
18040                     output.indent();
18041                     stmt.print(output);
18042                     if (!(i == last && is_toplevel)) {
18043                         output.newline();
18044                         if (is_toplevel) output.newline();
18045                     }
18046                 }
18047             });
18048         }
18049         AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
18050             force_statement(this.body, output);
18051         });
18052         DEFPRINT(AST_Statement, function(self, output) {
18053             self.body.print(output);
18054             output.semicolon();
18055         });
18056         DEFPRINT(AST_Toplevel, function(self, output) {
18057             display_body(self.body, true, output);
18058             output.print("");
18059         });
18060         DEFPRINT(AST_LabeledStatement, function(self, output) {
18061             self.label.print(output);
18062             output.colon();
18063             self.body.print(output);
18064         });
18065         DEFPRINT(AST_SimpleStatement, function(self, output) {
18066             self.body.print(output);
18067             output.semicolon();
18068         });
18069         function print_bracketed(body, output) {
18070             if (body.length > 0) output.with_block(function() {
18071                 display_body(body, false, output);
18072             }); else output.print("{}");
18073         }
18074         DEFPRINT(AST_BlockStatement, function(self, output) {
18075             print_bracketed(self.body, output);
18076         });
18077         DEFPRINT(AST_EmptyStatement, function(self, output) {
18078             output.semicolon();
18079         });
18080         DEFPRINT(AST_Do, function(self, output) {
18081             output.print("do");
18082             output.space();
18083             self._do_print_body(output);
18084             output.space();
18085             output.print("while");
18086             output.space();
18087             output.with_parens(function() {
18088                 self.condition.print(output);
18089             });
18090             output.semicolon();
18091         });
18092         DEFPRINT(AST_While, function(self, output) {
18093             output.print("while");
18094             output.space();
18095             output.with_parens(function() {
18096                 self.condition.print(output);
18097             });
18098             output.space();
18099             self._do_print_body(output);
18100         });
18101         DEFPRINT(AST_For, function(self, output) {
18102             output.print("for");
18103             output.space();
18104             output.with_parens(function() {
18105                 if (self.init) {
18106                     if (self.init instanceof AST_Definitions) {
18107                         self.init.print(output);
18108                     } else {
18109                         parenthesize_for_noin(self.init, output, true);
18110                     }
18111                     output.print(";");
18112                     output.space();
18113                 } else {
18114                     output.print(";");
18115                 }
18116                 if (self.condition) {
18117                     self.condition.print(output);
18118                     output.print(";");
18119                     output.space();
18120                 } else {
18121                     output.print(";");
18122                 }
18123                 if (self.step) {
18124                     self.step.print(output);
18125                 }
18126             });
18127             output.space();
18128             self._do_print_body(output);
18129         });
18130         DEFPRINT(AST_ForIn, function(self, output) {
18131             output.print("for");
18132             output.space();
18133             output.with_parens(function() {
18134                 self.init.print(output);
18135                 output.space();
18136                 output.print("in");
18137                 output.space();
18138                 self.object.print(output);
18139             });
18140             output.space();
18141             self._do_print_body(output);
18142         });
18143         DEFPRINT(AST_With, function(self, output) {
18144             output.print("with");
18145             output.space();
18146             output.with_parens(function() {
18147                 self.expression.print(output);
18148             });
18149             output.space();
18150             self._do_print_body(output);
18151         });
18152         AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) {
18153             var self = this;
18154             if (!nokeyword) {
18155                 output.print("function");
18156             }
18157             if (self.name) {
18158                 output.space();
18159                 self.name.print(output);
18160             }
18161             output.with_parens(function() {
18162                 self.argnames.forEach(function(arg, i) {
18163                     if (i) output.comma();
18164                     arg.print(output);
18165                 });
18166             });
18167             output.space();
18168             print_bracketed(self.body, output);
18169         });
18170         DEFPRINT(AST_Lambda, function(self, output) {
18171             self._do_print(output);
18172         });
18173         AST_Exit.DEFMETHOD("_do_print", function(output, kind) {
18174             output.print(kind);
18175             if (this.value) {
18176                 output.space();
18177                 this.value.print(output);
18178             }
18179             output.semicolon();
18180         });
18181         DEFPRINT(AST_Return, function(self, output) {
18182             self._do_print(output, "return");
18183         });
18184         DEFPRINT(AST_Throw, function(self, output) {
18185             self._do_print(output, "throw");
18186         });
18187         AST_LoopControl.DEFMETHOD("_do_print", function(output, kind) {
18188             output.print(kind);
18189             if (this.label) {
18190                 output.space();
18191                 this.label.print(output);
18192             }
18193             output.semicolon();
18194         });
18195         DEFPRINT(AST_Break, function(self, output) {
18196             self._do_print(output, "break");
18197         });
18198         DEFPRINT(AST_Continue, function(self, output) {
18199             self._do_print(output, "continue");
18200         });
18201         function make_then(self, output) {
18202             if (output.option("bracketize")) {
18203                 make_block(self.body, output);
18204                 return;
18205             }
18206             if (!self.body) return output.force_semicolon();
18207             if (self.body instanceof AST_Do && output.option("ie_proof")) {
18208                 make_block(self.body, output);
18209                 return;
18210             }
18211             var b = self.body;
18212             while (true) {
18213                 if (b instanceof AST_If) {
18214                     if (!b.alternative) {
18215                         make_block(self.body, output);
18216                         return;
18217                     }
18218                     b = b.alternative;
18219                 } else if (b instanceof AST_StatementWithBody) {
18220                     b = b.body;
18221                 } else break;
18222             }
18223             force_statement(self.body, output);
18224         }
18225         DEFPRINT(AST_If, function(self, output) {
18226             output.print("if");
18227             output.space();
18228             output.with_parens(function() {
18229                 self.condition.print(output);
18230             });
18231             output.space();
18232             if (self.alternative) {
18233                 make_then(self, output);
18234                 output.space();
18235                 output.print("else");
18236                 output.space();
18237                 force_statement(self.alternative, output);
18238             } else {
18239                 self._do_print_body(output);
18240             }
18241         });
18242         DEFPRINT(AST_Switch, function(self, output) {
18243             output.print("switch");
18244             output.space();
18245             output.with_parens(function() {
18246                 self.expression.print(output);
18247             });
18248             output.space();
18249             if (self.body.length > 0) output.with_block(function() {
18250                 self.body.forEach(function(stmt, i) {
18251                     if (i) output.newline();
18252                     output.indent(true);
18253                     stmt.print(output);
18254                 });
18255             }); else output.print("{}");
18256         });
18257         AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) {
18258             if (this.body.length > 0) {
18259                 output.newline();
18260                 this.body.forEach(function(stmt) {
18261                     output.indent();
18262                     stmt.print(output);
18263                     output.newline();
18264                 });
18265             }
18266         });
18267         DEFPRINT(AST_Default, function(self, output) {
18268             output.print("default:");
18269             self._do_print_body(output);
18270         });
18271         DEFPRINT(AST_Case, function(self, output) {
18272             output.print("case");
18273             output.space();
18274             self.expression.print(output);
18275             output.print(":");
18276             self._do_print_body(output);
18277         });
18278         DEFPRINT(AST_Try, function(self, output) {
18279             output.print("try");
18280             output.space();
18281             print_bracketed(self.body, output);
18282             if (self.bcatch) {
18283                 output.space();
18284                 self.bcatch.print(output);
18285             }
18286             if (self.bfinally) {
18287                 output.space();
18288                 self.bfinally.print(output);
18289             }
18290         });
18291         DEFPRINT(AST_Catch, function(self, output) {
18292             output.print("catch");
18293             output.space();
18294             output.with_parens(function() {
18295                 self.argname.print(output);
18296             });
18297             output.space();
18298             print_bracketed(self.body, output);
18299         });
18300         DEFPRINT(AST_Finally, function(self, output) {
18301             output.print("finally");
18302             output.space();
18303             print_bracketed(self.body, output);
18304         });
18305         AST_Definitions.DEFMETHOD("_do_print", function(output, kind) {
18306             output.print(kind);
18307             output.space();
18308             this.definitions.forEach(function(def, i) {
18309                 if (i) output.comma();
18310                 def.print(output);
18311             });
18312             var p = output.parent();
18313             var in_for = p instanceof AST_For || p instanceof AST_ForIn;
18314             var avoid_semicolon = in_for && p.init === this;
18315             if (!avoid_semicolon) output.semicolon();
18316         });
18317         DEFPRINT(AST_Var, function(self, output) {
18318             self._do_print(output, "var");
18319         });
18320         DEFPRINT(AST_Const, function(self, output) {
18321             self._do_print(output, "const");
18322         });
18323         function parenthesize_for_noin(node, output, noin) {
18324             if (!noin) node.print(output); else try {
18325                 node.walk(new TreeWalker(function(node) {
18326                     if (node instanceof AST_Binary && node.operator == "in") throw output;
18327                 }));
18328                 node.print(output);
18329             } catch (ex) {
18330                 if (ex !== output) throw ex;
18331                 node.print(output, true);
18332             }
18333         }
18334         DEFPRINT(AST_VarDef, function(self, output) {
18335             self.name.print(output);
18336             if (self.value) {
18337                 output.space();
18338                 output.print("=");
18339                 output.space();
18340                 var p = output.parent(1);
18341                 var noin = p instanceof AST_For || p instanceof AST_ForIn;
18342                 parenthesize_for_noin(self.value, output, noin);
18343             }
18344         });
18345         DEFPRINT(AST_Call, function(self, output) {
18346             self.expression.print(output);
18347             if (self instanceof AST_New && no_constructor_parens(self, output)) return;
18348             output.with_parens(function() {
18349                 self.args.forEach(function(expr, i) {
18350                     if (i) output.comma();
18351                     expr.print(output);
18352                 });
18353             });
18354         });
18355         DEFPRINT(AST_New, function(self, output) {
18356             output.print("new");
18357             output.space();
18358             AST_Call.prototype._codegen(self, output);
18359         });
18360         AST_Seq.DEFMETHOD("_do_print", function(output) {
18361             this.car.print(output);
18362             if (this.cdr) {
18363                 output.comma();
18364                 if (output.should_break()) {
18365                     output.newline();
18366                     output.indent();
18367                 }
18368                 this.cdr.print(output);
18369             }
18370         });
18371         DEFPRINT(AST_Seq, function(self, output) {
18372             self._do_print(output);
18373         });
18374         DEFPRINT(AST_Dot, function(self, output) {
18375             var expr = self.expression;
18376             expr.print(output);
18377             if (expr instanceof AST_Number && expr.getValue() >= 0) {
18378                 if (!/[xa-f.]/i.test(output.last())) {
18379                     output.print(".");
18380                 }
18381             }
18382             output.print(".");
18383             output.add_mapping(self.end);
18384             output.print_name(self.property);
18385         });
18386         DEFPRINT(AST_Sub, function(self, output) {
18387             self.expression.print(output);
18388             output.print("[");
18389             self.property.print(output);
18390             output.print("]");
18391         });
18392         DEFPRINT(AST_UnaryPrefix, function(self, output) {
18393             var op = self.operator;
18394             output.print(op);
18395             if (/^[a-z]/i.test(op)) output.space();
18396             self.expression.print(output);
18397         });
18398         DEFPRINT(AST_UnaryPostfix, function(self, output) {
18399             self.expression.print(output);
18400             output.print(self.operator);
18401         });
18402         DEFPRINT(AST_Binary, function(self, output) {
18403             self.left.print(output);
18404             output.space();
18405             output.print(self.operator);
18406             output.space();
18407             self.right.print(output);
18408         });
18409         DEFPRINT(AST_Conditional, function(self, output) {
18410             self.condition.print(output);
18411             output.space();
18412             output.print("?");
18413             output.space();
18414             self.consequent.print(output);
18415             output.space();
18416             output.colon();
18417             self.alternative.print(output);
18418         });
18419         DEFPRINT(AST_Array, function(self, output) {
18420             output.with_square(function() {
18421                 var a = self.elements, len = a.length;
18422                 if (len > 0) output.space();
18423                 a.forEach(function(exp, i) {
18424                     if (i) output.comma();
18425                     exp.print(output);
18426                 });
18427                 if (len > 0) output.space();
18428             });
18429         });
18430         DEFPRINT(AST_Object, function(self, output) {
18431             if (self.properties.length > 0) output.with_block(function() {
18432                 self.properties.forEach(function(prop, i) {
18433                     if (i) {
18434                         output.print(",");
18435                         output.newline();
18436                     }
18437                     output.indent();
18438                     prop.print(output);
18439                 });
18440                 output.newline();
18441             }); else output.print("{}");
18442         });
18443         DEFPRINT(AST_ObjectKeyVal, function(self, output) {
18444             var key = self.key;
18445             if (output.option("quote_keys")) {
18446                 output.print_string(key + "");
18447             } else if ((typeof key == "number" || !output.option("beautify") && +key + "" == key) && parseFloat(key) >= 0) {
18448                 output.print(make_num(key));
18449             } else if (!is_identifier(key)) {
18450                 output.print_string(key);
18451             } else {
18452                 output.print_name(key);
18453             }
18454             output.colon();
18455             self.value.print(output);
18456         });
18457         DEFPRINT(AST_ObjectSetter, function(self, output) {
18458             output.print("set");
18459             self.value._do_print(output, true);
18460         });
18461         DEFPRINT(AST_ObjectGetter, function(self, output) {
18462             output.print("get");
18463             self.value._do_print(output, true);
18464         });
18465         DEFPRINT(AST_Symbol, function(self, output) {
18466             var def = self.definition();
18467             output.print_name(def ? def.mangled_name || def.name : self.name);
18468         });
18469         DEFPRINT(AST_Undefined, function(self, output) {
18470             output.print("void 0");
18471         });
18472         DEFPRINT(AST_Hole, noop);
18473         DEFPRINT(AST_Infinity, function(self, output) {
18474             output.print("1/0");
18475         });
18476         DEFPRINT(AST_NaN, function(self, output) {
18477             output.print("0/0");
18478         });
18479         DEFPRINT(AST_This, function(self, output) {
18480             output.print("this");
18481         });
18482         DEFPRINT(AST_Constant, function(self, output) {
18483             output.print(self.getValue());
18484         });
18485         DEFPRINT(AST_String, function(self, output) {
18486             output.print_string(self.getValue());
18487         });
18488         DEFPRINT(AST_Number, function(self, output) {
18489             output.print(make_num(self.getValue()));
18490         });
18491         DEFPRINT(AST_RegExp, function(self, output) {
18492             var str = self.getValue().toString();
18493             if (output.option("ascii_only")) str = output.to_ascii(str);
18494             output.print(str);
18495             var p = output.parent();
18496             if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) output.print(" ");
18497         });
18498         function force_statement(stat, output) {
18499             if (output.option("bracketize")) {
18500                 if (!stat || stat instanceof AST_EmptyStatement) output.print("{}"); else if (stat instanceof AST_BlockStatement) stat.print(output); else output.with_block(function() {
18501                     output.indent();
18502                     stat.print(output);
18503                     output.newline();
18504                 });
18505             } else {
18506                 if (!stat || stat instanceof AST_EmptyStatement) output.force_semicolon(); else stat.print(output);
18507             }
18508         }
18509         function first_in_statement(output) {
18510             var a = output.stack(), i = a.length, node = a[--i], p = a[--i];
18511             while (i > 0) {
18512                 if (p instanceof AST_Statement && p.body === node) return true;
18513                 if (p instanceof AST_Seq && p.car === node || p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) || p instanceof AST_Dot && p.expression === node || p instanceof AST_Sub && p.expression === node || p instanceof AST_Conditional && p.condition === node || p instanceof AST_Binary && p.left === node || p instanceof AST_UnaryPostfix && p.expression === node) {
18514                     node = p;
18515                     p = a[--i];
18516                 } else {
18517                     return false;
18518                 }
18519             }
18520         }
18521         function no_constructor_parens(self, output) {
18522             return self.args.length == 0 && !output.option("beautify");
18523         }
18524         function best_of(a) {
18525             var best = a[0], len = best.length;
18526             for (var i = 1; i < a.length; ++i) {
18527                 if (a[i].length < len) {
18528                     best = a[i];
18529                     len = best.length;
18530                 }
18531             }
18532             return best;
18533         }
18534         function make_num(num) {
18535             var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace("e+", "e") ], m;
18536             if (Math.floor(num) === num) {
18537                 if (num >= 0) {
18538                     a.push("0x" + num.toString(16).toLowerCase(), "0" + num.toString(8));
18539                 } else {
18540                     a.push("-0x" + (-num).toString(16).toLowerCase(), "-0" + (-num).toString(8));
18541                 }
18542                 if (m = /^(.*?)(0+)$/.exec(num)) {
18543                     a.push(m[1] + "e" + m[2].length);
18544                 }
18545             } else if (m = /^0?\.(0+)(.*)$/.exec(num)) {
18546                 a.push(m[2] + "e-" + (m[1].length + m[2].length), str.substr(str.indexOf(".")));
18547             }
18548             return best_of(a);
18549         }
18550         function make_block(stmt, output) {
18551             if (stmt instanceof AST_BlockStatement) {
18552                 stmt.print(output);
18553                 return;
18554             }
18555             output.with_block(function() {
18556                 output.indent();
18557                 stmt.print(output);
18558                 output.newline();
18559             });
18560         }
18561         function DEFMAP(nodetype, generator) {
18562             nodetype.DEFMETHOD("add_source_map", function(stream) {
18563                 generator(this, stream);
18564             });
18565         }
18566         DEFMAP(AST_Node, noop);
18567         function basic_sourcemap_gen(self, output) {
18568             output.add_mapping(self.start);
18569         }
18570         DEFMAP(AST_Directive, basic_sourcemap_gen);
18571         DEFMAP(AST_Debugger, basic_sourcemap_gen);
18572         DEFMAP(AST_Symbol, basic_sourcemap_gen);
18573         DEFMAP(AST_Jump, basic_sourcemap_gen);
18574         DEFMAP(AST_StatementWithBody, basic_sourcemap_gen);
18575         DEFMAP(AST_LabeledStatement, noop);
18576         DEFMAP(AST_Lambda, basic_sourcemap_gen);
18577         DEFMAP(AST_Switch, basic_sourcemap_gen);
18578         DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);
18579         DEFMAP(AST_BlockStatement, basic_sourcemap_gen);
18580         DEFMAP(AST_Toplevel, noop);
18581         DEFMAP(AST_New, basic_sourcemap_gen);
18582         DEFMAP(AST_Try, basic_sourcemap_gen);
18583         DEFMAP(AST_Catch, basic_sourcemap_gen);
18584         DEFMAP(AST_Finally, basic_sourcemap_gen);
18585         DEFMAP(AST_Definitions, basic_sourcemap_gen);
18586         DEFMAP(AST_Constant, basic_sourcemap_gen);
18587         DEFMAP(AST_ObjectProperty, function(self, output) {
18588             output.add_mapping(self.start, self.key);
18589         });
18590     })();
18591     "use strict";
18592     function Compressor(options, false_by_default) {
18593         if (!(this instanceof Compressor)) return new Compressor(options, false_by_default);
18594         TreeTransformer.call(this, this.before, this.after);
18595         this.options = defaults(options, {
18596             sequences: !false_by_default,
18597             properties: !false_by_default,
18598             dead_code: !false_by_default,
18599             drop_debugger: !false_by_default,
18600             unsafe: false,
18601             unsafe_comps: false,
18602             conditionals: !false_by_default,
18603             comparisons: !false_by_default,
18604             evaluate: !false_by_default,
18605             booleans: !false_by_default,
18606             loops: !false_by_default,
18607             unused: !false_by_default,
18608             hoist_funs: !false_by_default,
18609             hoist_vars: false,
18610             if_return: !false_by_default,
18611             join_vars: !false_by_default,
18612             cascade: !false_by_default,
18613             side_effects: !false_by_default,
18614             screw_ie8: false,
18615             warnings: true,
18616             global_defs: {}
18617         }, true);
18618     }
18619     Compressor.prototype = new TreeTransformer();
18620     merge(Compressor.prototype, {
18621         option: function(key) {
18622             return this.options[key];
18623         },
18624         warn: function() {
18625             if (this.options.warnings) AST_Node.warn.apply(AST_Node, arguments);
18626         },
18627         before: function(node, descend, in_list) {
18628             if (node._squeezed) return node;
18629             if (node instanceof AST_Scope) {
18630                 node.drop_unused(this);
18631                 node = node.hoist_declarations(this);
18632             }
18633             descend(node, this);
18634             node = node.optimize(this);
18635             if (node instanceof AST_Scope) {
18636                 var save_warnings = this.options.warnings;
18637                 this.options.warnings = false;
18638                 node.drop_unused(this);
18639                 this.options.warnings = save_warnings;
18640             }
18641             node._squeezed = true;
18642             return node;
18643         }
18644     });
18645     (function() {
18646         function OPT(node, optimizer) {
18647             node.DEFMETHOD("optimize", function(compressor) {
18648                 var self = this;
18649                 if (self._optimized) return self;
18650                 var opt = optimizer(self, compressor);
18651                 opt._optimized = true;
18652                 if (opt === self) return opt;
18653                 return opt.transform(compressor);
18654             });
18655         }
18656         OPT(AST_Node, function(self, compressor) {
18657             return self;
18658         });
18659         AST_Node.DEFMETHOD("equivalent_to", function(node) {
18660             return this.print_to_string() == node.print_to_string();
18661         });
18662         function make_node(ctor, orig, props) {
18663             if (!props) props = {};
18664             if (orig) {
18665                 if (!props.start) props.start = orig.start;
18666                 if (!props.end) props.end = orig.end;
18667             }
18668             return new ctor(props);
18669         }
18670         function make_node_from_constant(compressor, val, orig) {
18671             if (val instanceof AST_Node) return val.transform(compressor);
18672             switch (typeof val) {
18673               case "string":
18674                 return make_node(AST_String, orig, {
18675                     value: val
18676                 }).optimize(compressor);
18678               case "number":
18679                 return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, {
18680                     value: val
18681                 }).optimize(compressor);
18683               case "boolean":
18684                 return make_node(val ? AST_True : AST_False, orig).optimize(compressor);
18686               case "undefined":
18687                 return make_node(AST_Undefined, orig).optimize(compressor);
18689               default:
18690                 if (val === null) {
18691                     return make_node(AST_Null, orig).optimize(compressor);
18692                 }
18693                 if (val instanceof RegExp) {
18694                     return make_node(AST_RegExp, orig).optimize(compressor);
18695                 }
18696                 throw new Error(string_template("Can't handle constant of type: {type}", {
18697                     type: typeof val
18698                 }));
18699             }
18700         }
18701         function as_statement_array(thing) {
18702             if (thing === null) return [];
18703             if (thing instanceof AST_BlockStatement) return thing.body;
18704             if (thing instanceof AST_EmptyStatement) return [];
18705             if (thing instanceof AST_Statement) return [ thing ];
18706             throw new Error("Can't convert thing to statement array");
18707         }
18708         function is_empty(thing) {
18709             if (thing === null) return true;
18710             if (thing instanceof AST_EmptyStatement) return true;
18711             if (thing instanceof AST_BlockStatement) return thing.body.length == 0;
18712             return false;
18713         }
18714         function loop_body(x) {
18715             if (x instanceof AST_Switch) return x;
18716             if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
18717                 return x.body instanceof AST_BlockStatement ? x.body : x;
18718             }
18719             return x;
18720         }
18721         function tighten_body(statements, compressor) {
18722             var CHANGED;
18723             do {
18724                 CHANGED = false;
18725                 statements = eliminate_spurious_blocks(statements);
18726                 if (compressor.option("dead_code")) {
18727                     statements = eliminate_dead_code(statements, compressor);
18728                 }
18729                 if (compressor.option("if_return")) {
18730                     statements = handle_if_return(statements, compressor);
18731                 }
18732                 if (compressor.option("sequences")) {
18733                     statements = sequencesize(statements, compressor);
18734                 }
18735                 if (compressor.option("join_vars")) {
18736                     statements = join_consecutive_vars(statements, compressor);
18737                 }
18738             } while (CHANGED);
18739             return statements;
18740             function eliminate_spurious_blocks(statements) {
18741                 var seen_dirs = [];
18742                 return statements.reduce(function(a, stat) {
18743                     if (stat instanceof AST_BlockStatement) {
18744                         CHANGED = true;
18745                         a.push.apply(a, eliminate_spurious_blocks(stat.body));
18746                     } else if (stat instanceof AST_EmptyStatement) {
18747                         CHANGED = true;
18748                     } else if (stat instanceof AST_Directive) {
18749                         if (seen_dirs.indexOf(stat.value) < 0) {
18750                             a.push(stat);
18751                             seen_dirs.push(stat.value);
18752                         } else {
18753                             CHANGED = true;
18754                         }
18755                     } else {
18756                         a.push(stat);
18757                     }
18758                     return a;
18759                 }, []);
18760             }
18761             function handle_if_return(statements, compressor) {
18762                 var self = compressor.self();
18763                 var in_lambda = self instanceof AST_Lambda;
18764                 var ret = [];
18765                 loop: for (var i = statements.length; --i >= 0; ) {
18766                     var stat = statements[i];
18767                     switch (true) {
18768                       case in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0:
18769                         CHANGED = true;
18770                         continue loop;
18772                       case stat instanceof AST_If:
18773                         if (stat.body instanceof AST_Return) {
18774                             if ((in_lambda && ret.length == 0 || ret[0] instanceof AST_Return && !ret[0].value) && !stat.body.value && !stat.alternative) {
18775                                 CHANGED = true;
18776                                 var cond = make_node(AST_SimpleStatement, stat.condition, {
18777                                     body: stat.condition
18778                                 });
18779                                 ret.unshift(cond);
18780                                 continue loop;
18781                             }
18782                             if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) {
18783                                 CHANGED = true;
18784                                 stat = stat.clone();
18785                                 stat.alternative = ret[0];
18786                                 ret[0] = stat.transform(compressor);
18787                                 continue loop;
18788                             }
18789                             if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) {
18790                                 CHANGED = true;
18791                                 stat = stat.clone();
18792                                 stat.alternative = ret[0] || make_node(AST_Return, stat, {
18793                                     value: make_node(AST_Undefined, stat)
18794                                 });
18795                                 ret[0] = stat.transform(compressor);
18796                                 continue loop;
18797                             }
18798                             if (!stat.body.value && in_lambda) {
18799                                 CHANGED = true;
18800                                 stat = stat.clone();
18801                                 stat.condition = stat.condition.negate(compressor);
18802                                 stat.body = make_node(AST_BlockStatement, stat, {
18803                                     body: as_statement_array(stat.alternative).concat(ret)
18804                                 });
18805                                 stat.alternative = null;
18806                                 ret = [ stat.transform(compressor) ];
18807                                 continue loop;
18808                             }
18809                             if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) {
18810                                 CHANGED = true;
18811                                 ret.push(make_node(AST_Return, ret[0], {
18812                                     value: make_node(AST_Undefined, ret[0])
18813                                 }).transform(compressor));
18814                                 ret = as_statement_array(stat.alternative).concat(ret);
18815                                 ret.unshift(stat);
18816                                 continue loop;
18817                             }
18818                         }
18819                         var ab = aborts(stat.body);
18820                         var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
18821                         if (ab && (ab instanceof AST_Return && !ab.value && in_lambda || ab instanceof AST_Continue && self === loop_body(lct) || ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct)) {
18822                             if (ab.label) {
18823                                 remove(ab.label.thedef.references, ab.label);
18824                             }
18825                             CHANGED = true;
18826                             var body = as_statement_array(stat.body).slice(0, -1);
18827                             stat = stat.clone();
18828                             stat.condition = stat.condition.negate(compressor);
18829                             stat.body = make_node(AST_BlockStatement, stat, {
18830                                 body: ret
18831                             });
18832                             stat.alternative = make_node(AST_BlockStatement, stat, {
18833                                 body: body
18834                             });
18835                             ret = [ stat.transform(compressor) ];
18836                             continue loop;
18837                         }
18838                         var ab = aborts(stat.alternative);
18839                         var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
18840                         if (ab && (ab instanceof AST_Return && !ab.value && in_lambda || ab instanceof AST_Continue && self === loop_body(lct) || ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct)) {
18841                             if (ab.label) {
18842                                 remove(ab.label.thedef.references, ab.label);
18843                             }
18844                             CHANGED = true;
18845                             stat = stat.clone();
18846                             stat.body = make_node(AST_BlockStatement, stat.body, {
18847                                 body: as_statement_array(stat.body).concat(ret)
18848                             });
18849                             stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
18850                                 body: as_statement_array(stat.alternative).slice(0, -1)
18851                             });
18852                             ret = [ stat.transform(compressor) ];
18853                             continue loop;
18854                         }
18855                         ret.unshift(stat);
18856                         break;
18858                       default:
18859                         ret.unshift(stat);
18860                         break;
18861                     }
18862                 }
18863                 return ret;
18864             }
18865             function eliminate_dead_code(statements, compressor) {
18866                 var has_quit = false;
18867                 var orig = statements.length;
18868                 var self = compressor.self();
18869                 statements = statements.reduce(function(a, stat) {
18870                     if (has_quit) {
18871                         extract_declarations_from_unreachable_code(compressor, stat, a);
18872                     } else {
18873                         if (stat instanceof AST_LoopControl) {
18874                             var lct = compressor.loopcontrol_target(stat.label);
18875                             if (stat instanceof AST_Break && lct instanceof AST_BlockStatement && loop_body(lct) === self || stat instanceof AST_Continue && loop_body(lct) === self) {
18876                                 if (stat.label) {
18877                                     remove(stat.label.thedef.references, stat.label);
18878                                 }
18879                             } else {
18880                                 a.push(stat);
18881                             }
18882                         } else {
18883                             a.push(stat);
18884                         }
18885                         if (aborts(stat)) has_quit = true;
18886                     }
18887                     return a;
18888                 }, []);
18889                 CHANGED = statements.length != orig;
18890                 return statements;
18891             }
18892             function sequencesize(statements, compressor) {
18893                 if (statements.length < 2) return statements;
18894                 var seq = [], ret = [];
18895                 function push_seq() {
18896                     seq = AST_Seq.from_array(seq);
18897                     if (seq) ret.push(make_node(AST_SimpleStatement, seq, {
18898                         body: seq
18899                     }));
18900                     seq = [];
18901                 }
18902                 statements.forEach(function(stat) {
18903                     if (stat instanceof AST_SimpleStatement) seq.push(stat.body); else push_seq(), ret.push(stat);
18904                 });
18905                 push_seq();
18906                 ret = sequencesize_2(ret, compressor);
18907                 CHANGED = ret.length != statements.length;
18908                 return ret;
18909             }
18910             function sequencesize_2(statements, compressor) {
18911                 function cons_seq(right) {
18912                     ret.pop();
18913                     var left = prev.body;
18914                     if (left instanceof AST_Seq) {
18915                         left.add(right);
18916                     } else {
18917                         left = AST_Seq.cons(left, right);
18918                     }
18919                     return left.transform(compressor);
18920                 }
18921                 var ret = [], prev = null;
18922                 statements.forEach(function(stat) {
18923                     if (prev) {
18924                         if (stat instanceof AST_For) {
18925                             var opera = {};
18926                             try {
18927                                 prev.body.walk(new TreeWalker(function(node) {
18928                                     if (node instanceof AST_Binary && node.operator == "in") throw opera;
18929                                 }));
18930                                 if (stat.init && !(stat.init instanceof AST_Definitions)) {
18931                                     stat.init = cons_seq(stat.init);
18932                                 } else if (!stat.init) {
18933                                     stat.init = prev.body;
18934                                     ret.pop();
18935                                 }
18936                             } catch (ex) {
18937                                 if (ex !== opera) throw ex;
18938                             }
18939                         } else if (stat instanceof AST_If) {
18940                             stat.condition = cons_seq(stat.condition);
18941                         } else if (stat instanceof AST_With) {
18942                             stat.expression = cons_seq(stat.expression);
18943                         } else if (stat instanceof AST_Exit && stat.value) {
18944                             stat.value = cons_seq(stat.value);
18945                         } else if (stat instanceof AST_Exit) {
18946                             stat.value = cons_seq(make_node(AST_Undefined, stat));
18947                         } else if (stat instanceof AST_Switch) {
18948                             stat.expression = cons_seq(stat.expression);
18949                         }
18950                     }
18951                     ret.push(stat);
18952                     prev = stat instanceof AST_SimpleStatement ? stat : null;
18953                 });
18954                 return ret;
18955             }
18956             function join_consecutive_vars(statements, compressor) {
18957                 var prev = null;
18958                 return statements.reduce(function(a, stat) {
18959                     if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) {
18960                         prev.definitions = prev.definitions.concat(stat.definitions);
18961                         CHANGED = true;
18962                     } else if (stat instanceof AST_For && prev instanceof AST_Definitions && (!stat.init || stat.init.TYPE == prev.TYPE)) {
18963                         CHANGED = true;
18964                         a.pop();
18965                         if (stat.init) {
18966                             stat.init.definitions = prev.definitions.concat(stat.init.definitions);
18967                         } else {
18968                             stat.init = prev;
18969                         }
18970                         a.push(stat);
18971                         prev = stat;
18972                     } else {
18973                         prev = stat;
18974                         a.push(stat);
18975                     }
18976                     return a;
18977                 }, []);
18978             }
18979         }
18980         function extract_declarations_from_unreachable_code(compressor, stat, target) {
18981             compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
18982             stat.walk(new TreeWalker(function(node) {
18983                 if (node instanceof AST_Definitions) {
18984                     compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
18985                     node.remove_initializers();
18986                     target.push(node);
18987                     return true;
18988                 }
18989                 if (node instanceof AST_Defun) {
18990                     target.push(node);
18991                     return true;
18992                 }
18993                 if (node instanceof AST_Scope) {
18994                     return true;
18995                 }
18996             }));
18997         }
18998         (function(def) {
18999             var unary_bool = [ "!", "delete" ];
19000             var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ];
19001             def(AST_Node, function() {
19002                 return false;
19003             });
19004             def(AST_UnaryPrefix, function() {
19005                 return member(this.operator, unary_bool);
19006             });
19007             def(AST_Binary, function() {
19008                 return member(this.operator, binary_bool) || (this.operator == "&&" || this.operator == "||") && this.left.is_boolean() && this.right.is_boolean();
19009             });
19010             def(AST_Conditional, function() {
19011                 return this.consequent.is_boolean() && this.alternative.is_boolean();
19012             });
19013             def(AST_Assign, function() {
19014                 return this.operator == "=" && this.right.is_boolean();
19015             });
19016             def(AST_Seq, function() {
19017                 return this.cdr.is_boolean();
19018             });
19019             def(AST_True, function() {
19020                 return true;
19021             });
19022             def(AST_False, function() {
19023                 return true;
19024             });
19025         })(function(node, func) {
19026             node.DEFMETHOD("is_boolean", func);
19027         });
19028         (function(def) {
19029             def(AST_Node, function() {
19030                 return false;
19031             });
19032             def(AST_String, function() {
19033                 return true;
19034             });
19035             def(AST_UnaryPrefix, function() {
19036                 return this.operator == "typeof";
19037             });
19038             def(AST_Binary, function(compressor) {
19039                 return this.operator == "+" && (this.left.is_string(compressor) || this.right.is_string(compressor));
19040             });
19041             def(AST_Assign, function(compressor) {
19042                 return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
19043             });
19044             def(AST_Seq, function(compressor) {
19045                 return this.cdr.is_string(compressor);
19046             });
19047             def(AST_Conditional, function(compressor) {
19048                 return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
19049             });
19050             def(AST_Call, function(compressor) {
19051                 return compressor.option("unsafe") && this.expression instanceof AST_SymbolRef && this.expression.name == "String" && this.expression.undeclared();
19052             });
19053         })(function(node, func) {
19054             node.DEFMETHOD("is_string", func);
19055         });
19056         function best_of(ast1, ast2) {
19057             return ast1.print_to_string().length > ast2.print_to_string().length ? ast2 : ast1;
19058         }
19059         (function(def) {
19060             AST_Node.DEFMETHOD("evaluate", function(compressor) {
19061                 if (!compressor.option("evaluate")) return [ this ];
19062                 try {
19063                     var val = this._eval(), ast = make_node_from_constant(compressor, val, this);
19064                     return [ best_of(ast, this), val ];
19065                 } catch (ex) {
19066                     if (ex !== def) throw ex;
19067                     return [ this ];
19068                 }
19069             });
19070             def(AST_Statement, function() {
19071                 throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
19072             });
19073             def(AST_Function, function() {
19074                 return [ this ];
19075             });
19076             function ev(node) {
19077                 return node._eval();
19078             }
19079             def(AST_Node, function() {
19080                 throw def;
19081             });
19082             def(AST_Constant, function() {
19083                 return this.getValue();
19084             });
19085             def(AST_UnaryPrefix, function() {
19086                 var e = this.expression;
19087                 switch (this.operator) {
19088                   case "!":
19089                     return !ev(e);
19091                   case "typeof":
19092                     if (e instanceof AST_Function) return typeof function() {};
19093                     e = ev(e);
19094                     if (e instanceof RegExp) throw def;
19095                     return typeof e;
19097                   case "void":
19098                     return void ev(e);
19100                   case "~":
19101                     return ~ev(e);
19103                   case "-":
19104                     e = ev(e);
19105                     if (e === 0) throw def;
19106                     return -e;
19108                   case "+":
19109                     return +ev(e);
19110                 }
19111                 throw def;
19112             });
19113             def(AST_Binary, function() {
19114                 var left = this.left, right = this.right;
19115                 switch (this.operator) {
19116                   case "&&":
19117                     return ev(left) && ev(right);
19119                   case "||":
19120                     return ev(left) || ev(right);
19122                   case "|":
19123                     return ev(left) | ev(right);
19125                   case "&":
19126                     return ev(left) & ev(right);
19128                   case "^":
19129                     return ev(left) ^ ev(right);
19131                   case "+":
19132                     return ev(left) + ev(right);
19134                   case "*":
19135                     return ev(left) * ev(right);
19137                   case "/":
19138                     return ev(left) / ev(right);
19140                   case "%":
19141                     return ev(left) % ev(right);
19143                   case "-":
19144                     return ev(left) - ev(right);
19146                   case "<<":
19147                     return ev(left) << ev(right);
19149                   case ">>":
19150                     return ev(left) >> ev(right);
19152                   case ">>>":
19153                     return ev(left) >>> ev(right);
19155                   case "==":
19156                     return ev(left) == ev(right);
19158                   case "===":
19159                     return ev(left) === ev(right);
19161                   case "!=":
19162                     return ev(left) != ev(right);
19164                   case "!==":
19165                     return ev(left) !== ev(right);
19167                   case "<":
19168                     return ev(left) < ev(right);
19170                   case "<=":
19171                     return ev(left) <= ev(right);
19173                   case ">":
19174                     return ev(left) > ev(right);
19176                   case ">=":
19177                     return ev(left) >= ev(right);
19179                   case "in":
19180                     return ev(left) in ev(right);
19182                   case "instanceof":
19183                     return ev(left) instanceof ev(right);
19184                 }
19185                 throw def;
19186             });
19187             def(AST_Conditional, function() {
19188                 return ev(this.condition) ? ev(this.consequent) : ev(this.alternative);
19189             });
19190             def(AST_SymbolRef, function() {
19191                 var d = this.definition();
19192                 if (d && d.constant && d.init) return ev(d.init);
19193                 throw def;
19194             });
19195         })(function(node, func) {
19196             node.DEFMETHOD("_eval", func);
19197         });
19198         (function(def) {
19199             function basic_negation(exp) {
19200                 return make_node(AST_UnaryPrefix, exp, {
19201                     operator: "!",
19202                     expression: exp
19203                 });
19204             }
19205             def(AST_Node, function() {
19206                 return basic_negation(this);
19207             });
19208             def(AST_Statement, function() {
19209                 throw new Error("Cannot negate a statement");
19210             });
19211             def(AST_Function, function() {
19212                 return basic_negation(this);
19213             });
19214             def(AST_UnaryPrefix, function() {
19215                 if (this.operator == "!") return this.expression;
19216                 return basic_negation(this);
19217             });
19218             def(AST_Seq, function(compressor) {
19219                 var self = this.clone();
19220                 self.cdr = self.cdr.negate(compressor);
19221                 return self;
19222             });
19223             def(AST_Conditional, function(compressor) {
19224                 var self = this.clone();
19225                 self.consequent = self.consequent.negate(compressor);
19226                 self.alternative = self.alternative.negate(compressor);
19227                 return best_of(basic_negation(this), self);
19228             });
19229             def(AST_Binary, function(compressor) {
19230                 var self = this.clone(), op = this.operator;
19231                 if (compressor.option("unsafe_comps")) {
19232                     switch (op) {
19233                       case "<=":
19234                         self.operator = ">";
19235                         return self;
19237                       case "<":
19238                         self.operator = ">=";
19239                         return self;
19241                       case ">=":
19242                         self.operator = "<";
19243                         return self;
19245                       case ">":
19246                         self.operator = "<=";
19247                         return self;
19248                     }
19249                 }
19250                 switch (op) {
19251                   case "==":
19252                     self.operator = "!=";
19253                     return self;
19255                   case "!=":
19256                     self.operator = "==";
19257                     return self;
19259                   case "===":
19260                     self.operator = "!==";
19261                     return self;
19263                   case "!==":
19264                     self.operator = "===";
19265                     return self;
19267                   case "&&":
19268                     self.operator = "||";
19269                     self.left = self.left.negate(compressor);
19270                     self.right = self.right.negate(compressor);
19271                     return best_of(basic_negation(this), self);
19273                   case "||":
19274                     self.operator = "&&";
19275                     self.left = self.left.negate(compressor);
19276                     self.right = self.right.negate(compressor);
19277                     return best_of(basic_negation(this), self);
19278                 }
19279                 return basic_negation(this);
19280             });
19281         })(function(node, func) {
19282             node.DEFMETHOD("negate", function(compressor) {
19283                 return func.call(this, compressor);
19284             });
19285         });
19286         (function(def) {
19287             def(AST_Node, function() {
19288                 return true;
19289             });
19290             def(AST_EmptyStatement, function() {
19291                 return false;
19292             });
19293             def(AST_Constant, function() {
19294                 return false;
19295             });
19296             def(AST_This, function() {
19297                 return false;
19298             });
19299             def(AST_Block, function() {
19300                 for (var i = this.body.length; --i >= 0; ) {
19301                     if (this.body[i].has_side_effects()) return true;
19302                 }
19303                 return false;
19304             });
19305             def(AST_SimpleStatement, function() {
19306                 return this.body.has_side_effects();
19307             });
19308             def(AST_Defun, function() {
19309                 return true;
19310             });
19311             def(AST_Function, function() {
19312                 return false;
19313             });
19314             def(AST_Binary, function() {
19315                 return this.left.has_side_effects() || this.right.has_side_effects();
19316             });
19317             def(AST_Assign, function() {
19318                 return true;
19319             });
19320             def(AST_Conditional, function() {
19321                 return this.condition.has_side_effects() || this.consequent.has_side_effects() || this.alternative.has_side_effects();
19322             });
19323             def(AST_Unary, function() {
19324                 return this.operator == "delete" || this.operator == "++" || this.operator == "--" || this.expression.has_side_effects();
19325             });
19326             def(AST_SymbolRef, function() {
19327                 return false;
19328             });
19329             def(AST_Object, function() {
19330                 for (var i = this.properties.length; --i >= 0; ) if (this.properties[i].has_side_effects()) return true;
19331                 return false;
19332             });
19333             def(AST_ObjectProperty, function() {
19334                 return this.value.has_side_effects();
19335             });
19336             def(AST_Array, function() {
19337                 for (var i = this.elements.length; --i >= 0; ) if (this.elements[i].has_side_effects()) return true;
19338                 return false;
19339             });
19340             def(AST_PropAccess, function() {
19341                 return true;
19342             });
19343             def(AST_Seq, function() {
19344                 return this.car.has_side_effects() || this.cdr.has_side_effects();
19345             });
19346         })(function(node, func) {
19347             node.DEFMETHOD("has_side_effects", func);
19348         });
19349         function aborts(thing) {
19350             return thing && thing.aborts();
19351         }
19352         (function(def) {
19353             def(AST_Statement, function() {
19354                 return null;
19355             });
19356             def(AST_Jump, function() {
19357                 return this;
19358             });
19359             function block_aborts() {
19360                 var n = this.body.length;
19361                 return n > 0 && aborts(this.body[n - 1]);
19362             }
19363             def(AST_BlockStatement, block_aborts);
19364             def(AST_SwitchBranch, block_aborts);
19365             def(AST_If, function() {
19366                 return this.alternative && aborts(this.body) && aborts(this.alternative);
19367             });
19368         })(function(node, func) {
19369             node.DEFMETHOD("aborts", func);
19370         });
19371         OPT(AST_Directive, function(self, compressor) {
19372             if (self.scope.has_directive(self.value) !== self.scope) {
19373                 return make_node(AST_EmptyStatement, self);
19374             }
19375             return self;
19376         });
19377         OPT(AST_Debugger, function(self, compressor) {
19378             if (compressor.option("drop_debugger")) return make_node(AST_EmptyStatement, self);
19379             return self;
19380         });
19381         OPT(AST_LabeledStatement, function(self, compressor) {
19382             if (self.body instanceof AST_Break && compressor.loopcontrol_target(self.body.label) === self.body) {
19383                 return make_node(AST_EmptyStatement, self);
19384             }
19385             return self.label.references.length == 0 ? self.body : self;
19386         });
19387         OPT(AST_Block, function(self, compressor) {
19388             self.body = tighten_body(self.body, compressor);
19389             return self;
19390         });
19391         OPT(AST_BlockStatement, function(self, compressor) {
19392             self.body = tighten_body(self.body, compressor);
19393             switch (self.body.length) {
19394               case 1:
19395                 return self.body[0];
19397               case 0:
19398                 return make_node(AST_EmptyStatement, self);
19399             }
19400             return self;
19401         });
19402         AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
19403             var self = this;
19404             if (compressor.option("unused") && !(self instanceof AST_Toplevel) && !self.uses_eval) {
19405                 var in_use = [];
19406                 var initializations = new Dictionary();
19407                 var scope = this;
19408                 var tw = new TreeWalker(function(node, descend) {
19409                     if (node !== self) {
19410                         if (node instanceof AST_Defun) {
19411                             initializations.add(node.name.name, node);
19412                             return true;
19413                         }
19414                         if (node instanceof AST_Definitions && scope === self) {
19415                             node.definitions.forEach(function(def) {
19416                                 if (def.value) {
19417                                     initializations.add(def.name.name, def.value);
19418                                     if (def.value.has_side_effects()) {
19419                                         def.value.walk(tw);
19420                                     }
19421                                 }
19422                             });
19423                             return true;
19424                         }
19425                         if (node instanceof AST_SymbolRef) {
19426                             push_uniq(in_use, node.definition());
19427                             return true;
19428                         }
19429                         if (node instanceof AST_Scope) {
19430                             var save_scope = scope;
19431                             scope = node;
19432                             descend();
19433                             scope = save_scope;
19434                             return true;
19435                         }
19436                     }
19437                 });
19438                 self.walk(tw);
19439                 for (var i = 0; i < in_use.length; ++i) {
19440                     in_use[i].orig.forEach(function(decl) {
19441                         var init = initializations.get(decl.name);
19442                         if (init) init.forEach(function(init) {
19443                             var tw = new TreeWalker(function(node) {
19444                                 if (node instanceof AST_SymbolRef) {
19445                                     push_uniq(in_use, node.definition());
19446                                 }
19447                             });
19448                             init.walk(tw);
19449                         });
19450                     });
19451                 }
19452                 var tt = new TreeTransformer(function before(node, descend, in_list) {
19453                     if (node instanceof AST_Lambda) {
19454                         for (var a = node.argnames, i = a.length; --i >= 0; ) {
19455                             var sym = a[i];
19456                             if (sym.unreferenced()) {
19457                                 a.pop();
19458                                 compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {
19459                                     name: sym.name,
19460                                     file: sym.start.file,
19461                                     line: sym.start.line,
19462                                     col: sym.start.col
19463                                 });
19464                             } else break;
19465                         }
19466                     }
19467                     if (node instanceof AST_Defun && node !== self) {
19468                         if (!member(node.name.definition(), in_use)) {
19469                             compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", {
19470                                 name: node.name.name,
19471                                 file: node.name.start.file,
19472                                 line: node.name.start.line,
19473                                 col: node.name.start.col
19474                             });
19475                             return make_node(AST_EmptyStatement, node);
19476                         }
19477                         return node;
19478                     }
19479                     if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
19480                         var def = node.definitions.filter(function(def) {
19481                             if (member(def.name.definition(), in_use)) return true;
19482                             var w = {
19483                                 name: def.name.name,
19484                                 file: def.name.start.file,
19485                                 line: def.name.start.line,
19486                                 col: def.name.start.col
19487                             };
19488                             if (def.value && def.value.has_side_effects()) {
19489                                 def._unused_side_effects = true;
19490                                 compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w);
19491                                 return true;
19492                             }
19493                             compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w);
19494                             return false;
19495                         });
19496                         def = mergeSort(def, function(a, b) {
19497                             if (!a.value && b.value) return -1;
19498                             if (!b.value && a.value) return 1;
19499                             return 0;
19500                         });
19501                         var side_effects = [];
19502                         for (var i = 0; i < def.length; ) {
19503                             var x = def[i];
19504                             if (x._unused_side_effects) {
19505                                 side_effects.push(x.value);
19506                                 def.splice(i, 1);
19507                             } else {
19508                                 if (side_effects.length > 0) {
19509                                     side_effects.push(x.value);
19510                                     x.value = AST_Seq.from_array(side_effects);
19511                                     side_effects = [];
19512                                 }
19513                                 ++i;
19514                             }
19515                         }
19516                         if (side_effects.length > 0) {
19517                             side_effects = make_node(AST_BlockStatement, node, {
19518                                 body: [ make_node(AST_SimpleStatement, node, {
19519                                     body: AST_Seq.from_array(side_effects)
19520                                 }) ]
19521                             });
19522                         } else {
19523                             side_effects = null;
19524                         }
19525                         if (def.length == 0 && !side_effects) {
19526                             return make_node(AST_EmptyStatement, node);
19527                         }
19528                         if (def.length == 0) {
19529                             return side_effects;
19530                         }
19531                         node.definitions = def;
19532                         if (side_effects) {
19533                             side_effects.body.unshift(node);
19534                             node = side_effects;
19535                         }
19536                         return node;
19537                     }
19538                     if (node instanceof AST_For && node.init instanceof AST_BlockStatement) {
19539                         descend(node, this);
19540                         var body = node.init.body.slice(0, -1);
19541                         node.init = node.init.body.slice(-1)[0].body;
19542                         body.push(node);
19543                         return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, {
19544                             body: body
19545                         });
19546                     }
19547                     if (node instanceof AST_Scope && node !== self) return node;
19548                 });
19549                 self.transform(tt);
19550             }
19551         });
19552         AST_Scope.DEFMETHOD("hoist_declarations", function(compressor) {
19553             var hoist_funs = compressor.option("hoist_funs");
19554             var hoist_vars = compressor.option("hoist_vars");
19555             var self = this;
19556             if (hoist_funs || hoist_vars) {
19557                 var dirs = [];
19558                 var hoisted = [];
19559                 var vars = new Dictionary(), vars_found = 0, var_decl = 0;
19560                 self.walk(new TreeWalker(function(node) {
19561                     if (node instanceof AST_Scope && node !== self) return true;
19562                     if (node instanceof AST_Var) {
19563                         ++var_decl;
19564                         return true;
19565                     }
19566                 }));
19567                 hoist_vars = hoist_vars && var_decl > 1;
19568                 var tt = new TreeTransformer(function before(node) {
19569                     if (node !== self) {
19570                         if (node instanceof AST_Directive) {
19571                             dirs.push(node);
19572                             return make_node(AST_EmptyStatement, node);
19573                         }
19574                         if (node instanceof AST_Defun && hoist_funs) {
19575                             hoisted.push(node);
19576                             return make_node(AST_EmptyStatement, node);
19577                         }
19578                         if (node instanceof AST_Var && hoist_vars) {
19579                             node.definitions.forEach(function(def) {
19580                                 vars.set(def.name.name, def);
19581                                 ++vars_found;
19582                             });
19583                             var seq = node.to_assignments();
19584                             var p = tt.parent();
19585                             if (p instanceof AST_ForIn && p.init === node) {
19586                                 if (seq == null) return node.definitions[0].name;
19587                                 return seq;
19588                             }
19589                             if (p instanceof AST_For && p.init === node) {
19590                                 return seq;
19591                             }
19592                             if (!seq) return make_node(AST_EmptyStatement, node);
19593                             return make_node(AST_SimpleStatement, node, {
19594                                 body: seq
19595                             });
19596                         }
19597                         if (node instanceof AST_Scope) return node;
19598                     }
19599                 });
19600                 self = self.transform(tt);
19601                 if (vars_found > 0) {
19602                     var defs = [];
19603                     vars.each(function(def, name) {
19604                         if (self instanceof AST_Lambda && find_if(function(x) {
19605                             return x.name == def.name.name;
19606                         }, self.argnames)) {
19607                             vars.del(name);
19608                         } else {
19609                             def = def.clone();
19610                             def.value = null;
19611                             defs.push(def);
19612                             vars.set(name, def);
19613                         }
19614                     });
19615                     if (defs.length > 0) {
19616                         for (var i = 0; i < self.body.length; ) {
19617                             if (self.body[i] instanceof AST_SimpleStatement) {
19618                                 var expr = self.body[i].body, sym, assign;
19619                                 if (expr instanceof AST_Assign && expr.operator == "=" && (sym = expr.left) instanceof AST_Symbol && vars.has(sym.name)) {
19620                                     var def = vars.get(sym.name);
19621                                     if (def.value) break;
19622                                     def.value = expr.right;
19623                                     remove(defs, def);
19624                                     defs.push(def);
19625                                     self.body.splice(i, 1);
19626                                     continue;
19627                                 }
19628                                 if (expr instanceof AST_Seq && (assign = expr.car) instanceof AST_Assign && assign.operator == "=" && (sym = assign.left) instanceof AST_Symbol && vars.has(sym.name)) {
19629                                     var def = vars.get(sym.name);
19630                                     if (def.value) break;
19631                                     def.value = assign.right;
19632                                     remove(defs, def);
19633                                     defs.push(def);
19634                                     self.body[i].body = expr.cdr;
19635                                     continue;
19636                                 }
19637                             }
19638                             if (self.body[i] instanceof AST_EmptyStatement) {
19639                                 self.body.splice(i, 1);
19640                                 continue;
19641                             }
19642                             if (self.body[i] instanceof AST_BlockStatement) {
19643                                 var tmp = [ i, 1 ].concat(self.body[i].body);
19644                                 self.body.splice.apply(self.body, tmp);
19645                                 continue;
19646                             }
19647                             break;
19648                         }
19649                         defs = make_node(AST_Var, self, {
19650                             definitions: defs
19651                         });
19652                         hoisted.push(defs);
19653                     }
19654                 }
19655                 self.body = dirs.concat(hoisted, self.body);
19656             }
19657             return self;
19658         });
19659         OPT(AST_SimpleStatement, function(self, compressor) {
19660             if (compressor.option("side_effects")) {
19661                 if (!self.body.has_side_effects()) {
19662                     compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start);
19663                     return make_node(AST_EmptyStatement, self);
19664                 }
19665             }
19666             return self;
19667         });
19668         OPT(AST_DWLoop, function(self, compressor) {
19669             var cond = self.condition.evaluate(compressor);
19670             self.condition = cond[0];
19671             if (!compressor.option("loops")) return self;
19672             if (cond.length > 1) {
19673                 if (cond[1]) {
19674                     return make_node(AST_For, self, {
19675                         body: self.body
19676                     });
19677                 } else if (self instanceof AST_While) {
19678                     if (compressor.option("dead_code")) {
19679                         var a = [];
19680                         extract_declarations_from_unreachable_code(compressor, self.body, a);
19681                         return make_node(AST_BlockStatement, self, {
19682                             body: a
19683                         });
19684                     }
19685                 }
19686             }
19687             return self;
19688         });
19689         function if_break_in_loop(self, compressor) {
19690             function drop_it(rest) {
19691                 rest = as_statement_array(rest);
19692                 if (self.body instanceof AST_BlockStatement) {
19693                     self.body = self.body.clone();
19694                     self.body.body = rest.concat(self.body.body.slice(1));
19695                     self.body = self.body.transform(compressor);
19696                 } else {
19697                     self.body = make_node(AST_BlockStatement, self.body, {
19698                         body: rest
19699                     }).transform(compressor);
19700                 }
19701                 if_break_in_loop(self, compressor);
19702             }
19703             var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
19704             if (first instanceof AST_If) {
19705                 if (first.body instanceof AST_Break && compressor.loopcontrol_target(first.body.label) === self) {
19706                     if (self.condition) {
19707                         self.condition = make_node(AST_Binary, self.condition, {
19708                             left: self.condition,
19709                             operator: "&&",
19710                             right: first.condition.negate(compressor)
19711                         });
19712                     } else {
19713                         self.condition = first.condition.negate(compressor);
19714                     }
19715                     drop_it(first.alternative);
19716                 } else if (first.alternative instanceof AST_Break && compressor.loopcontrol_target(first.alternative.label) === self) {
19717                     if (self.condition) {
19718                         self.condition = make_node(AST_Binary, self.condition, {
19719                             left: self.condition,
19720                             operator: "&&",
19721                             right: first.condition
19722                         });
19723                     } else {
19724                         self.condition = first.condition;
19725                     }
19726                     drop_it(first.body);
19727                 }
19728             }
19729         }
19730         OPT(AST_While, function(self, compressor) {
19731             if (!compressor.option("loops")) return self;
19732             self = AST_DWLoop.prototype.optimize.call(self, compressor);
19733             if (self instanceof AST_While) {
19734                 if_break_in_loop(self, compressor);
19735                 self = make_node(AST_For, self, self).transform(compressor);
19736             }
19737             return self;
19738         });
19739         OPT(AST_For, function(self, compressor) {
19740             var cond = self.condition;
19741             if (cond) {
19742                 cond = cond.evaluate(compressor);
19743                 self.condition = cond[0];
19744             }
19745             if (!compressor.option("loops")) return self;
19746             if (cond) {
19747                 if (cond.length > 1 && !cond[1]) {
19748                     if (compressor.option("dead_code")) {
19749                         var a = [];
19750                         if (self.init instanceof AST_Statement) {
19751                             a.push(self.init);
19752                         } else if (self.init) {
19753                             a.push(make_node(AST_SimpleStatement, self.init, {
19754                                 body: self.init
19755                             }));
19756                         }
19757                         extract_declarations_from_unreachable_code(compressor, self.body, a);
19758                         return make_node(AST_BlockStatement, self, {
19759                             body: a
19760                         });
19761                     }
19762                 }
19763             }
19764             if_break_in_loop(self, compressor);
19765             return self;
19766         });
19767         OPT(AST_If, function(self, compressor) {
19768             if (!compressor.option("conditionals")) return self;
19769             var cond = self.condition.evaluate(compressor);
19770             self.condition = cond[0];
19771             if (cond.length > 1) {
19772                 if (cond[1]) {
19773                     compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
19774                     if (compressor.option("dead_code")) {
19775                         var a = [];
19776                         if (self.alternative) {
19777                             extract_declarations_from_unreachable_code(compressor, self.alternative, a);
19778                         }
19779                         a.push(self.body);
19780                         return make_node(AST_BlockStatement, self, {
19781                             body: a
19782                         }).transform(compressor);
19783                     }
19784                 } else {
19785                     compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
19786                     if (compressor.option("dead_code")) {
19787                         var a = [];
19788                         extract_declarations_from_unreachable_code(compressor, self.body, a);
19789                         if (self.alternative) a.push(self.alternative);
19790                         return make_node(AST_BlockStatement, self, {
19791                             body: a
19792                         }).transform(compressor);
19793                     }
19794                 }
19795             }
19796             if (is_empty(self.alternative)) self.alternative = null;
19797             var negated = self.condition.negate(compressor);
19798             var negated_is_best = best_of(self.condition, negated) === negated;
19799             if (self.alternative && negated_is_best) {
19800                 negated_is_best = false;
19801                 self.condition = negated;
19802                 var tmp = self.body;
19803                 self.body = self.alternative || make_node(AST_EmptyStatement);
19804                 self.alternative = tmp;
19805             }
19806             if (is_empty(self.body) && is_empty(self.alternative)) {
19807                 return make_node(AST_SimpleStatement, self.condition, {
19808                     body: self.condition
19809                 }).transform(compressor);
19810             }
19811             if (self.body instanceof AST_SimpleStatement && self.alternative instanceof AST_SimpleStatement) {
19812                 return make_node(AST_SimpleStatement, self, {
19813                     body: make_node(AST_Conditional, self, {
19814                         condition: self.condition,
19815                         consequent: self.body.body,
19816                         alternative: self.alternative.body
19817                     })
19818                 }).transform(compressor);
19819             }
19820             if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
19821                 if (negated_is_best) return make_node(AST_SimpleStatement, self, {
19822                     body: make_node(AST_Binary, self, {
19823                         operator: "||",
19824                         left: negated,
19825                         right: self.body.body
19826                     })
19827                 }).transform(compressor);
19828                 return make_node(AST_SimpleStatement, self, {
19829                     body: make_node(AST_Binary, self, {
19830                         operator: "&&",
19831                         left: self.condition,
19832                         right: self.body.body
19833                     })
19834                 }).transform(compressor);
19835             }
19836             if (self.body instanceof AST_EmptyStatement && self.alternative && self.alternative instanceof AST_SimpleStatement) {
19837                 return make_node(AST_SimpleStatement, self, {
19838                     body: make_node(AST_Binary, self, {
19839                         operator: "||",
19840                         left: self.condition,
19841                         right: self.alternative.body
19842                     })
19843                 }).transform(compressor);
19844             }
19845             if (self.body instanceof AST_Exit && self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) {
19846                 return make_node(self.body.CTOR, self, {
19847                     value: make_node(AST_Conditional, self, {
19848                         condition: self.condition,
19849                         consequent: self.body.value || make_node(AST_Undefined, self.body).optimize(compressor),
19850                         alternative: self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor)
19851                     })
19852                 }).transform(compressor);
19853             }
19854             if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) {
19855                 self.condition = make_node(AST_Binary, self.condition, {
19856                     operator: "&&",
19857                     left: self.condition,
19858                     right: self.body.condition
19859                 }).transform(compressor);
19860                 self.body = self.body.body;
19861             }
19862             if (aborts(self.body)) {
19863                 if (self.alternative) {
19864                     var alt = self.alternative;
19865                     self.alternative = null;
19866                     return make_node(AST_BlockStatement, self, {
19867                         body: [ self, alt ]
19868                     }).transform(compressor);
19869                 }
19870             }
19871             if (aborts(self.alternative)) {
19872                 var body = self.body;
19873                 self.body = self.alternative;
19874                 self.condition = negated_is_best ? negated : self.condition.negate(compressor);
19875                 self.alternative = null;
19876                 return make_node(AST_BlockStatement, self, {
19877                     body: [ self, body ]
19878                 }).transform(compressor);
19879             }
19880             return self;
19881         });
19882         OPT(AST_Switch, function(self, compressor) {
19883             if (self.body.length == 0 && compressor.option("conditionals")) {
19884                 return make_node(AST_SimpleStatement, self, {
19885                     body: self.expression
19886                 }).transform(compressor);
19887             }
19888             for (;;) {
19889                 var last_branch = self.body[self.body.length - 1];
19890                 if (last_branch) {
19891                     var stat = last_branch.body[last_branch.body.length - 1];
19892                     if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) last_branch.body.pop();
19893                     if (last_branch instanceof AST_Default && last_branch.body.length == 0) {
19894                         self.body.pop();
19895                         continue;
19896                     }
19897                 }
19898                 break;
19899             }
19900             var exp = self.expression.evaluate(compressor);
19901             out: if (exp.length == 2) try {
19902                 self.expression = exp[0];
19903                 if (!compressor.option("dead_code")) break out;
19904                 var value = exp[1];
19905                 var in_if = false;
19906                 var in_block = false;
19907                 var started = false;
19908                 var stopped = false;
19909                 var ruined = false;
19910                 var tt = new TreeTransformer(function(node, descend, in_list) {
19911                     if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) {
19912                         return node;
19913                     } else if (node instanceof AST_Switch && node === self) {
19914                         node = node.clone();
19915                         descend(node, this);
19916                         return ruined ? node : make_node(AST_BlockStatement, node, {
19917                             body: node.body.reduce(function(a, branch) {
19918                                 return a.concat(branch.body);
19919                             }, [])
19920                         }).transform(compressor);
19921                     } else if (node instanceof AST_If || node instanceof AST_Try) {
19922                         var save = in_if;
19923                         in_if = !in_block;
19924                         descend(node, this);
19925                         in_if = save;
19926                         return node;
19927                     } else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) {
19928                         var save = in_block;
19929                         in_block = true;
19930                         descend(node, this);
19931                         in_block = save;
19932                         return node;
19933                     } else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) {
19934                         if (in_if) {
19935                             ruined = true;
19936                             return node;
19937                         }
19938                         if (in_block) return node;
19939                         stopped = true;
19940                         return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
19941                     } else if (node instanceof AST_SwitchBranch && this.parent() === self) {
19942                         if (stopped) return MAP.skip;
19943                         if (node instanceof AST_Case) {
19944                             var exp = node.expression.evaluate(compressor);
19945                             if (exp.length < 2) {
19946                                 throw self;
19947                             }
19948                             if (exp[1] === value || started) {
19949                                 started = true;
19950                                 if (aborts(node)) stopped = true;
19951                                 descend(node, this);
19952                                 return node;
19953                             }
19954                             return MAP.skip;
19955                         }
19956                         descend(node, this);
19957                         return node;
19958                     }
19959                 });
19960                 tt.stack = compressor.stack.slice();
19961                 self = self.transform(tt);
19962             } catch (ex) {
19963                 if (ex !== self) throw ex;
19964             }
19965             return self;
19966         });
19967         OPT(AST_Case, function(self, compressor) {
19968             self.body = tighten_body(self.body, compressor);
19969             return self;
19970         });
19971         OPT(AST_Try, function(self, compressor) {
19972             self.body = tighten_body(self.body, compressor);
19973             return self;
19974         });
19975         AST_Definitions.DEFMETHOD("remove_initializers", function() {
19976             this.definitions.forEach(function(def) {
19977                 def.value = null;
19978             });
19979         });
19980         AST_Definitions.DEFMETHOD("to_assignments", function() {
19981             var assignments = this.definitions.reduce(function(a, def) {
19982                 if (def.value) {
19983                     var name = make_node(AST_SymbolRef, def.name, def.name);
19984                     a.push(make_node(AST_Assign, def, {
19985                         operator: "=",
19986                         left: name,
19987                         right: def.value
19988                     }));
19989                 }
19990                 return a;
19991             }, []);
19992             if (assignments.length == 0) return null;
19993             return AST_Seq.from_array(assignments);
19994         });
19995         OPT(AST_Definitions, function(self, compressor) {
19996             if (self.definitions.length == 0) return make_node(AST_EmptyStatement, self);
19997             return self;
19998         });
19999         OPT(AST_Function, function(self, compressor) {
20000             self = AST_Lambda.prototype.optimize.call(self, compressor);
20001             if (compressor.option("unused")) {
20002                 if (self.name && self.name.unreferenced()) {
20003                     self.name = null;
20004                 }
20005             }
20006             return self;
20007         });
20008         OPT(AST_Call, function(self, compressor) {
20009             if (compressor.option("unsafe")) {
20010                 var exp = self.expression;
20011                 if (exp instanceof AST_SymbolRef && exp.undeclared()) {
20012                     switch (exp.name) {
20013                       case "Array":
20014                         if (self.args.length != 1) {
20015                             return make_node(AST_Array, self, {
20016                                 elements: self.args
20017                             });
20018                         }
20019                         break;
20021                       case "Object":
20022                         if (self.args.length == 0) {
20023                             return make_node(AST_Object, self, {
20024                                 properties: []
20025                             });
20026                         }
20027                         break;
20029                       case "String":
20030                         if (self.args.length == 0) return make_node(AST_String, self, {
20031                             value: ""
20032                         });
20033                         return make_node(AST_Binary, self, {
20034                             left: self.args[0],
20035                             operator: "+",
20036                             right: make_node(AST_String, self, {
20037                                 value: ""
20038                             })
20039                         });
20041                       case "Function":
20042                         if (all(self.args, function(x) {
20043                             return x instanceof AST_String;
20044                         })) {
20045                             try {
20046                                 var code = "(function(" + self.args.slice(0, -1).map(function(arg) {
20047                                     return arg.value;
20048                                 }).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
20049                                 var ast = parse(code);
20050                                 ast.figure_out_scope();
20051                                 var comp = new Compressor(compressor.options);
20052                                 ast = ast.transform(comp);
20053                                 ast.figure_out_scope();
20054                                 ast.mangle_names();
20055                                 var fun = ast.body[0].body.expression;
20056                                 var args = fun.argnames.map(function(arg, i) {
20057                                     return make_node(AST_String, self.args[i], {
20058                                         value: arg.print_to_string()
20059                                     });
20060                                 });
20061                                 var code = OutputStream();
20062                                 AST_BlockStatement.prototype._codegen.call(fun, fun, code);
20063                                 code = code.toString().replace(/^\{|\}$/g, "");
20064                                 args.push(make_node(AST_String, self.args[self.args.length - 1], {
20065                                     value: code
20066                                 }));
20067                                 self.args = args;
20068                                 return self;
20069                             } catch (ex) {
20070                                 if (ex instanceof JS_Parse_Error) {
20071                                     compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
20072                                     compressor.warn(ex.toString());
20073                                 } else {
20074                                     console.log(ex);
20075                                 }
20076                             }
20077                         }
20078                         break;
20079                     }
20080                 } else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
20081                     return make_node(AST_Binary, self, {
20082                         left: make_node(AST_String, self, {
20083                             value: ""
20084                         }),
20085                         operator: "+",
20086                         right: exp.expression
20087                     }).transform(compressor);
20088                 }
20089             }
20090             if (compressor.option("side_effects")) {
20091                 if (self.expression instanceof AST_Function && self.args.length == 0 && !AST_Block.prototype.has_side_effects.call(self.expression)) {
20092                     return make_node(AST_Undefined, self).transform(compressor);
20093                 }
20094             }
20095             return self;
20096         });
20097         OPT(AST_New, function(self, compressor) {
20098             if (compressor.option("unsafe")) {
20099                 var exp = self.expression;
20100                 if (exp instanceof AST_SymbolRef && exp.undeclared()) {
20101                     switch (exp.name) {
20102                       case "Object":
20103                       case "RegExp":
20104                       case "Function":
20105                       case "Error":
20106                       case "Array":
20107                         return make_node(AST_Call, self, self).transform(compressor);
20108                     }
20109                 }
20110             }
20111             return self;
20112         });
20113         OPT(AST_Seq, function(self, compressor) {
20114             if (!compressor.option("side_effects")) return self;
20115             if (!self.car.has_side_effects()) {
20116                 var p;
20117                 if (!(self.cdr instanceof AST_SymbolRef && self.cdr.name == "eval" && self.cdr.undeclared() && (p = compressor.parent()) instanceof AST_Call && p.expression === self)) {
20118                     return self.cdr;
20119                 }
20120             }
20121             if (compressor.option("cascade")) {
20122                 if (self.car instanceof AST_Assign && !self.car.left.has_side_effects() && self.car.left.equivalent_to(self.cdr)) {
20123                     return self.car;
20124                 }
20125                 if (!self.car.has_side_effects() && !self.cdr.has_side_effects() && self.car.equivalent_to(self.cdr)) {
20126                     return self.car;
20127                 }
20128             }
20129             return self;
20130         });
20131         AST_Unary.DEFMETHOD("lift_sequences", function(compressor) {
20132             if (compressor.option("sequences")) {
20133                 if (this.expression instanceof AST_Seq) {
20134                     var seq = this.expression;
20135                     var x = seq.to_array();
20136                     this.expression = x.pop();
20137                     x.push(this);
20138                     seq = AST_Seq.from_array(x).transform(compressor);
20139                     return seq;
20140                 }
20141             }
20142             return this;
20143         });
20144         OPT(AST_UnaryPostfix, function(self, compressor) {
20145             return self.lift_sequences(compressor);
20146         });
20147         OPT(AST_UnaryPrefix, function(self, compressor) {
20148             self = self.lift_sequences(compressor);
20149             var e = self.expression;
20150             if (compressor.option("booleans") && compressor.in_boolean_context()) {
20151                 switch (self.operator) {
20152                   case "!":
20153                     if (e instanceof AST_UnaryPrefix && e.operator == "!") {
20154                         return e.expression;
20155                     }
20156                     break;
20158                   case "typeof":
20159                     compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
20160                     return make_node(AST_True, self);
20161                 }
20162                 if (e instanceof AST_Binary && self.operator == "!") {
20163                     self = best_of(self, e.negate(compressor));
20164                 }
20165             }
20166             return self.evaluate(compressor)[0];
20167         });
20168         AST_Binary.DEFMETHOD("lift_sequences", function(compressor) {
20169             if (compressor.option("sequences")) {
20170                 if (this.left instanceof AST_Seq) {
20171                     var seq = this.left;
20172                     var x = seq.to_array();
20173                     this.left = x.pop();
20174                     x.push(this);
20175                     seq = AST_Seq.from_array(x).transform(compressor);
20176                     return seq;
20177                 }
20178                 if (this.right instanceof AST_Seq && !(this.operator == "||" || this.operator == "&&") && !this.left.has_side_effects()) {
20179                     var seq = this.right;
20180                     var x = seq.to_array();
20181                     this.right = x.pop();
20182                     x.push(this);
20183                     seq = AST_Seq.from_array(x).transform(compressor);
20184                     return seq;
20185                 }
20186             }
20187             return this;
20188         });
20189         var commutativeOperators = makePredicate("== === != !== * & | ^");
20190         OPT(AST_Binary, function(self, compressor) {
20191             function reverse(op, force) {
20192                 if (force || !(self.left.has_side_effects() || self.right.has_side_effects())) {
20193                     if (op) self.operator = op;
20194                     var tmp = self.left;
20195                     self.left = self.right;
20196                     self.right = tmp;
20197                 }
20198             }
20199             if (commutativeOperators(self.operator)) {
20200                 if (self.right instanceof AST_Constant && !(self.left instanceof AST_Constant)) {
20201                     reverse(null, true);
20202                 }
20203             }
20204             self = self.lift_sequences(compressor);
20205             if (compressor.option("comparisons")) switch (self.operator) {
20206               case "===":
20207               case "!==":
20208                 if (self.left.is_string(compressor) && self.right.is_string(compressor) || self.left.is_boolean() && self.right.is_boolean()) {
20209                     self.operator = self.operator.substr(0, 2);
20210                 }
20212               case "==":
20213               case "!=":
20214                 if (self.left instanceof AST_String && self.left.value == "undefined" && self.right instanceof AST_UnaryPrefix && self.right.operator == "typeof" && compressor.option("unsafe")) {
20215                     if (!(self.right.expression instanceof AST_SymbolRef) || !self.right.expression.undeclared()) {
20216                         self.right = self.right.expression;
20217                         self.left = make_node(AST_Undefined, self.left).optimize(compressor);
20218                         if (self.operator.length == 2) self.operator += "=";
20219                     }
20220                 }
20221                 break;
20222             }
20223             if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
20224               case "&&":
20225                 var ll = self.left.evaluate(compressor);
20226                 var rr = self.right.evaluate(compressor);
20227                 if (ll.length > 1 && !ll[1] || rr.length > 1 && !rr[1]) {
20228                     compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
20229                     return make_node(AST_False, self);
20230                 }
20231                 if (ll.length > 1 && ll[1]) {
20232                     return rr[0];
20233                 }
20234                 if (rr.length > 1 && rr[1]) {
20235                     return ll[0];
20236                 }
20237                 break;
20239               case "||":
20240                 var ll = self.left.evaluate(compressor);
20241                 var rr = self.right.evaluate(compressor);
20242                 if (ll.length > 1 && ll[1] || rr.length > 1 && rr[1]) {
20243                     compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
20244                     return make_node(AST_True, self);
20245                 }
20246                 if (ll.length > 1 && !ll[1]) {
20247                     return rr[0];
20248                 }
20249                 if (rr.length > 1 && !rr[1]) {
20250                     return ll[0];
20251                 }
20252                 break;
20254               case "+":
20255                 var ll = self.left.evaluate(compressor);
20256                 var rr = self.right.evaluate(compressor);
20257                 if (ll.length > 1 && ll[0] instanceof AST_String && ll[1] || rr.length > 1 && rr[0] instanceof AST_String && rr[1]) {
20258                     compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
20259                     return make_node(AST_True, self);
20260                 }
20261                 break;
20262             }
20263             var exp = self.evaluate(compressor);
20264             if (exp.length > 1) {
20265                 if (best_of(exp[0], self) !== self) return exp[0];
20266             }
20267             if (compressor.option("comparisons")) {
20268                 if (!(compressor.parent() instanceof AST_Binary) || compressor.parent() instanceof AST_Assign) {
20269                     var negated = make_node(AST_UnaryPrefix, self, {
20270                         operator: "!",
20271                         expression: self.negate(compressor)
20272                     });
20273                     self = best_of(self, negated);
20274                 }
20275                 switch (self.operator) {
20276                   case "<":
20277                     reverse(">");
20278                     break;
20280                   case "<=":
20281                     reverse(">=");
20282                     break;
20283                 }
20284             }
20285             if (self.operator == "+" && self.right instanceof AST_String && self.right.getValue() === "" && self.left instanceof AST_Binary && self.left.operator == "+" && self.left.is_string(compressor)) {
20286                 return self.left;
20287             }
20288             return self;
20289         });
20290         OPT(AST_SymbolRef, function(self, compressor) {
20291             if (self.undeclared()) {
20292                 var defines = compressor.option("global_defs");
20293                 if (defines && defines.hasOwnProperty(self.name)) {
20294                     return make_node_from_constant(compressor, defines[self.name], self);
20295                 }
20296                 switch (self.name) {
20297                   case "undefined":
20298                     return make_node(AST_Undefined, self);
20300                   case "NaN":
20301                     return make_node(AST_NaN, self);
20303                   case "Infinity":
20304                     return make_node(AST_Infinity, self);
20305                 }
20306             }
20307             return self;
20308         });
20309         OPT(AST_Undefined, function(self, compressor) {
20310             if (compressor.option("unsafe")) {
20311                 var scope = compressor.find_parent(AST_Scope);
20312                 var undef = scope.find_variable("undefined");
20313                 if (undef) {
20314                     var ref = make_node(AST_SymbolRef, self, {
20315                         name: "undefined",
20316                         scope: scope,
20317                         thedef: undef
20318                     });
20319                     ref.reference();
20320                     return ref;
20321                 }
20322             }
20323             return self;
20324         });
20325         var ASSIGN_OPS = [ "+", "-", "/", "*", "%", ">>", "<<", ">>>", "|", "^", "&" ];
20326         OPT(AST_Assign, function(self, compressor) {
20327             self = self.lift_sequences(compressor);
20328             if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary && self.right.left instanceof AST_SymbolRef && self.right.left.name == self.left.name && member(self.right.operator, ASSIGN_OPS)) {
20329                 self.operator = self.right.operator + "=";
20330                 self.right = self.right.right;
20331             }
20332             return self;
20333         });
20334         OPT(AST_Conditional, function(self, compressor) {
20335             if (!compressor.option("conditionals")) return self;
20336             if (self.condition instanceof AST_Seq) {
20337                 var car = self.condition.car;
20338                 self.condition = self.condition.cdr;
20339                 return AST_Seq.cons(car, self);
20340             }
20341             var cond = self.condition.evaluate(compressor);
20342             if (cond.length > 1) {
20343                 if (cond[1]) {
20344                     compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
20345                     return self.consequent;
20346                 } else {
20347                     compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
20348                     return self.alternative;
20349                 }
20350             }
20351             var negated = cond[0].negate(compressor);
20352             if (best_of(cond[0], negated) === negated) {
20353                 self = make_node(AST_Conditional, self, {
20354                     condition: negated,
20355                     consequent: self.alternative,
20356                     alternative: self.consequent
20357                 });
20358             }
20359             var consequent = self.consequent;
20360             var alternative = self.alternative;
20361             if (consequent instanceof AST_Assign && alternative instanceof AST_Assign && consequent.operator == alternative.operator && consequent.left.equivalent_to(alternative.left)) {
20362                 self = make_node(AST_Assign, self, {
20363                     operator: consequent.operator,
20364                     left: consequent.left,
20365                     right: make_node(AST_Conditional, self, {
20366                         condition: self.condition,
20367                         consequent: consequent.right,
20368                         alternative: alternative.right
20369                     })
20370                 });
20371             }
20372             return self;
20373         });
20374         OPT(AST_Boolean, function(self, compressor) {
20375             if (compressor.option("booleans")) {
20376                 var p = compressor.parent();
20377                 if (p instanceof AST_Binary && (p.operator == "==" || p.operator == "!=")) {
20378                     compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", {
20379                         operator: p.operator,
20380                         value: self.value,
20381                         file: p.start.file,
20382                         line: p.start.line,
20383                         col: p.start.col
20384                     });
20385                     return make_node(AST_Number, self, {
20386                         value: +self.value
20387                     });
20388                 }
20389                 return make_node(AST_UnaryPrefix, self, {
20390                     operator: "!",
20391                     expression: make_node(AST_Number, self, {
20392                         value: 1 - self.value
20393                     })
20394                 });
20395             }
20396             return self;
20397         });
20398         OPT(AST_Sub, function(self, compressor) {
20399             var prop = self.property;
20400             if (prop instanceof AST_String && compressor.option("properties")) {
20401                 prop = prop.getValue();
20402                 if (compressor.option("screw_ie8") && RESERVED_WORDS(prop) || !RESERVED_WORDS(prop) && is_identifier_string(prop)) {
20403                     return make_node(AST_Dot, self, {
20404                         expression: self.expression,
20405                         property: prop
20406                     });
20407                 }
20408             }
20409             return self;
20410         });
20411         function literals_in_boolean_context(self, compressor) {
20412             if (compressor.option("booleans") && compressor.in_boolean_context()) {
20413                 return make_node(AST_True, self);
20414             }
20415             return self;
20416         }
20417         OPT(AST_Array, literals_in_boolean_context);
20418         OPT(AST_Object, literals_in_boolean_context);
20419         OPT(AST_RegExp, literals_in_boolean_context);
20420     })();
20421     "use strict";
20422     function SourceMap(options) {
20423         options = defaults(options, {
20424             file: null,
20425             root: null,
20426             orig: null
20427         });
20428         var generator = new MOZ_SourceMap.SourceMapGenerator({
20429             file: options.file,
20430             sourceRoot: options.root
20431         });
20432         var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
20433         function add(source, gen_line, gen_col, orig_line, orig_col, name) {
20434             if (orig_map) {
20435                 var info = orig_map.originalPositionFor({
20436                     line: orig_line,
20437                     column: orig_col
20438                 });
20439                 source = info.source;
20440                 orig_line = info.line;
20441                 orig_col = info.column;
20442                 name = info.name;
20443             }
20444             generator.addMapping({
20445                 generated: {
20446                     line: gen_line,
20447                     column: gen_col
20448                 },
20449                 original: {
20450                     line: orig_line,
20451                     column: orig_col
20452                 },
20453                 source: source,
20454                 name: name
20455             });
20456         }
20457         return {
20458             add: add,
20459             get: function() {
20460                 return generator;
20461             },
20462             toString: function() {
20463                 return generator.toString();
20464             }
20465         };
20466     }
20467     "use strict";
20468     (function() {
20469         var MOZ_TO_ME = {
20470             TryStatement: function(M) {
20471                 return new AST_Try({
20472                     start: my_start_token(M),
20473                     end: my_end_token(M),
20474                     body: from_moz(M.block).body,
20475                     bcatch: from_moz(M.handlers[0]),
20476                     bfinally: M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
20477                 });
20478             },
20479             CatchClause: function(M) {
20480                 return new AST_Catch({
20481                     start: my_start_token(M),
20482                     end: my_end_token(M),
20483                     argname: from_moz(M.param),
20484                     body: from_moz(M.body).body
20485                 });
20486             },
20487             ObjectExpression: function(M) {
20488                 return new AST_Object({
20489                     start: my_start_token(M),
20490                     end: my_end_token(M),
20491                     properties: M.properties.map(function(prop) {
20492                         var key = prop.key;
20493                         var name = key.type == "Identifier" ? key.name : key.value;
20494                         var args = {
20495                             start: my_start_token(key),
20496                             end: my_end_token(prop.value),
20497                             key: name,
20498                             value: from_moz(prop.value)
20499                         };
20500                         switch (prop.kind) {
20501                           case "init":
20502                             return new AST_ObjectKeyVal(args);
20504                           case "set":
20505                             args.value.name = from_moz(key);
20506                             return new AST_ObjectSetter(args);
20508                           case "get":
20509                             args.value.name = from_moz(key);
20510                             return new AST_ObjectGetter(args);
20511                         }
20512                     })
20513                 });
20514             },
20515             SequenceExpression: function(M) {
20516                 return AST_Seq.from_array(M.expressions.map(from_moz));
20517             },
20518             MemberExpression: function(M) {
20519                 return new (M.computed ? AST_Sub : AST_Dot)({
20520                     start: my_start_token(M),
20521                     end: my_end_token(M),
20522                     property: M.computed ? from_moz(M.property) : M.property.name,
20523                     expression: from_moz(M.object)
20524                 });
20525             },
20526             SwitchCase: function(M) {
20527                 return new (M.test ? AST_Case : AST_Default)({
20528                     start: my_start_token(M),
20529                     end: my_end_token(M),
20530                     expression: from_moz(M.test),
20531                     body: M.consequent.map(from_moz)
20532                 });
20533             },
20534             Literal: function(M) {
20535                 var val = M.value, args = {
20536                     start: my_start_token(M),
20537                     end: my_end_token(M)
20538                 };
20539                 if (val === null) return new AST_Null(args);
20540                 switch (typeof val) {
20541                   case "string":
20542                     args.value = val;
20543                     return new AST_String(args);
20545                   case "number":
20546                     args.value = val;
20547                     return new AST_Number(args);
20549                   case "boolean":
20550                     return new (val ? AST_True : AST_False)(args);
20552                   default:
20553                     args.value = val;
20554                     return new AST_RegExp(args);
20555                 }
20556             },
20557             UnaryExpression: From_Moz_Unary,
20558             UpdateExpression: From_Moz_Unary,
20559             Identifier: function(M) {
20560                 var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
20561                 return new (M.name == "this" ? AST_This : p.type == "LabeledStatement" ? AST_Label : p.type == "VariableDeclarator" && p.id === M ? p.kind == "const" ? AST_SymbolConst : AST_SymbolVar : p.type == "FunctionExpression" ? p.id === M ? AST_SymbolLambda : AST_SymbolFunarg : p.type == "FunctionDeclaration" ? p.id === M ? AST_SymbolDefun : AST_SymbolFunarg : p.type == "CatchClause" ? AST_SymbolCatch : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef : AST_SymbolRef)({
20562                     start: my_start_token(M),
20563                     end: my_end_token(M),
20564                     name: M.name
20565                 });
20566             }
20567         };
20568         function From_Moz_Unary(M) {
20569             var prefix = "prefix" in M ? M.prefix : M.type == "UnaryExpression" ? true : false;
20570             return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
20571                 start: my_start_token(M),
20572                 end: my_end_token(M),
20573                 operator: M.operator,
20574                 expression: from_moz(M.argument)
20575             });
20576         }
20577         var ME_TO_MOZ = {};
20578         map("Node", AST_Node);
20579         map("Program", AST_Toplevel, "body@body");
20580         map("Function", AST_Function, "id>name, params@argnames, body%body");
20581         map("EmptyStatement", AST_EmptyStatement);
20582         map("BlockStatement", AST_BlockStatement, "body@body");
20583         map("ExpressionStatement", AST_SimpleStatement, "expression>body");
20584         map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
20585         map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
20586         map("BreakStatement", AST_Break, "label>label");
20587         map("ContinueStatement", AST_Continue, "label>label");
20588         map("WithStatement", AST_With, "object>expression, body>body");
20589         map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body");
20590         map("ReturnStatement", AST_Return, "argument>value");
20591         map("ThrowStatement", AST_Throw, "argument>value");
20592         map("WhileStatement", AST_While, "test>condition, body>body");
20593         map("DoWhileStatement", AST_Do, "test>condition, body>body");
20594         map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
20595         map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
20596         map("DebuggerStatement", AST_Debugger);
20597         map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body");
20598         map("VariableDeclaration", AST_Var, "declarations@definitions");
20599         map("VariableDeclarator", AST_VarDef, "id>name, init>value");
20600         map("ThisExpression", AST_This);
20601         map("ArrayExpression", AST_Array, "elements@elements");
20602         map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body");
20603         map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
20604         map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
20605         map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
20606         map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
20607         map("NewExpression", AST_New, "callee>expression, arguments@args");
20608         map("CallExpression", AST_Call, "callee>expression, arguments@args");
20609         function my_start_token(moznode) {
20610             return new AST_Token({
20611                 file: moznode.loc && moznode.loc.source,
20612                 line: moznode.loc && moznode.loc.start.line,
20613                 col: moznode.loc && moznode.loc.start.column,
20614                 pos: moznode.start,
20615                 endpos: moznode.start
20616             });
20617         }
20618         function my_end_token(moznode) {
20619             return new AST_Token({
20620                 file: moznode.loc && moznode.loc.source,
20621                 line: moznode.loc && moznode.loc.end.line,
20622                 col: moznode.loc && moznode.loc.end.column,
20623                 pos: moznode.end,
20624                 endpos: moznode.end
20625             });
20626         }
20627         function map(moztype, mytype, propmap) {
20628             var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
20629             moz_to_me += "return new mytype({\n" + "start: my_start_token(M),\n" + "end: my_end_token(M)";
20630             if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) {
20631                 var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
20632                 if (!m) throw new Error("Can't understand property map: " + prop);
20633                 var moz = "M." + m[1], how = m[2], my = m[3];
20634                 moz_to_me += ",\n" + my + ": ";
20635                 if (how == "@") {
20636                     moz_to_me += moz + ".map(from_moz)";
20637                 } else if (how == ">") {
20638                     moz_to_me += "from_moz(" + moz + ")";
20639                 } else if (how == "=") {
20640                     moz_to_me += moz;
20641                 } else if (how == "%") {
20642                     moz_to_me += "from_moz(" + moz + ").body";
20643                 } else throw new Error("Can't understand operator in propmap: " + prop);
20644             });
20645             moz_to_me += "\n})}";
20646             moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(mytype, my_start_token, my_end_token, from_moz);
20647             return MOZ_TO_ME[moztype] = moz_to_me;
20648         }
20649         var FROM_MOZ_STACK = null;
20650         function from_moz(node) {
20651             FROM_MOZ_STACK.push(node);
20652             var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
20653             FROM_MOZ_STACK.pop();
20654             return ret;
20655         }
20656         AST_Node.from_mozilla_ast = function(node) {
20657             var save_stack = FROM_MOZ_STACK;
20658             FROM_MOZ_STACK = [];
20659             var ast = from_moz(node);
20660             FROM_MOZ_STACK = save_stack;
20661             return ast;
20662         };
20663     })();
20664     exports["array_to_hash"] = array_to_hash;
20665     exports["slice"] = slice;
20666     exports["characters"] = characters;
20667     exports["member"] = member;
20668     exports["find_if"] = find_if;
20669     exports["repeat_string"] = repeat_string;
20670     exports["DefaultsError"] = DefaultsError;
20671     exports["defaults"] = defaults;
20672     exports["merge"] = merge;
20673     exports["noop"] = noop;
20674     exports["MAP"] = MAP;
20675     exports["push_uniq"] = push_uniq;
20676     exports["string_template"] = string_template;
20677     exports["remove"] = remove;
20678     exports["mergeSort"] = mergeSort;
20679     exports["set_difference"] = set_difference;
20680     exports["set_intersection"] = set_intersection;
20681     exports["makePredicate"] = makePredicate;
20682     exports["all"] = all;
20683     exports["Dictionary"] = Dictionary;
20684     exports["DEFNODE"] = DEFNODE;
20685     exports["AST_Token"] = AST_Token;
20686     exports["AST_Node"] = AST_Node;
20687     exports["AST_Statement"] = AST_Statement;
20688     exports["AST_Debugger"] = AST_Debugger;
20689     exports["AST_Directive"] = AST_Directive;
20690     exports["AST_SimpleStatement"] = AST_SimpleStatement;
20691     exports["walk_body"] = walk_body;
20692     exports["AST_Block"] = AST_Block;
20693     exports["AST_BlockStatement"] = AST_BlockStatement;
20694     exports["AST_EmptyStatement"] = AST_EmptyStatement;
20695     exports["AST_StatementWithBody"] = AST_StatementWithBody;
20696     exports["AST_LabeledStatement"] = AST_LabeledStatement;
20697     exports["AST_DWLoop"] = AST_DWLoop;
20698     exports["AST_Do"] = AST_Do;
20699     exports["AST_While"] = AST_While;
20700     exports["AST_For"] = AST_For;
20701     exports["AST_ForIn"] = AST_ForIn;
20702     exports["AST_With"] = AST_With;
20703     exports["AST_Scope"] = AST_Scope;
20704     exports["AST_Toplevel"] = AST_Toplevel;
20705     exports["AST_Lambda"] = AST_Lambda;
20706     exports["AST_Accessor"] = AST_Accessor;
20707     exports["AST_Function"] = AST_Function;
20708     exports["AST_Defun"] = AST_Defun;
20709     exports["AST_Jump"] = AST_Jump;
20710     exports["AST_Exit"] = AST_Exit;
20711     exports["AST_Return"] = AST_Return;
20712     exports["AST_Throw"] = AST_Throw;
20713     exports["AST_LoopControl"] = AST_LoopControl;
20714     exports["AST_Break"] = AST_Break;
20715     exports["AST_Continue"] = AST_Continue;
20716     exports["AST_If"] = AST_If;
20717     exports["AST_Switch"] = AST_Switch;
20718     exports["AST_SwitchBranch"] = AST_SwitchBranch;
20719     exports["AST_Default"] = AST_Default;
20720     exports["AST_Case"] = AST_Case;
20721     exports["AST_Try"] = AST_Try;
20722     exports["AST_Catch"] = AST_Catch;
20723     exports["AST_Finally"] = AST_Finally;
20724     exports["AST_Definitions"] = AST_Definitions;
20725     exports["AST_Var"] = AST_Var;
20726     exports["AST_Const"] = AST_Const;
20727     exports["AST_VarDef"] = AST_VarDef;
20728     exports["AST_Call"] = AST_Call;
20729     exports["AST_New"] = AST_New;
20730     exports["AST_Seq"] = AST_Seq;
20731     exports["AST_PropAccess"] = AST_PropAccess;
20732     exports["AST_Dot"] = AST_Dot;
20733     exports["AST_Sub"] = AST_Sub;
20734     exports["AST_Unary"] = AST_Unary;
20735     exports["AST_UnaryPrefix"] = AST_UnaryPrefix;
20736     exports["AST_UnaryPostfix"] = AST_UnaryPostfix;
20737     exports["AST_Binary"] = AST_Binary;
20738     exports["AST_Conditional"] = AST_Conditional;
20739     exports["AST_Assign"] = AST_Assign;
20740     exports["AST_Array"] = AST_Array;
20741     exports["AST_Object"] = AST_Object;
20742     exports["AST_ObjectProperty"] = AST_ObjectProperty;
20743     exports["AST_ObjectKeyVal"] = AST_ObjectKeyVal;
20744     exports["AST_ObjectSetter"] = AST_ObjectSetter;
20745     exports["AST_ObjectGetter"] = AST_ObjectGetter;
20746     exports["AST_Symbol"] = AST_Symbol;
20747     exports["AST_SymbolAccessor"] = AST_SymbolAccessor;
20748     exports["AST_SymbolDeclaration"] = AST_SymbolDeclaration;
20749     exports["AST_SymbolVar"] = AST_SymbolVar;
20750     exports["AST_SymbolConst"] = AST_SymbolConst;
20751     exports["AST_SymbolFunarg"] = AST_SymbolFunarg;
20752     exports["AST_SymbolDefun"] = AST_SymbolDefun;
20753     exports["AST_SymbolLambda"] = AST_SymbolLambda;
20754     exports["AST_SymbolCatch"] = AST_SymbolCatch;
20755     exports["AST_Label"] = AST_Label;
20756     exports["AST_SymbolRef"] = AST_SymbolRef;
20757     exports["AST_LabelRef"] = AST_LabelRef;
20758     exports["AST_This"] = AST_This;
20759     exports["AST_Constant"] = AST_Constant;
20760     exports["AST_String"] = AST_String;
20761     exports["AST_Number"] = AST_Number;
20762     exports["AST_RegExp"] = AST_RegExp;
20763     exports["AST_Atom"] = AST_Atom;
20764     exports["AST_Null"] = AST_Null;
20765     exports["AST_NaN"] = AST_NaN;
20766     exports["AST_Undefined"] = AST_Undefined;
20767     exports["AST_Hole"] = AST_Hole;
20768     exports["AST_Infinity"] = AST_Infinity;
20769     exports["AST_Boolean"] = AST_Boolean;
20770     exports["AST_False"] = AST_False;
20771     exports["AST_True"] = AST_True;
20772     exports["TreeWalker"] = TreeWalker;
20773     exports["KEYWORDS"] = KEYWORDS;
20774     exports["KEYWORDS_ATOM"] = KEYWORDS_ATOM;
20775     exports["RESERVED_WORDS"] = RESERVED_WORDS;
20776     exports["KEYWORDS_BEFORE_EXPRESSION"] = KEYWORDS_BEFORE_EXPRESSION;
20777     exports["OPERATOR_CHARS"] = OPERATOR_CHARS;
20778     exports["RE_HEX_NUMBER"] = RE_HEX_NUMBER;
20779     exports["RE_OCT_NUMBER"] = RE_OCT_NUMBER;
20780     exports["RE_DEC_NUMBER"] = RE_DEC_NUMBER;
20781     exports["OPERATORS"] = OPERATORS;
20782     exports["WHITESPACE_CHARS"] = WHITESPACE_CHARS;
20783     exports["PUNC_BEFORE_EXPRESSION"] = PUNC_BEFORE_EXPRESSION;
20784     exports["PUNC_CHARS"] = PUNC_CHARS;
20785     exports["REGEXP_MODIFIERS"] = REGEXP_MODIFIERS;
20786     exports["UNICODE"] = UNICODE;
20787     exports["is_letter"] = is_letter;
20788     exports["is_digit"] = is_digit;
20789     exports["is_alphanumeric_char"] = is_alphanumeric_char;
20790     exports["is_unicode_combining_mark"] = is_unicode_combining_mark;
20791     exports["is_unicode_connector_punctuation"] = is_unicode_connector_punctuation;
20792     exports["is_identifier"] = is_identifier;
20793     exports["is_identifier_start"] = is_identifier_start;
20794     exports["is_identifier_char"] = is_identifier_char;
20795     exports["is_identifier_string"] = is_identifier_string;
20796     exports["parse_js_number"] = parse_js_number;
20797     exports["JS_Parse_Error"] = JS_Parse_Error;
20798     exports["js_error"] = js_error;
20799     exports["is_token"] = is_token;
20800     exports["EX_EOF"] = EX_EOF;
20801     exports["tokenizer"] = tokenizer;
20802     exports["UNARY_PREFIX"] = UNARY_PREFIX;
20803     exports["UNARY_POSTFIX"] = UNARY_POSTFIX;
20804     exports["ASSIGNMENT"] = ASSIGNMENT;
20805     exports["PRECEDENCE"] = PRECEDENCE;
20806     exports["STATEMENTS_WITH_LABELS"] = STATEMENTS_WITH_LABELS;
20807     exports["ATOMIC_START_TOKEN"] = ATOMIC_START_TOKEN;
20808     exports["parse"] = parse;
20809     exports["TreeTransformer"] = TreeTransformer;
20810     exports["SymbolDef"] = SymbolDef;
20811     exports["base54"] = base54;
20812     exports["OutputStream"] = OutputStream;
20813     exports["Compressor"] = Compressor;
20814     exports["SourceMap"] = SourceMap;
20815 })({}, function() {
20816     return exports;
20817 }());
20819 var UglifyJS = exports.UglifyJS;
20821 UglifyJS.AST_Node.warn_function = function(txt) {
20822     logger.error("uglifyjs2 WARN: " + txt);
20825 //JRB: MODIFIED FROM UGLIFY SOURCE
20826 //to take a name for the file, and then set toplevel.filename to be that name.
20827 exports.minify = function(files, options, name) {
20828     options = UglifyJS.defaults(options, {
20829         outSourceMap : null,
20830         sourceRoot   : null,
20831         inSourceMap  : null,
20832         fromString   : false,
20833         warnings     : false,
20834         mangle       : {},
20835         output       : null,
20836         compress     : {}
20837     });
20838     if (typeof files == "string")
20839         files = [ files ];
20841     // 1. parse
20842     var toplevel = null;
20843     files.forEach(function(file){
20844         var code = options.fromString
20845             ? file
20846             : rjsFile.readFile(file, "utf8");
20847         toplevel = UglifyJS.parse(code, {
20848             filename: options.fromString ? name : file,
20849             toplevel: toplevel
20850         });
20851     });
20853     // 2. compress
20854     if (options.compress) {
20855         var compress = { warnings: options.warnings };
20856         UglifyJS.merge(compress, options.compress);
20857         toplevel.figure_out_scope();
20858         var sq = UglifyJS.Compressor(compress);
20859         toplevel = toplevel.transform(sq);
20860     }
20862     // 3. mangle
20863     if (options.mangle) {
20864         toplevel.figure_out_scope();
20865         toplevel.compute_char_frequency();
20866         toplevel.mangle_names(options.mangle);
20867     }
20869     // 4. output
20870     var map = null;
20871     var inMap = null;
20872     if (options.inSourceMap) {
20873         inMap = rjsFile.readFile(options.inSourceMap, "utf8");
20874     }
20875     if (options.outSourceMap) map = UglifyJS.SourceMap({
20876         file: options.outSourceMap,
20877         orig: inMap,
20878         root: options.sourceRoot
20879     });
20880     var output = { source_map: map };
20881     if (options.output) {
20882         UglifyJS.merge(output, options.output);
20883     }
20884     var stream = UglifyJS.OutputStream(output);
20885     toplevel.print(stream);
20886     return {
20887         code : stream + "",
20888         map  : map + ""
20889     };
20892 // exports.describe_ast = function() {
20893 //     function doitem(ctor) {
20894 //         var sub = {};
20895 //         ctor.SUBCLASSES.forEach(function(ctor){
20896 //             sub[ctor.TYPE] = doitem(ctor);
20897 //         });
20898 //         var ret = {};
20899 //         if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS;
20900 //         if (ctor.SUBCLASSES.length > 0) ret.sub = sub;
20901 //         return ret;
20902 //     }
20903 //     return doitem(UglifyJS.AST_Node).sub;
20904 // }
20906 exports.describe_ast = function() {
20907     var out = UglifyJS.OutputStream({ beautify: true });
20908     function doitem(ctor) {
20909         out.print("AST_" + ctor.TYPE);
20910         var props = ctor.SELF_PROPS.filter(function(prop){
20911             return !/^\$/.test(prop);
20912         });
20913         if (props.length > 0) {
20914             out.space();
20915             out.with_parens(function(){
20916                 props.forEach(function(prop, i){
20917                     if (i) out.space();
20918                     out.print(prop);
20919                 });
20920             });
20921         }
20922         if (ctor.documentation) {
20923             out.space();
20924             out.print_string(ctor.documentation);
20925         }
20926         if (ctor.SUBCLASSES.length > 0) {
20927             out.space();
20928             out.with_block(function(){
20929                 ctor.SUBCLASSES.forEach(function(ctor, i){
20930                     out.indent();
20931                     doitem(ctor);
20932                     out.newline();
20933                 });
20934             });
20935         }
20936     };
20937     doitem(UglifyJS.AST_Node);
20938     return out + "";
20943  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
20944  * Available via the MIT or new BSD license.
20945  * see: http://github.com/jrburke/requirejs for details
20946  */
20948 /*jslint plusplus: true */
20949 /*global define: false */
20951 define('parse', ['./esprimaAdapter', 'lang'], function (esprima, lang) {
20952     'use strict';
20954     function arrayToString(ary) {
20955         var output = '[';
20956         if (ary) {
20957             ary.forEach(function (item, i) {
20958                 output += (i > 0 ? ',' : '') + '"' + lang.jsEscape(item) + '"';
20959             });
20960         }
20961         output += ']';
20963         return output;
20964     }
20966     //This string is saved off because JSLint complains
20967     //about obj.arguments use, as 'reserved word'
20968     var argPropName = 'arguments';
20970     //From an esprima example for traversing its ast.
20971     function traverse(object, visitor) {
20972         var key, child;
20974         if (!object) {
20975             return;
20976         }
20978         if (visitor.call(null, object) === false) {
20979             return false;
20980         }
20981         for (key in object) {
20982             if (object.hasOwnProperty(key)) {
20983                 child = object[key];
20984                 if (typeof child === 'object' && child !== null) {
20985                     if (traverse(child, visitor) === false) {
20986                         return false;
20987                     }
20988                 }
20989             }
20990         }
20991     }
20993     //Like traverse, but visitor returning false just
20994     //stops that subtree analysis, not the rest of tree
20995     //visiting.
20996     function traverseBroad(object, visitor) {
20997         var key, child;
20999         if (!object) {
21000             return;
21001         }
21003         if (visitor.call(null, object) === false) {
21004             return false;
21005         }
21006         for (key in object) {
21007             if (object.hasOwnProperty(key)) {
21008                 child = object[key];
21009                 if (typeof child === 'object' && child !== null) {
21010                     traverse(child, visitor);
21011                 }
21012             }
21013         }
21014     }
21016     /**
21017      * Pulls out dependencies from an array literal with just string members.
21018      * If string literals, will just return those string values in an array,
21019      * skipping other items in the array.
21020      *
21021      * @param {Node} node an AST node.
21022      *
21023      * @returns {Array} an array of strings.
21024      * If null is returned, then it means the input node was not a valid
21025      * dependency.
21026      */
21027     function getValidDeps(node) {
21028         if (!node || node.type !== 'ArrayExpression' || !node.elements) {
21029             return;
21030         }
21032         var deps = [];
21034         node.elements.some(function (elem) {
21035             if (elem.type === 'Literal') {
21036                 deps.push(elem.value);
21037             }
21038         });
21040         return deps.length ? deps : undefined;
21041     }
21043     /**
21044      * Main parse function. Returns a string of any valid require or
21045      * define/require.def calls as part of one JavaScript source string.
21046      * @param {String} moduleName the module name that represents this file.
21047      * It is used to create a default define if there is not one already for the
21048      * file. This allows properly tracing dependencies for builds. Otherwise, if
21049      * the file just has a require() call, the file dependencies will not be
21050      * properly reflected: the file will come before its dependencies.
21051      * @param {String} moduleName
21052      * @param {String} fileName
21053      * @param {String} fileContents
21054      * @param {Object} options optional options. insertNeedsDefine: true will
21055      * add calls to require.needsDefine() if appropriate.
21056      * @returns {String} JS source string or null, if no require or
21057      * define/require.def calls are found.
21058      */
21059     function parse(moduleName, fileName, fileContents, options) {
21060         options = options || {};
21062         //Set up source input
21063         var i, moduleCall, depString,
21064             moduleDeps = [],
21065             result = '',
21066             moduleList = [],
21067             needsDefine = true,
21068             astRoot = esprima.parse(fileContents);
21070         parse.recurse(astRoot, function (callName, config, name, deps) {
21071             if (!deps) {
21072                 deps = [];
21073             }
21075             if (callName === 'define' && (!name || name === moduleName)) {
21076                 needsDefine = false;
21077             }
21079             if (!name) {
21080                 //If there is no module name, the dependencies are for
21081                 //this file/default module name.
21082                 moduleDeps = moduleDeps.concat(deps);
21083             } else {
21084                 moduleList.push({
21085                     name: name,
21086                     deps: deps
21087                 });
21088             }
21090             //If define was found, no need to dive deeper, unless
21091             //the config explicitly wants to dig deeper.
21092             return !!options.findNestedDependencies;
21093         }, options);
21095         if (options.insertNeedsDefine && needsDefine) {
21096             result += 'require.needsDefine("' + moduleName + '");';
21097         }
21099         if (moduleDeps.length || moduleList.length) {
21100             for (i = 0; i < moduleList.length; i++) {
21101                 moduleCall = moduleList[i];
21102                 if (result) {
21103                     result += '\n';
21104                 }
21106                 //If this is the main module for this file, combine any
21107                 //"anonymous" dependencies (could come from a nested require
21108                 //call) with this module.
21109                 if (moduleCall.name === moduleName) {
21110                     moduleCall.deps = moduleCall.deps.concat(moduleDeps);
21111                     moduleDeps = [];
21112                 }
21114                 depString = arrayToString(moduleCall.deps);
21115                 result += 'define("' + moduleCall.name + '",' +
21116                           depString + ');';
21117             }
21118             if (moduleDeps.length) {
21119                 if (result) {
21120                     result += '\n';
21121                 }
21122                 depString = arrayToString(moduleDeps);
21123                 result += 'define("' + moduleName + '",' + depString + ');';
21124             }
21125         }
21127         return result || null;
21128     }
21130     parse.traverse = traverse;
21131     parse.traverseBroad = traverseBroad;
21133     /**
21134      * Handles parsing a file recursively for require calls.
21135      * @param {Array} parentNode the AST node to start with.
21136      * @param {Function} onMatch function to call on a parse match.
21137      * @param {Object} [options] This is normally the build config options if
21138      * it is passed.
21139      */
21140     parse.recurse = function (object, onMatch, options) {
21141         //Like traverse, but skips if branches that would not be processed
21142         //after has application that results in tests of true or false boolean
21143         //literal values.
21144         var key, child,
21145             hasHas = options && options.has;
21147         if (!object) {
21148             return;
21149         }
21151         //If has replacement has resulted in if(true){} or if(false){}, take
21152         //the appropriate branch and skip the other one.
21153         if (hasHas && object.type === 'IfStatement' && object.test.type &&
21154                 object.test.type === 'Literal') {
21155             if (object.test.value) {
21156                 //Take the if branch
21157                 this.recurse(object.consequent, onMatch, options);
21158             } else {
21159                 //Take the else branch
21160                 this.recurse(object.alternate, onMatch, options);
21161             }
21162         } else {
21163             if (this.parseNode(object, onMatch) === false) {
21164                 return;
21165             }
21166             for (key in object) {
21167                 if (object.hasOwnProperty(key)) {
21168                     child = object[key];
21169                     if (typeof child === 'object' && child !== null) {
21170                         this.recurse(child, onMatch, options);
21171                     }
21172                 }
21173             }
21174         }
21175     };
21177     /**
21178      * Determines if the file defines the require/define module API.
21179      * Specifically, it looks for the `define.amd = ` expression.
21180      * @param {String} fileName
21181      * @param {String} fileContents
21182      * @returns {Boolean}
21183      */
21184     parse.definesRequire = function (fileName, fileContents) {
21185         var found = false;
21187         traverse(esprima.parse(fileContents), function (node) {
21188             if (parse.hasDefineAmd(node)) {
21189                 found = true;
21191                 //Stop traversal
21192                 return false;
21193             }
21194         });
21196         return found;
21197     };
21199     /**
21200      * Finds require("") calls inside a CommonJS anonymous module wrapped in a
21201      * define(function(require, exports, module){}) wrapper. These dependencies
21202      * will be added to a modified define() call that lists the dependencies
21203      * on the outside of the function.
21204      * @param {String} fileName
21205      * @param {String|Object} fileContents: a string of contents, or an already
21206      * parsed AST tree.
21207      * @returns {Array} an array of module names that are dependencies. Always
21208      * returns an array, but could be of length zero.
21209      */
21210     parse.getAnonDeps = function (fileName, fileContents) {
21211         var astRoot = typeof fileContents === 'string' ?
21212                       esprima.parse(fileContents) : fileContents,
21213             defFunc = this.findAnonDefineFactory(astRoot);
21215         return parse.getAnonDepsFromNode(defFunc);
21216     };
21218     /**
21219      * Finds require("") calls inside a CommonJS anonymous module wrapped
21220      * in a define function, given an AST node for the definition function.
21221      * @param {Node} node the AST node for the definition function.
21222      * @returns {Array} and array of dependency names. Can be of zero length.
21223      */
21224     parse.getAnonDepsFromNode = function (node) {
21225         var deps = [],
21226             funcArgLength;
21228         if (node) {
21229             this.findRequireDepNames(node, deps);
21231             //If no deps, still add the standard CommonJS require, exports,
21232             //module, in that order, to the deps, but only if specified as
21233             //function args. In particular, if exports is used, it is favored
21234             //over the return value of the function, so only add it if asked.
21235             funcArgLength = node.params && node.params.length;
21236             if (funcArgLength) {
21237                 deps = (funcArgLength > 1 ? ["require", "exports", "module"] :
21238                         ["require"]).concat(deps);
21239             }
21240         }
21241         return deps;
21242     };
21244     parse.isDefineNodeWithArgs = function (node) {
21245         return node && node.type === 'CallExpression' &&
21246                node.callee && node.callee.type === 'Identifier' &&
21247                node.callee.name === 'define' && node[argPropName];
21248     };
21250     /**
21251      * Finds the function in define(function (require, exports, module){});
21252      * @param {Array} node
21253      * @returns {Boolean}
21254      */
21255     parse.findAnonDefineFactory = function (node) {
21256         var match;
21258         traverse(node, function (node) {
21259             var arg0, arg1;
21261             if (parse.isDefineNodeWithArgs(node)) {
21263                 //Just the factory function passed to define
21264                 arg0 = node[argPropName][0];
21265                 if (arg0 && arg0.type === 'FunctionExpression') {
21266                     match = arg0;
21267                     return false;
21268                 }
21270                 //A string literal module ID followed by the factory function.
21271                 arg1 = node[argPropName][1];
21272                 if (arg0.type === 'Literal' &&
21273                         arg1 && arg1.type === 'FunctionExpression') {
21274                     match = arg1;
21275                     return false;
21276                 }
21277             }
21278         });
21280         return match;
21281     };
21283     /**
21284      * Finds any config that is passed to requirejs. That includes calls to
21285      * require/requirejs.config(), as well as require({}, ...) and
21286      * requirejs({}, ...)
21287      * @param {String} fileContents
21288      *
21289      * @returns {Object} a config details object with the following properties:
21290      * - config: {Object} the config object found. Can be undefined if no
21291      * config found.
21292      * - range: {Array} the start index and end index in the contents where
21293      * the config was found. Can be undefined if no config found.
21294      * Can throw an error if the config in the file cannot be evaluated in
21295      * a build context to valid JavaScript.
21296      */
21297     parse.findConfig = function (fileContents) {
21298         /*jslint evil: true */
21299         var jsConfig, foundConfig, stringData, foundRange, quote, quoteMatch,
21300             quoteRegExp = /(:\s|\[\s*)(['"])/,
21301             astRoot = esprima.parse(fileContents, {
21302                 loc: true
21303             });
21305         traverse(astRoot, function (node) {
21306             var arg,
21307                 requireType = parse.hasRequire(node);
21309             if (requireType && (requireType === 'require' ||
21310                     requireType === 'requirejs' ||
21311                     requireType === 'requireConfig' ||
21312                     requireType === 'requirejsConfig')) {
21314                 arg = node[argPropName] && node[argPropName][0];
21316                 if (arg && arg.type === 'ObjectExpression') {
21317                     stringData = parse.nodeToString(fileContents, arg);
21318                     jsConfig = stringData.value;
21319                     foundRange = stringData.range;
21320                     return false;
21321                 }
21322             } else {
21323                 arg = parse.getRequireObjectLiteral(node);
21324                 if (arg) {
21325                     stringData = parse.nodeToString(fileContents, arg);
21326                     jsConfig = stringData.value;
21327                     foundRange = stringData.range;
21328                     return false;
21329                 }
21330             }
21331         });
21333         if (jsConfig) {
21334             // Eval the config
21335             quoteMatch = quoteRegExp.exec(jsConfig);
21336             quote = (quoteMatch && quoteMatch[2]) || '"';
21337             foundConfig = eval('(' + jsConfig + ')');
21338         }
21340         return {
21341             config: foundConfig,
21342             range: foundRange,
21343             quote: quote
21344         };
21345     };
21347     /** Returns the node for the object literal assigned to require/requirejs,
21348      * for holding a declarative config.
21349      */
21350     parse.getRequireObjectLiteral = function (node) {
21351         if (node.id && node.id.type === 'Identifier' &&
21352                 (node.id.name === 'require' || node.id.name === 'requirejs') &&
21353                 node.init && node.init.type === 'ObjectExpression') {
21354             return node.init;
21355         }
21356     };
21358     /**
21359      * Renames require/requirejs/define calls to be ns + '.' + require/requirejs/define
21360      * Does *not* do .config calls though. See pragma.namespace for the complete
21361      * set of namespace transforms. This function is used because require calls
21362      * inside a define() call should not be renamed, so a simple regexp is not
21363      * good enough.
21364      * @param  {String} fileContents the contents to transform.
21365      * @param  {String} ns the namespace, *not* including trailing dot.
21366      * @return {String} the fileContents with the namespace applied
21367      */
21368     parse.renameNamespace = function (fileContents, ns) {
21369         var lines,
21370             locs = [],
21371             astRoot = esprima.parse(fileContents, {
21372                 loc: true
21373             });
21375         parse.recurse(astRoot, function (callName, config, name, deps, node) {
21376             locs.push(node.loc);
21377             //Do not recurse into define functions, they should be using
21378             //local defines.
21379             return callName !== 'define';
21380         }, {});
21382         if (locs.length) {
21383             lines = fileContents.split('\n');
21385             //Go backwards through the found locs, adding in the namespace name
21386             //in front.
21387             locs.reverse();
21388             locs.forEach(function (loc) {
21389                 var startIndex = loc.start.column,
21390                 //start.line is 1-based, not 0 based.
21391                 lineIndex = loc.start.line - 1,
21392                 line = lines[lineIndex];
21394                 lines[lineIndex] = line.substring(0, startIndex) +
21395                                    ns + '.' +
21396                                    line.substring(startIndex,
21397                                                       line.length);
21398             });
21400             fileContents = lines.join('\n');
21401         }
21403         return fileContents;
21404     };
21406     /**
21407      * Finds all dependencies specified in dependency arrays and inside
21408      * simplified commonjs wrappers.
21409      * @param {String} fileName
21410      * @param {String} fileContents
21411      *
21412      * @returns {Array} an array of dependency strings. The dependencies
21413      * have not been normalized, they may be relative IDs.
21414      */
21415     parse.findDependencies = function (fileName, fileContents, options) {
21416         var dependencies = [],
21417             astRoot = esprima.parse(fileContents);
21419         parse.recurse(astRoot, function (callName, config, name, deps) {
21420             if (deps) {
21421                 dependencies = dependencies.concat(deps);
21422             }
21423         }, options);
21425         return dependencies;
21426     };
21428     /**
21429      * Finds only CJS dependencies, ones that are the form
21430      * require('stringLiteral')
21431      */
21432     parse.findCjsDependencies = function (fileName, fileContents) {
21433         var dependencies = [];
21435         traverse(esprima.parse(fileContents), function (node) {
21436             var arg;
21438             if (node && node.type === 'CallExpression' && node.callee &&
21439                     node.callee.type === 'Identifier' &&
21440                     node.callee.name === 'require' && node[argPropName] &&
21441                     node[argPropName].length === 1) {
21442                 arg = node[argPropName][0];
21443                 if (arg.type === 'Literal') {
21444                     dependencies.push(arg.value);
21445                 }
21446             }
21447         });
21449         return dependencies;
21450     };
21452     //function define() {}
21453     parse.hasDefDefine = function (node) {
21454         return node.type === 'FunctionDeclaration' && node.id &&
21455                     node.id.type === 'Identifier' && node.id.name === 'define';
21456     };
21458     //define.amd = ...
21459     parse.hasDefineAmd = function (node) {
21460         return node && node.type === 'AssignmentExpression' &&
21461             node.left && node.left.type === 'MemberExpression' &&
21462             node.left.object && node.left.object.name === 'define' &&
21463             node.left.property && node.left.property.name === 'amd';
21464     };
21466     //define.amd reference, as in: if (define.amd)
21467     parse.refsDefineAmd = function (node) {
21468         return node && node.type === 'MemberExpression' &&
21469         node.object && node.object.name === 'define' &&
21470         node.object.type === 'Identifier' &&
21471         node.property && node.property.name === 'amd' &&
21472         node.property.type === 'Identifier';
21473     };
21475     //require(), requirejs(), require.config() and requirejs.config()
21476     parse.hasRequire = function (node) {
21477         var callName,
21478             c = node && node.callee;
21480         if (node && node.type === 'CallExpression' && c) {
21481             if (c.type === 'Identifier' &&
21482                     (c.name === 'require' ||
21483                     c.name === 'requirejs')) {
21484                 //A require/requirejs({}, ...) call
21485                 callName = c.name;
21486             } else if (c.type === 'MemberExpression' &&
21487                     c.object &&
21488                     c.object.type === 'Identifier' &&
21489                     (c.object.name === 'require' ||
21490                         c.object.name === 'requirejs') &&
21491                     c.property && c.property.name === 'config') {
21492                 // require/requirejs.config({}) call
21493                 callName = c.object.name + 'Config';
21494             }
21495         }
21497         return callName;
21498     };
21500     //define()
21501     parse.hasDefine = function (node) {
21502         return node && node.type === 'CallExpression' && node.callee &&
21503             node.callee.type === 'Identifier' &&
21504             node.callee.name === 'define';
21505     };
21507     /**
21508      * If there is a named define in the file, returns the name. Does not
21509      * scan for mulitple names, just the first one.
21510      */
21511     parse.getNamedDefine = function (fileContents) {
21512         var name;
21513         traverse(esprima.parse(fileContents), function (node) {
21514             if (node && node.type === 'CallExpression' && node.callee &&
21515             node.callee.type === 'Identifier' &&
21516             node.callee.name === 'define' &&
21517             node[argPropName] && node[argPropName][0] &&
21518             node[argPropName][0].type === 'Literal') {
21519                 name = node[argPropName][0].value;
21520                 return false;
21521             }
21522         });
21524         return name;
21525     };
21527     /**
21528      * Determines if define(), require({}|[]) or requirejs was called in the
21529      * file. Also finds out if define() is declared and if define.amd is called.
21530      */
21531     parse.usesAmdOrRequireJs = function (fileName, fileContents) {
21532         var uses;
21534         traverse(esprima.parse(fileContents), function (node) {
21535             var type, callName, arg;
21537             if (parse.hasDefDefine(node)) {
21538                 //function define() {}
21539                 type = 'declaresDefine';
21540             } else if (parse.hasDefineAmd(node)) {
21541                 type = 'defineAmd';
21542             } else {
21543                 callName = parse.hasRequire(node);
21544                 if (callName) {
21545                     arg = node[argPropName] && node[argPropName][0];
21546                     if (arg && (arg.type === 'ObjectExpression' ||
21547                             arg.type === 'ArrayExpression')) {
21548                         type = callName;
21549                     }
21550                 } else if (parse.hasDefine(node)) {
21551                     type = 'define';
21552                 }
21553             }
21555             if (type) {
21556                 if (!uses) {
21557                     uses = {};
21558                 }
21559                 uses[type] = true;
21560             }
21561         });
21563         return uses;
21564     };
21566     /**
21567      * Determines if require(''), exports.x =, module.exports =,
21568      * __dirname, __filename are used. So, not strictly traditional CommonJS,
21569      * also checks for Node variants.
21570      */
21571     parse.usesCommonJs = function (fileName, fileContents) {
21572         var uses = null,
21573             assignsExports = false;
21576         traverse(esprima.parse(fileContents), function (node) {
21577             var type,
21578                 exp = node.expression || node.init;
21580             if (node.type === 'Identifier' &&
21581                     (node.name === '__dirname' || node.name === '__filename')) {
21582                 type = node.name.substring(2);
21583             } else if (node.type === 'VariableDeclarator' && node.id &&
21584                     node.id.type === 'Identifier' &&
21585                         node.id.name === 'exports') {
21586                 //Hmm, a variable assignment for exports, so does not use cjs
21587                 //exports.
21588                 type = 'varExports';
21589             } else if (exp && exp.type === 'AssignmentExpression' && exp.left &&
21590                     exp.left.type === 'MemberExpression' && exp.left.object) {
21591                 if (exp.left.object.name === 'module' && exp.left.property &&
21592                         exp.left.property.name === 'exports') {
21593                     type = 'moduleExports';
21594                 } else if (exp.left.object.name === 'exports' &&
21595                         exp.left.property) {
21596                     type = 'exports';
21597                 }
21599             } else if (node && node.type === 'CallExpression' && node.callee &&
21600                     node.callee.type === 'Identifier' &&
21601                     node.callee.name === 'require' && node[argPropName] &&
21602                     node[argPropName].length === 1 &&
21603                     node[argPropName][0].type === 'Literal') {
21604                 type = 'require';
21605             }
21607             if (type) {
21608                 if (type === 'varExports') {
21609                     assignsExports = true;
21610                 } else if (type !== 'exports' || !assignsExports) {
21611                     if (!uses) {
21612                         uses = {};
21613                     }
21614                     uses[type] = true;
21615                 }
21616             }
21617         });
21619         return uses;
21620     };
21623     parse.findRequireDepNames = function (node, deps) {
21624         traverse(node, function (node) {
21625             var arg;
21627             if (node && node.type === 'CallExpression' && node.callee &&
21628                     node.callee.type === 'Identifier' &&
21629                     node.callee.name === 'require' &&
21630                     node[argPropName] && node[argPropName].length === 1) {
21632                 arg = node[argPropName][0];
21633                 if (arg.type === 'Literal') {
21634                     deps.push(arg.value);
21635                 }
21636             }
21637         });
21638     };
21640     /**
21641      * Determines if a specific node is a valid require or define/require.def
21642      * call.
21643      * @param {Array} node
21644      * @param {Function} onMatch a function to call when a match is found.
21645      * It is passed the match name, and the config, name, deps possible args.
21646      * The config, name and deps args are not normalized.
21647      *
21648      * @returns {String} a JS source string with the valid require/define call.
21649      * Otherwise null.
21650      */
21651     parse.parseNode = function (node, onMatch) {
21652         var name, deps, cjsDeps, arg, factory, exp, refsDefine, bodyNode,
21653             args = node && node[argPropName],
21654             callName = parse.hasRequire(node);
21656         if (callName === 'require' || callName === 'requirejs') {
21657             //A plain require/requirejs call
21658             arg = node[argPropName] && node[argPropName][0];
21659             if (arg.type !== 'ArrayExpression') {
21660                 if (arg.type === 'ObjectExpression') {
21661                     //A config call, try the second arg.
21662                     arg = node[argPropName][1];
21663                 }
21664             }
21666             deps = getValidDeps(arg);
21667             if (!deps) {
21668                 return;
21669             }
21671             return onMatch("require", null, null, deps, node);
21672         } else if (parse.hasDefine(node) && args && args.length) {
21673             name = args[0];
21674             deps = args[1];
21675             factory = args[2];
21677             if (name.type === 'ArrayExpression') {
21678                 //No name, adjust args
21679                 factory = deps;
21680                 deps = name;
21681                 name = null;
21682             } else if (name.type === 'FunctionExpression') {
21683                 //Just the factory, no name or deps
21684                 factory = name;
21685                 name = deps = null;
21686             } else if (name.type !== 'Literal') {
21687                  //An object literal, just null out
21688                 name = deps = factory = null;
21689             }
21691             if (name && name.type === 'Literal' && deps) {
21692                 if (deps.type === 'FunctionExpression') {
21693                     //deps is the factory
21694                     factory = deps;
21695                     deps = null;
21696                 } else if (deps.type === 'ObjectExpression') {
21697                     //deps is object literal, null out
21698                     deps = factory = null;
21699                 } else if (deps.type === 'Identifier' && args.length === 2) {
21700                     // define('id', factory)
21701                     deps = factory = null;
21702                 }
21703             }
21705             if (deps && deps.type === 'ArrayExpression') {
21706                 deps = getValidDeps(deps);
21707             } else if (factory && factory.type === 'FunctionExpression') {
21708                 //If no deps and a factory function, could be a commonjs sugar
21709                 //wrapper, scan the function for dependencies.
21710                 cjsDeps = parse.getAnonDepsFromNode(factory);
21711                 if (cjsDeps.length) {
21712                     deps = cjsDeps;
21713                 }
21714             } else if (deps || factory) {
21715                 //Does not match the shape of an AMD call.
21716                 return;
21717             }
21719             //Just save off the name as a string instead of an AST object.
21720             if (name && name.type === 'Literal') {
21721                 name = name.value;
21722             }
21724             return onMatch("define", null, name, deps, node);
21725         } else if (node.type === 'CallExpression' && node.callee &&
21726                    node.callee.type === 'FunctionExpression' &&
21727                    node.callee.body && node.callee.body.body &&
21728                    node.callee.body.body.length === 1 &&
21729                    node.callee.body.body[0].type === 'IfStatement') {
21730             bodyNode = node.callee.body.body[0];
21731             //Look for a define(Identifier) case, but only if inside an
21732             //if that has a define.amd test
21733             if (bodyNode.consequent && bodyNode.consequent.body) {
21734                 exp = bodyNode.consequent.body[0];
21735                 if (exp.type === 'ExpressionStatement' && exp.expression &&
21736                     parse.hasDefine(exp.expression) &&
21737                     exp.expression.arguments &&
21738                     exp.expression.arguments.length === 1 &&
21739                     exp.expression.arguments[0].type === 'Identifier') {
21741                     //Calls define(Identifier) as first statement in body.
21742                     //Confirm the if test references define.amd
21743                     traverse(bodyNode.test, function (node) {
21744                         if (parse.refsDefineAmd(node)) {
21745                             refsDefine = true;
21746                             return false;
21747                         }
21748                     });
21750                     if (refsDefine) {
21751                         return onMatch("define", null, null, null, exp.expression);
21752                     }
21753                 }
21754             }
21755         }
21756     };
21758     /**
21759      * Converts an AST node into a JS source string by extracting
21760      * the node's location from the given contents string. Assumes
21761      * esprima.parse() with loc was done.
21762      * @param {String} contents
21763      * @param {Object} node
21764      * @returns {String} a JS source string.
21765      */
21766     parse.nodeToString = function (contents, node) {
21767         var loc = node.loc,
21768             lines = contents.split('\n'),
21769             firstLine = loc.start.line > 1 ?
21770                         lines.slice(0, loc.start.line - 1).join('\n') + '\n' :
21771                         '',
21772             preamble = firstLine +
21773                        lines[loc.start.line - 1].substring(0, loc.start.column),
21774             extracted =  lines[loc.start.line - 1].substring(loc.start.column) +
21775                      '\n' +
21776                      lines.slice(loc.start.line, loc.end.line - 1).join('\n') +
21777                      '\n' +
21778                      lines[loc.end.line - 1].substring(0, loc.end.column);
21780         return {
21781             value: extracted,
21782             range: [
21783                 preamble.length,
21784                 preamble.length + extracted.length
21785             ]
21786         };
21787     };
21789     /**
21790      * Extracts license comments from JS text.
21791      * @param {String} fileName
21792      * @param {String} contents
21793      * @returns {String} a string of license comments.
21794      */
21795     parse.getLicenseComments = function (fileName, contents) {
21796         var commentNode, refNode, subNode, value, i, j,
21797             //xpconnect's Reflect does not support comment or range, but
21798             //prefer continued operation vs strict parity of operation,
21799             //as license comments can be expressed in other ways, like
21800             //via wrap args, or linked via sourcemaps.
21801             ast = esprima.parse(contents, {
21802                 comment: true,
21803                 range: true
21804             }),
21805             result = '',
21806             existsMap = {},
21807             lineEnd = contents.indexOf('\r') === -1 ? '\n' : '\r\n';
21809         if (ast.comments) {
21810             for (i = 0; i < ast.comments.length; i++) {
21811                 commentNode = ast.comments[i];
21813                 if (commentNode.type === 'Line') {
21814                     value = '//' + commentNode.value + lineEnd;
21815                     refNode = commentNode;
21817                     if (i + 1 >= ast.comments.length) {
21818                         value += lineEnd;
21819                     } else {
21820                         //Look for immediately adjacent single line comments
21821                         //since it could from a multiple line comment made out
21822                         //of single line comments. Like this comment.
21823                         for (j = i + 1; j < ast.comments.length; j++) {
21824                             subNode = ast.comments[j];
21825                             if (subNode.type === 'Line' &&
21826                                     subNode.range[0] === refNode.range[1] + 1) {
21827                                 //Adjacent single line comment. Collect it.
21828                                 value += '//' + subNode.value + lineEnd;
21829                                 refNode = subNode;
21830                             } else {
21831                                 //No more single line comment blocks. Break out
21832                                 //and continue outer looping.
21833                                 break;
21834                             }
21835                         }
21836                         value += lineEnd;
21837                         i = j - 1;
21838                     }
21839                 } else {
21840                     value = '/*' + commentNode.value + '*/' + lineEnd + lineEnd;
21841                 }
21843                 if (!existsMap[value] && (value.indexOf('license') !== -1 ||
21844                         (commentNode.type === 'Block' &&
21845                             value.indexOf('/*!') === 0) ||
21846                         value.indexOf('opyright') !== -1 ||
21847                         value.indexOf('(c)') !== -1)) {
21849                     result += value;
21850                     existsMap[value] = true;
21851                 }
21853             }
21854         }
21856         return result;
21857     };
21859     return parse;
21862  * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
21863  * Available via the MIT or new BSD license.
21864  * see: http://github.com/jrburke/requirejs for details
21865  */
21867 /*global define */
21869 define('transform', [ './esprimaAdapter', './parse', 'logger', 'lang'],
21870 function (esprima, parse, logger, lang) {
21871     'use strict';
21872     var transform,
21873         baseIndentRegExp = /^([ \t]+)/,
21874         indentRegExp = /\{[\r\n]+([ \t]+)/,
21875         keyRegExp = /^[_A-Za-z]([A-Za-z\d_]*)$/,
21876         bulkIndentRegExps = {
21877             '\n': /\n/g,
21878             '\r\n': /\r\n/g
21879         };
21881     function applyIndent(str, indent, lineReturn) {
21882         var regExp = bulkIndentRegExps[lineReturn];
21883         return str.replace(regExp, '$&' + indent);
21884     }
21886     transform = {
21887         toTransport: function (namespace, moduleName, path, contents, onFound, options) {
21888             options = options || {};
21890             var astRoot, contentLines, modLine,
21891                 foundAnon,
21892                 scanCount = 0,
21893                 scanReset = false,
21894                 defineInfos = [];
21896             try {
21897                 astRoot = esprima.parse(contents, {
21898                     loc: true
21899                 });
21900             } catch (e) {
21901                 logger.trace('toTransport skipping ' + path + ': ' +
21902                              e.toString());
21903                 return contents;
21904             }
21906             //Find the define calls and their position in the files.
21907             parse.traverseBroad(astRoot, function (node) {
21908                 var args, firstArg, firstArgLoc, factoryNode,
21909                     needsId, depAction, foundId,
21910                     sourceUrlData, range,
21911                     namespaceExists = false;
21913                 namespaceExists = namespace &&
21914                                 node.type === 'CallExpression' &&
21915                                 node.callee  && node.callee.object &&
21916                                 node.callee.object.type === 'Identifier' &&
21917                                 node.callee.object.name === namespace &&
21918                                 node.callee.property.type === 'Identifier' &&
21919                                 node.callee.property.name === 'define';
21921                 if (namespaceExists || parse.isDefineNodeWithArgs(node)) {
21922                     //The arguments are where its at.
21923                     args = node.arguments;
21924                     if (!args || !args.length) {
21925                         return;
21926                     }
21928                     firstArg = args[0];
21929                     firstArgLoc = firstArg.loc;
21931                     if (args.length === 1) {
21932                         if (firstArg.type === 'Identifier') {
21933                             //The define(factory) case, but
21934                             //only allow it if one Identifier arg,
21935                             //to limit impact of false positives.
21936                             needsId = true;
21937                             depAction = 'empty';
21938                         } else if (firstArg.type === 'FunctionExpression') {
21939                             //define(function(){})
21940                             factoryNode = firstArg;
21941                             needsId = true;
21942                             depAction = 'scan';
21943                         } else if (firstArg.type === 'ObjectExpression') {
21944                             //define({});
21945                             needsId = true;
21946                             depAction = 'skip';
21947                         } else if (firstArg.type === 'Literal' &&
21948                                    typeof firstArg.value === 'number') {
21949                             //define('12345');
21950                             needsId = true;
21951                             depAction = 'skip';
21952                         } else if (firstArg.type === 'UnaryExpression' &&
21953                                    firstArg.operator === '-' &&
21954                                    firstArg.argument &&
21955                                    firstArg.argument.type === 'Literal' &&
21956                                    typeof firstArg.argument.value === 'number') {
21957                             //define('-12345');
21958                             needsId = true;
21959                             depAction = 'skip';
21960                         } else if (firstArg.type === 'MemberExpression' &&
21961                                    firstArg.object &&
21962                                    firstArg.property &&
21963                                    firstArg.property.type === 'Identifier') {
21964                             //define(this.key);
21965                             needsId = true;
21966                             depAction = 'empty';
21967                         }
21968                     } else if (firstArg.type === 'ArrayExpression') {
21969                         //define([], ...);
21970                         needsId = true;
21971                         depAction = 'skip';
21972                     } else if (firstArg.type === 'Literal' &&
21973                                typeof firstArg.value === 'string') {
21974                         //define('string', ....)
21975                         //Already has an ID.
21976                         needsId = false;
21977                         if (args.length === 2 &&
21978                             args[1].type === 'FunctionExpression') {
21979                             //Needs dependency scanning.
21980                             factoryNode = args[1];
21981                             depAction = 'scan';
21982                         } else {
21983                             depAction = 'skip';
21984                         }
21985                     } else {
21986                         //Unknown define entity, keep looking, even
21987                         //in the subtree for this node.
21988                         return;
21989                     }
21991                     range = {
21992                         foundId: foundId,
21993                         needsId: needsId,
21994                         depAction: depAction,
21995                         namespaceExists: namespaceExists,
21996                         node: node,
21997                         defineLoc: node.loc,
21998                         firstArgLoc: firstArgLoc,
21999                         factoryNode: factoryNode,
22000                         sourceUrlData: sourceUrlData
22001                     };
22003                     //Only transform ones that do not have IDs. If it has an
22004                     //ID but no dependency array, assume it is something like
22005                     //a phonegap implementation, that has its own internal
22006                     //define that cannot handle dependency array constructs,
22007                     //and if it is a named module, then it means it has been
22008                     //set for transport form.
22009                     if (range.needsId) {
22010                         if (foundAnon) {
22011                             logger.trace(path + ' has more than one anonymous ' +
22012                                 'define. May be a built file from another ' +
22013                                 'build system like, Ender. Skipping normalization.');
22014                             defineInfos = [];
22015                             return false;
22016                         } else {
22017                             foundAnon = range;
22018                             defineInfos.push(range);
22019                         }
22020                     } else if (depAction === 'scan') {
22021                         scanCount += 1;
22022                         if (scanCount > 1) {
22023                             //Just go back to an array that just has the
22024                             //anon one, since this is an already optimized
22025                             //file like the phonegap one.
22026                             if (!scanReset) {
22027                                 defineInfos =  foundAnon ? [foundAnon] : [];
22028                                 scanReset = true;
22029                             }
22030                         } else {
22031                             defineInfos.push(range);
22032                         }
22033                     }
22034                 }
22035             });
22037             if (!defineInfos.length) {
22038                 return contents;
22039             }
22041             //Reverse the matches, need to start from the bottom of
22042             //the file to modify it, so that the ranges are still true
22043             //further up.
22044             defineInfos.reverse();
22046             contentLines = contents.split('\n');
22048             modLine = function (loc, contentInsertion) {
22049                 var startIndex = loc.start.column,
22050                 //start.line is 1-based, not 0 based.
22051                 lineIndex = loc.start.line - 1,
22052                 line = contentLines[lineIndex];
22053                 contentLines[lineIndex] = line.substring(0, startIndex) +
22054                                            contentInsertion +
22055                                            line.substring(startIndex,
22056                                                               line.length);
22057             };
22059             defineInfos.forEach(function (info) {
22060                 var deps,
22061                     contentInsertion = '',
22062                     depString = '';
22064                 //Do the modifications "backwards", in other words, start with the
22065                 //one that is farthest down and work up, so that the ranges in the
22066                 //defineInfos still apply. So that means deps, id, then namespace.
22067                 if (info.needsId && moduleName) {
22068                     contentInsertion += "'" + moduleName + "',";
22069                 }
22071                 if (info.depAction === 'scan') {
22072                     deps = parse.getAnonDepsFromNode(info.factoryNode);
22074                     if (deps.length) {
22075                         depString = '[' + deps.map(function (dep) {
22076                             return "'" + dep + "'";
22077                         }) + ']';
22078                     } else {
22079                         depString = '[]';
22080                     }
22081                     depString +=  ',';
22083                     if (info.factoryNode) {
22084                         //Already have a named module, need to insert the
22085                         //dependencies after the name.
22086                         modLine(info.factoryNode.loc, depString);
22087                     } else {
22088                         contentInsertion += depString;
22089                     }
22090                 }
22092                 if (contentInsertion) {
22093                     modLine(info.firstArgLoc, contentInsertion);
22094                 }
22096                 //Do namespace last so that ui does not mess upthe parenRange
22097                 //used above.
22098                 if (namespace && !info.namespaceExists) {
22099                     modLine(info.defineLoc, namespace + '.');
22100                 }
22102                 //Notify any listener for the found info
22103                 if (onFound) {
22104                     onFound(info);
22105                 }
22106             });
22108             contents = contentLines.join('\n');
22110             if (options.useSourceUrl) {
22111                 contents = 'eval("' + lang.jsEscape(contents) +
22112                     '\\n//# sourceURL=' + (path.indexOf('/') === 0 ? '' : '/') +
22113                     path +
22114                     '");\n';
22115             }
22117             return contents;
22118         },
22120         /**
22121          * Modify the contents of a require.config/requirejs.config call. This
22122          * call will LOSE any existing comments that are in the config string.
22123          *
22124          * @param  {String} fileContents String that may contain a config call
22125          * @param  {Function} onConfig Function called when the first config
22126          * call is found. It will be passed an Object which is the current
22127          * config, and the onConfig function should return an Object to use
22128          * as the config.
22129          * @return {String} the fileContents with the config changes applied.
22130          */
22131         modifyConfig: function (fileContents, onConfig) {
22132             var details = parse.findConfig(fileContents),
22133                 config = details.config;
22135             if (config) {
22136                 config = onConfig(config);
22137                 if (config) {
22138                     return transform.serializeConfig(config,
22139                                               fileContents,
22140                                               details.range[0],
22141                                               details.range[1],
22142                                               {
22143                                                 quote: details.quote
22144                                               });
22145                 }
22146             }
22148             return fileContents;
22149         },
22151         serializeConfig: function (config, fileContents, start, end, options) {
22152             //Calculate base level of indent
22153             var indent, match, configString, outDentRegExp,
22154                 baseIndent = '',
22155                 startString = fileContents.substring(0, start),
22156                 existingConfigString = fileContents.substring(start, end),
22157                 lineReturn = existingConfigString.indexOf('\r') === -1 ? '\n' : '\r\n',
22158                 lastReturnIndex = startString.lastIndexOf('\n');
22160             //Get the basic amount of indent for the require config call.
22161             if (lastReturnIndex === -1) {
22162                 lastReturnIndex = 0;
22163             }
22165             match = baseIndentRegExp.exec(startString.substring(lastReturnIndex + 1, start));
22166             if (match && match[1]) {
22167                 baseIndent = match[1];
22168             }
22170             //Calculate internal indentation for config
22171             match = indentRegExp.exec(existingConfigString);
22172             if (match && match[1]) {
22173                 indent = match[1];
22174             }
22176             if (!indent || indent.length < baseIndent) {
22177                 indent = '  ';
22178             } else {
22179                 indent = indent.substring(baseIndent.length);
22180             }
22182             outDentRegExp = new RegExp('(' + lineReturn + ')' + indent, 'g');
22184             configString = transform.objectToString(config, {
22185                                                     indent: indent,
22186                                                     lineReturn: lineReturn,
22187                                                     outDentRegExp: outDentRegExp,
22188                                                     quote: options && options.quote
22189                                                 });
22191             //Add in the base indenting level.
22192             configString = applyIndent(configString, baseIndent, lineReturn);
22194             return startString + configString + fileContents.substring(end);
22195         },
22197         /**
22198          * Tries converting a JS object to a string. This will likely suck, and
22199          * is tailored to the type of config expected in a loader config call.
22200          * So, hasOwnProperty fields, strings, numbers, arrays and functions,
22201          * no weird recursively referenced stuff.
22202          * @param  {Object} obj        the object to convert
22203          * @param  {Object} options    options object with the following values:
22204          *         {String} indent     the indentation to use for each level
22205          *         {String} lineReturn the type of line return to use
22206          *         {outDentRegExp} outDentRegExp the regexp to use to outdent functions
22207          *         {String} quote      the quote type to use, ' or ". Optional. Default is "
22208          * @param  {String} totalIndent the total indent to print for this level
22209          * @return {String}            a string representation of the object.
22210          */
22211         objectToString: function (obj, options, totalIndent) {
22212             var startBrace, endBrace, nextIndent,
22213                 first = true,
22214                 value = '',
22215                 lineReturn = options.lineReturn,
22216                 indent = options.indent,
22217                 outDentRegExp = options.outDentRegExp,
22218                 quote = options.quote || '"';
22220             totalIndent = totalIndent || '';
22221             nextIndent = totalIndent + indent;
22223             if (obj === null) {
22224                 value = 'null';
22225             } else if (obj === undefined) {
22226                 value = 'undefined';
22227             } else if (typeof obj === 'number' || typeof obj === 'boolean') {
22228                 value = obj;
22229             } else if (typeof obj === 'string') {
22230                 //Use double quotes in case the config may also work as JSON.
22231                 value = quote + lang.jsEscape(obj) + quote;
22232             } else if (lang.isArray(obj)) {
22233                 lang.each(obj, function (item, i) {
22234                     value += (i !== 0 ? ',' + lineReturn : '' ) +
22235                         nextIndent +
22236                         transform.objectToString(item,
22237                                                  options,
22238                                                  nextIndent);
22239                 });
22241                 startBrace = '[';
22242                 endBrace = ']';
22243             } else if (lang.isFunction(obj) || lang.isRegExp(obj)) {
22244                 //The outdent regexp just helps pretty up the conversion
22245                 //just in node. Rhino strips comments and does a different
22246                 //indent scheme for Function toString, so not really helpful
22247                 //there.
22248                 value = obj.toString().replace(outDentRegExp, '$1');
22249             } else {
22250                 //An object
22251                 lang.eachProp(obj, function (v, prop) {
22252                     value += (first ? '': ',' + lineReturn) +
22253                         nextIndent +
22254                         (keyRegExp.test(prop) ? prop : quote + lang.jsEscape(prop) + quote )+
22255                         ': ' +
22256                         transform.objectToString(v,
22257                                                  options,
22258                                                  nextIndent);
22259                     first = false;
22260                 });
22261                 startBrace = '{';
22262                 endBrace = '}';
22263             }
22265             if (startBrace) {
22266                 value = startBrace +
22267                         lineReturn +
22268                         value +
22269                         lineReturn + totalIndent +
22270                         endBrace;
22271             }
22273             return value;
22274         }
22275     };
22277     return transform;
22280  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
22281  * Available via the MIT or new BSD license.
22282  * see: http://github.com/jrburke/requirejs for details
22283  */
22285 /*jslint regexp: true, plusplus: true  */
22286 /*global define: false */
22288 define('pragma', ['parse', 'logger'], function (parse, logger) {
22289     'use strict';
22290     function Temp() {}
22292     function create(obj, mixin) {
22293         Temp.prototype = obj;
22294         var temp = new Temp(), prop;
22296         //Avoid any extra memory hanging around
22297         Temp.prototype = null;
22299         if (mixin) {
22300             for (prop in mixin) {
22301                 if (mixin.hasOwnProperty(prop) && !temp.hasOwnProperty(prop)) {
22302                     temp[prop] = mixin[prop];
22303                 }
22304             }
22305         }
22307         return temp; // Object
22308     }
22310     var pragma = {
22311         conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/,
22312         useStrictRegExp: /['"]use strict['"];/g,
22313         hasRegExp: /has\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
22314         configRegExp: /(^|[^\.])(requirejs|require)(\.config)\s*\(/g,
22315         nsWrapRegExp: /\/\*requirejs namespace: true \*\//,
22316         apiDefRegExp: /var requirejs, require, define;/,
22317         defineCheckRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\.\s*amd/g,
22318         defineStringCheckRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\[\s*["']amd["']\s*\]/g,
22319         defineTypeFirstCheckRegExp: /\s*["']function["']\s*===\s*typeof\s+define\s*&&\s*define\s*\.\s*amd/g,
22320         defineJQueryRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\.\s*amd\s*&&\s*define\s*\.\s*amd\s*\.\s*jQuery/g,
22321         defineHasRegExp: /typeof\s+define\s*==(=)?\s*['"]function['"]\s*&&\s*typeof\s+define\.amd\s*==(=)?\s*['"]object['"]\s*&&\s*define\.amd/g,
22322         defineTernaryRegExp: /typeof\s+define\s*===\s*['"]function["']\s*&&\s*define\s*\.\s*amd\s*\?\s*define/,
22323         amdefineRegExp: /if\s*\(\s*typeof define\s*\!==\s*'function'\s*\)\s*\{\s*[^\{\}]+amdefine[^\{\}]+\}/g,
22325         removeStrict: function (contents, config) {
22326             return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, '');
22327         },
22329         namespace: function (fileContents, ns, onLifecycleName) {
22330             if (ns) {
22331                 //Namespace require/define calls
22332                 fileContents = fileContents.replace(pragma.configRegExp, '$1' + ns + '.$2$3(');
22335                 fileContents = parse.renameNamespace(fileContents, ns);
22337                 //Namespace define ternary use:
22338                 fileContents = fileContents.replace(pragma.defineTernaryRegExp,
22339                                                     "typeof " + ns + ".define === 'function' && " + ns + ".define.amd ? " + ns + ".define");
22341                 //Namespace define jquery use:
22342                 fileContents = fileContents.replace(pragma.defineJQueryRegExp,
22343                                                     "typeof " + ns + ".define === 'function' && " + ns + ".define.amd && " + ns + ".define.amd.jQuery");
22345                 //Namespace has.js define use:
22346                 fileContents = fileContents.replace(pragma.defineHasRegExp,
22347                                                     "typeof " + ns + ".define === 'function' && typeof " + ns + ".define.amd === 'object' && " + ns + ".define.amd");
22349                 //Namespace define checks.
22350                 //Do these ones last, since they are a subset of the more specific
22351                 //checks above.
22352                 fileContents = fileContents.replace(pragma.defineCheckRegExp,
22353                                                     "typeof " + ns + ".define === 'function' && " + ns + ".define.amd");
22354                 fileContents = fileContents.replace(pragma.defineStringCheckRegExp,
22355                                                     "typeof " + ns + ".define === 'function' && " + ns + ".define['amd']");
22356                 fileContents = fileContents.replace(pragma.defineTypeFirstCheckRegExp,
22357                                                     "'function' === typeof " + ns + ".define && " + ns + ".define.amd");
22359                 //Check for require.js with the require/define definitions
22360                 if (pragma.apiDefRegExp.test(fileContents) &&
22361                     fileContents.indexOf("if (!" + ns + " || !" + ns + ".requirejs)") === -1) {
22362                     //Wrap the file contents in a typeof check, and a function
22363                     //to contain the API globals.
22364                     fileContents = "var " + ns + ";(function () { if (!" + ns + " || !" + ns + ".requirejs) {\n" +
22365                                     "if (!" + ns + ") { " + ns + ' = {}; } else { require = ' + ns + '; }\n' +
22366                                     fileContents +
22367                                     "\n" +
22368                                     ns + ".requirejs = requirejs;" +
22369                                     ns + ".require = require;" +
22370                                     ns + ".define = define;\n" +
22371                                     "}\n}());";
22372                 }
22374                 //Finally, if the file wants a special wrapper because it ties
22375                 //in to the requirejs internals in a way that would not fit
22376                 //the above matches, do that. Look for /*requirejs namespace: true*/
22377                 if (pragma.nsWrapRegExp.test(fileContents)) {
22378                     //Remove the pragma.
22379                     fileContents = fileContents.replace(pragma.nsWrapRegExp, '');
22381                     //Alter the contents.
22382                     fileContents = '(function () {\n' +
22383                                    'var require = ' + ns + '.require,' +
22384                                    'requirejs = ' + ns + '.requirejs,' +
22385                                    'define = ' + ns + '.define;\n' +
22386                                    fileContents +
22387                                    '\n}());';
22388                 }
22389             }
22391             return fileContents;
22392         },
22394         /**
22395          * processes the fileContents for some //>> conditional statements
22396          */
22397         process: function (fileName, fileContents, config, onLifecycleName, pluginCollector) {
22398             /*jslint evil: true */
22399             var foundIndex = -1, startIndex = 0, lineEndIndex, conditionLine,
22400                 matches, type, marker, condition, isTrue, endRegExp, endMatches,
22401                 endMarkerIndex, shouldInclude, startLength, lifecycleHas, deps,
22402                 i, dep, moduleName, collectorMod,
22403                 lifecyclePragmas, pragmas = config.pragmas, hasConfig = config.has,
22404                 //Legacy arg defined to help in dojo conversion script. Remove later
22405                 //when dojo no longer needs conversion:
22406                 kwArgs = pragmas;
22408             //Mix in a specific lifecycle scoped object, to allow targeting
22409             //some pragmas/has tests to only when files are saved, or at different
22410             //lifecycle events. Do not bother with kwArgs in this section, since
22411             //the old dojo kwArgs were for all points in the build lifecycle.
22412             if (onLifecycleName) {
22413                 lifecyclePragmas = config['pragmas' + onLifecycleName];
22414                 lifecycleHas = config['has' + onLifecycleName];
22416                 if (lifecyclePragmas) {
22417                     pragmas = create(pragmas || {}, lifecyclePragmas);
22418                 }
22420                 if (lifecycleHas) {
22421                     hasConfig = create(hasConfig || {}, lifecycleHas);
22422                 }
22423             }
22425             //Replace has references if desired
22426             if (hasConfig) {
22427                 fileContents = fileContents.replace(pragma.hasRegExp, function (match, test) {
22428                     if (hasConfig.hasOwnProperty(test)) {
22429                         return !!hasConfig[test];
22430                     }
22431                     return match;
22432                 });
22433             }
22435             if (!config.skipPragmas) {
22437                 while ((foundIndex = fileContents.indexOf("//>>", startIndex)) !== -1) {
22438                     //Found a conditional. Get the conditional line.
22439                     lineEndIndex = fileContents.indexOf("\n", foundIndex);
22440                     if (lineEndIndex === -1) {
22441                         lineEndIndex = fileContents.length - 1;
22442                     }
22444                     //Increment startIndex past the line so the next conditional search can be done.
22445                     startIndex = lineEndIndex + 1;
22447                     //Break apart the conditional.
22448                     conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1);
22449                     matches = conditionLine.match(pragma.conditionalRegExp);
22450                     if (matches) {
22451                         type = matches[1];
22452                         marker = matches[2];
22453                         condition = matches[3];
22454                         isTrue = false;
22455                         //See if the condition is true.
22456                         try {
22457                             isTrue = !!eval("(" + condition + ")");
22458                         } catch (e) {
22459                             throw "Error in file: " +
22460                                    fileName +
22461                                    ". Conditional comment: " +
22462                                    conditionLine +
22463                                    " failed with this error: " + e;
22464                         }
22466                         //Find the endpoint marker.
22467                         endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g");
22468                         endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length));
22469                         if (endMatches) {
22470                             endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length;
22472                             //Find the next line return based on the match position.
22473                             lineEndIndex = fileContents.indexOf("\n", endMarkerIndex);
22474                             if (lineEndIndex === -1) {
22475                                 lineEndIndex = fileContents.length - 1;
22476                             }
22478                             //Should we include the segment?
22479                             shouldInclude = ((type === "exclude" && !isTrue) || (type === "include" && isTrue));
22481                             //Remove the conditional comments, and optionally remove the content inside
22482                             //the conditional comments.
22483                             startLength = startIndex - foundIndex;
22484                             fileContents = fileContents.substring(0, foundIndex) +
22485                                 (shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "") +
22486                                 fileContents.substring(lineEndIndex + 1, fileContents.length);
22488                             //Move startIndex to foundIndex, since that is the new position in the file
22489                             //where we need to look for more conditionals in the next while loop pass.
22490                             startIndex = foundIndex;
22491                         } else {
22492                             throw "Error in file: " +
22493                                   fileName +
22494                                   ". Cannot find end marker for conditional comment: " +
22495                                   conditionLine;
22497                         }
22498                     }
22499                 }
22500             }
22502             //If need to find all plugin resources to optimize, do that now,
22503             //before namespacing, since the namespacing will change the API
22504             //names.
22505             //If there is a plugin collector, scan the file for plugin resources.
22506             if (config.optimizeAllPluginResources && pluginCollector) {
22507                 try {
22508                     deps = parse.findDependencies(fileName, fileContents);
22509                     if (deps.length) {
22510                         for (i = 0; i < deps.length; i++) {
22511                             dep = deps[i];
22512                             if (dep.indexOf('!') !== -1) {
22513                                 moduleName = dep.split('!')[0];
22514                                 collectorMod = pluginCollector[moduleName];
22515                                 if (!collectorMod) {
22516                                  collectorMod = pluginCollector[moduleName] = [];
22517                                 }
22518                                 collectorMod.push(dep);
22519                             }
22520                         }
22521                     }
22522                 } catch (eDep) {
22523                     logger.error('Parse error looking for plugin resources in ' +
22524                                  fileName + ', skipping.');
22525                 }
22526             }
22528             //Strip amdefine use for node-shared modules.
22529             fileContents = fileContents.replace(pragma.amdefineRegExp, '');
22531             //Do namespacing
22532             if (onLifecycleName === 'OnSave' && config.namespace) {
22533                 fileContents = pragma.namespace(fileContents, config.namespace, onLifecycleName);
22534             }
22537             return pragma.removeStrict(fileContents, config);
22538         }
22539     };
22541     return pragma;
22543 if(env === 'browser') {
22545  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
22546  * Available via the MIT or new BSD license.
22547  * see: http://github.com/jrburke/requirejs for details
22548  */
22550 /*jslint strict: false */
22551 /*global define: false */
22553 define('browser/optimize', {});
22557 if(env === 'node') {
22559  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
22560  * Available via the MIT or new BSD license.
22561  * see: http://github.com/jrburke/requirejs for details
22562  */
22564 /*jslint strict: false */
22565 /*global define: false */
22567 define('node/optimize', {});
22571 if(env === 'rhino') {
22573  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
22574  * Available via the MIT or new BSD license.
22575  * see: http://github.com/jrburke/requirejs for details
22576  */
22578 /*jslint sloppy: true, plusplus: true */
22579 /*global define, java, Packages, com */
22581 define('rhino/optimize', ['logger', 'env!env/file'], function (logger, file) {
22583     //Add .reduce to Rhino so UglifyJS can run in Rhino,
22584     //inspired by https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
22585     //but rewritten for brevity, and to be good enough for use by UglifyJS.
22586     if (!Array.prototype.reduce) {
22587         Array.prototype.reduce = function (fn /*, initialValue */) {
22588             var i = 0,
22589                 length = this.length,
22590                 accumulator;
22592             if (arguments.length >= 2) {
22593                 accumulator = arguments[1];
22594             } else {
22595                 if (length) {
22596                     while (!(i in this)) {
22597                         i++;
22598                     }
22599                     accumulator = this[i++];
22600                 }
22601             }
22603             for (; i < length; i++) {
22604                 if (i in this) {
22605                     accumulator = fn.call(undefined, accumulator, this[i], i, this);
22606                 }
22607             }
22609             return accumulator;
22610         };
22611     }
22613     var JSSourceFilefromCode, optimize,
22614         mapRegExp = /"file":"[^"]+"/;
22616     //Bind to Closure compiler, but if it is not available, do not sweat it.
22617     try {
22618         JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.JSSourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]);
22619     } catch (e) {}
22621     //Helper for closure compiler, because of weird Java-JavaScript interactions.
22622     function closurefromCode(filename, content) {
22623         return JSSourceFilefromCode.invoke(null, [filename, content]);
22624     }
22627     function getFileWriter(fileName, encoding) {
22628         var outFile = new java.io.File(fileName), outWriter, parentDir;
22630         parentDir = outFile.getAbsoluteFile().getParentFile();
22631         if (!parentDir.exists()) {
22632             if (!parentDir.mkdirs()) {
22633                 throw "Could not create directory: " + parentDir.getAbsolutePath();
22634             }
22635         }
22637         if (encoding) {
22638             outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding);
22639         } else {
22640             outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
22641         }
22643         return new java.io.BufferedWriter(outWriter);
22644     }
22646     optimize = {
22647         closure: function (fileName, fileContents, outFileName, keepLines, config) {
22648             config = config || {};
22649             var result, mappings, optimized, compressed, baseName, writer,
22650                 outBaseName, outFileNameMap, outFileNameMapContent,
22651                 jscomp = Packages.com.google.javascript.jscomp,
22652                 flags = Packages.com.google.common.flags,
22653                 //Fake extern
22654                 externSourceFile = closurefromCode("fakeextern.js", " "),
22655                 //Set up source input
22656                 jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
22657                 options, option, FLAG_compilation_level, compiler,
22658                 Compiler = Packages.com.google.javascript.jscomp.Compiler;
22660             logger.trace("Minifying file: " + fileName);
22662             baseName = (new java.io.File(fileName)).getName();
22664             //Set up options
22665             options = new jscomp.CompilerOptions();
22666             for (option in config.CompilerOptions) {
22667                 // options are false by default and jslint wanted an if statement in this for loop
22668                 if (config.CompilerOptions[option]) {
22669                     options[option] = config.CompilerOptions[option];
22670                 }
22672             }
22673             options.prettyPrint = keepLines || options.prettyPrint;
22675             FLAG_compilation_level = jscomp.CompilationLevel[config.CompilationLevel || 'SIMPLE_OPTIMIZATIONS'];
22676             FLAG_compilation_level.setOptionsForCompilationLevel(options);
22678             if (config.generateSourceMaps) {
22679                 mappings = new java.util.ArrayList();
22681                 mappings.add(new com.google.javascript.jscomp.SourceMap.LocationMapping(fileName, baseName + ".src"));
22682                 options.setSourceMapLocationMappings(mappings);
22683                 options.setSourceMapOutputPath(fileName + ".map");
22684             }
22686             //Trigger the compiler
22687             Compiler.setLoggingLevel(Packages.java.util.logging.Level[config.loggingLevel || 'WARNING']);
22688             compiler = new Compiler();
22690             result = compiler.compile(externSourceFile, jsSourceFile, options);
22691             if (result.success) {
22692                 optimized = String(compiler.toSource());
22694                 if (config.generateSourceMaps && result.sourceMap && outFileName) {
22695                     outBaseName = (new java.io.File(outFileName)).getName();
22697                     file.saveUtf8File(outFileName + ".src", fileContents);
22699                     outFileNameMap = outFileName + ".map";
22700                     writer = getFileWriter(outFileNameMap, "utf-8");
22701                     result.sourceMap.appendTo(writer, outFileName);
22702                     writer.close();
22704                     //Not sure how better to do this, but right now the .map file
22705                     //leaks the full OS path in the "file" property. Manually
22706                     //modify it to not do that.
22707                     file.saveFile(outFileNameMap,
22708                         file.readFile(outFileNameMap).replace(mapRegExp, '"file":"' + baseName + '"'));
22710                     fileContents = optimized + "\n//# sourceMappingURL=" + outBaseName + ".map";
22711                 } else {
22712                     fileContents = optimized;
22713                 }
22714                 return fileContents;
22715             } else {
22716                 throw new Error('Cannot closure compile file: ' + fileName + '. Skipping it.');
22717             }
22719             return fileContents;
22720         }
22721     };
22723     return optimize;
22727 if(env === 'xpconnect') {
22728 define('xpconnect/optimize', {});
22731  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
22732  * Available via the MIT or new BSD license.
22733  * see: http://github.com/jrburke/requirejs for details
22734  */
22736 /*jslint plusplus: true, nomen: true, regexp: true */
22737 /*global define: false */
22739 define('optimize', [ 'lang', 'logger', 'env!env/optimize', 'env!env/file', 'parse',
22740          'pragma', 'uglifyjs/index', 'uglifyjs2',
22741          'source-map'],
22742 function (lang,   logger,   envOptimize,        file,           parse,
22743           pragma, uglify,             uglify2,
22744           sourceMap) {
22745     'use strict';
22747     var optimize,
22748         cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/ig,
22749         cssCommentImportRegExp = /\/\*[^\*]*@import[^\*]*\*\//g,
22750         cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g,
22751         SourceMapGenerator = sourceMap.SourceMapGenerator,
22752         SourceMapConsumer =sourceMap.SourceMapConsumer;
22754     /**
22755      * If an URL from a CSS url value contains start/end quotes, remove them.
22756      * This is not done in the regexp, since my regexp fu is not that strong,
22757      * and the CSS spec allows for ' and " in the URL if they are backslash escaped.
22758      * @param {String} url
22759      */
22760     function cleanCssUrlQuotes(url) {
22761         //Make sure we are not ending in whitespace.
22762         //Not very confident of the css regexps above that there will not be ending
22763         //whitespace.
22764         url = url.replace(/\s+$/, "");
22766         if (url.charAt(0) === "'" || url.charAt(0) === "\"") {
22767             url = url.substring(1, url.length - 1);
22768         }
22770         return url;
22771     }
22773     /**
22774      * Inlines nested stylesheets that have @import calls in them.
22775      * @param {String} fileName the file name
22776      * @param {String} fileContents the file contents
22777      * @param {String} cssImportIgnore comma delimited string of files to ignore
22778      * @param {String} cssPrefix string to be prefixed before relative URLs
22779      * @param {Object} included an object used to track the files already imported
22780      */
22781     function flattenCss(fileName, fileContents, cssImportIgnore, cssPrefix, included) {
22782         //Find the last slash in the name.
22783         fileName = fileName.replace(lang.backSlashRegExp, "/");
22784         var endIndex = fileName.lastIndexOf("/"),
22785             //Make a file path based on the last slash.
22786             //If no slash, so must be just a file name. Use empty string then.
22787             filePath = (endIndex !== -1) ? fileName.substring(0, endIndex + 1) : "",
22788             //store a list of merged files
22789             importList = [],
22790             skippedList = [];
22792         //First make a pass by removing an commented out @import calls.
22793         fileContents = fileContents.replace(cssCommentImportRegExp, '');
22795         //Make sure we have a delimited ignore list to make matching faster
22796         if (cssImportIgnore && cssImportIgnore.charAt(cssImportIgnore.length - 1) !== ",") {
22797             cssImportIgnore += ",";
22798         }
22800         fileContents = fileContents.replace(cssImportRegExp, function (fullMatch, urlStart, importFileName, urlEnd, mediaTypes) {
22801             //Only process media type "all" or empty media type rules.
22802             if (mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) !== "all")) {
22803                 skippedList.push(fileName);
22804                 return fullMatch;
22805             }
22807             importFileName = cleanCssUrlQuotes(importFileName);
22809             //Ignore the file import if it is part of an ignore list.
22810             if (cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") !== -1) {
22811                 return fullMatch;
22812             }
22814             //Make sure we have a unix path for the rest of the operation.
22815             importFileName = importFileName.replace(lang.backSlashRegExp, "/");
22817             try {
22818                 //if a relative path, then tack on the filePath.
22819                 //If it is not a relative path, then the readFile below will fail,
22820                 //and we will just skip that import.
22821                 var fullImportFileName = importFileName.charAt(0) === "/" ? importFileName : filePath + importFileName,
22822                     importContents = file.readFile(fullImportFileName), i,
22823                     importEndIndex, importPath, fixedUrlMatch, colonIndex, parts, flat;
22825                 //Skip the file if it has already been included.
22826                 if (included[fullImportFileName]) {
22827                     return '';
22828                 }
22829                 included[fullImportFileName] = true;
22831                 //Make sure to flatten any nested imports.
22832                 flat = flattenCss(fullImportFileName, importContents, cssImportIgnore, cssPrefix, included);
22833                 importContents = flat.fileContents;
22835                 if (flat.importList.length) {
22836                     importList.push.apply(importList, flat.importList);
22837                 }
22838                 if (flat.skippedList.length) {
22839                     skippedList.push.apply(skippedList, flat.skippedList);
22840                 }
22842                 //Make the full import path
22843                 importEndIndex = importFileName.lastIndexOf("/");
22845                 //Make a file path based on the last slash.
22846                 //If no slash, so must be just a file name. Use empty string then.
22847                 importPath = (importEndIndex !== -1) ? importFileName.substring(0, importEndIndex + 1) : "";
22849                 //fix url() on relative import (#5)
22850                 importPath = importPath.replace(/^\.\//, '');
22852                 //Modify URL paths to match the path represented by this file.
22853                 importContents = importContents.replace(cssUrlRegExp, function (fullMatch, urlMatch) {
22854                     fixedUrlMatch = cleanCssUrlQuotes(urlMatch);
22855                     fixedUrlMatch = fixedUrlMatch.replace(lang.backSlashRegExp, "/");
22857                     //Only do the work for relative URLs. Skip things that start with / or have
22858                     //a protocol.
22859                     colonIndex = fixedUrlMatch.indexOf(":");
22860                     if (fixedUrlMatch.charAt(0) !== "/" && (colonIndex === -1 || colonIndex > fixedUrlMatch.indexOf("/"))) {
22861                         //It is a relative URL, tack on the cssPrefix and path prefix
22862                         urlMatch = cssPrefix + importPath + fixedUrlMatch;
22864                     } else {
22865                         logger.trace(importFileName + "\n  URL not a relative URL, skipping: " + urlMatch);
22866                     }
22868                     //Collapse .. and .
22869                     parts = urlMatch.split("/");
22870                     for (i = parts.length - 1; i > 0; i--) {
22871                         if (parts[i] === ".") {
22872                             parts.splice(i, 1);
22873                         } else if (parts[i] === "..") {
22874                             if (i !== 0 && parts[i - 1] !== "..") {
22875                                 parts.splice(i - 1, 2);
22876                                 i -= 1;
22877                             }
22878                         }
22879                     }
22881                     return "url(" + parts.join("/") + ")";
22882                 });
22884                 importList.push(fullImportFileName);
22885                 return importContents;
22886             } catch (e) {
22887                 logger.warn(fileName + "\n  Cannot inline css import, skipping: " + importFileName);
22888                 return fullMatch;
22889             }
22890         });
22892         return {
22893             importList : importList,
22894             skippedList: skippedList,
22895             fileContents : fileContents
22896         };
22897     }
22899     optimize = {
22900         /**
22901          * Optimizes a file that contains JavaScript content. Optionally collects
22902          * plugin resources mentioned in a file, and then passes the content
22903          * through an minifier if one is specified via config.optimize.
22904          *
22905          * @param {String} fileName the name of the file to optimize
22906          * @param {String} fileContents the contents to optimize. If this is
22907          * a null value, then fileName will be used to read the fileContents.
22908          * @param {String} outFileName the name of the file to use for the
22909          * saved optimized content.
22910          * @param {Object} config the build config object.
22911          * @param {Array} [pluginCollector] storage for any plugin resources
22912          * found.
22913          */
22914         jsFile: function (fileName, fileContents, outFileName, config, pluginCollector) {
22915             if (!fileContents) {
22916                 fileContents = file.readFile(fileName);
22917             }
22919             fileContents = optimize.js(fileName, fileContents, outFileName, config, pluginCollector);
22921             file.saveUtf8File(outFileName, fileContents);
22922         },
22924         /**
22925          * Optimizes a file that contains JavaScript content. Optionally collects
22926          * plugin resources mentioned in a file, and then passes the content
22927          * through an minifier if one is specified via config.optimize.
22928          *
22929          * @param {String} fileName the name of the file that matches the
22930          * fileContents.
22931          * @param {String} fileContents the string of JS to optimize.
22932          * @param {Object} [config] the build config object.
22933          * @param {Array} [pluginCollector] storage for any plugin resources
22934          * found.
22935          */
22936         js: function (fileName, fileContents, outFileName, config, pluginCollector) {
22937             var optFunc, optConfig,
22938                 parts = (String(config.optimize)).split('.'),
22939                 optimizerName = parts[0],
22940                 keepLines = parts[1] === 'keepLines',
22941                 licenseContents = '';
22943             config = config || {};
22945             //Apply pragmas/namespace renaming
22946             fileContents = pragma.process(fileName, fileContents, config, 'OnSave', pluginCollector);
22948             //Optimize the JS files if asked.
22949             if (optimizerName && optimizerName !== 'none') {
22950                 optFunc = envOptimize[optimizerName] || optimize.optimizers[optimizerName];
22951                 if (!optFunc) {
22952                     throw new Error('optimizer with name of "' +
22953                                     optimizerName +
22954                                     '" not found for this environment');
22955                 }
22957                 optConfig = config[optimizerName] || {};
22958                 if (config.generateSourceMaps) {
22959                     optConfig.generateSourceMaps = !!config.generateSourceMaps;
22960                 }
22962                 try {
22963                     if (config.preserveLicenseComments) {
22964                         //Pull out any license comments for prepending after optimization.
22965                         try {
22966                             licenseContents = parse.getLicenseComments(fileName, fileContents);
22967                         } catch (e) {
22968                             throw new Error('Cannot parse file: ' + fileName + ' for comments. Skipping it. Error is:\n' + e.toString());
22969                         }
22970                     }
22972                     fileContents = licenseContents + optFunc(fileName,
22973                                                              fileContents,
22974                                                              outFileName,
22975                                                              keepLines,
22976                                                              optConfig);
22977                 } catch (e) {
22978                     if (config.throwWhen && config.throwWhen.optimize) {
22979                         throw e;
22980                     } else {
22981                         logger.error(e);
22982                     }
22983                 }
22984             }
22986             return fileContents;
22987         },
22989         /**
22990          * Optimizes one CSS file, inlining @import calls, stripping comments, and
22991          * optionally removes line returns.
22992          * @param {String} fileName the path to the CSS file to optimize
22993          * @param {String} outFileName the path to save the optimized file.
22994          * @param {Object} config the config object with the optimizeCss and
22995          * cssImportIgnore options.
22996          */
22997         cssFile: function (fileName, outFileName, config) {
22999             //Read in the file. Make sure we have a JS string.
23000             var originalFileContents = file.readFile(fileName),
23001                 flat = flattenCss(fileName, originalFileContents, config.cssImportIgnore, config.cssPrefix, {}),
23002                 //Do not use the flattened CSS if there was one that was skipped.
23003                 fileContents = flat.skippedList.length ? originalFileContents : flat.fileContents,
23004                 startIndex, endIndex, buildText, comment;
23006             if (flat.skippedList.length) {
23007                 logger.warn('Cannot inline @imports for ' + fileName +
23008                             ',\nthe following files had media queries in them:\n' +
23009                             flat.skippedList.join('\n'));
23010             }
23012             //Do comment removal.
23013             try {
23014                 if (config.optimizeCss.indexOf(".keepComments") === -1) {
23015                     startIndex = 0;
23016                     //Get rid of comments.
23017                     while ((startIndex = fileContents.indexOf("/*", startIndex)) !== -1) {
23018                         endIndex = fileContents.indexOf("*/", startIndex + 2);
23019                         if (endIndex === -1) {
23020                             throw "Improper comment in CSS file: " + fileName;
23021                         }
23022                         comment = fileContents.substring(startIndex, endIndex);
23024                         if (config.preserveLicenseComments &&
23025                             (comment.indexOf('license') !== -1 ||
23026                              comment.indexOf('opyright') !== -1 ||
23027                              comment.indexOf('(c)') !== -1)) {
23028                             //Keep the comment, just increment the startIndex
23029                             startIndex = endIndex;
23030                         } else {
23031                             fileContents = fileContents.substring(0, startIndex) + fileContents.substring(endIndex + 2, fileContents.length);
23032                             startIndex = 0;
23033                         }
23034                     }
23035                 }
23036                 //Get rid of newlines.
23037                 if (config.optimizeCss.indexOf(".keepLines") === -1) {
23038                     fileContents = fileContents.replace(/[\r\n]/g, "");
23039                     fileContents = fileContents.replace(/\s+/g, " ");
23040                     fileContents = fileContents.replace(/\{\s/g, "{");
23041                     fileContents = fileContents.replace(/\s\}/g, "}");
23042                 } else {
23043                     //Remove multiple empty lines.
23044                     fileContents = fileContents.replace(/(\r\n)+/g, "\r\n");
23045                     fileContents = fileContents.replace(/(\n)+/g, "\n");
23046                 }
23047             } catch (e) {
23048                 fileContents = originalFileContents;
23049                 logger.error("Could not optimized CSS file: " + fileName + ", error: " + e);
23050             }
23052             file.saveUtf8File(outFileName, fileContents);
23054             //text output to stdout and/or written to build.txt file
23055             buildText = "\n"+ outFileName.replace(config.dir, "") +"\n----------------\n";
23056             flat.importList.push(fileName);
23057             buildText += flat.importList.map(function(path){
23058                 return path.replace(config.dir, "");
23059             }).join("\n");
23061             return {
23062                 importList: flat.importList,
23063                 buildText: buildText +"\n"
23064             };
23065         },
23067         /**
23068          * Optimizes CSS files, inlining @import calls, stripping comments, and
23069          * optionally removes line returns.
23070          * @param {String} startDir the path to the top level directory
23071          * @param {Object} config the config object with the optimizeCss and
23072          * cssImportIgnore options.
23073          */
23074         css: function (startDir, config) {
23075             var buildText = "",
23076                 importList = [],
23077                 shouldRemove = config.dir && config.removeCombined,
23078                 i, fileName, result, fileList;
23079             if (config.optimizeCss.indexOf("standard") !== -1) {
23080                 fileList = file.getFilteredFileList(startDir, /\.css$/, true);
23081                 if (fileList) {
23082                     for (i = 0; i < fileList.length; i++) {
23083                         fileName = fileList[i];
23084                         logger.trace("Optimizing (" + config.optimizeCss + ") CSS file: " + fileName);
23085                         result = optimize.cssFile(fileName, fileName, config);
23086                         buildText += result.buildText;
23087                         if (shouldRemove) {
23088                             result.importList.pop();
23089                             importList = importList.concat(result.importList);
23090                         }
23091                     }
23092                 }
23094                 if (shouldRemove) {
23095                     importList.forEach(function (path) {
23096                         if (file.exists(path)) {
23097                             file.deleteFile(path);
23098                         }
23099                     });
23100                 }
23101             }
23102             return buildText;
23103         },
23105         optimizers: {
23106             uglify: function (fileName, fileContents, outFileName, keepLines, config) {
23107                 var parser = uglify.parser,
23108                     processor = uglify.uglify,
23109                     ast, errMessage, errMatch;
23111                 config = config || {};
23113                 logger.trace("Uglifying file: " + fileName);
23115                 try {
23116                     ast = parser.parse(fileContents, config.strict_semicolons);
23117                     if (config.no_mangle !== true) {
23118                         ast = processor.ast_mangle(ast, config);
23119                     }
23120                     ast = processor.ast_squeeze(ast, config);
23122                     fileContents = processor.gen_code(ast, config);
23124                     if (config.max_line_length) {
23125                         fileContents = processor.split_lines(fileContents, config.max_line_length);
23126                     }
23128                     //Add trailing semicolon to match uglifyjs command line version
23129                     fileContents += ';';
23130                 } catch (e) {
23131                     errMessage = e.toString();
23132                     errMatch = /\nError(\r)?\n/.exec(errMessage);
23133                     if (errMatch) {
23134                         errMessage = errMessage.substring(0, errMatch.index);
23135                     }
23136                     throw new Error('Cannot uglify file: ' + fileName + '. Skipping it. Error is:\n' + errMessage);
23137                 }
23138                 return fileContents;
23139             },
23140             uglify2: function (fileName, fileContents, outFileName, keepLines, config) {
23141                 var result, existingMap, resultMap, finalMap, sourceIndex,
23142                     uconfig = {},
23143                     existingMapPath = outFileName + '.map',
23144                     baseName = fileName && fileName.split('/').pop();
23146                 config = config || {};
23148                 lang.mixin(uconfig, config, true);
23150                 uconfig.fromString = true;
23152                 if (config.generateSourceMaps && outFileName) {
23153                     uconfig.outSourceMap = baseName;
23155                     if (file.exists(existingMapPath)) {
23156                         uconfig.inSourceMap = existingMapPath;
23157                         existingMap = JSON.parse(file.readFile(existingMapPath));
23158                     }
23159                 }
23161                 logger.trace("Uglify2 file: " + fileName);
23163                 try {
23164                     //var tempContents = fileContents.replace(/\/\/\# sourceMappingURL=.*$/, '');
23165                     result = uglify2.minify(fileContents, uconfig, baseName + '.src.js');
23166                     if (uconfig.outSourceMap && result.map) {
23167                         resultMap = result.map;
23168                         if (existingMap) {
23169                             resultMap = JSON.parse(resultMap);
23170                             finalMap = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(resultMap));
23171                             finalMap.applySourceMap(new SourceMapConsumer(existingMap));
23172                             resultMap = finalMap.toString();
23173                         } else {
23174                             file.saveFile(outFileName + '.src.js', fileContents);
23175                         }
23176                         file.saveFile(outFileName + '.map', resultMap);
23177                         fileContents = result.code + "\n//# sourceMappingURL=" + baseName + ".map";
23178                     } else {
23179                         fileContents = result.code;
23180                     }
23181                 } catch (e) {
23182                     throw new Error('Cannot uglify2 file: ' + fileName + '. Skipping it. Error is:\n' + e.toString());
23183                 }
23184                 return fileContents;
23185             }
23186         }
23187     };
23189     return optimize;
23192  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
23193  * Available via the MIT or new BSD license.
23194  * see: http://github.com/jrburke/requirejs for details
23195  */
23197  * This file patches require.js to communicate with the build system.
23198  */
23200 //Using sloppy since this uses eval for some code like plugins,
23201 //which may not be strict mode compliant. So if use strict is used
23202 //below they will have strict rules applied and may cause an error.
23203 /*jslint sloppy: true, nomen: true, plusplus: true, regexp: true */
23204 /*global require, define: true */
23206 //NOT asking for require as a dependency since the goal is to modify the
23207 //global require below
23208 define('requirePatch', [ 'env!env/file', 'pragma', 'parse', 'lang', 'logger', 'commonJs', 'prim'], function (
23209     file,
23210     pragma,
23211     parse,
23212     lang,
23213     logger,
23214     commonJs,
23215     prim
23216 ) {
23218     var allowRun = true,
23219         hasProp = lang.hasProp,
23220         falseProp = lang.falseProp,
23221         getOwn = lang.getOwn;
23223     //This method should be called when the patches to require should take hold.
23224     return function () {
23225         if (!allowRun) {
23226             return;
23227         }
23228         allowRun = false;
23230         var layer,
23231             pluginBuilderRegExp = /(["']?)pluginBuilder(["']?)\s*[=\:]\s*["']([^'"\s]+)["']/,
23232             oldNewContext = require.s.newContext,
23233             oldDef,
23235             //create local undefined values for module and exports,
23236             //so that when files are evaled in this function they do not
23237             //see the node values used for r.js
23238             exports,
23239             module;
23241         /**
23242          * Reset "global" build caches that are kept around between
23243          * build layer builds. Useful to do when there are multiple
23244          * top level requirejs.optimize() calls.
23245          */
23246         require._cacheReset = function () {
23247             //Stored raw text caches, used by browser use.
23248             require._cachedRawText = {};
23249             //Stored cached file contents for reuse in other layers.
23250             require._cachedFileContents = {};
23251             //Store which cached files contain a require definition.
23252             require._cachedDefinesRequireUrls = {};
23253         };
23254         require._cacheReset();
23256         /**
23257          * Makes sure the URL is something that can be supported by the
23258          * optimization tool.
23259          * @param {String} url
23260          * @returns {Boolean}
23261          */
23262         require._isSupportedBuildUrl = function (url) {
23263             //Ignore URLs with protocols, hosts or question marks, means either network
23264             //access is needed to fetch it or it is too dynamic. Note that
23265             //on Windows, full paths are used for some urls, which include
23266             //the drive, like c:/something, so need to test for something other
23267             //than just a colon.
23268             if (url.indexOf("://") === -1 && url.indexOf("?") === -1 &&
23269                     url.indexOf('empty:') !== 0 && url.indexOf('//') !== 0) {
23270                 return true;
23271             } else {
23272                 if (!layer.ignoredUrls[url]) {
23273                     if (url.indexOf('empty:') === -1) {
23274                         logger.info('Cannot optimize network URL, skipping: ' + url);
23275                     }
23276                     layer.ignoredUrls[url] = true;
23277                 }
23278                 return false;
23279             }
23280         };
23282         function normalizeUrlWithBase(context, moduleName, url) {
23283             //Adjust the URL if it was not transformed to use baseUrl.
23284             if (require.jsExtRegExp.test(moduleName)) {
23285                 url = (context.config.dir || context.config.dirBaseUrl) + url;
23286             }
23287             return url;
23288         }
23290         //Overrides the new context call to add existing tracking features.
23291         require.s.newContext = function (name) {
23292             var context = oldNewContext(name),
23293                 oldEnable = context.enable,
23294                 moduleProto = context.Module.prototype,
23295                 oldInit = moduleProto.init,
23296                 oldCallPlugin = moduleProto.callPlugin;
23298             //Only do this for the context used for building.
23299             if (name === '_') {
23300                 //For build contexts, do everything sync
23301                 context.nextTick = function (fn) {
23302                     fn();
23303                 };
23305                 context.needFullExec = {};
23306                 context.fullExec = {};
23307                 context.plugins = {};
23308                 context.buildShimExports = {};
23310                 //Override the shim exports function generator to just
23311                 //spit out strings that can be used in the stringified
23312                 //build output.
23313                 context.makeShimExports = function (value) {
23314                     function fn() {
23315                         return '(function (global) {\n' +
23316                             '    return function () {\n' +
23317                             '        var ret, fn;\n' +
23318                             (value.init ?
23319                                     ('       fn = ' + value.init.toString() + ';\n' +
23320                                     '        ret = fn.apply(global, arguments);\n') : '') +
23321                             (value.exports ?
23322                                     '        return ret || global.' + value.exports + ';\n' :
23323                                     '        return ret;\n') +
23324                             '    };\n' +
23325                             '}(this))';
23326                     }
23328                     return fn;
23329                 };
23331                 context.enable = function (depMap, parent) {
23332                     var id = depMap.id,
23333                         parentId = parent && parent.map.id,
23334                         needFullExec = context.needFullExec,
23335                         fullExec = context.fullExec,
23336                         mod = getOwn(context.registry, id);
23338                     if (mod && !mod.defined) {
23339                         if (parentId && getOwn(needFullExec, parentId)) {
23340                             needFullExec[id] = true;
23341                         }
23343                     } else if ((getOwn(needFullExec, id) && falseProp(fullExec, id)) ||
23344                                (parentId && getOwn(needFullExec, parentId) &&
23345                                 falseProp(fullExec, id))) {
23346                         context.require.undef(id);
23347                     }
23349                     return oldEnable.apply(context, arguments);
23350                 };
23352                 //Override load so that the file paths can be collected.
23353                 context.load = function (moduleName, url) {
23354                     /*jslint evil: true */
23355                     var contents, pluginBuilderMatch, builderName,
23356                         shim, shimExports;
23358                     //Do not mark the url as fetched if it is
23359                     //not an empty: URL, used by the optimizer.
23360                     //In that case we need to be sure to call
23361                     //load() for each module that is mapped to
23362                     //empty: so that dependencies are satisfied
23363                     //correctly.
23364                     if (url.indexOf('empty:') === 0) {
23365                         delete context.urlFetched[url];
23366                     }
23368                     //Only handle urls that can be inlined, so that means avoiding some
23369                     //URLs like ones that require network access or may be too dynamic,
23370                     //like JSONP
23371                     if (require._isSupportedBuildUrl(url)) {
23372                         //Adjust the URL if it was not transformed to use baseUrl.
23373                         url = normalizeUrlWithBase(context, moduleName, url);
23375                         //Save the module name to path  and path to module name mappings.
23376                         layer.buildPathMap[moduleName] = url;
23377                         layer.buildFileToModule[url] = moduleName;
23379                         if (hasProp(context.plugins, moduleName)) {
23380                             //plugins need to have their source evaled as-is.
23381                             context.needFullExec[moduleName] = true;
23382                         }
23384                         prim().start(function () {
23385                             if (hasProp(require._cachedFileContents, url) &&
23386                                     (falseProp(context.needFullExec, moduleName) ||
23387                                     getOwn(context.fullExec, moduleName))) {
23388                                 contents = require._cachedFileContents[url];
23390                                 //If it defines require, mark it so it can be hoisted.
23391                                 //Done here and in the else below, before the
23392                                 //else block removes code from the contents.
23393                                 //Related to #263
23394                                 if (!layer.existingRequireUrl && require._cachedDefinesRequireUrls[url]) {
23395                                     layer.existingRequireUrl = url;
23396                                 }
23397                             } else {
23398                                 //Load the file contents, process for conditionals, then
23399                                 //evaluate it.
23400                                 return require._cacheReadAsync(url).then(function (text) {
23401                                     contents = text;
23403                                     if (context.config.cjsTranslate &&
23404                                         (!context.config.shim || !lang.hasProp(context.config.shim, moduleName))) {
23405                                         contents = commonJs.convert(url, contents);
23406                                     }
23408                                     //If there is a read filter, run it now.
23409                                     if (context.config.onBuildRead) {
23410                                         contents = context.config.onBuildRead(moduleName, url, contents);
23411                                     }
23413                                     contents = pragma.process(url, contents, context.config, 'OnExecute');
23415                                     //Find out if the file contains a require() definition. Need to know
23416                                     //this so we can inject plugins right after it, but before they are needed,
23417                                     //and to make sure this file is first, so that define calls work.
23418                                     try {
23419                                         if (!layer.existingRequireUrl && parse.definesRequire(url, contents)) {
23420                                             layer.existingRequireUrl = url;
23421                                             require._cachedDefinesRequireUrls[url] = true;
23422                                         }
23423                                     } catch (e1) {
23424                                         throw new Error('Parse error using esprima ' +
23425                                                         'for file: ' + url + '\n' + e1);
23426                                     }
23427                                 }).then(function () {
23428                                     if (hasProp(context.plugins, moduleName)) {
23429                                         //This is a loader plugin, check to see if it has a build extension,
23430                                         //otherwise the plugin will act as the plugin builder too.
23431                                         pluginBuilderMatch = pluginBuilderRegExp.exec(contents);
23432                                         if (pluginBuilderMatch) {
23433                                             //Load the plugin builder for the plugin contents.
23434                                             builderName = context.makeModuleMap(pluginBuilderMatch[3],
23435                                                                                 context.makeModuleMap(moduleName),
23436                                                                                 null,
23437                                                                                 true).id;
23438                                             return require._cacheReadAsync(context.nameToUrl(builderName));
23439                                         }
23440                                     }
23441                                     return contents;
23442                                 }).then(function (text) {
23443                                     contents = text;
23445                                     //Parse out the require and define calls.
23446                                     //Do this even for plugins in case they have their own
23447                                     //dependencies that may be separate to how the pluginBuilder works.
23448                                     try {
23449                                         if (falseProp(context.needFullExec, moduleName)) {
23450                                             contents = parse(moduleName, url, contents, {
23451                                                 insertNeedsDefine: true,
23452                                                 has: context.config.has,
23453                                                 findNestedDependencies: context.config.findNestedDependencies
23454                                             });
23455                                         }
23456                                     } catch (e2) {
23457                                         throw new Error('Parse error using esprima ' +
23458                                                         'for file: ' + url + '\n' + e2);
23459                                     }
23461                                     require._cachedFileContents[url] = contents;
23462                                 });
23463                             }
23464                         }).then(function () {
23465                             if (contents) {
23466                                 eval(contents);
23467                             }
23469                             try {
23470                                 //If have a string shim config, and this is
23471                                 //a fully executed module, try to see if
23472                                 //it created a variable in this eval scope
23473                                 if (getOwn(context.needFullExec, moduleName)) {
23474                                     shim = getOwn(context.config.shim, moduleName);
23475                                     if (shim && shim.exports) {
23476                                         shimExports = eval(shim.exports);
23477                                         if (typeof shimExports !== 'undefined') {
23478                                             context.buildShimExports[moduleName] = shimExports;
23479                                         }
23480                                     }
23481                                 }
23483                                 //Need to close out completion of this module
23484                                 //so that listeners will get notified that it is available.
23485                                 context.completeLoad(moduleName);
23486                             } catch (e) {
23487                                 //Track which module could not complete loading.
23488                                 if (!e.moduleTree) {
23489                                     e.moduleTree = [];
23490                                 }
23491                                 e.moduleTree.push(moduleName);
23492                                 throw e;
23493                             }
23494                         }).then(null, function (eOuter) {
23496                             if (!eOuter.fileName) {
23497                                 eOuter.fileName = url;
23498                             }
23499                             throw eOuter;
23500                         }).end();
23501                     } else {
23502                         //With unsupported URLs still need to call completeLoad to
23503                         //finish loading.
23504                         context.completeLoad(moduleName);
23505                     }
23506                 };
23508                 //Marks module has having a name, and optionally executes the
23509                 //callback, but only if it meets certain criteria.
23510                 context.execCb = function (name, cb, args, exports) {
23511                     var buildShimExports = getOwn(layer.context.buildShimExports, name);
23513                     if (buildShimExports) {
23514                         return buildShimExports;
23515                     } else if (cb.__requireJsBuild || getOwn(layer.context.needFullExec, name)) {
23516                         return cb.apply(exports, args);
23517                     }
23518                     return undefined;
23519                 };
23521                 moduleProto.init = function (depMaps) {
23522                     if (context.needFullExec[this.map.id]) {
23523                         lang.each(depMaps, lang.bind(this, function (depMap) {
23524                             if (typeof depMap === 'string') {
23525                                 depMap = context.makeModuleMap(depMap,
23526                                                (this.map.isDefine ? this.map : this.map.parentMap));
23527                             }
23529                             if (!context.fullExec[depMap.id]) {
23530                                 context.require.undef(depMap.id);
23531                             }
23532                         }));
23533                     }
23535                     return oldInit.apply(this, arguments);
23536                 };
23538                 moduleProto.callPlugin = function () {
23539                     var map = this.map,
23540                         pluginMap = context.makeModuleMap(map.prefix),
23541                         pluginId = pluginMap.id,
23542                         pluginMod = getOwn(context.registry, pluginId);
23544                     context.plugins[pluginId] = true;
23545                     context.needFullExec[pluginId] = true;
23547                     //If the module is not waiting to finish being defined,
23548                     //undef it and start over, to get full execution.
23549                     if (falseProp(context.fullExec, pluginId) && (!pluginMod || pluginMod.defined)) {
23550                         context.require.undef(pluginMap.id);
23551                     }
23553                     return oldCallPlugin.apply(this, arguments);
23554                 };
23555             }
23557             return context;
23558         };
23560         //Clear up the existing context so that the newContext modifications
23561         //above will be active.
23562         delete require.s.contexts._;
23564         /** Reset state for each build layer pass. */
23565         require._buildReset = function () {
23566             var oldContext = require.s.contexts._;
23568             //Clear up the existing context.
23569             delete require.s.contexts._;
23571             //Set up new context, so the layer object can hold onto it.
23572             require({});
23574             layer = require._layer = {
23575                 buildPathMap: {},
23576                 buildFileToModule: {},
23577                 buildFilePaths: [],
23578                 pathAdded: {},
23579                 modulesWithNames: {},
23580                 needsDefine: {},
23581                 existingRequireUrl: "",
23582                 ignoredUrls: {},
23583                 context: require.s.contexts._
23584             };
23586             //Return the previous context in case it is needed, like for
23587             //the basic config object.
23588             return oldContext;
23589         };
23591         require._buildReset();
23593         //Override define() to catch modules that just define an object, so that
23594         //a dummy define call is not put in the build file for them. They do
23595         //not end up getting defined via context.execCb, so we need to catch them
23596         //at the define call.
23597         oldDef = define;
23599         //This function signature does not have to be exact, just match what we
23600         //are looking for.
23601         define = function (name) {
23602             if (typeof name === "string" && falseProp(layer.needsDefine, name)) {
23603                 layer.modulesWithNames[name] = true;
23604             }
23605             return oldDef.apply(require, arguments);
23606         };
23608         define.amd = oldDef.amd;
23610         //Add some utilities for plugins
23611         require._readFile = file.readFile;
23612         require._fileExists = function (path) {
23613             return file.exists(path);
23614         };
23616         //Called when execManager runs for a dependency. Used to figure out
23617         //what order of execution.
23618         require.onResourceLoad = function (context, map) {
23619             var id = map.id,
23620                 url;
23622             //If build needed a full execution, indicate it
23623             //has been done now. But only do it if the context is tracking
23624             //that. Only valid for the context used in a build, not for
23625             //other contexts being run, like for useLib, plain requirejs
23626             //use in node/rhino.
23627             if (context.needFullExec && getOwn(context.needFullExec, id)) {
23628                 context.fullExec[id] = true;
23629             }
23631             //A plugin.
23632             if (map.prefix) {
23633                 if (falseProp(layer.pathAdded, id)) {
23634                     layer.buildFilePaths.push(id);
23635                     //For plugins the real path is not knowable, use the name
23636                     //for both module to file and file to module mappings.
23637                     layer.buildPathMap[id] = id;
23638                     layer.buildFileToModule[id] = id;
23639                     layer.modulesWithNames[id] = true;
23640                     layer.pathAdded[id] = true;
23641                 }
23642             } else if (map.url && require._isSupportedBuildUrl(map.url)) {
23643                 //If the url has not been added to the layer yet, and it
23644                 //is from an actual file that was loaded, add it now.
23645                 url = normalizeUrlWithBase(context, id, map.url);
23646                 if (!layer.pathAdded[url] && getOwn(layer.buildPathMap, id)) {
23647                     //Remember the list of dependencies for this layer.
23648                     layer.buildFilePaths.push(url);
23649                     layer.pathAdded[url] = true;
23650                 }
23651             }
23652         };
23654         //Called by output of the parse() function, when a file does not
23655         //explicitly call define, probably just require, but the parse()
23656         //function normalizes on define() for dependency mapping and file
23657         //ordering works correctly.
23658         require.needsDefine = function (moduleName) {
23659             layer.needsDefine[moduleName] = true;
23660         };
23661     };
23664  * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
23665  * Available via the MIT or new BSD license.
23666  * see: http://github.com/jrburke/requirejs for details
23667  */
23669 /*jslint */
23670 /*global define: false, console: false */
23672 define('commonJs', ['env!env/file', 'parse'], function (file, parse) {
23673     'use strict';
23674     var commonJs = {
23675         //Set to false if you do not want this file to log. Useful in environments
23676         //like node where you want the work to happen without noise.
23677         useLog: true,
23679         convertDir: function (commonJsPath, savePath) {
23680             var fileList, i,
23681                 jsFileRegExp = /\.js$/,
23682                 fileName, convertedFileName, fileContents;
23684             //Get list of files to convert.
23685             fileList = file.getFilteredFileList(commonJsPath, /\w/, true);
23687             //Normalize on front slashes and make sure the paths do not end in a slash.
23688             commonJsPath = commonJsPath.replace(/\\/g, "/");
23689             savePath = savePath.replace(/\\/g, "/");
23690             if (commonJsPath.charAt(commonJsPath.length - 1) === "/") {
23691                 commonJsPath = commonJsPath.substring(0, commonJsPath.length - 1);
23692             }
23693             if (savePath.charAt(savePath.length - 1) === "/") {
23694                 savePath = savePath.substring(0, savePath.length - 1);
23695             }
23697             //Cycle through all the JS files and convert them.
23698             if (!fileList || !fileList.length) {
23699                 if (commonJs.useLog) {
23700                     if (commonJsPath === "convert") {
23701                         //A request just to convert one file.
23702                         console.log('\n\n' + commonJs.convert(savePath, file.readFile(savePath)));
23703                     } else {
23704                         console.log("No files to convert in directory: " + commonJsPath);
23705                     }
23706                 }
23707             } else {
23708                 for (i = 0; i < fileList.length; i++) {
23709                     fileName = fileList[i];
23710                     convertedFileName = fileName.replace(commonJsPath, savePath);
23712                     //Handle JS files.
23713                     if (jsFileRegExp.test(fileName)) {
23714                         fileContents = file.readFile(fileName);
23715                         fileContents = commonJs.convert(fileName, fileContents);
23716                         file.saveUtf8File(convertedFileName, fileContents);
23717                     } else {
23718                         //Just copy the file over.
23719                         file.copyFile(fileName, convertedFileName, true);
23720                     }
23721                 }
23722             }
23723         },
23725         /**
23726          * Does the actual file conversion.
23727          *
23728          * @param {String} fileName the name of the file.
23729          *
23730          * @param {String} fileContents the contents of a file :)
23731          *
23732          * @returns {String} the converted contents
23733          */
23734         convert: function (fileName, fileContents) {
23735             //Strip out comments.
23736             try {
23737                 var preamble = '',
23738                     commonJsProps = parse.usesCommonJs(fileName, fileContents);
23740                 //First see if the module is not already RequireJS-formatted.
23741                 if (parse.usesAmdOrRequireJs(fileName, fileContents) || !commonJsProps) {
23742                     return fileContents;
23743                 }
23745                 if (commonJsProps.dirname || commonJsProps.filename) {
23746                     preamble = 'var __filename = module.uri || "", ' +
23747                                '__dirname = __filename.substring(0, __filename.lastIndexOf("/") + 1); ';
23748                 }
23750                 //Construct the wrapper boilerplate.
23751                 fileContents = 'define(function (require, exports, module) {' +
23752                     preamble +
23753                     fileContents +
23754                     '\n});\n';
23756             } catch (e) {
23757                 console.log("commonJs.convert: COULD NOT CONVERT: " + fileName + ", so skipping it. Error was: " + e);
23758                 return fileContents;
23759             }
23761             return fileContents;
23762         }
23763     };
23765     return commonJs;
23768  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
23769  * Available via the MIT or new BSD license.
23770  * see: http://github.com/jrburke/requirejs for details
23771  */
23773 /*jslint plusplus: true, nomen: true, regexp: true  */
23774 /*global define, requirejs */
23777 define('build', function (require) {
23778     'use strict';
23780     var build, buildBaseConfig,
23781         lang = require('lang'),
23782         prim = require('prim'),
23783         logger = require('logger'),
23784         file = require('env!env/file'),
23785         parse = require('parse'),
23786         optimize = require('optimize'),
23787         pragma = require('pragma'),
23788         transform = require('transform'),
23789         requirePatch = require('requirePatch'),
23790         env = require('env'),
23791         commonJs = require('commonJs'),
23792         SourceMapGenerator = require('source-map/source-map-generator'),
23793         hasProp = lang.hasProp,
23794         getOwn = lang.getOwn,
23795         falseProp = lang.falseProp,
23796         endsWithSemiColonRegExp = /;\s*$/;
23798     prim.nextTick = function (fn) {
23799         fn();
23800     };
23802     //Now map require to the outermost requirejs, now that we have
23803     //local dependencies for this module. The rest of the require use is
23804     //manipulating the requirejs loader.
23805     require = requirejs;
23807     //Caching function for performance. Attached to
23808     //require so it can be reused in requirePatch.js. _cachedRawText
23809     //set up by requirePatch.js
23810     require._cacheReadAsync = function (path, encoding) {
23811         var d;
23813         if (lang.hasProp(require._cachedRawText, path)) {
23814             d = prim();
23815             d.resolve(require._cachedRawText[path]);
23816             return d.promise;
23817         } else {
23818             return file.readFileAsync(path, encoding).then(function (text) {
23819                 require._cachedRawText[path] = text;
23820                 return text;
23821             });
23822         }
23823     };
23825     buildBaseConfig = {
23826         appDir: "",
23827         pragmas: {},
23828         paths: {},
23829         optimize: "uglify",
23830         optimizeCss: "standard.keepLines",
23831         inlineText: true,
23832         isBuild: true,
23833         optimizeAllPluginResources: false,
23834         findNestedDependencies: false,
23835         preserveLicenseComments: true,
23836         //By default, all files/directories are copied, unless
23837         //they match this regexp, by default just excludes .folders
23838         dirExclusionRegExp: file.dirExclusionRegExp,
23839         _buildPathToModuleIndex: {}
23840     };
23842     /**
23843      * Some JS may not be valid if concatenated with other JS, in particular
23844      * the style of omitting semicolons and rely on ASI. Add a semicolon in
23845      * those cases.
23846      */
23847     function addSemiColon(text, config) {
23848         if (config.skipSemiColonInsertion || endsWithSemiColonRegExp.test(text)) {
23849             return text;
23850         } else {
23851             return text + ";";
23852         }
23853     }
23855     function endsWithSlash(dirName) {
23856         if (dirName.charAt(dirName.length - 1) !== "/") {
23857             dirName += "/";
23858         }
23859         return dirName;
23860     }
23862     //Method used by plugin writeFile calls, defined up here to avoid
23863     //jslint warning about "making a function in a loop".
23864     function makeWriteFile(namespace, layer) {
23865         function writeFile(name, contents) {
23866             logger.trace('Saving plugin-optimized file: ' + name);
23867             file.saveUtf8File(name, contents);
23868         }
23870         writeFile.asModule = function (moduleName, fileName, contents) {
23871             writeFile(fileName,
23872                 build.toTransport(namespace, moduleName, fileName, contents, layer));
23873         };
23875         return writeFile;
23876     }
23878     /**
23879      * Main API entry point into the build. The args argument can either be
23880      * an array of arguments (like the onese passed on a command-line),
23881      * or it can be a JavaScript object that has the format of a build profile
23882      * file.
23883      *
23884      * If it is an object, then in addition to the normal properties allowed in
23885      * a build profile file, the object should contain one other property:
23886      *
23887      * The object could also contain a "buildFile" property, which is a string
23888      * that is the file path to a build profile that contains the rest
23889      * of the build profile directives.
23890      *
23891      * This function does not return a status, it should throw an error if
23892      * there is a problem completing the build.
23893      */
23894     build = function (args) {
23895         var buildFile, cmdConfig, errorMsg, errorStack, stackMatch, errorTree,
23896             i, j, errorMod,
23897             stackRegExp = /( {4}at[^\n]+)\n/,
23898             standardIndent = '  ';
23900         return prim().start(function () {
23901             if (!args || lang.isArray(args)) {
23902                 if (!args || args.length < 1) {
23903                     logger.error("build.js buildProfile.js\n" +
23904                           "where buildProfile.js is the name of the build file (see example.build.js for hints on how to make a build file).");
23905                     return undefined;
23906                 }
23908                 //Next args can include a build file path as well as other build args.
23909                 //build file path comes first. If it does not contain an = then it is
23910                 //a build file path. Otherwise, just all build args.
23911                 if (args[0].indexOf("=") === -1) {
23912                     buildFile = args[0];
23913                     args.splice(0, 1);
23914                 }
23916                 //Remaining args are options to the build
23917                 cmdConfig = build.convertArrayToObject(args);
23918                 cmdConfig.buildFile = buildFile;
23919             } else {
23920                 cmdConfig = args;
23921             }
23923             return build._run(cmdConfig);
23924         }).then(null, function (e) {
23925             errorMsg = e.toString();
23926             errorTree = e.moduleTree;
23927             stackMatch = stackRegExp.exec(errorMsg);
23929             if (stackMatch) {
23930                 errorMsg += errorMsg.substring(0, stackMatch.index + stackMatch[0].length + 1);
23931             }
23933             //If a module tree that shows what module triggered the error,
23934             //print it out.
23935             if (errorTree && errorTree.length > 0) {
23936                 errorMsg += '\nIn module tree:\n';
23938                 for (i = errorTree.length - 1; i > -1; i--) {
23939                     errorMod = errorTree[i];
23940                     if (errorMod) {
23941                         for (j = errorTree.length - i; j > -1; j--) {
23942                             errorMsg += standardIndent;
23943                         }
23944                         errorMsg += errorMod + '\n';
23945                     }
23946                 }
23948                 logger.error(errorMsg);
23949             }
23951             errorStack = e.stack;
23953             if (typeof args === 'string' && args.indexOf('stacktrace=true') !== -1) {
23954                 errorMsg += '\n' + errorStack;
23955             } else {
23956                 if (!stackMatch && errorStack) {
23957                     //Just trim out the first "at" in the stack.
23958                     stackMatch = stackRegExp.exec(errorStack);
23959                     if (stackMatch) {
23960                         errorMsg += '\n' + stackMatch[0] || '';
23961                     }
23962                 }
23963             }
23965             throw new Error(errorMsg);
23966         });
23967     };
23969     build._run = function (cmdConfig) {
23970         var buildPaths, fileName, fileNames,
23971             paths, i,
23972             baseConfig, config,
23973             modules, srcPath, buildContext,
23974             destPath, moduleMap, parentModuleMap, context,
23975             resources, resource, plugin, fileContents,
23976             pluginProcessed = {},
23977             buildFileContents = "",
23978             pluginCollector = {};
23980         return prim().start(function () {
23981             var prop;
23983             //Can now run the patches to require.js to allow it to be used for
23984             //build generation. Do it here instead of at the top of the module
23985             //because we want normal require behavior to load the build tool
23986             //then want to switch to build mode.
23987             requirePatch();
23989             config = build.createConfig(cmdConfig);
23990             paths = config.paths;
23992             //Remove the previous build dir, in case it contains source transforms,
23993             //like the ones done with onBuildRead and onBuildWrite.
23994             if (config.dir && !config.keepBuildDir && file.exists(config.dir)) {
23995                 file.deleteFile(config.dir);
23996             }
23998             if (!config.out && !config.cssIn) {
23999                 //This is not just a one-off file build but a full build profile, with
24000                 //lots of files to process.
24002                 //First copy all the baseUrl content
24003                 file.copyDir((config.appDir || config.baseUrl), config.dir, /\w/, true);
24005                 //Adjust baseUrl if config.appDir is in play, and set up build output paths.
24006                 buildPaths = {};
24007                 if (config.appDir) {
24008                     //All the paths should be inside the appDir, so just adjust
24009                     //the paths to use the dirBaseUrl
24010                     for (prop in paths) {
24011                         if (hasProp(paths, prop)) {
24012                             buildPaths[prop] = paths[prop].replace(config.appDir, config.dir);
24013                         }
24014                     }
24015                 } else {
24016                     //If no appDir, then make sure to copy the other paths to this directory.
24017                     for (prop in paths) {
24018                         if (hasProp(paths, prop)) {
24019                             //Set up build path for each path prefix, but only do so
24020                             //if the path falls out of the current baseUrl
24021                             if (paths[prop].indexOf(config.baseUrl) === 0) {
24022                                 buildPaths[prop] = paths[prop].replace(config.baseUrl, config.dirBaseUrl);
24023                             } else {
24024                                 buildPaths[prop] = paths[prop] === 'empty:' ? 'empty:' : prop.replace(/\./g, "/");
24026                                 //Make sure source path is fully formed with baseUrl,
24027                                 //if it is a relative URL.
24028                                 srcPath = paths[prop];
24029                                 if (srcPath.indexOf('/') !== 0 && srcPath.indexOf(':') === -1) {
24030                                     srcPath = config.baseUrl + srcPath;
24031                                 }
24033                                 destPath = config.dirBaseUrl + buildPaths[prop];
24035                                 //Skip empty: paths
24036                                 if (srcPath !== 'empty:') {
24037                                     //If the srcPath is a directory, copy the whole directory.
24038                                     if (file.exists(srcPath) && file.isDirectory(srcPath)) {
24039                                         //Copy files to build area. Copy all files (the /\w/ regexp)
24040                                         file.copyDir(srcPath, destPath, /\w/, true);
24041                                     } else {
24042                                         //Try a .js extension
24043                                         srcPath += '.js';
24044                                         destPath += '.js';
24045                                         file.copyFile(srcPath, destPath);
24046                                     }
24047                                 }
24048                             }
24049                         }
24050                     }
24051                 }
24052             }
24054             //Figure out source file location for each module layer. Do this by seeding require
24055             //with source area configuration. This is needed so that later the module layers
24056             //can be manually copied over to the source area, since the build may be
24057             //require multiple times and the above copyDir call only copies newer files.
24058             require({
24059                 baseUrl: config.baseUrl,
24060                 paths: paths,
24061                 packagePaths: config.packagePaths,
24062                 packages: config.packages
24063             });
24064             buildContext = require.s.contexts._;
24065             modules = config.modules;
24067             if (modules) {
24068                 modules.forEach(function (module) {
24069                     if (module.name) {
24070                         module._sourcePath = buildContext.nameToUrl(module.name);
24071                         //If the module does not exist, and this is not a "new" module layer,
24072                         //as indicated by a true "create" property on the module, and
24073                         //it is not a plugin-loaded resource, and there is no
24074                         //'rawText' containing the module's source then throw an error.
24075                         if (!file.exists(module._sourcePath) && !module.create &&
24076                                 module.name.indexOf('!') === -1 &&
24077                                 (!config.rawText || !lang.hasProp(config.rawText, module.name))) {
24078                             throw new Error("ERROR: module path does not exist: " +
24079                                             module._sourcePath + " for module named: " + module.name +
24080                                             ". Path is relative to: " + file.absPath('.'));
24081                         }
24082                     }
24083                 });
24084             }
24086             if (config.out) {
24087                 //Just set up the _buildPath for the module layer.
24088                 require(config);
24089                 if (!config.cssIn) {
24090                     config.modules[0]._buildPath = typeof config.out === 'function' ?
24091                                                    'FUNCTION' : config.out;
24092                 }
24093             } else if (!config.cssIn) {
24094                 //Now set up the config for require to use the build area, and calculate the
24095                 //build file locations. Pass along any config info too.
24096                 baseConfig = {
24097                     baseUrl: config.dirBaseUrl,
24098                     paths: buildPaths
24099                 };
24101                 lang.mixin(baseConfig, config);
24102                 require(baseConfig);
24104                 if (modules) {
24105                     modules.forEach(function (module) {
24106                         if (module.name) {
24107                             module._buildPath = buildContext.nameToUrl(module.name, null);
24108                             if (!module.create) {
24109                                 file.copyFile(module._sourcePath, module._buildPath);
24110                             }
24111                         }
24112                     });
24113                 }
24114             }
24116             //Run CSS optimizations before doing JS module tracing, to allow
24117             //things like text loader plugins loading CSS to get the optimized
24118             //CSS.
24119             if (config.optimizeCss && config.optimizeCss !== "none" && config.dir) {
24120                 buildFileContents += optimize.css(config.dir, config);
24121             }
24122         }).then(function () {
24123             var actions = [];
24125             if (modules) {
24126                 actions = modules.map(function (module, i) {
24127                     return function () {
24128                         //Save off buildPath to module index in a hash for quicker
24129                         //lookup later.
24130                         config._buildPathToModuleIndex[module._buildPath] = i;
24132                         //Call require to calculate dependencies.
24133                         return build.traceDependencies(module, config)
24134                             .then(function (layer) {
24135                                 module.layer = layer;
24136                             });
24137                     };
24138                 });
24140                 return prim.serial(actions);
24141             }
24142         }).then(function () {
24143             var actions;
24145             if (modules) {
24146                 //Now build up shadow layers for anything that should be excluded.
24147                 //Do this after tracing dependencies for each module, in case one
24148                 //of those modules end up being one of the excluded values.
24149                 actions = modules.map(function (module) {
24150                     return function () {
24151                         if (module.exclude) {
24152                             module.excludeLayers = [];
24153                             return prim.serial(module.exclude.map(function (exclude, i) {
24154                                 return function () {
24155                                     //See if it is already in the list of modules.
24156                                     //If not trace dependencies for it.
24157                                     var found = build.findBuildModule(exclude, modules);
24158                                     if (found) {
24159                                         module.excludeLayers[i] = found;
24160                                     } else {
24161                                         return build.traceDependencies({name: exclude}, config)
24162                                             .then(function (layer) {
24163                                                 module.excludeLayers[i] = { layer: layer };
24164                                             });
24165                                     }
24166                                 };
24167                             }));
24168                         }
24169                     };
24170                 });
24172                 return prim.serial(actions);
24173             }
24174         }).then(function () {
24175             if (modules) {
24176                 return prim.serial(modules.map(function (module) {
24177                     return function () {
24178                         if (module.exclude) {
24179                             //module.exclude is an array of module names. For each one,
24180                             //get the nested dependencies for it via a matching entry
24181                             //in the module.excludeLayers array.
24182                             module.exclude.forEach(function (excludeModule, i) {
24183                                 var excludeLayer = module.excludeLayers[i].layer,
24184                                     map = excludeLayer.buildFileToModule;
24185                                 excludeLayer.buildFilePaths.forEach(function(filePath){
24186                                     build.removeModulePath(map[filePath], filePath, module.layer);
24187                                 });
24188                             });
24189                         }
24190                         if (module.excludeShallow) {
24191                             //module.excludeShallow is an array of module names.
24192                             //shallow exclusions are just that module itself, and not
24193                             //its nested dependencies.
24194                             module.excludeShallow.forEach(function (excludeShallowModule) {
24195                                 var path = getOwn(module.layer.buildPathMap, excludeShallowModule);
24196                                 if (path) {
24197                                     build.removeModulePath(excludeShallowModule, path, module.layer);
24198                                 }
24199                             });
24200                         }
24202                         //Flatten them and collect the build output for each module.
24203                         return build.flattenModule(module, module.layer, config).then(function (builtModule) {
24204                             var finalText, baseName;
24205                             //Save it to a temp file for now, in case there are other layers that
24206                             //contain optimized content that should not be included in later
24207                             //layer optimizations. See issue #56.
24208                             if (module._buildPath === 'FUNCTION') {
24209                                 module._buildText = builtModule.text;
24210                                 module._buildSourceMap = builtModule.sourceMap;
24211                             } else {
24212                                 finalText = builtModule.text;
24213                                 if (builtModule.sourceMap) {
24214                                     baseName = module._buildPath.split('/');
24215                                     baseName = baseName.pop();
24216                                     finalText += '\n//# sourceMappingURL=' + baseName + '.map';
24217                                     file.saveUtf8File(module._buildPath + '.map', builtModule.sourceMap);
24218                                 }
24219                                 file.saveUtf8File(module._buildPath + '-temp', finalText);
24221                             }
24222                             buildFileContents += builtModule.buildText;
24223                         });
24224                     };
24225                 }));
24226             }
24227         }).then(function () {
24228             var moduleName;
24229             if (modules) {
24230                 //Now move the build layers to their final position.
24231                 modules.forEach(function (module) {
24232                     var finalPath = module._buildPath;
24233                     if (finalPath !== 'FUNCTION') {
24234                         if (file.exists(finalPath)) {
24235                             file.deleteFile(finalPath);
24236                         }
24237                         file.renameFile(finalPath + '-temp', finalPath);
24239                         //And finally, if removeCombined is specified, remove
24240                         //any of the files that were used in this layer.
24241                         //Be sure not to remove other build layers.
24242                         if (config.removeCombined) {
24243                             module.layer.buildFilePaths.forEach(function (path) {
24244                                 if (file.exists(path) && !modules.some(function (mod) {
24245                                         return mod._buildPath === path;
24246                                     })) {
24247                                     file.deleteFile(path);
24248                                 }
24249                             });
24250                         }
24251                     }
24253                     //Signal layer is done
24254                     if (config.onModuleBundleComplete) {
24255                         config.onModuleBundleComplete(module.onCompleteData);
24256                     }
24257                 });
24258             }
24260             //If removeCombined in play, remove any empty directories that
24261             //may now exist because of its use
24262             if (config.removeCombined && !config.out && config.dir) {
24263                 file.deleteEmptyDirs(config.dir);
24264             }
24266             //Do other optimizations.
24267             if (config.out && !config.cssIn) {
24268                 //Just need to worry about one JS file.
24269                 fileName = config.modules[0]._buildPath;
24270                 if (fileName === 'FUNCTION') {
24271                     config.modules[0]._buildText = optimize.js(fileName,
24272                                                                config.modules[0]._buildText,
24273                                                                null,
24274                                                                config);
24275                 } else {
24276                     optimize.jsFile(fileName, null, fileName, config);
24277                 }
24278             } else if (!config.cssIn) {
24279                 //Normal optimizations across modules.
24281                 //JS optimizations.
24282                 fileNames = file.getFilteredFileList(config.dir, /\.js$/, true);
24283                 fileNames.forEach(function (fileName) {
24284                     var cfg, override, moduleIndex;
24286                     //Generate the module name from the config.dir root.
24287                     moduleName = fileName.replace(config.dir, '');
24288                     //Get rid of the extension
24289                     moduleName = moduleName.substring(0, moduleName.length - 3);
24291                     //If there is an override for a specific layer build module,
24292                     //and this file is that module, mix in the override for use
24293                     //by optimize.jsFile.
24294                     moduleIndex = getOwn(config._buildPathToModuleIndex, fileName);
24295                     //Normalize, since getOwn could have returned undefined
24296                     moduleIndex = moduleIndex === 0 || moduleIndex > 0 ? moduleIndex : -1;
24298                     //Try to avoid extra work if the other files do not need to
24299                     //be read. Build layers should be processed at the very
24300                     //least for optimization.
24301                     if (moduleIndex > -1 || !config.skipDirOptimize ||
24302                             config.normalizeDirDefines === "all" ||
24303                             config.cjsTranslate) {
24304                         //Convert the file to transport format, but without a name
24305                         //inserted (by passing null for moduleName) since the files are
24306                         //standalone, one module per file.
24307                         fileContents = file.readFile(fileName);
24310                         //For builds, if wanting cjs translation, do it now, so that
24311                         //the individual modules can be loaded cross domain via
24312                         //plain script tags.
24313                         if (config.cjsTranslate &&
24314                             (!config.shim || !lang.hasProp(config.shim, moduleName))) {
24315                             fileContents = commonJs.convert(fileName, fileContents);
24316                         }
24318                         if (moduleIndex === -1) {
24319                             if (config.onBuildRead) {
24320                                 fileContents = config.onBuildRead(moduleName,
24321                                                                   fileName,
24322                                                                   fileContents);
24323                             }
24325                             //Only do transport normalization if this is not a build
24326                             //layer (since it was already normalized) and if
24327                             //normalizeDirDefines indicated all should be done.
24328                             if (config.normalizeDirDefines === "all") {
24329                                 fileContents = build.toTransport(config.namespace,
24330                                                              null,
24331                                                              fileName,
24332                                                              fileContents);
24333                             }
24335                             if (config.onBuildWrite) {
24336                                 fileContents = config.onBuildWrite(moduleName,
24337                                                                    fileName,
24338                                                                    fileContents);
24339                             }
24340                         }
24342                         override = moduleIndex > -1 ?
24343                                    config.modules[moduleIndex].override : null;
24344                         if (override) {
24345                             cfg = build.createOverrideConfig(config, override);
24346                         } else {
24347                             cfg = config;
24348                         }
24350                         if (moduleIndex > -1 || !config.skipDirOptimize) {
24351                             optimize.jsFile(fileName, fileContents, fileName, cfg, pluginCollector);
24352                         }
24353                     }
24354                 });
24356                 //Normalize all the plugin resources.
24357                 context = require.s.contexts._;
24359                 for (moduleName in pluginCollector) {
24360                     if (hasProp(pluginCollector, moduleName)) {
24361                         parentModuleMap = context.makeModuleMap(moduleName);
24362                         resources = pluginCollector[moduleName];
24363                         for (i = 0; i < resources.length; i++) {
24364                             resource = resources[i];
24365                             moduleMap = context.makeModuleMap(resource, parentModuleMap);
24366                             if (falseProp(context.plugins, moduleMap.prefix)) {
24367                                 //Set the value in context.plugins so it
24368                                 //will be evaluated as a full plugin.
24369                                 context.plugins[moduleMap.prefix] = true;
24371                                 //Do not bother if the plugin is not available.
24372                                 if (!file.exists(require.toUrl(moduleMap.prefix + '.js'))) {
24373                                     continue;
24374                                 }
24376                                 //Rely on the require in the build environment
24377                                 //to be synchronous
24378                                 context.require([moduleMap.prefix]);
24380                                 //Now that the plugin is loaded, redo the moduleMap
24381                                 //since the plugin will need to normalize part of the path.
24382                                 moduleMap = context.makeModuleMap(resource, parentModuleMap);
24383                             }
24385                             //Only bother with plugin resources that can be handled
24386                             //processed by the plugin, via support of the writeFile
24387                             //method.
24388                             if (falseProp(pluginProcessed, moduleMap.id)) {
24389                                 //Only do the work if the plugin was really loaded.
24390                                 //Using an internal access because the file may
24391                                 //not really be loaded.
24392                                 plugin = getOwn(context.defined, moduleMap.prefix);
24393                                 if (plugin && plugin.writeFile) {
24394                                     plugin.writeFile(
24395                                         moduleMap.prefix,
24396                                         moduleMap.name,
24397                                         require,
24398                                         makeWriteFile(
24399                                             config.namespace
24400                                         ),
24401                                         context.config
24402                                     );
24403                                 }
24405                                 pluginProcessed[moduleMap.id] = true;
24406                             }
24407                         }
24409                     }
24410                 }
24412                 //console.log('PLUGIN COLLECTOR: ' + JSON.stringify(pluginCollector, null, "  "));
24415                 //All module layers are done, write out the build.txt file.
24416                 file.saveUtf8File(config.dir + "build.txt", buildFileContents);
24417             }
24419             //If just have one CSS file to optimize, do that here.
24420             if (config.cssIn) {
24421                 buildFileContents += optimize.cssFile(config.cssIn, config.out, config).buildText;
24422             }
24424             if (typeof config.out === 'function') {
24425                 config.out(config.modules[0]._buildText);
24426             }
24428             //Print out what was built into which layers.
24429             if (buildFileContents) {
24430                 logger.info(buildFileContents);
24431                 return buildFileContents;
24432             }
24434             return '';
24435         });
24436     };
24438     /**
24439      * Converts command line args like "paths.foo=../some/path"
24440      * result.paths = { foo: '../some/path' } where prop = paths,
24441      * name = paths.foo and value = ../some/path, so it assumes the
24442      * name=value splitting has already happened.
24443      */
24444     function stringDotToObj(result, name, value) {
24445         var parts = name.split('.');
24447         parts.forEach(function (prop, i) {
24448             if (i === parts.length - 1) {
24449                 result[prop] = value;
24450             } else {
24451                 if (falseProp(result, prop)) {
24452                     result[prop] = {};
24453                 }
24454                 result = result[prop];
24455             }
24457         });
24458     }
24460     build.objProps = {
24461         paths: true,
24462         wrap: true,
24463         pragmas: true,
24464         pragmasOnSave: true,
24465         has: true,
24466         hasOnSave: true,
24467         uglify: true,
24468         uglify2: true,
24469         closure: true,
24470         map: true,
24471         throwWhen: true
24472     };
24474     build.hasDotPropMatch = function (prop) {
24475         var dotProp,
24476             index = prop.indexOf('.');
24478         if (index !== -1) {
24479             dotProp = prop.substring(0, index);
24480             return hasProp(build.objProps, dotProp);
24481         }
24482         return false;
24483     };
24485     /**
24486      * Converts an array that has String members of "name=value"
24487      * into an object, where the properties on the object are the names in the array.
24488      * Also converts the strings "true" and "false" to booleans for the values.
24489      * member name/value pairs, and converts some comma-separated lists into
24490      * arrays.
24491      * @param {Array} ary
24492      */
24493     build.convertArrayToObject = function (ary) {
24494         var result = {}, i, separatorIndex, prop, value,
24495             needArray = {
24496                 "include": true,
24497                 "exclude": true,
24498                 "excludeShallow": true,
24499                 "insertRequire": true,
24500                 "stubModules": true,
24501                 "deps": true
24502             };
24504         for (i = 0; i < ary.length; i++) {
24505             separatorIndex = ary[i].indexOf("=");
24506             if (separatorIndex === -1) {
24507                 throw "Malformed name/value pair: [" + ary[i] + "]. Format should be name=value";
24508             }
24510             value = ary[i].substring(separatorIndex + 1, ary[i].length);
24511             if (value === "true") {
24512                 value = true;
24513             } else if (value === "false") {
24514                 value = false;
24515             }
24517             prop = ary[i].substring(0, separatorIndex);
24519             //Convert to array if necessary
24520             if (getOwn(needArray, prop)) {
24521                 value = value.split(",");
24522             }
24524             if (build.hasDotPropMatch(prop)) {
24525                 stringDotToObj(result, prop, value);
24526             } else {
24527                 result[prop] = value;
24528             }
24529         }
24530         return result; //Object
24531     };
24533     build.makeAbsPath = function (path, absFilePath) {
24534         if (!absFilePath) {
24535             return path;
24536         }
24538         //Add abspath if necessary. If path starts with a slash or has a colon,
24539         //then already is an abolute path.
24540         if (path.indexOf('/') !== 0 && path.indexOf(':') === -1) {
24541             path = absFilePath +
24542                    (absFilePath.charAt(absFilePath.length - 1) === '/' ? '' : '/') +
24543                    path;
24544             path = file.normalize(path);
24545         }
24546         return path.replace(lang.backSlashRegExp, '/');
24547     };
24549     build.makeAbsObject = function (props, obj, absFilePath) {
24550         var i, prop;
24551         if (obj) {
24552             for (i = 0; i < props.length; i++) {
24553                 prop = props[i];
24554                 if (hasProp(obj, prop) && typeof obj[prop] === 'string') {
24555                     obj[prop] = build.makeAbsPath(obj[prop], absFilePath);
24556                 }
24557             }
24558         }
24559     };
24561     /**
24562      * For any path in a possible config, make it absolute relative
24563      * to the absFilePath passed in.
24564      */
24565     build.makeAbsConfig = function (config, absFilePath) {
24566         var props, prop, i;
24568         props = ["appDir", "dir", "baseUrl"];
24569         for (i = 0; i < props.length; i++) {
24570             prop = props[i];
24572             if (getOwn(config, prop)) {
24573                 //Add abspath if necessary, make sure these paths end in
24574                 //slashes
24575                 if (prop === "baseUrl") {
24576                     config.originalBaseUrl = config.baseUrl;
24577                     if (config.appDir) {
24578                         //If baseUrl with an appDir, the baseUrl is relative to
24579                         //the appDir, *not* the absFilePath. appDir and dir are
24580                         //made absolute before baseUrl, so this will work.
24581                         config.baseUrl = build.makeAbsPath(config.originalBaseUrl, config.appDir);
24582                     } else {
24583                         //The dir output baseUrl is same as regular baseUrl, both
24584                         //relative to the absFilePath.
24585                         config.baseUrl = build.makeAbsPath(config[prop], absFilePath);
24586                     }
24587                 } else {
24588                     config[prop] = build.makeAbsPath(config[prop], absFilePath);
24589                 }
24591                 config[prop] = endsWithSlash(config[prop]);
24592             }
24593         }
24595         build.makeAbsObject(["out", "cssIn"], config, absFilePath);
24596         build.makeAbsObject(["startFile", "endFile"], config.wrap, absFilePath);
24597     };
24599     /**
24600      * Creates a relative path to targetPath from refPath.
24601      * Only deals with file paths, not folders. If folders,
24602      * make sure paths end in a trailing '/'.
24603      */
24604     build.makeRelativeFilePath = function (refPath, targetPath) {
24605         var i, dotLength, finalParts, length,
24606             refParts = refPath.split('/'),
24607             targetParts = targetPath.split('/'),
24608             //Pull off file name
24609             targetName = targetParts.pop(),
24610             dotParts = [];
24612         //Also pop off the ref file name to make the matches against
24613         //targetParts equivalent.
24614         refParts.pop();
24616         length = refParts.length;
24618         for (i = 0; i < length; i += 1) {
24619             if (refParts[i] !== targetParts[i]) {
24620                 break;
24621             }
24622         }
24624         //Now i is the index in which they diverge.
24625         finalParts = targetParts.slice(i);
24627         dotLength = length - i;
24628         for (i = 0; i > -1 && i < dotLength; i += 1) {
24629             dotParts.push('..');
24630         }
24632         return dotParts.join('/') + (dotParts.length ? '/' : '') +
24633                finalParts.join('/') + (finalParts.length ? '/' : '') +
24634                targetName;
24635     };
24637     build.nestedMix = {
24638         paths: true,
24639         has: true,
24640         hasOnSave: true,
24641         pragmas: true,
24642         pragmasOnSave: true
24643     };
24645     /**
24646      * Mixes additional source config into target config, and merges some
24647      * nested config, like paths, correctly.
24648      */
24649     function mixConfig(target, source) {
24650         var prop, value;
24652         for (prop in source) {
24653             if (hasProp(source, prop)) {
24654                 //If the value of the property is a plain object, then
24655                 //allow a one-level-deep mixing of it.
24656                 value = source[prop];
24657                 if (typeof value === 'object' && value &&
24658                         !lang.isArray(value) && !lang.isFunction(value) &&
24659                         !lang.isRegExp(value)) {
24660                     target[prop] = lang.mixin({}, target[prop], value, true);
24661                 } else {
24662                     target[prop] = value;
24663                 }
24664             }
24665         }
24667         //Set up log level since it can affect if errors are thrown
24668         //or caught and passed to errbacks while doing config setup.
24669         if (lang.hasProp(target, 'logLevel')) {
24670             logger.logLevel(target.logLevel);
24671         }
24672     }
24674     /**
24675      * Converts a wrap.startFile or endFile to be start/end as a string.
24676      * the startFile/endFile values can be arrays.
24677      */
24678     function flattenWrapFile(wrap, keyName, absFilePath) {
24679         var keyFileName = keyName + 'File';
24681         if (typeof wrap[keyName] !== 'string' && wrap[keyFileName]) {
24682             wrap[keyName] = '';
24683             if (typeof wrap[keyFileName] === 'string') {
24684                 wrap[keyFileName] = [wrap[keyFileName]];
24685             }
24686             wrap[keyFileName].forEach(function (fileName) {
24687                 wrap[keyName] += (wrap[keyName] ? '\n' : '') +
24688                     file.readFile(build.makeAbsPath(fileName, absFilePath));
24689             });
24690         } else if (wrap[keyName] === null ||  wrap[keyName] === undefined) {
24691             //Allow missing one, just set to empty string.
24692             wrap[keyName] = '';
24693         } else if (typeof wrap[keyName] !== 'string') {
24694             throw new Error('wrap.' + keyName + ' or wrap.' + keyFileName + ' malformed');
24695         }
24696     }
24698     /**
24699      * Creates a config object for an optimization build.
24700      * It will also read the build profile if it is available, to create
24701      * the configuration.
24702      *
24703      * @param {Object} cfg config options that take priority
24704      * over defaults and ones in the build file. These options could
24705      * be from a command line, for instance.
24706      *
24707      * @param {Object} the created config object.
24708      */
24709     build.createConfig = function (cfg) {
24710         /*jslint evil: true */
24711         var config = {}, buildFileContents, buildFileConfig, mainConfig,
24712             mainConfigFile, mainConfigPath, buildFile, absFilePath;
24714         //Make sure all paths are relative to current directory.
24715         absFilePath = file.absPath('.');
24716         build.makeAbsConfig(cfg, absFilePath);
24717         build.makeAbsConfig(buildBaseConfig, absFilePath);
24719         lang.mixin(config, buildBaseConfig);
24720         lang.mixin(config, cfg, true);
24722         //Set up log level early since it can affect if errors are thrown
24723         //or caught and passed to errbacks, even while constructing config.
24724         if (lang.hasProp(config, 'logLevel')) {
24725             logger.logLevel(config.logLevel);
24726         }
24728         if (config.buildFile) {
24729             //A build file exists, load it to get more config.
24730             buildFile = file.absPath(config.buildFile);
24732             //Find the build file, and make sure it exists, if this is a build
24733             //that has a build profile, and not just command line args with an in=path
24734             if (!file.exists(buildFile)) {
24735                 throw new Error("ERROR: build file does not exist: " + buildFile);
24736             }
24738             absFilePath = config.baseUrl = file.absPath(file.parent(buildFile));
24740             //Load build file options.
24741             buildFileContents = file.readFile(buildFile);
24742             try {
24743                 buildFileConfig = eval("(" + buildFileContents + ")");
24744                 build.makeAbsConfig(buildFileConfig, absFilePath);
24746                 //Mix in the config now so that items in mainConfigFile can
24747                 //be resolved relative to them if necessary, like if appDir
24748                 //is set here, but the baseUrl is in mainConfigFile. Will
24749                 //re-mix in the same build config later after mainConfigFile
24750                 //is processed, since build config should take priority.
24751                 mixConfig(config, buildFileConfig);
24752             } catch (e) {
24753                 throw new Error("Build file " + buildFile + " is malformed: " + e);
24754             }
24755         }
24757         mainConfigFile = config.mainConfigFile || (buildFileConfig && buildFileConfig.mainConfigFile);
24758         if (mainConfigFile) {
24759             mainConfigFile = build.makeAbsPath(mainConfigFile, absFilePath);
24760             if (!file.exists(mainConfigFile)) {
24761                 throw new Error(mainConfigFile + ' does not exist.');
24762             }
24763             try {
24764                 mainConfig = parse.findConfig(file.readFile(mainConfigFile)).config;
24765             } catch (configError) {
24766                 throw new Error('The config in mainConfigFile ' +
24767                         mainConfigFile +
24768                         ' cannot be used because it cannot be evaluated' +
24769                         ' correctly while running in the optimizer. Try only' +
24770                         ' using a config that is also valid JSON, or do not use' +
24771                         ' mainConfigFile and instead copy the config values needed' +
24772                         ' into a build file or command line arguments given to the optimizer.\n' +
24773                         'Source error from parsing: ' + mainConfigFile + ': ' + configError);
24774             }
24775             if (mainConfig) {
24776                 mainConfigPath = mainConfigFile.substring(0, mainConfigFile.lastIndexOf('/'));
24778                 //Add in some existing config, like appDir, since they can be
24779                 //used inside the mainConfigFile -- paths and baseUrl are
24780                 //relative to them.
24781                 if (config.appDir && !mainConfig.appDir) {
24782                     mainConfig.appDir = config.appDir;
24783                 }
24785                 //If no baseUrl, then use the directory holding the main config.
24786                 if (!mainConfig.baseUrl) {
24787                     mainConfig.baseUrl = mainConfigPath;
24788                 }
24790                 build.makeAbsConfig(mainConfig, mainConfigPath);
24791                 mixConfig(config, mainConfig);
24792             }
24793         }
24795         //Mix in build file config, but only after mainConfig has been mixed in.
24796         if (buildFileConfig) {
24797             mixConfig(config, buildFileConfig);
24798         }
24800         //Re-apply the override config values. Command line
24801         //args should take precedence over build file values.
24802         mixConfig(config, cfg);
24804         //Fix paths to full paths so that they can be adjusted consistently
24805         //lately to be in the output area.
24806         lang.eachProp(config.paths, function (value, prop) {
24807             if (lang.isArray(value)) {
24808                 throw new Error('paths fallback not supported in optimizer. ' +
24809                                 'Please provide a build config path override ' +
24810                                 'for ' + prop);
24811             }
24812             config.paths[prop] = build.makeAbsPath(value, config.baseUrl);
24813         });
24815         //Set final output dir
24816         if (hasProp(config, "baseUrl")) {
24817             if (config.appDir) {
24818                 config.dirBaseUrl = build.makeAbsPath(config.originalBaseUrl, config.dir);
24819             } else {
24820                 config.dirBaseUrl = config.dir || config.baseUrl;
24821             }
24822             //Make sure dirBaseUrl ends in a slash, since it is
24823             //concatenated with other strings.
24824             config.dirBaseUrl = endsWithSlash(config.dirBaseUrl);
24825         }
24827         //Check for errors in config
24828         if (config.main) {
24829             throw new Error('"main" passed as an option, but the ' +
24830                             'supported option is called "name".');
24831         }
24832         if (config.out && !config.name && !config.modules && !config.include &&
24833                 !config.cssIn) {
24834             throw new Error('Missing either a "name", "include" or "modules" ' +
24835                             'option');
24836         }
24837         if (config.cssIn) {
24838             if (config.dir || config.appDir) {
24839                 throw new Error('cssIn is only for the output of single file ' +
24840                     'CSS optimizations and is not compatible with "dir" or "appDir" configuration.');
24841             }
24842             if (!config.out) {
24843                 throw new Error('"out" option missing.');
24844             }
24845         }
24846         if (!config.cssIn && !config.baseUrl) {
24847             //Just use the current directory as the baseUrl
24848             config.baseUrl = './';
24849         }
24850         if (!config.out && !config.dir) {
24851             throw new Error('Missing either an "out" or "dir" config value. ' +
24852                             'If using "appDir" for a full project optimization, ' +
24853                             'use "dir". If you want to optimize to one file, ' +
24854                             'use "out".');
24855         }
24856         if (config.appDir && config.out) {
24857             throw new Error('"appDir" is not compatible with "out". Use "dir" ' +
24858                             'instead. appDir is used to copy whole projects, ' +
24859                             'where "out" with "baseUrl" is used to just ' +
24860                             'optimize to one file.');
24861         }
24862         if (config.out && config.dir) {
24863             throw new Error('The "out" and "dir" options are incompatible.' +
24864                             ' Use "out" if you are targeting a single file for' +
24865                             ' for optimization, and "dir" if you want the appDir' +
24866                             ' or baseUrl directories optimized.');
24867         }
24869         if (config.dir) {
24870             // Make sure the output dir is not set to a parent of the
24871             // source dir or the same dir, as it will result in source
24872             // code deletion.
24873             if (config.dir === config.baseUrl ||
24874                 config.dir === config.appDir ||
24875                 (config.baseUrl && build.makeRelativeFilePath(config.dir,
24876                                            config.baseUrl).indexOf('..') !== 0) ||
24877                 (config.appDir &&
24878                     build.makeRelativeFilePath(config.dir, config.appDir).indexOf('..') !== 0)) {
24879                 throw new Error('"dir" is set to a parent or same directory as' +
24880                                 ' "appDir" or "baseUrl". This can result in' +
24881                                 ' the deletion of source code. Stopping.');
24882             }
24883         }
24885         if (config.insertRequire && !lang.isArray(config.insertRequire)) {
24886             throw new Error('insertRequire should be a list of module IDs' +
24887                             ' to insert in to a require([]) call.');
24888         }
24890         if (config.generateSourceMaps) {
24891             if (config.preserveLicenseComments && config.optimize !== 'none') {
24892                 throw new Error('Cannot use preserveLicenseComments and ' +
24893                     'generateSourceMaps together. Either explcitly set ' +
24894                     'preserveLicenseComments to false (default is true) or ' +
24895                     'turn off generateSourceMaps. If you want source maps with ' +
24896                     'license comments, see: ' +
24897                     'http://requirejs.org/docs/errors.html#sourcemapcomments');
24898             } else if (config.optimize !== 'none' &&
24899                        config.optimize !== 'closure' &&
24900                        config.optimize !== 'uglify2') {
24901                 //Allow optimize: none to pass, since it is useful when toggling
24902                 //minification on and off to debug something, and it implicitly
24903                 //works, since it does not need a source map.
24904                 throw new Error('optimize: "' + config.optimize +
24905                     '" does not support generateSourceMaps.');
24906             }
24907         }
24909         if ((config.name || config.include) && !config.modules) {
24910             //Just need to build one file, but may be part of a whole appDir/
24911             //baseUrl copy, but specified on the command line, so cannot do
24912             //the modules array setup. So create a modules section in that
24913             //case.
24914             config.modules = [
24915                 {
24916                     name: config.name,
24917                     out: config.out,
24918                     create: config.create,
24919                     include: config.include,
24920                     exclude: config.exclude,
24921                     excludeShallow: config.excludeShallow,
24922                     insertRequire: config.insertRequire,
24923                     stubModules: config.stubModules
24924                 }
24925             ];
24926             delete config.stubModules;
24927         } else if (config.modules && config.out) {
24928             throw new Error('If the "modules" option is used, then there ' +
24929                             'should be a "dir" option set and "out" should ' +
24930                             'not be used since "out" is only for single file ' +
24931                             'optimization output.');
24932         } else if (config.modules && config.name) {
24933             throw new Error('"name" and "modules" options are incompatible. ' +
24934                             'Either use "name" if doing a single file ' +
24935                             'optimization, or "modules" if you want to target ' +
24936                             'more than one file for optimization.');
24937         }
24939         if (config.out && !config.cssIn) {
24940             //Just one file to optimize.
24942             //Does not have a build file, so set up some defaults.
24943             //Optimizing CSS should not be allowed, unless explicitly
24944             //asked for on command line. In that case the only task is
24945             //to optimize a CSS file.
24946             if (!cfg.optimizeCss) {
24947                 config.optimizeCss = "none";
24948             }
24949         }
24951         //Normalize cssPrefix
24952         if (config.cssPrefix) {
24953             //Make sure cssPrefix ends in a slash
24954             config.cssPrefix = endsWithSlash(config.cssPrefix);
24955         } else {
24956             config.cssPrefix = '';
24957         }
24959         //Cycle through modules and combine any local stubModules with
24960         //global values.
24961         if (config.modules && config.modules.length) {
24962             config.modules.forEach(function (mod) {
24963                 if (config.stubModules) {
24964                     mod.stubModules = config.stubModules.concat(mod.stubModules || []);
24965                 }
24967                 //Create a hash lookup for the stubModules config to make lookup
24968                 //cheaper later.
24969                 if (mod.stubModules) {
24970                     mod.stubModules._byName = {};
24971                     mod.stubModules.forEach(function (id) {
24972                         mod.stubModules._byName[id] = true;
24973                     });
24974                 }
24975             });
24976         }
24978         //Get any wrap text.
24979         try {
24980             if (config.wrap) {
24981                 if (config.wrap === true) {
24982                     //Use default values.
24983                     config.wrap = {
24984                         start: '(function () {',
24985                         end: '}());'
24986                     };
24987                 } else {
24988                     flattenWrapFile(config.wrap, 'start', absFilePath);
24989                     flattenWrapFile(config.wrap, 'end', absFilePath);
24990                 }
24991             }
24992         } catch (wrapError) {
24993             throw new Error('Malformed wrap config: ' + wrapError.toString());
24994         }
24996         //Do final input verification
24997         if (config.context) {
24998             throw new Error('The build argument "context" is not supported' +
24999                             ' in a build. It should only be used in web' +
25000                             ' pages.');
25001         }
25003         //Set up normalizeDirDefines. If not explicitly set, if optimize "none",
25004         //set to "skip" otherwise set to "all".
25005         if (!hasProp(config, 'normalizeDirDefines')) {
25006             if (config.optimize === 'none' || config.skipDirOptimize) {
25007                 config.normalizeDirDefines = 'skip';
25008             } else {
25009                 config.normalizeDirDefines = 'all';
25010             }
25011         }
25013         //Set file.fileExclusionRegExp if desired
25014         if (hasProp(config, 'fileExclusionRegExp')) {
25015             if (typeof config.fileExclusionRegExp === "string") {
25016                 file.exclusionRegExp = new RegExp(config.fileExclusionRegExp);
25017             } else {
25018                 file.exclusionRegExp = config.fileExclusionRegExp;
25019             }
25020         } else if (hasProp(config, 'dirExclusionRegExp')) {
25021             //Set file.dirExclusionRegExp if desired, this is the old
25022             //name for fileExclusionRegExp before 1.0.2. Support for backwards
25023             //compatibility
25024             file.exclusionRegExp = config.dirExclusionRegExp;
25025         }
25027         //Remove things that may cause problems in the build.
25028         delete config.jQuery;
25029         delete config.enforceDefine;
25030         delete config.urlArgs;
25032         return config;
25033     };
25035     /**
25036      * finds the module being built/optimized with the given moduleName,
25037      * or returns null.
25038      * @param {String} moduleName
25039      * @param {Array} modules
25040      * @returns {Object} the module object from the build profile, or null.
25041      */
25042     build.findBuildModule = function (moduleName, modules) {
25043         var i, module;
25044         for (i = 0; i < modules.length; i++) {
25045             module = modules[i];
25046             if (module.name === moduleName) {
25047                 return module;
25048             }
25049         }
25050         return null;
25051     };
25053     /**
25054      * Removes a module name and path from a layer, if it is supposed to be
25055      * excluded from the layer.
25056      * @param {String} moduleName the name of the module
25057      * @param {String} path the file path for the module
25058      * @param {Object} layer the layer to remove the module/path from
25059      */
25060     build.removeModulePath = function (module, path, layer) {
25061         var index = layer.buildFilePaths.indexOf(path);
25062         if (index !== -1) {
25063             layer.buildFilePaths.splice(index, 1);
25064         }
25065     };
25067     /**
25068      * Uses the module build config object to trace the dependencies for the
25069      * given module.
25070      *
25071      * @param {Object} module the module object from the build config info.
25072      * @param {Object} the build config object.
25073      *
25074      * @returns {Object} layer information about what paths and modules should
25075      * be in the flattened module.
25076      */
25077     build.traceDependencies = function (module, config) {
25078         var include, override, layer, context, baseConfig, oldContext,
25079             rawTextByIds,
25080             syncChecks = {
25081                 rhino: true,
25082                 node: true,
25083                 xpconnect: true
25084             },
25085             deferred = prim();
25087         //Reset some state set up in requirePatch.js, and clean up require's
25088         //current context.
25089         oldContext = require._buildReset();
25091         //Grab the reset layer and context after the reset, but keep the
25092         //old config to reuse in the new context.
25093         baseConfig = oldContext.config;
25094         layer = require._layer;
25095         context = layer.context;
25097         //Put back basic config, use a fresh object for it.
25098         //WARNING: probably not robust for paths and packages/packagePaths,
25099         //since those property's objects can be modified. But for basic
25100         //config clone it works out.
25101         require(lang.mixin({}, baseConfig, true));
25103         logger.trace("\nTracing dependencies for: " + (module.name || module.out));
25104         include = module.name && !module.create ? [module.name] : [];
25105         if (module.include) {
25106             include = include.concat(module.include);
25107         }
25109         //If there are overrides to basic config, set that up now.;
25110         if (module.override) {
25111             override = lang.mixin({}, baseConfig, true);
25112             lang.mixin(override, module.override, true);
25113             require(override);
25114         }
25116         //Now, populate the rawText cache with any values explicitly passed in
25117         //via config.
25118         rawTextByIds = require.s.contexts._.config.rawText;
25119         if (rawTextByIds) {
25120             lang.eachProp(rawTextByIds, function (contents, id) {
25121                 var url = require.toUrl(id) + '.js';
25122                 require._cachedRawText[url] = contents;
25123             });
25124         }
25127         //Configure the callbacks to be called.
25128         deferred.reject.__requireJsBuild = true;
25130         //Use a wrapping function so can check for errors.
25131         function includeFinished(value) {
25132             //If a sync build environment, check for errors here, instead of
25133             //in the then callback below, since some errors, like two IDs pointed
25134             //to same URL but only one anon ID will leave the loader in an
25135             //unresolved state since a setTimeout cannot be used to check for
25136             //timeout.
25137             var hasError = false;
25138             if (syncChecks[env.get()]) {
25139                 try {
25140                     build.checkForErrors(context);
25141                 } catch (e) {
25142                     hasError = true;
25143                     deferred.reject(e);
25144                 }
25145             }
25147             if (!hasError) {
25148                 deferred.resolve(value);
25149             }
25150         }
25151         includeFinished.__requireJsBuild = true;
25153         //Figure out module layer dependencies by calling require to do the work.
25154         require(include, includeFinished, deferred.reject);
25156         return deferred.promise.then(function () {
25157             //Reset config
25158             if (module.override) {
25159                 require(baseConfig);
25160             }
25162             build.checkForErrors(context);
25164             return layer;
25165         });
25166     };
25168     build.checkForErrors = function (context) {
25169         //Check to see if it all loaded. If not, then throw, and give
25170         //a message on what is left.
25171         var id, prop, mod, errUrl, idParts, pluginId,
25172             errMessage = '',
25173             failedPluginMap = {},
25174             failedPluginIds = [],
25175             errIds = [],
25176             errUrlMap = {},
25177             errUrlConflicts = {},
25178             hasErrUrl = false,
25179             registry = context.registry;
25181         for (id in registry) {
25182             if (hasProp(registry, id) && id.indexOf('_@r') !== 0) {
25183                 mod = getOwn(registry, id);
25184                 if (id.indexOf('_unnormalized') === -1 && mod && mod.enabled) {
25185                     errIds.push(id);
25186                     errUrl = mod.map.url;
25188                     if (errUrlMap[errUrl]) {
25189                         hasErrUrl = true;
25190                         //This error module has the same URL as another
25191                         //error module, could be misconfiguration.
25192                         if (!errUrlConflicts[errUrl]) {
25193                             errUrlConflicts[errUrl] = [];
25194                             //Store the original module that had the same URL.
25195                             errUrlConflicts[errUrl].push(errUrlMap[errUrl]);
25196                         }
25197                         errUrlConflicts[errUrl].push(id);
25198                     } else {
25199                         errUrlMap[errUrl] = id;
25200                     }
25201                 }
25203                 //Look for plugins that did not call load()
25204                 idParts = id.split('!');
25205                 pluginId = idParts[0];
25206                 if (idParts.length > 1 && falseProp(failedPluginMap, pluginId)) {
25207                     failedPluginIds.push(pluginId);
25208                     failedPluginMap[pluginId] = true;
25209                 }
25210             }
25211         }
25213         if (errIds.length || failedPluginIds.length) {
25214             if (failedPluginIds.length) {
25215                 errMessage += 'Loader plugin' +
25216                     (failedPluginIds.length === 1 ? '' : 's') +
25217                     ' did not call ' +
25218                     'the load callback in the build: ' +
25219                     failedPluginIds.join(', ') + '\n';
25220             }
25221             errMessage += 'Module loading did not complete for: ' + errIds.join(', ');
25223             if (hasErrUrl) {
25224                 errMessage += '\nThe following modules share the same URL. This ' +
25225                               'could be a misconfiguration if that URL only has ' +
25226                               'one anonymous module in it:';
25227                 for (prop in errUrlConflicts) {
25228                     if (hasProp(errUrlConflicts, prop)) {
25229                         errMessage += '\n' + prop + ': ' +
25230                                       errUrlConflicts[prop].join(', ');
25231                     }
25232                 }
25233             }
25234             throw new Error(errMessage);
25235         }
25237     };
25239     build.createOverrideConfig = function (config, override) {
25240         var cfg = {};
25242         lang.mixin(cfg, config, true);
25243         lang.eachProp(override, function (value, prop) {
25244             if (hasProp(build.objProps, prop)) {
25245                 //An object property, merge keys. Start a new object
25246                 //so that source object in config does not get modified.
25247                 cfg[prop] = {};
25248                 lang.mixin(cfg[prop], config[prop], true);
25249                 lang.mixin(cfg[prop], override[prop], true);
25250             } else {
25251                 cfg[prop] = override[prop];
25252             }
25253         });
25254         return cfg;
25255     };
25257     /**
25258      * Uses the module build config object to create an flattened version
25259      * of the module, with deep dependencies included.
25260      *
25261      * @param {Object} module the module object from the build config info.
25262      *
25263      * @param {Object} layer the layer object returned from build.traceDependencies.
25264      *
25265      * @param {Object} the build config object.
25266      *
25267      * @returns {Object} with two properties: "text", the text of the flattened
25268      * module, and "buildText", a string of text representing which files were
25269      * included in the flattened module text.
25270      */
25271     build.flattenModule = function (module, layer, config) {
25272         var fileContents, sourceMapGenerator,
25273             sourceMapBase,
25274             buildFileContents = '';
25276         return prim().start(function () {
25277             var reqIndex, currContents,
25278                 moduleName, shim, packageConfig, nonPackageName,
25279                 parts, builder, writeApi,
25280                 namespace, namespaceWithDot, stubModulesByName,
25281                 context = layer.context,
25282                 onLayerEnds = [],
25283                 onLayerEndAdded = {};
25285             //Use override settings, particularly for pragmas
25286             //Do this before the var readings since it reads config values.
25287             if (module.override) {
25288                 config = build.createOverrideConfig(config, module.override);
25289             }
25291             namespace = config.namespace || '';
25292             namespaceWithDot = namespace ? namespace + '.' : '';
25293             stubModulesByName = (module.stubModules && module.stubModules._byName) || {};
25295             //Start build output for the module.
25296             module.onCompleteData = {
25297                 name: module.name,
25298                 path: (config.dir ? module._buildPath.replace(config.dir, "") : module._buildPath),
25299                 included: []
25300             };
25302             buildFileContents += "\n" +
25303                                   module.onCompleteData.path +
25304                                  "\n----------------\n";
25306             //If there was an existing file with require in it, hoist to the top.
25307             if (layer.existingRequireUrl) {
25308                 reqIndex = layer.buildFilePaths.indexOf(layer.existingRequireUrl);
25309                 if (reqIndex !== -1) {
25310                     layer.buildFilePaths.splice(reqIndex, 1);
25311                     layer.buildFilePaths.unshift(layer.existingRequireUrl);
25312                 }
25313             }
25315             if (config.generateSourceMaps) {
25316                 sourceMapBase = config.dir || config.baseUrl;
25317                 sourceMapGenerator = new SourceMapGenerator.SourceMapGenerator({
25318                     file: module._buildPath.replace(sourceMapBase, '')
25319                 });
25320             }
25322             //Write the built module to disk, and build up the build output.
25323             fileContents = "";
25324             return prim.serial(layer.buildFilePaths.map(function (path) {
25325                 return function () {
25326                     var lineCount,
25327                         singleContents = '';
25329                     moduleName = layer.buildFileToModule[path];
25330                     //If the moduleName is for a package main, then update it to the
25331                     //real main value.
25332                     packageConfig = layer.context.config.pkgs &&
25333                                     getOwn(layer.context.config.pkgs, moduleName);
25334                     if (packageConfig) {
25335                         nonPackageName = moduleName;
25336                         moduleName += '/' + packageConfig.main;
25337                     }
25339                     return prim().start(function () {
25340                         //Figure out if the module is a result of a build plugin, and if so,
25341                         //then delegate to that plugin.
25342                         parts = context.makeModuleMap(moduleName);
25343                         builder = parts.prefix && getOwn(context.defined, parts.prefix);
25344                         if (builder) {
25345                             if (builder.onLayerEnd && falseProp(onLayerEndAdded, parts.prefix)) {
25346                                 onLayerEnds.push(builder);
25347                                 onLayerEndAdded[parts.prefix] = true;
25348                             }
25350                             if (builder.write) {
25351                                 writeApi = function (input) {
25352                                     singleContents += "\n" + addSemiColon(input, config);
25353                                     if (config.onBuildWrite) {
25354                                         singleContents = config.onBuildWrite(moduleName, path, singleContents);
25355                                     }
25356                                 };
25357                                 writeApi.asModule = function (moduleName, input) {
25358                                     singleContents += "\n" +
25359                                         addSemiColon(build.toTransport(namespace, moduleName, path, input, layer, {
25360                                             useSourceUrl: layer.context.config.useSourceUrl
25361                                         }), config);
25362                                     if (config.onBuildWrite) {
25363                                         singleContents = config.onBuildWrite(moduleName, path, singleContents);
25364                                     }
25365                                 };
25366                                 builder.write(parts.prefix, parts.name, writeApi);
25367                             }
25368                             return;
25369                         } else {
25370                             return prim().start(function () {
25371                                 if (hasProp(stubModulesByName, moduleName)) {
25372                                     //Just want to insert a simple module definition instead
25373                                     //of the source module. Useful for plugins that inline
25374                                     //all their resources.
25375                                     if (hasProp(layer.context.plugins, moduleName)) {
25376                                         //Slightly different content for plugins, to indicate
25377                                         //that dynamic loading will not work.
25378                                         return 'define({load: function(id){throw new Error("Dynamic load not allowed: " + id);}});';
25379                                     } else {
25380                                         return 'define({});';
25381                                     }
25382                                 } else {
25383                                     return require._cacheReadAsync(path);
25384                                 }
25385                             }).then(function (text) {
25386                                 var hasPackageName;
25388                                 currContents = text;
25390                                 if (config.cjsTranslate &&
25391                                     (!config.shim || !lang.hasProp(config.shim, moduleName))) {
25392                                     currContents = commonJs.convert(path, currContents);
25393                                 }
25395                                 if (config.onBuildRead) {
25396                                     currContents = config.onBuildRead(moduleName, path, currContents);
25397                                 }
25399                                 if (packageConfig) {
25400                                     hasPackageName = (nonPackageName === parse.getNamedDefine(currContents));
25401                                 }
25403                                 if (namespace) {
25404                                     currContents = pragma.namespace(currContents, namespace);
25405                                 }
25407                                 currContents = build.toTransport(namespace, moduleName, path, currContents, layer, {
25408                                     useSourceUrl: config.useSourceUrl
25409                                 });
25411                                 if (packageConfig && !hasPackageName) {
25412                                     currContents = addSemiColon(currContents, config) + '\n';
25413                                     currContents += namespaceWithDot + "define('" +
25414                                                     packageConfig.name + "', ['" + moduleName +
25415                                                     "'], function (main) { return main; });\n";
25416                                 }
25418                                 if (config.onBuildWrite) {
25419                                     currContents = config.onBuildWrite(moduleName, path, currContents);
25420                                 }
25422                                 //Semicolon is for files that are not well formed when
25423                                 //concatenated with other content.
25424                                 singleContents += "\n" + addSemiColon(currContents, config);
25425                             });
25426                         }
25427                     }).then(function () {
25428                         var sourceMapPath, sourceMapLineNumber,
25429                             shortPath = path.replace(config.dir, "");
25431                         module.onCompleteData.included.push(shortPath);
25432                         buildFileContents += shortPath + "\n";
25434                         //Some files may not have declared a require module, and if so,
25435                         //put in a placeholder call so the require does not try to load them
25436                         //after the module is processed.
25437                         //If we have a name, but no defined module, then add in the placeholder.
25438                         if (moduleName && falseProp(layer.modulesWithNames, moduleName) && !config.skipModuleInsertion) {
25439                             shim = config.shim && (getOwn(config.shim, moduleName) || (packageConfig && getOwn(config.shim, nonPackageName)));
25440                             if (shim) {
25441                                 singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", ' +
25442                                                  (shim.deps && shim.deps.length ?
25443                                                         build.makeJsArrayString(shim.deps) + ', ' : '') +
25444                                                  (shim.exportsFn ? shim.exportsFn() : 'function(){}') +
25445                                                  ');\n';
25446                             } else {
25447                                 singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", function(){});\n';
25448                             }
25449                         }
25451                         //Add to the source map
25452                         if (sourceMapGenerator) {
25453                             sourceMapPath = build.makeRelativeFilePath(module._buildPath, path);
25454                             sourceMapLineNumber = fileContents.split('\n').length - 1;
25455                             lineCount = singleContents.split('\n').length;
25456                             for (var i = 1; i <= lineCount; i += 1) {
25457                                 sourceMapGenerator.addMapping({
25458                                     generated: {
25459                                         line: sourceMapLineNumber + i,
25460                                         column: 0
25461                                     },
25462                                     original: {
25463                                         line: i,
25464                                         column: 0
25465                                     },
25466                                     source: sourceMapPath
25467                                 });
25468                             }
25470                             //Store the content of the original in the source
25471                             //map since other transforms later like minification
25472                             //can mess up translating back to the original
25473                             //source
25474                             sourceMapGenerator.setSourceContent(sourceMapPath, singleContents);
25475                         }
25477                         //Add the file to the final contents
25478                         fileContents += singleContents;
25479                     });
25480                 };
25481             })).then(function () {
25482                 if (onLayerEnds.length) {
25483                     onLayerEnds.forEach(function (builder) {
25484                         var path;
25485                         if (typeof module.out === 'string') {
25486                             path = module.out;
25487                         } else if (typeof module._buildPath === 'string') {
25488                             path = module._buildPath;
25489                         }
25490                         builder.onLayerEnd(function (input) {
25491                             fileContents += "\n" + addSemiColon(input, config);
25492                         }, {
25493                             name: module.name,
25494                             path: path
25495                         });
25496                     });
25497                 }
25499                 if (module.create) {
25500                     //The ID is for a created layer. Write out
25501                     //a module definition for it in case the
25502                     //built file is used with enforceDefine
25503                     //(#432)
25504                     fileContents += '\n' + namespaceWithDot + 'define("' + module.name + '", function(){});\n';
25505                 }
25507                 //Add a require at the end to kick start module execution, if that
25508                 //was desired. Usually this is only specified when using small shim
25509                 //loaders like almond.
25510                 if (module.insertRequire) {
25511                     fileContents += '\n' + namespaceWithDot + 'require(["' + module.insertRequire.join('", "') + '"]);\n';
25512                 }
25513             });
25514         }).then(function () {
25515             return {
25516                 text: config.wrap ?
25517                         config.wrap.start + fileContents + config.wrap.end :
25518                         fileContents,
25519                 buildText: buildFileContents,
25520                 sourceMap: sourceMapGenerator ?
25521                               JSON.stringify(sourceMapGenerator.toJSON(), null, '  ') :
25522                               undefined
25523             };
25524         });
25525     };
25527     //Converts an JS array of strings to a string representation.
25528     //Not using JSON.stringify() for Rhino's sake.
25529     build.makeJsArrayString = function (ary) {
25530         return '["' + ary.map(function (item) {
25531             //Escape any double quotes, backslashes
25532             return lang.jsEscape(item);
25533         }).join('","') + '"]';
25534     };
25536     build.toTransport = function (namespace, moduleName, path, contents, layer, options) {
25537         var baseUrl = layer && layer.context.config.baseUrl;
25539         function onFound(info) {
25540             //Only mark this module as having a name if not a named module,
25541             //or if a named module and the name matches expectations.
25542             if (layer && (info.needsId || info.foundId === moduleName)) {
25543                 layer.modulesWithNames[moduleName] = true;
25544             }
25545         }
25547         //Convert path to be a local one to the baseUrl, useful for
25548         //useSourceUrl.
25549         if (baseUrl) {
25550             path = path.replace(baseUrl, '');
25551         }
25553         return transform.toTransport(namespace, moduleName, path, contents, onFound, options);
25554     };
25556     return build;
25559     }
25562     /**
25563      * Sets the default baseUrl for requirejs to be directory of top level
25564      * script.
25565      */
25566     function setBaseUrl(fileName) {
25567         //Use the file name's directory as the baseUrl if available.
25568         dir = fileName.replace(/\\/g, '/');
25569         if (dir.indexOf('/') !== -1) {
25570             dir = dir.split('/');
25571             dir.pop();
25572             dir = dir.join('/');
25573             exec("require({baseUrl: '" + dir + "'});");
25574         }
25575     }
25577     function createRjsApi() {
25578         //Create a method that will run the optimzer given an object
25579         //config.
25580         requirejs.optimize = function (config, callback, errback) {
25581             if (!loadedOptimizedLib) {
25582                 loadLib();
25583                 loadedOptimizedLib = true;
25584             }
25586             //Create the function that will be called once build modules
25587             //have been loaded.
25588             var runBuild = function (build, logger, quit) {
25589                 //Make sure config has a log level, and if not,
25590                 //make it "silent" by default.
25591                 config.logLevel = config.hasOwnProperty('logLevel') ?
25592                                   config.logLevel : logger.SILENT;
25594                 //Reset build internals first in case this is part
25595                 //of a long-running server process that could have
25596                 //exceptioned out in a bad state. It is only defined
25597                 //after the first call though.
25598                 if (requirejs._buildReset) {
25599                     requirejs._buildReset();
25600                     requirejs._cacheReset();
25601                 }
25603                 function done(result) {
25604                     //And clean up, in case something else triggers
25605                     //a build in another pathway.
25606                     if (requirejs._buildReset) {
25607                         requirejs._buildReset();
25608                         requirejs._cacheReset();
25609                     }
25611                     // Ensure errors get propagated to the errback
25612                     if (result instanceof Error) {
25613                       throw result;
25614                     }
25616                     return result;
25617                 }
25619                 errback = errback || function (err) {
25620                     // Using console here since logger may have
25621                     // turned off error logging. Since quit is
25622                     // called want to be sure a message is printed.
25623                     console.log(err);
25624                     quit(1);
25625                 };
25627                 build(config).then(done, done).then(callback, errback);
25628             };
25630             requirejs({
25631                 context: 'build'
25632             }, ['build', 'logger', 'env!env/quit'], runBuild);
25633         };
25635         requirejs.tools = {
25636             useLib: function (contextName, callback) {
25637                 if (!callback) {
25638                     callback = contextName;
25639                     contextName = 'uselib';
25640                 }
25642                 if (!useLibLoaded[contextName]) {
25643                     loadLib();
25644                     useLibLoaded[contextName] = true;
25645                 }
25647                 var req = requirejs({
25648                     context: contextName
25649                 });
25651                 req(['build'], function () {
25652                     callback(req);
25653                 });
25654             }
25655         };
25657         requirejs.define = define;
25658     }
25660     //If in Node, and included via a require('requirejs'), just export and
25661     //THROW IT ON THE GROUND!
25662     if (env === 'node' && reqMain !== module) {
25663         setBaseUrl(path.resolve(reqMain ? reqMain.filename : '.'));
25665         createRjsApi();
25667         module.exports = requirejs;
25668         return;
25669     } else if (env === 'browser') {
25670         //Only option is to use the API.
25671         setBaseUrl(location.href);
25672         createRjsApi();
25673         return;
25674     } else if ((env === 'rhino' || env === 'xpconnect') &&
25675             //User sets up requirejsAsLib variable to indicate it is loaded
25676             //via load() to be used as a library.
25677             typeof requirejsAsLib !== 'undefined' && requirejsAsLib) {
25678         //This script is loaded via rhino's load() method, expose the
25679         //API and get out.
25680         setBaseUrl(fileName);
25681         createRjsApi();
25682         return;
25683     }
25685     if (commandOption === 'o') {
25686         //Do the optimizer work.
25687         loadLib();
25689         /**
25690  * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
25691  * Available via the MIT or new BSD license.
25692  * see: http://github.com/jrburke/requirejs for details
25693  */
25696  * Create a build.js file that has the build options you want and pass that
25697  * build file to this file to do the build. See example.build.js for more information.
25698  */
25700 /*jslint strict: false, nomen: false */
25701 /*global require: false */
25703 require({
25704     baseUrl: require.s.contexts._.config.baseUrl,
25705     //Use a separate context than the default context so that the
25706     //build can use the default context.
25707     context: 'build',
25708     catchError: {
25709         define: true
25710     }
25711 },       ['env!env/args', 'env!env/quit', 'logger', 'build'],
25712 function (args, quit, logger, build) {
25713     build(args).then(function () {}, function (err) {
25714         logger.error(err);
25715         quit(1);
25716     });
25720     } else if (commandOption === 'v') {
25721         console.log('r.js: ' + version +
25722                     ', RequireJS: ' + this.requirejsVars.require.version +
25723                     ', UglifyJS2: 2.3.6, UglifyJS: 1.3.4');
25724     } else if (commandOption === 'convert') {
25725         loadLib();
25727         this.requirejsVars.require(['env!env/args', 'commonJs', 'env!env/print'],
25728             function (args, commonJs, print) {
25730                 var srcDir, outDir;
25731                 srcDir = args[0];
25732                 outDir = args[1];
25734                 if (!srcDir || !outDir) {
25735                     print('Usage: path/to/commonjs/modules output/dir');
25736                     return;
25737                 }
25739                 commonJs.convertDir(args[0], args[1]);
25740             });
25741     } else {
25742         //Just run an app
25744         //Load the bundled libraries for use in the app.
25745         if (commandOption === 'lib') {
25746             loadLib();
25747         }
25749         setBaseUrl(fileName);
25751         if (exists(fileName)) {
25752             exec(readFile(fileName), fileName);
25753         } else {
25754             showHelp();
25755         }
25756     }
25758 }((typeof console !== 'undefined' ? console : undefined),
25759     (typeof Packages !== 'undefined' || (typeof window === 'undefined' &&
25760         typeof Components !== 'undefined' && Components.interfaces) ?
25761         Array.prototype.slice.call(arguments, 0) : []),
25762     (typeof readFile !== 'undefined' ? readFile : undefined)));